D1405.extract-man.sh (3837B)
1 #!/bin/bash 2 3 function ble/complete/mandb/search-file/.check { 4 local path=$1 5 if [[ $path && -s $path ]]; then 6 ret=$path 7 return 0 8 else 9 return 1 10 fi 11 } 12 function ble/complete/mandb/search-file { 13 local command=$1 14 15 # Try "man -w" first 16 ble/complete/mandb/search-file/.check "$(man -w "$command" 2>/dev/null)" && return 0 17 18 local manpath=${MANPATH:-/usr/share/man:/usr/local/share/man:/usr/local/man} 19 ble/string#split manpath : "$manpath" 20 local path 21 for path in "${manpath[@]}"; do 22 ble/complete/mandb/search-file/.check "$path/man1/$man.1.gz" && return 0 23 ble/complete/mandb/search-file/.check "$path/man1/$man.1" && return 0 24 ble/complete/mandb/search-file/.check "$path/man1/$man.8.gz" && return 0 25 ble/complete/mandb/search-file/.check "$path/man1/$man.8" && return 0 26 done 27 return 1 28 } 29 30 ble/complete/mandb/search-file "${1:-grep}" || return 1 31 path=$ret 32 33 if [[ $ret == *.gz ]]; then 34 gzip -cd "$path" #/usr/share/man/man1/grep.1.gz 35 else 36 cat "$path" 37 fi | 38 awk ' 39 BEGIN { 40 g_key = ""; 41 g_desc = ""; 42 print ".TH __ble_ignore__ 1 __ble_ignore__ __ble_ignore__"; 43 print ".ll 9999" 44 } 45 function flush_topic() { 46 if (g_key == "") return; 47 print "__ble_key__"; 48 print ".TP"; 49 print g_key; 50 print ""; 51 print "__ble_desc__"; 52 print ""; 53 print g_desc; 54 print ""; 55 56 g_key = ""; 57 g_desc = ""; 58 } 59 60 /^\.TP\y/ { flush_topic(); mode = "key"; next; } 61 /^\.(SS|SH)\y/ { flush_topic(); next; } 62 63 mode == "key" { 64 g_key = $0; 65 g_desc = ""; 66 mode = "desc"; 67 next; 68 } 69 mode == "desc" { 70 if (g_desc != "") g_desc = g_desc "\n"; 71 g_desc = g_desc $0; 72 } 73 74 END { flush_topic(); } 75 ' | groff -Tutf8 -man | awk ' 76 function process_pair(name, desc) { 77 if (!(g_name ~ /^-/)) return; 78 79 # FS (\034) は ble.sh で内部使用の為除外する。 80 sep = "\x1b[1;91m:\x1b[m"; 81 #sep = "\034"; 82 if (g_name ~ /\034/) return; 83 gsub(/\034/, "\x1b[7m^\\\x1b[27m", desc); 84 85 n = split(name, names, /,[[:space:]]*/); 86 sub(/(\. |; ).*/, ".", desc); 87 for (i = 1; i <= n; i++) { 88 name = names[i]; 89 insert_suffix = " "; 90 menu_suffix = ""; 91 if (match(name, /[[ =]/)) { 92 m = substr(name, RSTART, 1); 93 if (m == "=") { 94 insert_suffix = "="; 95 } else if (m == "[") { 96 insert_suffix = ""; 97 } 98 menu_suffix = substr(name, RSTART); 99 name = substr(name, 1, RSTART - 1); 100 } 101 printf("%s" sep "%s" sep "%s" sep "%s\n", name, menu_suffix, insert_suffix, desc); 102 } 103 } 104 105 function flush_pair() { 106 if (g_name == "") return; 107 if (g_name ~ /^-/) { 108 process_pair(g_name, g_desc); 109 #print "\x1b[1;94m" g_name "\x1b[0m"; 110 #print g_desc; 111 #print ""; 112 } 113 g_name = ""; 114 g_desc = ""; 115 } 116 117 sub(/^[[:space:]]*__ble_key__/, "", $0) { 118 flush_pair(); 119 mode = "key"; 120 } 121 sub(/^[[:space:]]*__ble_desc__/, "", $0) { 122 mode = "desc"; 123 } 124 125 mode == "key" { 126 line = $0; 127 gsub(/\x1b\[[ -?]*[@-~]/, "", line); # CSI seq 128 gsub(/\x1b[ -/]*[0-~]/, "", line); # ESC seq 129 gsub(/\x0E/, "", line); 130 gsub(/\x0F/, "", line); 131 gsub(/^[[:space:]]*|[[:space:]]*$/, "", line); 132 #gsub(/[[:space:]]+/, " ", line); 133 if (line == "") next; 134 if (g_name != "") g_name = g_name " "; 135 g_name = g_name line; 136 } 137 138 mode == "desc" { 139 line = $0; 140 gsub(/^[[:space:]]*|[[:space:]]*$/, "", line); 141 #gsub(/[[:space:]]+/, " ", line); 142 if (line == "") { 143 if (g_desc != "") mode = ""; 144 next; 145 } 146 if (g_desc != "") g_desc = g_desc " "; 147 g_desc = g_desc line; 148 } 149 150 END { flush_pair(); } 151 ' | sort -k 1