Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I make tab-completion filter files by extension?

Assume myprogram only consumes *.data files as command line arguments. In terminal, when we do

$ myprogram <tab>

we want only the *.data files to be listed for tab auto-complete. How is this behavior achieved? The shell being used is Bash.

like image 591
Yixing Avatar asked Aug 24 '15 18:08

Yixing


People also ask

How does Tab autocomplete work?

Using autocomplete is as simple as pressing the [TAB] and the active command line options will fill-in. If more than one option is available, you can hit [TAB] twice to display all possible choices and continue typing until there is only one matching choice left.

Does Bash have tab completion?

The programmable completion feature in Bash permits typing a partial command, then pressing the [Tab] key to auto-complete the command sequence. [1] If multiple completions are possible, then [Tab] lists them all. Let's see how it works. Tab completion also works for variables and path names.

Where do I put Bash completion scripts?

If you want to enable the completion for all users, you can just copy the script under /etc/bash_completion. d/ and it will automatically be loaded by Bash.


2 Answers

Option 1

Type the following into your bash shell

complete -f -X '!*.data' myprogram

the -f option tells complete to only complete based on file names, not directories. the -X option allows you to specify the filter pattern.

Option 2

Note: This solution is global. It will affect tab-completion in every directory and on every command (meaning things like cd or rm, as well as myprogram). It works by allowing you to specify file extensions that will not appear in tab-complete. This is not exactly what you asked for, but if there aren't many files other than *.data in your working directory, excluding all the options won't be too much of a pain. For both these reasons this option is probably not what you want but it is still worth noting.

In the file ~/.bash_profile add the line

FIGNORE=".py:.txt:.out:.exe:.c:<etc>"

The syntax there is to create a colon-separated list of the file extensions you want to ignore. After saving the new .bash_profile you must type . ~/.bash_profile for the changes you made to take effect.

Further info

For more info about the complete command check out Programmable Completion Builtins in the Bash manual.

like image 120
Dsel Avatar answered Oct 29 '22 04:10

Dsel


Better use _filedir instead of "raw" complete.

Justification

  • grep _filedir -r $(pkg-config --variable=completionsdir bash-completion) | wc -l
  • tilde (~) paths are being expanded
  • Prefixes are removed for directories, i.e. for /home/tux/Do<TAB><TAB>, the list you get as a reply removes '/home/tux' and is thus much more compact
  • Easier to implement and more failsafe

MWE

Write a file "completions/myprogram", which you source by . completions/myprogram. Content:

_myprogram()
{
    # init bash-completion's stuff
    _init_completion || return

    # fill COMPREPLY using bash-completion's routine
    _filedir '@(data)'
}
complete -F _myprogram myprogram
like image 30
Johannes Avatar answered Oct 29 '22 04:10

Johannes