Search code examples
bashpowershelltab-completion

bash behaviour of pressing <tab> twice for filename completion


As an example, say that I type part of a name:

$ vi partn                         <= here I press <tab><tab>
partname     partnook     partnum  <= these are the results

This is standard behaviour in bash and that is fine, but I've been working a lot on PowerShell lately where the default behaviour is that if you press tab, it cycles through the names, completing each name and then pressing tab again will go to the next file, so if I pressed tab one time, I see vi ./partname, then press tab again, I see vi ./partnook, then tab again I see vi ./partnum. I tend to prefer this behaviour as it's less typing (you just hit tab to cycle through until you get the filename or command that you want).

Everything is customisable in Linux of course, so can someone advise how I might change the default bash behaviour to follow the above by default?


Solution

  • To persistently make tab-completion not require two Tab keypresses whenever there are multiple matching completions and to instead cycle through them, in-line:

    Option A: If you either already have:

    • an /etc/inputrc file (applies system-wide, modification requires sudo)
    • and/or a ~/.inputrc file (user-specific)

    and/or

    you're planning to customize the Readline library extensively and/or want to make customizations effective for scripts too when they call read -e:

    Add line:

    "\C-i": menu-complete
    

    to either file, depending on whether you want the setting to be effective for all users or the current user (create the file, if necessary).

    Note: Alternatively, you can simply turn off the need to press Tab twice and exhibit the standard behavior instantly, which means showing a multi-column list of all possible completions, and then redisplaying the input line, to allow you to type additional characters to either fully complete the argument or to type enough of it so that the next Tab keypress unambiguously completes:

    set show-all-if-ambiguous on
    

    Option B: Alternatively, you may add Readline commands to your user-specific initialization file (~/.bash_profile on macOS, ~/.bashrc on Linux and other Unix-like platforms), by passing them as a single argument to the bind builtin:

    bind '"\C-i": menu-complete'
    

    If you prefer the show-all-matches behavior:

    bind 'set show-all-if-ambiguous on'
    

    Note that bind commands in ~/.bash_profile / ~/.bashrc take precedence over equivalent commands in either /etc/inputrc or ~/.inputrc.

    As implied above, configuring Readline this way will not take effect in scripts that call read -e in order to activate Readline support for reading user input.