NEDIT_require_macro_file("RSextensions.nm") NEDIT_require_macro_file("RScolor.nm") # ============================================================================== # ManHelp(): calls man(1) for either the selected text or for the current word # or a user-supplied man subject. The result is written to a window, with # the "Man page output" language set, which may replace or append to # previous output of this command. Rangesets are used instead of bold # and underline/italic. # ============================================================================== define ManHelp { # set up regex shortcuts w_ = "[-\\w.]" # word and '-', '.' (for valid man page names) W_ = "[^-\\w.]" # not (word and '-', '.') n_ = "\\d" # digit wS_ = w_"*" # 0-or-more word and '-' wP_ = w_"+" # 1-or-more word and '-' aS_ = "[\\l_]*" # 0-or-more letter and '_' nP_ = n_"+" # 1-or-more digit po_ = "\\(" # open parenthesis pp_ = "[][!\"#$%&'*+,./:;<=>?@\\\\^_`{|}~-]*" # punctuations pc_ = "\\)" # close parenthesis naa_ = n_ aS_ pp_ # digit then letters (for valid man section, eg 1M) # add punctuations for things like 3C++ NAA_ = po_ naa_ pc_ # parenthesised man section hNL_ = "-\n\\s*" # hyphenated newline and space sequence #*old version - not allowing space between man word and parenthesised section* # xref = wP_ "(?:" hNL_ wP_ ")?" NAA_ # sub_1_po_2_pc = "([^(]+)" po_ "([^)]+)" pc_ # xref allows spaces between a man word and its parenthesised section xref = wP_ "(?:" hNL_ wP_ ")?[\t ]*" NAA_ # sub_1_po_2_pc extracts the man word and its parenthesised section # to build the man command line sub_1_po_2_pc = "([^(\\s]+)[\t ]*" po_ "([^)]+)" pc_ s = "" sel = get_selection() allowReplace = 0 if ($language_mode == "Man page output" && $highlight_syntax) { allowReplace = 2 # first step is to find the extent of the man reference: use highlighting pos = $cursor ok = 0 while (1) { pattern = "" if (pos < $text_length) { aPattern = get_pattern_at_pos(pos) if ("pattern" in aPattern) pattern = aPattern["pattern"] } if (search_string(pattern, "cross reference.*", 0, "regex") >= 0) pos-- else { if (pos < $cursor) # we did move back - so we did have a reference { pos++ ok = 1 break } else break } } if (ok) { if (pos == search(xref, pos, "regex")) { endpos = $search_end s = get_range(pos, endpos) s = replace_in_string(s, hNL_, "", "regex", "copy") s = replace_in_string(s, sub_1_po_2_pc, "-s \\2 \\1", "regex") } } } # if that didn't work, try this: if (s == "") { # use regexes to attempt to find either something like wwww(naaa) # or just pick up the current word pos = $cursor # if we are just after a ")", move in front of it if (search(")", pos - 1, "literal") >= 0) pos-- # if we have aaa), move to front of aaa while (pos == search(aS_ pc_, pos, "regex")) pos-- # do we have a digit (single) in front of that? if so, step back if (pos == search(naa_ pc_, pos, "regex")) pos-- # now do we have wwww(naaa)? if so step back in front of that while (pos == search(wS_ NAA_, pos, "regex")) pos-- # move back past preceding spaces, a single newline, hyphen and word chars front = search("("W_"|^)"wP_ hNL_, pos + 1, "regex", "backward") if (front >= 0) { if (pos == $search_end - 1) { pos = front if (pos == search(w_, pos, "regex")) pos-- } } # what if we're already at the first part of a hyphenated reference? while (pos == search(xref, pos, "regex")) pos-- # by the time we get here we have stepped back one too far (or not at all) if (pos < $cursor) # did move back - so we may be in front of a reference pos++ # right: now what have we got??? does it match aaaa(naaa)? if (pos == search(xref, pos, "regex")) { s = get_range(pos, $search_end) s = replace_in_string(s, hNL_, "", "regex", "copy") s = replace_in_string(s, sub_1_po_2_pc, "-s \\2 \\1", "regex") } else # ok: that didn't work - try a plain word... { pos = $cursor if (search(w_, pos - 1, "regex") == pos - 1) pos-- while (pos == search(w_, pos, "regex")) pos-- if (pos < $cursor) # did move back so we may be in front of a reference pos++ if (pos == search(wP_, pos, "regex")) s = get_range(pos, $search_end) # pick up the word } } # what about a selection? subject = "" if (sel != "") { # remove spaces from the selection string back-word(1two) sel = replace_in_string(sel, "[\\s\n]+", "", "regex", "copy") # we only allow a selection if it matches wwww or wwww(naaa) if (sel != "" && \ search_string(sel, wP_"(?:"NAA_")?", 0, "regex") == 0) { str = replace_in_string(sel, sub_1_po_2_pc, "-s \\2 \\1", "regex") if (str == "") { if (search_string(sel, W_, 0, "regex") >= 0) # non-word chars? { #dialog("Quoting "sel"\nReason: "W_" found at "search_string(sel,W_,0,"regex")) str = "'" sel "'" # then quote the rest } else str = sel } sel = str # choose between selection and word? if (s == "") s = sel else if (s != sel) { prompt = "man (-s section) subject" prompt = prompt "\nselection: " sel prompt = prompt "\nword found: " s str = string_dialog(prompt, "Selection", "Word found", "Cancel") if ($string_dialog_button < 1 || $string_dialog_button > 2) return if (str == "") { if ($string_dialog_button == 1) str = sel else str = s } s = str subject = s } } } button = 0 if (subject == "") { subject = s prompt = "man (-s section) subject" if (subject != "") prompt = prompt "\ndefault: " subject if (allowReplace) s = string_dialog(prompt, "New Window", "Replace", \ "Add at end", "Cancel") else s = string_dialog(prompt, "OK", "Cancel") if (s == "") s = subject button = $string_dialog_button } else { prompt = "man " subject if (allowReplace) button = dialog(prompt, "New Window", "Replace", "Add at end", "Cancel") else button = dialog(prompt, "OK", "Cancel") } if (button < 1 || button > 1 + allowReplace) return tryAgain = 1 while (tryAgain) { manargs = s mancmd = "/bin/sh -c 'man \"$@\" 2>/dev/null' - " manargs # mancmd = "man " manargs manout = shell_command(mancmd, "") # test results: shell return value may not work # (man always "succeeds" on Sun) manOK = ($shell_cmd_status == 0) BadManSolaris = "No manual entry for " if (substring(manout, 0, length(BadManSolaris)) == BadManSolaris) manOK = 0 # any more platform-specific messages? # Linux (BSD?) doesn't accept -s for section argument # try again without it if we failed if (!manOK) { sectArg = search_string(s, "(?<=^|\\s)-s", 0, "regex") if (sectArg >= 0) { # cut out the -s s = substring(s, 0, sectArg) substring(s, $search_end) } else tryAgain = 0 } else tryAgain = 0 } if (manOK) { if (button == 1) { if ($language_mode == "Man page output") new("tab") else new("window") focus_window("last") set_incremental_backup(0) set_make_backup_copy(0) set_show_line_numbers(0) set_statistics_line(0) set_use_tabs(0) set_wrap_text("none") set_language_mode("Man page output") set_highlight_syntax(1) } else { if (button == 2) replace_range(0, $text_length, "") else if (button == 3) { set_cursor_pos($text_length) insert_string("\n") rso = rangeset_fetch("break", \ "color", RangeSet_mapToDark("#4080c0"), \ "mode", "exclude") rangeset_add(rso, $text_length - 1, $text_length) } } deselect_all() s = manout # remove repeated blank lines s = replace_in_string(s, "\n(?:\\s*\n)+\n", "\n\n", "regex", "copy") # lo and hi mark beginning and end of man text lo = $cursor orig = lo insert_string(s) hi = $cursor set_cursor_pos(lo) # replace +/_ combination with plus-or-minus character if (search("+\b_", 0) >= 0) replace_all("+\b_", "±") # create and color rangesets for bold/underline highlights rsm = rangeset_fetch("underlined", "color", RangeSet_mapToDark("#80C0FF")) rsn = rangeset_fetch("bold", "color", RangeSet_mapToDark("#80FFFF")) while (1) { # nlo = search("_\b.", lo, "regex") nlo = search("(?:_\b.)+", lo, "regex") if (nlo == -1 || nlo >= hi) break # replace_range(nlo, nlo + 2, "") # remove underscore+backspace # hi = hi - 2 # change end marker position # lo = nlo # advance search position # rangeset_add("m", lo, lo + 1) # color the "underlined" character nle = $search_end s = get_range(nlo, nle) s = replace_in_string(s, "_\b", "", "copy") replace_range(nlo, nle, s) rangeset_add(rsm, nlo, nlo + length(s)) lo = nlo # advance search position } lo = orig while (1) { # strictly bold is a repetition of a single character with a backspace, # but bullets are often rendered as an overlay of "o" and "+", so we # treat both together, retaining only the character after the backspace. # nlo = search(".\b.", lo, "regex") nlo = search("(?:.\b.)+", lo, "regex") if (nlo == -1 || nlo >= hi) break # replace_range(nlo, nlo + 2, "") # remove 1st-char+backspace # hi = hi - 2 # change end marker position # lo = nlo # advance search position # rangeset_add("n", lo, lo + 1) # color the "bold" character nle = $search_end s = get_range(nlo, nle) s = replace_in_string(s, ".\b", "", "regex", "copy") replace_range(nlo, nle, s) rangeset_add(rsn, nlo, nlo + length(s)) lo = nlo # advance search position } } else { s = shell_command("man " manargs " | head", "") s = replace_in_string(s, ".\b", "", "regex", "copy") dialog("Command 'man "manargs"' failed: " $shell_cmd_status "\n\n" s) } }