ajwood
ajwood

Reputation: 19057

Multiple tab-completion routines in Bash terminal

Is it possible to have multiple tab-completion routines, triggered by different key combinations?

For example, I have a custom tab-completion function which parses the output of myprog -help to tab-complete options. Is there some way I could keep the default tab-complete behaviour on Tab untouched, and bind my custom completion to something like Shift+Tab?

Upvotes: 3

Views: 778

Answers (1)

Alex North-Keys
Alex North-Keys

Reputation: 4373

The keybindings themselves are part of readline, and can be changed in your ~/.inputrc or use the bind command in your .bashrc (etc.), but they don't bind directly to user-defined functions, only indirectly as macros that might call those functions.

"\C-xhf": dump-functions        # for ~/.inputrc
bind '"\C-xhf":dump-functions'  # in .bashrc (etc.)

bind -l will show you builtin functions you can bind to. You can add macros this way, which let's you run any bash function you want, although not in completion context, so the results don't get stuffed back into the command line. Example:

"\C-xc":  "echo hi\n"       # note it's a just macro, not a direct binding.

I'm guessing you already know you can override completion with the complete builtin for commands at the left on the command line. Normally I'd just suggest creating your own completion routines that way and using them instead of working out a way to call an alternate set. Example:

_complete_ssh ()
{
    local ssharg="${COMP_WORDS[COMP_CWORD]}"
    local filter=cat
    case "$ssharg" in *@*) filter="sed s/^/${ssharg%@*}@/" ;; esac
    local host=${ssharg##*@}
    COMPREPLY=( $(compgen -W "`
        sed 's/[, ].*//'  ~/.ssh*/known_hosts{,2} | sort | uniq
    `" $host | $filter ))
    return 0
}
complete -F _complete_ssh ssh          # for any command starting with "ssh "...

I experimented with binding universal-argument to see if it would affect a function run via a macro ("C-xu" to prefix UA, then "C-xf" to run a function), but I haven't noticed anything to indicate the function can detect UA. You'd think bind would have a option to regurgitate what UA was for the previous command, or a $-something, which might have allowed a user-defined completer sub-function to detect UA from inside of complete, and thus behave differently, but I don't see any sign of the idea in the readline source code. There's no obvious way to see what keybinding evoked a function or macro either (I didn't expect one), to allow mapping two keybindings to the same complete builtin, then backtracking to see which keybinding triggered it.

Note that Shift-TAB would be hard to bind anyway, and impossible to type from an old-school terminal. bash doesn't use the X libraries and can't see Shift directly as a modifier, instead depending on terminals or terminal emulators for input in some character set, which don't have an applicable concept of modifiers.

Upvotes: 2

Related Questions