Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do not autocomplete certain extensions from file names in shell for vim

I've noticed a really cool feature of bash-completion in bash. Let's say I have a directory with files

a.java
a.class
b.java
b.class

if I start typing vim a Tab , bash will autocomplete a.java. It knows I don't want to edit a.class

I was wondering how it achieves this behavior. In my bash_completion.d directory there are a bunch of completion files, but vim does not have one. How does vim achieve this behavior, and how do I modify it to include other file extensions to ignore?

like image 593
Max Coplan Avatar asked Oct 09 '18 23:10

Max Coplan


1 Answers

On Ubuntu, if I install the package bash-completion, I can see its contents with:

$ dpkg -L bash-completion

In the output, /etc/bash_completion is listed.
Inside, the following command is written:

. /usr/share/bash-completion/bash_completion

It sources the file /usr/share/bash-completion/bash_completion.

The location of these files vary from an OS to another:

Note: I use a Mac, and on macOS the bash-completion file is stored (by default) in /usr/local/etc/bash_completion, and the bash_completion.d directory is in /usr/local/etc/bash_completion.d

On my system, /usr/share/bash-completion/bash_completion contains this line:

_install_xspec '*.@(o|so|so.!(conf|*/*)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite

I think this line is responsible for the behavior you're observing.

If you want to tweak it to make bash exclude the foo and bar extensions when completing a filename after the $ vim command, you could try the following procedure.

  1. Create the file ~/.bash_completion

Inside the latter, write:

for bcfile in ~/.bash_completion.d/* ; do
  [ -f "$bcfile" ] && . $bcfile
done
  1. Create the ~/.bash_completion.d/ directory.

  2. Inside this directory, create a vim file.

Inside the latter, write:

complete -f -X '*.@(o|so|so.!(conf|*/*)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class|foo|bar)' vi vim gvim rvim view rview rgvim rgview gview

complete is a bash builtin command which allows you to specify how arguments to a command name should be completed.
-f is a shorthand for -A file, which specifies to bash that you want to see only filenames in your suggestions.
-X excludes anything which matches the following pattern.

Note that I have merely copied the pattern used in /usr/share/bash-completion/bash_completion, and added the foo and bar extensions:

*.@(o|so|so.!(conf|*/*)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class|foo|bar)
                                                                           ^^^^^^^

It's up to you to modify the pattern to exclude the real extensions you want to avoid.

The names after the pattern tell bash for which commands should it exclude these extensions.
In the previous command, they are:

vi vim gvim rvim view rview rgvim rgview gview

All of them invoke a version of Vi or Vim. You could add other editor names at the end.

For more information see:

$ man bash

Look for the READLINE section and the Programmable Completion subsection, as well as the description of the complete builtin in the SHELL BUILTIN COMMANDS section.

See also An introduction to bash completion part 1 and An introduction to bash completion part 2.

like image 93
user938271 Avatar answered Nov 08 '22 19:11

user938271