How do I add autocompletion for my stfu
command?
How do I add autocompletion for my stfu
command?
I have a little helper command in ~/.zshrc
called stfu
.
stfu() { if [ -z "$1" ]; then echo "Usage: stfu <program> [arguments...]" return 1 fi nohup "$@" &>/dev/null & disown } complete -W "$(ls /usr/bin)" stfu
stfu
will run some other command but also detach it from the terminal and make any output shut up. I use it for things such as starting a browser from the terminal without worrying about CTRL+Z
, bg
, and disown
.
$ stfu firefox -safe-mode # Will not output stuff to the terminal, and # I can close the terminal too.
Here’s my issue:
On the second argument and above, when I hit tab, how do I let autocomplete suggest me the arguments and command line switches for the command I’m passing in?
e.g. stfu ls -<tab>
should show me whatever ls’s completion function is, rather than listing every /usr/bin
command again.
# Intended completion $ stfu cat -<TAB> -e -- equivalent to -vE --help -- display help and exit --number -n -- number all output lines --number-nonblank -b -- number nonempty output lines, overrides -n --show-all -A -- equivalent to -vET --show-ends -E -- display $ at end of each line --show-nonprinting -v -- use ^ and M- notation, except for LFD and TAB --show-tabs -T -- display TAB characters as ^I --squeeze-blank -s -- suppress repeated empty output lines -t -- equivalent to -vT -u -- ignored # Actual completion $ stfu cat <tab> ...a list of all /usr/bin commands $ stfu cat -<tab> ...nothing, since no /usr/bin commands start with -
(repost, prev was removed)
EDIT: Solved.
I needed to set the curcontext
to the second word. Below is my (iffily annotated) zsh implementation, enjoy >:)
stfu() { if [ -z "$1" ]; then echo "Usage: stfu <program> [arguments...]" return 1 fi nohup "$@" &>/dev/null & disown } #complete -W "$(ls /usr/bin)" stfu _stfu() { # Curcontext looks like this: # $ stfu <tab> # :complete:stfu: local curcontext="$curcontext" #typeset -A opt_args # idk what this does, i removed it _arguments \ '1: :_command_names -e' \ '*::args:->args' case $state in args) # idk where CURRENT came from if (( CURRENT > 1 )); then # $words is magic that splits up the "words" in a shell command. # 1. stfu # 2. yourSubCommand # 3. argument 1 to that subcommand local cmd=${words[2]} # We update the autocompletion curcontext to # pay attention to your subcommand instead curcontext="$cmd" # Call completion function _normal fi ;; esac } compdef _stfu stfu
Deduced via docs (look for The Dispatcher), this dude's docs, stackoverflow and overreliance on ChatGPT.
EDIT: Best solution (Andy)
stfu() { if [ -z "$1" ]; then echo "Usage: stfu <program> [arguments...]" return 1 fi nohup "$@" &>/dev/null & disown } _stfu () { # shift autocomplete to right shift words (( CURRENT-=1 )) _normal } compdef _stfu stfu