diff --git a/share/functions/__fish_print_help.fish b/share/functions/__fish_print_help.fish index 8e4d30004..46246e342 100644 --- a/share/functions/__fish_print_help.fish +++ b/share/functions/__fish_print_help.fish @@ -1,12 +1,6 @@ - function __fish_print_help --description "Print help message for the specified fish function or builtin" --argument item - - switch $argv[1] - case '.' + if test "$item" = '.' set item source - - case '*' - set item $argv[1] end # Do nothing if the file does not exist @@ -14,27 +8,81 @@ function __fish_print_help --description "Print help message for the specified f return end - # These two expressions take care of underlines (Should be italic) - set -l cmd1 s/_\x08'\(.\)'/(set_color --underline)\\1(set_color normal)/g - set -l cmd2 s/'\(.\)'\x08_/(set_color --underline)\\1(set_color normal)/g - - # This expression should take care of bold characters. It's not - # waterproof, since it doesn't check that the same character is - # used both before and after the backspace, since regular - # languages don't allow backreferences. - set -l cmd3 s/.\x08'\(.\)'/(set_color --bold)\\1(set_color normal)/g - - # Combine all expressions in a single variable - set -l sed_cmd -e $cmd1 -e $cmd2 -e $cmd3 + set -l IFS \n\ \t # Render help output, save output into the variable 'help' - set -l help (nroff -man "$__fish_datadir/man/man1/$item.1" ^ /dev/null ) - set -l lines (count $help) + set -l help + set -l rLL + if command test -t 1 + # We want to simulate `man`'s dynamic line length, because + # defaulting to 80 kind of sucks. + # Note: using `command test` instead of `test` because `test -t 1` + # doesn't seem to work right. + # Note: grab the size from the stdout terminal in case it's somehow + # different than the stdin of fish. + set -l cols + begin + # use fd 3 to copy our stdout because we need to pipe the output of stty + stty size 0<&3 | read _ cols + end 3<&1 + set cols (expr $cols - 4) # leave a bit of space on the right + set rLL -rLL=$cols[1]n + end + set help (nroff -man -t $rLL "$__fish_datadir/man/man1/$item.1" ^/dev/null) - # Print an empty line first - echo - - # Filter and print help - printf "%s\n" $help| tail -n (expr $lines - 5) | head -n (expr $lines - 8) | sed $sed_cmd + # The original implementation trimmed off the top 5 lines and bottom 3 lines + # from the nroff output. Perhaps that's reliable, but the magic numbers make + # me extremely nervous. Instead, let's just strip out any lines that start + # in the first column. "normal" manpages put all section headers in the first + # column, but fish manpages only leave NAME like that, which we want to trim + # away anyway. + # + # While we're at it, let's compress sequences of blank lines down to a single + # blank line, to duplicate the default behavior of `man`, or more accurately, + # the `-s` flag to `less` that `man` passes. + set -l state blank + for line in $help + # categorize the line + set -l line_type + switch $line + case ' *' \t\* + # starts with whitespace, check if it has non-whitespace + printf "%s\n" $line | read -l word _ + if test -n $word + set line_type normal + else + # lines with just spaces probably shouldn't happen + # but let's consider them to be blank + set line_type blank + end + case '' + set line_type blank + case '*' + # not leading space, and not empty, so must contain a non-space + # in the first column. That makes it a header/footer. + set line_type meta + end + switch $state + case normal + switch $line_type + case normal + printf "%s\n" $line + case blank + set state blank + case meta + # skip it + end + case blank + switch $line_type + case normal + echo # print the blank line + printf "%s\n" $line + set state normal + case blank meta + # skip it + end + end + end | ul # post-process with `ul`, to interpret the old-style grotty escapes + echo # print a trailing blank line end