7

Just now, dpkg --help spit out three pages of output in my face. I was maybe interested in the first ten lines, which show the general usage and most common arguments.

I'd like that, whenever I run a program (any program) with --help as the only argument, if the output is longer than $(tput lines), it would automatically get piped through less. Is it easily doable in bash?

Edit: In the end, the best solution for me was to switch to zsh. Either one of the following snippets in your ~/.zshrc will do the job; each one has its own tradeoffs:

# Modify the input line before it runs
function lessify() {
    if [[ "$BUFFER" =~ " --help$" ]] ; then
        BUFFER="$BUFFER | less -FX"
    fi  
    zle accept-line
}

zle -N lessify_widget lessify
# Bind to the Enter key
bindkey '^M' lessify_widget

or

# Alias --help ; ignore rest of the line 
alias -g -- --help="--help | less -FX ; true "

Also, in researching this question, I've probably wasted more time than this will ever save me. Don't regret it one bit.

Mihai
  • 1,102
  • 1
    The task easy do in zsh by alias -g and not too easy in bash. May be you'd satisfy with man dpkg? – Costas Feb 12 '15 at 12:37
  • 1
    Not really. a) Not all utilities have manpages; b) man always uses less, which you'll have to exit - that's one keypress I'd like to avoid; and c) sometime I automatically type <some_program> --help just out of habit. – Mihai Feb 12 '15 at 12:42
  • I will consider switching to zsh, though. – Mihai Feb 12 '15 at 12:45
  • Aside from checking if the output is longer than a certain treshold, wouldn't alias --help='--help | less' do the trick? – Simon Klaver Feb 12 '15 at 13:11
  • @TheJustist alias --help='--help | less -F' might just possibly work. I'll check it and update this comment, and then you could post this as an answer. ... Edit: No luck. An alias must be the first word of a command. – Mihai Feb 12 '15 at 13:19
  • Would a script called 'Help' (for example) help you? Such as #!/bin/bash <newline> $1 --help | less -F which you can call as Help <program>. Do not know if this works, just a quick idea. – Simon Klaver Feb 12 '15 at 13:26
  • Agreed with The Justist: can't do this in bash without a function. the zsh global alias idea will work. – glenn jackman Feb 12 '15 at 14:48
  • You can get your desired effect with expect, but seriously, you should not do this: expect -c 'spawn bash; interact -- "--help\r" {send -- "--help | less\r"} – glenn jackman Feb 12 '15 at 14:52
  • 1
    Personally, I just have m set as an alias to less (I used to use more, hence the m) and all I need to do is type command --help | m to get what you're after. Is it really worth writing a function for this? – terdon Feb 12 '15 at 16:24

2 Answers2

6

In bash, you can do this with the debug features, although it's a pretty fragile solution and very dependent on your environment.

Enable extended debugging (see the manual for details):

shopt -s extdebug

Create a helprun function:

helprun() {
    if [ "$#" -eq 2 ] && [ "$2" = '--help' ]; then
        "$@" | less -F
        return 1
    fi
}

Then trap all commands with it:

trap 'helprun $BASH_COMMAND' DEBUG

This will run helprun <command> for every command, and if it is a --help command, pipe it through less, returning 1 so that the command isn't executed (thanks to extdebug). If it isn't, it just runs as normal.

There are probably edge cases I haven't handled here...

Stephen Kitt
  • 434,908
2

Alternative method is to write a script which does the same:

#!/bin/bash
$1 --help | less -F

Call it Help for example, chmod +x Help to make it an executable and place it somewhere in your PATH, such as /bin or /usr/bin. Then everytime you want to list the help of a program, you use Help <program> instead of <program> --help.