|
Home | Switchboard | Unix Administration | Red Hat | TCP/IP Networks | Neoliberalism | Toxic Managers |
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and bastardization of classic Unix |
|
One of the most powerful (and typically underused) features of many shells (ksh, bash, zsh) is filename completion facility, introduced to Unix in C shell, and originated in DEC TOPS-20 operating system.
|
The idea behind filename completion is that when you need to type a filename, you should not have to type more than is necessary to identify the file unambiguously. This is an excellent idea although it is limited by absence of visual feedback (compare with OFM filename completion). Still in moderate dozes it can save you some typing.
There is also a possibility to increase efficiency of programming completion by considering the type of arguments (which can be deducted from the command and its options) that particular command accepts. For example if you have type cd command you are interesting in the list of directories not any other type of files.
Later version of bash, starting from 3.2 has quite elaborate completion system. Now bash offers several forms of completion, including path, file, user, host and variable completion.
ls /bo[TAB]
When you press the Tab key the argument /bo is automatically replaced with the value /boot. If there are two directories /boot and /boot_bak, then you need to type the Tab key twice and you get the list of all directories with the given prefix.
File completion is based on the type of command you use. for example tar command will try to
complete the file with archive that have extension .tar, .tar.gz of .tgz.
If you use tar command and want regular file completion you should use Esc-Tab
or Shift-Tab or instead of Tab to revert to standard filename expansion.
bash completion extends bash's standard completion behavior to achieve complex command lines with just a few keystrokes. This project was conceived to produce programmable completion routines for the most common Linux/UNIX commands, reducing the amount of typing sysadmins and programmers need to do on a daily basis.
It will create among other things /etc/bash_completion file that you can source. But /etc/profile.d/bash_completion.sh module does the trick as well.
Debian has probably the best maintained version of this package ( bash-completion ) which has tremendous number of completion modules for various commands. You can import certain modules that make value for you into RHEL or SLES installation Just download and untar Debian source package and select those modules that are interesting to you (.xz extension, which is not popular in RHEL or Suse, is understood by GNU tar, use -J option).
Sometimes you need to create you own particular type of completion. This is a very interesting and productive exercise for programs that you use often. I highly recommend you doing that if you use particular program on daily basis. Look at An introduction to bash completion part 2 and study Debian completion package.
As in case of filesystem traversal with cd command completion propose the directory based of the prefix you types, using completion in this way, you can simplify traversal to the deeply nested directories that is a hall mark of many open source (for example SGE) or commercial packages such as OpenView, Tivoli, etc.
A very interesting example of completion is incremental searching of command history, usually bound to C-r (Ctrl-R). This is a sort of cross between the other two: press it, and start typing a word which exists somewhere in the history. By the time you've typed enough of it to uniquely identify it, it will be available for reuse. This feature is available in bash (C-r by default), tcsh (not bound by default) and zsh (C-r by default).
Modern implementation of completion goes beyond file names. When you can press a key (often TAB) and the shell automatically cleverly completes the rest of the word you are typing, based on the context you are typing it in. bash offers basic filename, hostname and command completion.
Only tcsh and zsh offer fully programmable context-sensitive completion of many different types with zsh functionality clearly superior. Later versions of bash improved the completion system making it quite usable.
The most primitive completion is when instead of typing in the arguments/options following a command, the user presses TAB TAB and the shell automatically inserts (or gives you the option of inserting) filename based on context of command you're editing.
In more advanced implementation type of the file matters. For example, say you want to extract files from a UNIX tape archive (.tar or .tar.gz file) of the Linux kernel source tree, which you just downloaded to the /tmp directory. You type:
tar -zxvf l[pressTab TAB] tar -zxvf linux-2.0.38.tar.gz
If you had chosen -xvf instead, it would complete on files ending in .tar. Say there was also a file called allmail.tar in tmp:
tar -xvf [press TAB] tar -xvf allmail.tar
In ksh93 it means two things:
Programmable completion indefinitely extends the type of completion you can perform.
Bash supports several completion modes (via readline). Only few first have practical importance and return on investment for other modes might in general be negative:
complete (TAB)
possible-completions (M-?)
insert-completions (M-*)
possible-completions
.
menu-complete ()
complete
, but replaces the word to be completed with a single match
from the list of possible completions. Repeated execution of menu-complete
steps through
the list of possible completions, inserting each match in turn. At the end of the list of completions,
the bell is rung (subject to the setting of bell-style
) and the original text is restored.
An argument of n moves n positions forward in the list of matches; a negative
argument may be used to move backward through the list. This command is intended to be bound to
TAB, but is unbound by default. delete-char-or-list ()
delete-char
). If at the end of the line, behaves identically to possible-completions
.
This command is unbound by default. complete-filename (M-/)
possible-filename-completions (C-x /)
complete-username (M-~)
possible-username-completions (C-x ~)
complete-variable (M-$)
possible-variable-completions (C-x $)
complete-hostname (M-@)
possible-hostname-completions (C-x @)
complete-command (M-!)
possible-command-completions (C-x !)
dynamic-complete-history (M-TAB)
complete-into-braces (M-{)
Backslash (\) is the command that tells the Korn shell to do filename completion in vi-mode. If you type in a word, type ESC to enter control mode, and then type \, one of four things will happen:
If there is no file whose name begins with the word, the shell will beep and nothing further will happen.
If there is exactly one way to complete the filename and the file is a regular file, the shell will type the rest of the filename, followed by a space in case you want to type in more command arguments.
If there is exactly one way to complete the filename and the file is a directory, the shell will complete the filename, followed by a slash.
If there is more than one way to complete the filename, the shell will complete out to the longest common prefix among the available choices.
A related command is *.
It behaves similarly to
ESC \, but if there is more than one completion possibility (number four
in the list above), it lists all of them and allows you to type further. Thus, it resembles the
*
shell wildcard character.
The command = does the same kind of filename expansion as the
*
shell wildcard, but in a different way. Instead of expanding the filenames
onto the command line, it prints them in a numbered list with one filename on each line. Then it gives
you your shell prompt back and retypes whatever was on your command line before you typed
=. You can select the filename you which and put it on the command line
using the middle button of the mouse.
[esc] [=]
Display list of pathnames that result from expanding the word under the cursor.[esc] [esc]
Append characters to the word under the cursor to complete the pathname of an existing file.[esc] [*]
Replace words under the cursor with the list of pathnames that result from expanding the word.2.7. Command completion -- vi mode
[=]
Display list of pathnames that result from expanding the word under the cursor.[\]
Append characters to the word under the cursor to complete the pathname of an existing file.[*]
Replace words under the cursor with the list of pathnames that result from expanding the word.
= |
Pathname listing. Causes the current word on the command line to be expanded to a list of pathnames. For example, |
$ls m<ESC>= 1) myfile 2) myhome $
\ |
Pathname completion. Causes the current word on the command line to be expanded to a filename or directory. If it is a directory then a / is added. For example, |
$ echo my<Esc>\
would expand to myfile. | |
@letter |
Searches your list of aliases for one named _letter. If an alias is defined, its value is inserted as keystrokes. For example, |
alias _Q='LBi"^V<Esc>Ea"^V<Esc>'
now if you are editing a command and type <Esc>@Q the current word you are on would be quoted. | |
# |
Insert a # (comment marker) at the beginning of a command. |
the zsh extended completion includes: the ytalk, finger and ssh commands, which complete on usernames and hostnames (automatically appending an @ symbol in between); the find command, which has different completions for each option (e.g. completes file/directory names for the initial parameter(s), users for -user, groups for -group ... zsh is even able to treat the arguments to -exec as a whole new command line!). The rpm, cvs, and gcc completions are even more fiendish.
You certainly get "hardcore hacker" points for fully grokking the internals of the zsh completion system. However, you can rejoice in the knowledge that you won't ever need to in order to enjoy this sophisticated time-saver, since the latest development versions come with a complete, `out of the box' pre-configured completions system.
Please visit Heiner Steven SHELLdorado: the best shell scripting site on the Internet |
Jul 09, 2020 | zwischenzugs.com
TL;DR
These commands can tell you what key bindings you have in your bash shell by default.
bind -P | grep 'can be' stty -a | grep ' = ..;'BackgroundI'd aways wondered what key strokes did what in bash – I'd picked up some well-known ones (CTRL-r, CTRL-v, CTRL-d etc) from bugging people when I saw them being used, but always wondered whether there was a list of these I could easily get and comprehend. I found some, but always forgot where it was when I needed them, and couldn't remember many of them anyway.
Then debugging a problem tab completion in 'here' documents, I stumbled across bind.
bind and stty'bind' is a bash builtin, which means it's not a program like awk or grep, but is picked up and handled by the bash program itself.
It manages the various key bindings in the bash shell, covering everything from autocomplete to transposing two characters on the command line. You can read all about it in the bash man page (in the builtins section, near the end).
Bind is not responsible for all the key bindings in your shell – running the stty will show the ones that apply to the terminal:
stty -a | grep ' = ..;'These take precedence and can be confusing if you've tried to bind the same thing in your shell! Further confusion is caused by the fact that '^D' means 'CTRL and d pressed together whereas in bind output, it would be 'C-d'.
edit: am indebted to joepvd from hackernews for this beauty
$ stty -a | awk 'BEGIN{RS="[;n]+ ?"}; /= ..$/' intr = ^C quit = ^ erase = ^? kill = ^U eof = ^D swtch = ^Z susp = ^Z rprnt = ^R werase = ^W lnext = ^V flush = ^OBreaking Down the Commandbind -P | grep canCan be considered (almost) equivalent to a more instructive command:
bind -l | sed 's/.*/bind -q /' | /bin/bash 2>&1 | grep -v warning: | grep can'bind -l' lists all the available keystroke functions. For example, 'complete' is the auto-complete function normally triggered by hitting 'tab' twice. The output of this is passed to a sed command which passes each function name to 'bind -q', which queries the bindings.
sed 's/.*/bind -q /'The output of this is passed for running into /bin/bash.
/bin/bash 2>&1 | grep -v warning: | grep 'can be'Note that this invocation of bash means that locally-set bindings will revert to the default bash ones for the output.
The '2>&1' puts the error output (the warnings) to the same output channel, filtering out warnings with a 'grep -v' and then filtering on output that describes how to trigger the function.
In the output of bind -q, 'C-' means 'the ctrl key and'. So 'C-c' is the normal. Similarly, 't' means 'escape', so 'tt' means 'autocomplete', and 'e' means escape:
$ bind -q complete complete can be invoked via "C-i", "ee".and is also bound to 'C-i' (though on my machine I appear to need to press it twice – not sure why).
Add to bashrcI added this alias as 'binds' in my bashrc so I could easily get hold of this list in the future.
alias binds="bind -P | grep 'can be'"Now whenever I forget a binding, I type 'binds', and have a read :)
[adinserter block="1″]
The ZingerBrowsing through the bash manual, I noticed that an option to bind enables binding to
-x keyseq:shell-commandSo now all I need to remember is one shortcut to get my list (CTRL-x, then CTRL-o):
bind -x '"C-xC-o":bind -P | grep can'Of course, you can bind to a single key if you want, and any command you want. You could also use this for practical jokes on your colleagues
Now I'm going to sort through my history to see what I type most often :)
This post is based on material from Docker in Practice , available on Manning's Early Access Program. Get 39% off with the code: 39miell
Jul 07, 2020 | zwischenzugs.com
The Missing Readline Primer zwischenzugs Uncategorized April 23, 2019 7 Minutes
Readline is one of those technologies that is so commonly used many users don't realise it's there.
I went looking for a good primer on it so I could understand it better, but failed to find one. This is an attempt to write a primer that may help users get to grips with it, based on what I've managed to glean as I've tried to research and experiment with it over the years.
Bash Without ReadlineFirst you're going to see what bash looks like without readline.
In your 'normal' bash shell, hit the
TAB
key twice. You should see something like this:Display all 2335 possibilities? (y or n)That's because bash normally has an 'autocomplete' function that allows you to see what commands are available to you if you tap tab twice.
Hit
n
to get out of that autocomplete.Another useful function that's commonly used is that if you hit the up arrow key a few times, then the previously-run commands should be brought back to the command line.
Now type:
$ bash --noeditingThe
--noediting
flag starts up bash without the readline library enabled.If you hit
TAB
twice now you will see something different: the shell no longer 'sees' your tab and just sends a tab direct to the screen, moving your cursor along. Autocomplete has gone.Autocomplete is just one of the things that the readline library gives you in the terminal. You might want to try hitting the up or down arrows as you did above to see that that no longer works as well.
Hit return to get a fresh command line, and exit your non-readline-enabled bash shell:
$ exitOther ShortcutsThere are a great many shortcuts like autocomplete available to you if readline is enabled. I'll quickly outline four of the most commonly-used of these before explaining how you can find out more.
$ echo 'some command'There should not be many surprises there. Now if you hit the 'up' arrow, you will see you can get the last command back on your line. If you like, you can re-run the command, but there are other things you can do with readline before you hit return.
If you hold down the
ctrl
key and then hita
at the same time your cursor will return to the start of the line. Another way of representing this 'multi-key' way of inputting is to write it like this:\C-a
. This is one conventional way to represent this kind of input. The\C
represents the control key, and the-a
represents that thea
key is depressed at the same time.Now if you hit
\C-e
(ctrl
ande
) then your cursor has moved to the end of the line. I use these two dozens of times a day.Another frequently useful one is
\C-l
, which clears the screen, but leaves your command line intact.The last one I'll show you allows you to search your history to find matching commands while you type. Hit
\C-r
, and then typeec
. You should see theecho
command you just ran like this:(reverse-i-search)`ec': echo echoThen do it again, but keep hitting
\C-r
over and over. You should see all the commands that have `ec` in them that you've input before (if you've only got oneecho
command in your history then you will only see one). As you see them you are placed at that point in your history and you can move up and down from there or just hit return to re-run if you want.There are many more shortcuts that you can use that readline gives you. Next I'll show you how to view these. Using `bind` to Show Readline Shortcuts
If you type:
$ bind -pYou will see a list of bindings that readline is capable of. There's a lot of them!
Have a read through if you're interested, but don't worry about understanding them all yet.
If you type:
$ bind -p | grep C-ayou'll pick out the 'beginning-of-line' binding you used before, and see the
\C-a
notation I showed you before.As an exercise at this point, you might want to look for the
\C-e
and\C-r
bindings we used previously.If you want to look through the entirety of the
bind -p
output, then you will want to know that\M
refers to theMeta
key (which you might also know as theAlt
key), and\e
refers to theEsc
key on your keyboard. The 'escape' key bindings are different in that you don't hit it and another key at the same time, rather you hit it, and then hit another key afterwards. So, for example, typing theEsc
key, and then the?
key also tries to auto-complete the command you are typing. This is documented as:"\e?": possible-completionsin the
Readline and Terminal Optionsbind -p
output.If you've looked over the possibilities that readline offers you, you might have seen the
\C-r
binding we looked at earlier:"\C-r": reverse-search-historyYou might also have seen that there is another binding that allows you to search forward through your history too:
"\C-s": forward-search-historyWhat often happens to me is that I hit
\C-r
over and over again, and then go too fast through the history and fly past the command I was looking for. In these cases I might try to hit\C-s
to search forward and get to the one I missed.Watch out though! Hitting
\C-s
to search forward through the history might well not work for you.Why is this, if the binding is there and readline is switched on?
It's because something picked up the
\C-s
before it got to the readline library: the terminal settings.The terminal program you are running in may have standard settings that do other things on hitting some of these shortcuts before readline gets to see it.
If you type:
$ stty -eyou should get output similar to this:
speed 9600 baud; 47 rows; 202 columns; lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo -extproc iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel -iutf8 -ignbrk brkint -inpck -ignpar -parmrk oflags: opost onlcr -oxtabs -onocr -onlret cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow -dtrflow -mdmbuf discard dsusp eof eol eol2 erase intr kill lnext ^O ^Y ^D <undef> <undef> ^? ^C ^U ^V min quit reprint start status stop susp time werase 1 ^\ ^R ^Q ^T ^S ^Z 0 ^WYou can see on the last four lines (
discard dsusp [...]
) there is a table of key bindings that your terminal will pick up before readline sees them. The^
character (known as the 'caret') here represents thectrl
key that we previously represented with a\C
.If you think this is confusing I won't disagree. Unfortunately in the history of Unix and Linux documenters did not stick to one way of describing these key combinations.
If you encounter a problem where the terminal options seem to catch a shortcut key binding before it gets to readline, then you can use the
stty
program to unset that binding. In this case, we want to unset the 'stop' binding.If you are in the same situation, type:
$ stty stop undefNow, if you re-run
stty -e
, the last two lines might look like this:[...] min quit reprint start status stop susp time werase 1 ^\ ^R ^Q ^T <undef> ^Z 0 ^Wwhere the
stop
entry now has<undef>
underneath it.Strangely, for me
C-r
is also bound to 'reprint' above (^R
).But (on my terminals at least) that gets to readline without issue as I search up the history. Why this is the case I haven't been able to figure out. I suspect that reprint is ignored by modern terminals that don't need to 'reprint' the current line.
While we are looking at this table:
discard dsusp eof eol eol2 erase intr kill lnext ^O ^Y ^D <undef> <undef> ^? ^C ^U ^V min quit reprint start status stop susp time werase 1 ^\ ^R ^Q ^T <undef> ^Z 0 ^Wit's worth noting a few other key bindings that are used regularly.
First, one you may well already be familiar with is
\C-c
, which interrupts a program, terminating it:$ sleep 99 [[Hit \C-c]] ^C $Similarly,
\C-z
suspends a program, allowing you to 'foreground' it again and continue with thefg
builtin.$ sleep 10 [[ Hit \C-z]] ^Z [1]+ Stopped sleep 10 $ fg sleep 10
\C-d
sends an 'end of file' character. It's often used to indicate to a program that input is over. If you type it on a bash shell, the bash shell you are in will close.Finally,
\C-w
deletes the word before the cursorThese are the most commonly-used shortcuts that are picked up by the terminal before they get to the readline library.
Daz April 29, 2019 at 11:15 pm
Hi Ian,
What OS are you running because stty -e gives the following on Centos 6.x and Ubuntu 18.04.2
Leon May 14, 2019 at 5:12 amstty -e
stty: invalid argument '-e'
Try 'stty –help' for more information. Replyyachris May 16, 2019 at 4:40 pm`stty -a` works for me (Ubuntu 14)
AriSweedler May 17, 2019 at 4:50 amYou might want to check out the 'rlwrap' program. It allows you to have readline behavior on programs that don't natively support readline, but which have a 'type in a command' type interface. For instance, we use Oracle here (alas :-) ) and the 'sqlplus' program, that lets you type SQL commands to an Oracle instance does not have anything like readline built into it, so you can't go back to edit previous commands. But running 'rlwrap sqlplus' gives me readline behavior in sqlplus! It's fantastic to have.
I was told to use this in a class, and I didn't understand what I did. One rabbit hole later, I was shocked and amazed at how advanced the readline library is. One thing I'd like to add is that you can write a '~/.inputrc' file and have those readline commands sourced at startup!
I do not know exactly when or how the inputrc is read.
Most of what I learned about inputrc stuff is from https://www.topbug.net/blog/2017/07/31/inputrc-for-humans/ .
Here is my inputrc, if anyone wants: https://github.com/AriSweedler/dotfiles/blob/master/.inputrc .
Apr 26, 2018 | opensource.com
Bash completion is a functionality through which Bash helps users type their commands more quickly and easily. It does this by presenting possible options when users press the Tab key while typing a command.
$ git < tab >< tab >
How it works
git git-receive-pack git-upload-archive
gitk git-shell git-upload-pack
$ git-s < tab >
$ git-shellMore Linux resources
The completion script is code that uses the builtin Bash command
- What is Linux?
- What are Linux containers?
- Download Now: Linux commands cheat sheet
- Advanced Linux commands cheat sheet
- Our latest Linux articles
complete
to define which completion suggestions can be displayed for a given executable . The nature of the completion options vary, from simple static to highly sophisticated. Why bother?This functionality helps users by:
Hands-on
- saving them from typing text when it can be auto-completed
- helping them know the available continuations to their commands
- preventing errors and improving their experience by hiding or showing options based on what they have already typed
Here's what we will do in this tutorial:
We will first create a dummy executable script called
dothis
. All it does is execute the command that resides on the number that was passed as an argument in the user's history. For example, the following command will simply execute thels -a
command, given that it exists in history with number235
:dothis 235Then we will create a Bash completion script that will display commands along with their number from the user's history, and we will "bind" it to the
$ dothis < tab >< tab >dothis
executable.
215 ls
216 ls -la
217 cd ~
218 man history
219 git status
220 history | cut -c 8 - bash_screen.png
You can see a gif demonstrating the functionality at this tutorial's code repository on GitHub .
Let the show begin.
Creating the executable scriptCreate a file named
if [ -z "$1" ] ; thendothis
in your working directory and add the following code:
echo "No command number passed"
exit 2
fiexists =$ ( fc -l -1000 | grep ^ $1 -- 2 >/ dev / null )
if [ -n " $exists " ] ; then
fc -s -- "$1"
else
echo "Command with number $1 was not found in recent history"
exit 2
fiNotes:
- We first check if the script was called with an argument
- We then check if the specific number is included in the last 1000 commands
- if it exists, we execute the command using the
fc
functionality- otherwise, we display an error message
Make the script executable with:
chmod +x ./dothisWe will execute this script many times in this tutorial, so I suggest you place it in a folder that is included in your path so that we can access it from anywhere by typing
dothis
.I installed it in my home bin folder using:
install ./dothis ~/bin/dothisYou can do the same given that you have a
~/bin
folder and it is included in yourPATH
variable.Check to see if it's working:
dothisYou should see this:
$ dothis
No command number passedDone.
Creating the completion scriptCreate a file named
dothis-completion.bash
. From now on, we will refer to this file with the term completion script .Once we add some code to it, we will
source
it to allow the completion to take effect. We mustsource
this file every single time we change something in it .Later in this tutorial, we will discuss our options for registering this script whenever a Bash shell opens.
Static completionSuppose that the
dothis
program supported a list of commands, for example:
now
tomorrow
never
Let's use the
complete
command to register this list for completion. To use the proper terminology, we say we use thecomplete
command to define a completion specification ( compspec ) for our program.Add this to the completion script.
#/usr/bin/env bash
complete -W "now tomorrow never" dothisHere's what we specified with the
complete
command above:
- we used the
-W
( wordlist ) option to provide a list of words for completion.- we defined to which "program" these completion words will be used (the
dothis
parameter)Source the file:
source ./dothis-completion.bashNow try pressing Tab twice in the command line, as shown below:
$ dothis < tab >< tab >
never now tomorrowTry again after typing the
$ dothis n < tab >< tab >n
:
never nowMagic! The completion options are automatically filtered to match only those starting with
n
.Note: The options are not displayed in the order that we defined them in the word list; they are automatically sorted.
There are many other options to be used instead of the
-W
that we used in this section. Most produce completions in a fixed manner, meaning that we don't intervene dynamically to filter their output.For example, if we want to have directory names as completion words for the
dothis
program, we would change the complete command to the following:complete -A directory dothisPressing Tab after the
$ dothis < tab >< tab >dothis
program would get us a list of the directories in the current directory from which we execute the script:
dir1 / dir2 / dir3 /Find the complete list of the available flags in the Bash Reference Manual .
Dynamic completionWe will be producing the completions of the
dothis
executable with the following logic:
- If the user presses the Tab key right after the command, we will show the last 50 executed commands along with their numbers in history
- If the user presses the Tab key after typing a number that matches more than one command from history, we will show only those commands along with their numbers in history
- If the user presses the Tab key after a number that matches exactly one command in history, we auto-complete the number without appending the command's literal (if this is confusing, no worries -- you will understand later)
Let's start by defining a function that will execute each time the user requests completion on a
#/usr/bin/env bashdothis
command. Change the completion script to this:
_dothis_completions ()
{
COMPREPLY+= ( "now" )
COMPREPLY+= ( "tomorrow" )
COMPREPLY+= ( "never" )
}complete -F _dothis_completions dothis
Note the following:
- we used the
-F
flag in the complete command defining that the_dothis_completions
is the function that will provide the completions of thedothis
executableCOMPREPLY
is an array variable used to store the completions -- the completion mechanism uses this variable to display its contents as completionsNow source the script and go for completion:
$ dothis < tab >< tab >
never now tomorrowPerfect. We produce the same completions as in the previous section with the word list. Or not? Try this:
$ dothis nev < tab >< tab >
never now tomorrowAs you can see, even though we type nev and then request for completion, the available options are always the same and nothing gets completed automatically. Why is this happening?
- The contents of the
COMPREPLY
variable are always displayed. The function is now responsible for adding/removing entries from there.- If the
COMPREPLY
variable had only one element, then that word would be automatically completed in the command. Since the current implementation always returns the same three words, this will not happen.Enter
compgen
: a builtin command that generates completions supporting most of the options of thecomplete
command (ex.-W
for word list,-d
for directories) and filtering them based on what the user has already typed.Don't worry if you feel confused; everything will become clear later.
Type the following in the console to better understand what
$ compgen -W "now tomorrow never"compgen
does:
now
tomorrow
never
$ compgen -W "now tomorrow never" n
now
never
$ compgen -W "now tomorrow never" t
tomorrowSo now we can use it, but we need to find a way to know what has been typed after the
dothis
command. We already have the way: The Bash completion facilities provide Bash variables related to the completion taking place. Here are the more important ones:
COMP_WORDS
: an array of all the words typed after the name of the program thecompspec
belongs toCOMP_CWORD
: an index of theCOMP_WORDS
array pointing to the word the current cursor is at -- in other words, the index of the word the cursor was when the tab key was pressedCOMP_LINE
: the current command lineTo access the word just after the
dothis
word, we can use the value ofCOMP_WORDS[1]
Change the completion script again:
#/usr/bin/env bash
_dothis_completions ()
{
COMPREPLY = ( $ ( compgen -W "now tomorrow never" " ${COMP_WORDS[1]} " ))
}complete -F _dothis_completions dothis
Source, and there you are:
$ dothis
never now tomorrow
$ dothis n
never nowNow, instead of the words now, tomorrow, never , we would like to see actual numbers from the command history.
The
fc -l
command followed by a negative number-n
displays the last n commands. So we will use:fc -l -50which lists the last 50 executed commands along with their numbers. The only manipulation we need to do is replace tabs with spaces to display them properly from the completion mechanism.
sed
to the rescue.Change the completion script as follows:
#/usr/bin/env bash
_dothis_completions ()
{
COMPREPLY = ( $ ( compgen -W " $(fc -l -50 | sed 's/\t//') " -- " ${COMP_WORDS[1]} " ))
}complete -F _dothis_completions dothis
Source and test in the console:
$ dothis < tab >< tab >
632 source dothis-completion.bash 649 source dothis-completion.bash 666 cat ~ / .bash_profile
633 clear 650 clear 667 cat ~ / .bashrc
634 source dothis-completion.bash 651 source dothis-completion.bash 668 clear
635 source dothis-completion.bash 652 source dothis-completion.bash 669 install . / dothis ~ / bin / dothis
636 clear 653 source dothis-completion.bash 670 dothis
637 source dothis-completion.bash 654 clear 671 dothis 6546545646
638 clear 655 dothis 654 672 clear
639 source dothis-completion.bash 656 dothis 631 673 dothis
640 source dothis-completion.bash 657 dothis 150 674 dothis 651
641 source dothis-completion.bash 658 dothis 675 source dothis-completion.bash
642 clear 659 clear 676 dothis 651
643 dothis 623 ls -la 660 dothis 677 dothis 659
644 clear 661 install . / dothis ~ / bin / dothis 678 clear
645 source dothis-completion.bash 662 dothis 679 dothis 665
646 clear 663 install . / dothis ~ / bin / dothis 680 clear
647 source dothis-completion.bash 664 dothis 681 clear
648 clear 665 cat ~ / .bashrcNot bad.
We do have a problem, though. Try typing a number as you see it in your completion list and then press the key again.
$ dothis 623 < tab >
$ dothis 623 ls 623 ls -la
...
$ dothis 623 ls 623 ls 623 ls 623 ls 623 ls -laThis is happening because in our completion script, we used the
${COMP_WORDS[1]}
to always check the first typed word after thedothis
command (the number623
in the above snippet). Hence the completion continues to suggest the same completion again and again when the Tab key is pressed.To fix this, we will not allow any kind of completion to take place if at least one argument has already been typed. We will add a condition in our function that checks the size of the aforementioned
#/usr/bin/env bashCOMP_WORDS
array.
_dothis_completions ()
{
if [ " ${#COMP_WORDS[@]} " ! = "2" ] ; then
return
fiCOMPREPLY = ( $ ( compgen -W " $(fc -l -50 | sed 's/\t//') " -- " ${COMP_WORDS[1]} " ))
}complete -F _dothis_completions dothis
Source and retry.
$ dothis 623 < tab >
$ dothis 623 ls -la < tab > # SUCCESS: nothing happens hereThere is another thing we don't like, though. We do want to display the numbers along with the corresponding commands to help users decide which one is desired, but when there is only one completion suggestion and it gets automatically picked by the completion mechanism, we shouldn't append the command literal too .
In other words, our
dothis
executable accepts only a number, and we haven't added any functionality to check or expect other arguments. When our completion function gives only one result, we should trim the command literal and respond only with the command number.To accomplish this, we will keep the response of the
compgen
command in an array variable, and if its size is 1 , we will trim the one and only element to keep just the number. Otherwise, we'll let the array as is.Change the completion script to this:
#/usr/bin/env bash
_dothis_completions ()
{
if [ " ${#COMP_WORDS[@]} " ! = "2" ] ; then
return
fi# keep the suggestions in a local variable
local suggestions = ( $ ( compgen -W " $(fc -l -50 | sed 's/\t/ /') " -- " ${COMP_WORDS[1]} " ))if [ " ${#suggestions[@]} " == "1" ] ; then
# if there's only one match, we remove the command literal
# to proceed with the automatic completion of the number
local number =$ ( echo ${suggestions[0]/%\ */} )
COMPREPLY = ( " $number " )
else
# more than one suggestions resolved,
# respond with the suggestions intact
COMPREPLY = ( " ${suggestions[@]} " )
fi
}complete -F _dothis_completions dothis
Registering the completion scriptIf you want to enable the completion just for you on your machine, all you have to do is add a line in your
.bashrc
file sourcing the script:source <path-to-your-script>/dothis-completion.bashIf you want to enable the completion for all users, you can just copy the script under
Fine-tuning the completion script/etc/bash_completion.d/
and it will automatically be loaded by Bash.Here are some extra steps for better results:
Displaying each entry in a new lineIn the Bash completion script I was working on, I too had to present suggestions consisting of two parts. I wanted to display the first part in the default color and the second part in gray to distinguish it as help text. In this tutorial's example, it would be nice to present the numbers in the default color and the command literal in a less fancy one.
Unfortunately, this is not possible, at least for now, because the completions are displayed as plain text and color directives are not processed (for example:
\e[34mBlue
).What we can do to improve the user experience (or not) is to display each entry in a new line. This solution is not that obvious since we can't just append a new line character in each
COMPREPLY
entry. We will follow a rather hackish method and pad suggestion literals to a width that fills the terminal.Enter
#/usr/bin/env bashprintf
. If you want to display each suggestion on each own line, change the completion script to the following:
_dothis_completions ()
{
if [ " ${#COMP_WORDS[@]} " ! = "2" ] ; then
return
filocal IFS =$ '\n'
local suggestions = ( $ ( compgen -W " $(fc -l -50 | sed 's/\t//') " -- " ${COMP_WORDS[1]} " ))if [ " ${#suggestions[@]} " == "1" ] ; then
local number = " ${suggestions[0]/%\ */} "
COMPREPLY = ( " $number " )
else
for i in " ${!suggestions[@]} " ; do
suggestions [ $i ] = " $(printf '%*s' "-$COLUMNS" "${suggestions[$i]}") "
doneCOMPREPLY = ( " ${suggestions[@]} " )
fi
}complete -F _dothis_completions dothis
Source and test:
dothis < tab >< tab >
...
499 source dothis-completion.bash
500 clear
...
503 dothis 500Customizable behaviorIn our case, we hard-coded to display the last 50 commands for completion. This is not a good practice. We should first respect what each user might prefer. If he/she hasn't made any preference, we should default to 50.
To accomplish that, we will check if an environment variable
DOTHIS_COMPLETION_COMMANDS_NUMBER
has been set.Change the completion script one last time:
#/usr/bin/env bash
_dothis_completions ()
{
if [ " ${#COMP_WORDS[@]} " ! = "2" ] ; then
return
filocal commands_number = ${DOTHIS_COMPLETION_COMMANDS_NUMBER:-50}
local IFS =$ '\n'
local suggestions = ( $ ( compgen -W " $(fc -l -$commands_number | sed 's/\t//') " -- " ${COMP_WORDS[1]} " ))if [ " ${#suggestions[@]} " == "1" ] ; then
local number = " ${suggestions[0]/%\ */} "
COMPREPLY = ( " $number " )
else
for i in " ${!suggestions[@]} " ; do
suggestions [ $i ] = " $(printf '%*s' "-$COLUMNS" "${suggestions[$i]}") "
doneCOMPREPLY = ( " ${suggestions[@]} " )
fi
}complete -F _dothis_completions dothis
Source and test:
export DOTHIS_COMPLETION_COMMANDS_NUMBER = 5
$ dothis < tab >< tab >
505 clear
506 source . / dothis-completion.bash
507 dothis clear
508 clear
509 export DOTHIS_COMPLETION_COMMANDS_NUMBER = 5 Useful linksCode and comments
- Git's completion script
- Bash Reference Manual: Programmable Completion
- Bash Reference Manual: Programmable Completion Builtins
- Bash Reference Manual: A Programmable Completion Example
- Bash Reference Manual: Bash Variables
You can find the code of this tutorial on GitHub .
For feedback, comments, typos, etc., please open an issue in the repository.
Lazarus Lazaridis - I am an open source enthusiast and I like helping developers with tutorials and tools . I usually code in Ruby especially when it's on Rails but I also speak Java, Go, bash & C#. I have studied CS at Athens University of Economics and Business and I live in Athens, Greece. My nickname is iridakos and I publish tech related posts on my personal blog iridakos.com .
Posted by Anonymous (203.206.xx.xx) on Wed 19 May 2010 at 04:51
Anyone interested, here's my clearcase completion script for bash: http://jan.tomka.name/project/clearcase-completion-bash
A Basic Example
How Completion WorksAs a basic example we'll first look at adding some simple completions to the binary foo. This hypothetical command takes three arguments:
- --help
- Shows the help options for foo, and exits.
- --version
- Shows the version of the foo command, and exits.
- --verbose
- Runs foo with extra verbosity
To handle these arguments we'll create a new file /etc/bash_completion.d/foo. This file will be automatically sourced (or loaded) when the bash completion code is loaded.
Inside that file save the following text:
_foo() { local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" opts="--help --verbose --version" if [[ ${cur} == -* ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 fi } complete -F _foo fooTo test it you can now source the file:
skx@lappy:~$ . /etc/bash_completion.d/foo skx@lappy:~$ foo --[TAB] --help --verbose --versionIf you experiment you'll see that it successfully completes the arguments as expected. Type "foo --h[TAB]" and the --help argument is completed. Press [TAB] a few times and you'll see all the options. (In this case it doesn't actually matter if you don't have a binary called foo installed upon your system.)
So now that we have something working we should look at how it actually works!
A Complex ExampleThe previous example showed a simple bash function which was invoked to handle completion for a command.
This function starts out by defining some variables cur being the current word being typed, prev being the previous word typed, and opts which is our list of options to complete.
The option completing is then handled by use of the compgen command via this line:
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )What this does is set the value of $COMPREPLY to the output of running the command:
compgen -W "${opts}" -- ${cur}If you replace these variables with their contents you'll see how that works:
compgen -W "--help --verbose --version" -- "userinput"This command attempts to return the match of the current word "${cur}" against the list "--help --verbose --version". If you run this command in a shell you'll be able to experiment with it and see how it works:
skx@lappy:~$ compgen -W "--help --verbose --version" -- -- --help --verbose --version skx@lappy:~$ compgen -W "--help --verbose --version" -- --h --helpHere you first see what happens if the user enters just "--" - all three options match so they are returned. In the second attempt the user enters --h and this is enough to specify --help unambiguously, so that is returned.
In our function we simply set "COMPREPLY" to this result, and return. This allows bash to replace our current word with the output. COMPREPLY is a special variable which has a particular meaning within bash. Inside completion routines it is used to denote the output of the completion attempt.
From the bash reference manual we can read the description of COMPREPLY:
- COMPREPLY
- An array variable from which Bash reads the possible completions generated by a shell function invoked by the programmable completion facility
We can also see how we found the current word using the array COMP_WORDS to find both the current and the previous word by looking them up:
- COMP_WORDS
- An array variable consisting of the individual words in the current command line. This variable is available only in shell functions invoked by the programmable completion facilities.
- COMP_CWORD
- An index into ${COMP_WORDS} of the word containing the current cursor position. This variable is available only in shell functions invoked by the programmable completion facilities
Other CompletionMany commands are more complicated to fill out, and have numerous options which depend upon their previous ones.
As a relevant example Xen ships with a command called xm this has some basic options:
- xm list
- List all running Xen instances
- xm create ConfigName
- Create a new Xen instances using the configuration file in /etc/xen called ConfigName.
- xm console Name
- Connect to the console of the running machine named "Name".
In general the command is "xm operation args" where "args" varies depending upon the initial operation selected.
Setting up basic completion of inital operation can be handled in much the same way as our previous example the only difference is that the operations don't start with a "--" prefix. However completing the arguments requires special handling.
If you recall we have access to the previous token upon the command line, and using that we can take different actions for each operation.
The sample code looks like this:
_xm() { local cur prev opts base COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" # # The basic options we'll complete. # opts="console create list" # # Complete the arguments to some of the basic commands. # case "${prev}" in console) local running=$(for x in `xm list --long | grep \(name | grep -v Domain-0 | awk '{ print $2 }' | tr -d \)`; do echo ${x} ; done ) COMPREPLY=( $(compgen -W "${running}" -- ${cur}) ) return 0 ;; create) local names=$(for x in `ls -1 /etc/xen/*.cfg`; do echo ${x/\/etc\/xen\//} ; done ) COMPREPLY=( $(compgen -W "${names}" -- ${cur}) ) return 0 ;; *) ;; esac COMPREPLY=($(compgen -W "${opts}" -- ${cur})) return 0 } complete -F _xm xmHere we've setup the initial completion of the operations and then added special handling for the two operations "create" and "console". In both cases we use compgen to complete the input based upon the text that is supplied by the user, compared against a dynamically created list.
For the "console" operation we complete based upon the output of this command:
xm list --long | grep \(name | grep -v Domain-0 | awk '{ print $2 }' | tr -d \)This gives us a list of the running Xen systems.
For the creation operation we complete based upon the output of this command:
for x in `ls -1 /etc/xen/*.cfg`; do echo ${x/\/etc\/xen\//} ; doneThis takes a directory listing of the /etc/xen directory and outputs the names of any files ending in .cfg. For example:
skx@lappy:~$ for x in `ls -1 /etc/xen/*.cfg`; do echo ${x/\/etc\/xen\//}; done etch.cfg root.cfg sarge.cfg steve.cfg x.cfg skx@lappy:~$Using the compgen command we've shown how to match user input against particular strings, both by using a fixed set of choices and by using the output of commands.
It is also possible to match directory names, process names, and other things. See the bash manual for a full description by running "man bash".
The final example demonstrates how to complete files and hostnames in response to two initial options:
# # Completion for foo: # # foo file [filename] # foo hostname [hostname] # _foo() { local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" opts="file hostname" case "${prev}" in file) COMPREPLY=( $(compgen -f ${cur}) ) return 0 ;; hostname) COMPREPLY=( $(compgen -A hostname ${cur}) ) return 0 ;; *) ;; esac COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) } complete -F _foo fooUsing these examples you should now be able to create your own custom completion functions. 95% of the time you only need to complete from a set of available options, the other times you'll need to deal with dynamic argument generation much like we did for the xm command.
Breaking the options down into a small collection of pipes and testing them outside the completion environment (just in the shell) is probably the best approach, then once you've got a working command line just paste it into your function.
For reference my xm completion code can be found online.
The Debian bash package features support for command line completion through the file /etc/bash_completion. This page of the chicken wiki provides a file to add completion for the chicken tools in bash. Currently, only chicken-setup is supported. Hopefully csi and csc will follow.
Copy the following code in a file named chicken in /etc/bash_completion.d. Alternatively, sourc >*.egg files.chicken-setup -<tab> completes for options.
options. # chicken-setup command line completion for bash. # # version 0.2 -- 2007.01.13 -- vo minh thu # - chicken-setupcompletes for *.egg files. # version 0.1 -- 2007.01.13 -- vo minh thu _chicken_setup() { local cur prev frst opts COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} frst=${COMP_WORDS[1]} opts='-help -version -repository -program-path -host \ -uninstall -list -run -script -eval -verbose \ -keep -csc-option -dont-ask -no-install -docindex \ -check -test -ls -fetch-tree -tree -svn -revision \ -local -destdir' paroptions=${opts} # the following options take zero or one argument case "${prev}" in '-repository' | '-program-path' | '-local' | '-destdir' ) COMPREPLY=( $(compgen -A directory ${cur}) ) return 0;; '-host' ) COMPREPLY=( $(compgen -A hostname ${cur}) ) return 0;; '-run' | '-script' | '-tree' ) COMPREPLY=( $(compgen -A file ${cur}) ) return 0;; '-uninstall' | '-ls' ) local exts=$( chicken-setup -list | awk '{ print $1 }' ) COMPREPLY=( $(compgen -W "${exts}" -- ${cur}) ) return 0;; esac # the following options take zero or more arguments case "${frst}" in '-list' | '-test' ) local exts=$( chicken-setup -list | awk '{ print $1 }' ) COMPREPLY=( $(compgen -W "${exts}" -- ${cur}) ) return 0;; esac case ${cur} in -* ) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0;; * ) COMPREPLY=($(compgen -f -X "egg" -- ${cur})) esac } [ "$have" ] && complete
Sometimes this luxury drives me crazy...
If I have a tar file not named with suffix .tar and I type "tar xvf filenamebeginning<tab>", what will happen?
Same effect for many other extension driven suggestions or completions...
It is very usefull to know, that if I type "\tar" instead of "tar", command completion will not happen at all. Even if "tar was aliased, "\tar" will override this IIRC...
But now for something (not really) completely different...
Another nice feature for small functions or big screens is the way functions are "completed". Try
"function _mc<tab><tab>".
You can edit the function with bash's commandline editor and even rename the function name.
Similar for aliases. Assume having aliased "ll" to somethig obvious then "alias ll=<tab>" gives the alias definition als editable line...
====
If I have a tar file not named with suffix .tar and I type "tar xvf filenamebeginning", what will happen?You will try Shift-TAB (or ESC-TAB or Alt-/) instead ofTab to revert to standard filename expansion.
Rant is a build tool that uses Ruby as the underlying scripting language. It is a competitor to SCons (which uses Python as the programming language) but perhaps more especially to Rake, which like Rant is build on Ruby. There has been a lot written about the relationship of Rake and Rant elsewhere and I am not yet in a position to comment on this as I am only just beginning to try Rant having done some work with SCons and Rake.
The problem is that whilst Rake comes with a Bash completion script, Rant does not.
The Solution
The solution is totally clear: create a Bash completion script for Rant. Given the similarity between Rake and Rant, and having done equivalents for SCons and Gant, it is easy to take the Rake script and edit it a bit. So I came up with a script (that you can download by clicking here) that seems to do the job. It almost certainly has error and/or bugs but for the moment it 'works for me'.
To use this script you can do one of:
- Ensure you have a ~/.bash_completion file that includes all the scripts in a personal Bash completion script library. I have a directory ~/bash_completion.d in which I put the various scripts – copying directly the way that Bash organizes scripts in /etc. My ~/.bash_completion file then contains a copy of the relevant bit of the system script:
# -*- mode:shell-script -*- for file in bash_completion.d/* do [[ ${file##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|.rpm*) ]] && [ \( -f $file -o -h $file \) -a -r $file ] && . $file done
- Append the contents of the file to your ~/.bash_completion file.
- Put the file in /etc/bash_completion.d with all the other system-wide scripts.
The last has the advantage of working for all users of the machine but does require super-user privileges. I use the first (obviously).
The Bash shell has this sweet feature where you can use theTab key to auto-complete certain things. For example, when I am in my home directory, the following command:
$cd Do[TAB-key]
will automatically yield:
$cd Documents
If you are an absolute novice, like I was, not so long ago, discoveringTab completion in the terminal can make you go "Wow!". Wait till you hear the rest now
Though you can use theTab key to complete the names of files and directories, by default the completion is pretty "dumb". If you have already typed
$cd D
you would expect that theTab key would cause only the directory names to be completed, but if I try it on my machine, theTab completion tool uses filenames too.Now, don't despair! There is now a smart bashTab completion trick you can use. Smart completion even complete the arguments to commands!!
To enable smart completion, edit your
/etc/bash.bashrc
file. Uncomment the following lines, by removing the # in the beginning of the lines:
#if [ -f /etc/bash_completion ]; then
# . /etc/bash_completion
#fi
Now you can useTab completion to power your way through commands.
You can even extend bash smart completion to your own favourite commands by using /etc/bash_completion, the "complete" utility and /etc/bash_completion.d . Explaining the nitty-gritty is beyond me. I refer you to the Debian Administration gurus for more information regarding smarter bash completion.
Basic Bash Completion will work in any bash shell. It allows for completion of:
- File Names
- Directory Names
- Executable Names
- User Names (when they are prefixed with a ~)
- Host Names (when they are prefixed with a @)
- Variable Names (when they are prefixed with a $)
This is done simply by pressing theTab key after enough of the word you are trying to complete has been typed in. If when hittingTab the word is not completed there are probably multiple possibilities for the completion. PressTab again and it will list the possibilities. Sometimes on my machine I have to hit it a third time.
Extended Programmable Bash Completion is a program that you can install to complete much more than the names of the things listed above. With extended bash completion you can, for example, complete the name of a computer you are trying to connect to with ssh or scp. It achieves this by looking through the known_hosts file and using the hosts listed there for the completion. This is greatly customizable and the package and more information can be found here.
Configuration of Programmable Bash Completion is done in /etc/bash_completion. Here is a list of completions that are in my bash_completion file by default.
- completes on signal names
- completes on network interfaces
- expands tildes in pathnames
- completes on process IDs
- completes on process group IDs
- completes on user IDs
- completes on group IDs
- ifconfig(8) and iwconfig(8) helper function
- bash alias completion
- bash export completion
- bash shell function completion
- bash complete completion
- service completion
- chown(1) completion
- chgrp(1) completion
- umount(8) completion
- mount(8) completion
- Linux rmmod(8) completion
- Linux insmod(8), modprobe(8) and modinfo(8) completion
- man(1) completion
- renice(8) completion
- kill(1) completion
- Linux and FreeBSD killall(1) completion
- GNU find(1) completion
- Linux ifconfig(8) completion
- Linux iwconfig(8) completion
- RedHat & Debian GNU/Linux if{up,down} completion
- Linux ipsec(8) completion (for FreeS/WAN)
- Postfix completion
- cvs(1) completion
- rpm completion
- apt-get(8) completion
- chsh(1) completion
- chkconfig(8) completion
- user@host completion
- host completion based on ssh's known_hosts
- ssh(1) completion
- scp(1) completion
- rsync(1) completion
- Linux route(8) completion
- GNU make(1) completion
- GNU tar(1) completion
- jar(1) completion
- Linux iptables(8) completion
- tcpdump(8) completion
- autorpm(8) completion
- ant(1) completion
- mysqladmin(1) completion
- gzip(1) completion
- bzip2(1) completion
- openssl(1) completion
- screen(1) completion
- lftp(1) bookmark completion
- ncftp(1) bookmark completion
- gdb(1) completion
- Postgresql completion
- psql(1) completion
- createdb(1) completion
- dropdb(1) completion
- gcc(1) completion
- Linux cardctl(8) completion
- Debian dpkg(8) completion
- Debian GNU dpkg-reconfigure(8) completion
- Debian Linux dselect(8) completion
- Java completion
- PINE address-book completion
- mutt completion
- Debian reportbug(1) completion
- Debian querybts(1) completion
- update-alternatives completion
- Python completion
- Perl completion
- rcs(1) completion
- lilo(8) completion
- links completion
- FreeBSD package management tool completion
- FreeBSD kernel module commands
- FreeBSD portupgrade completion
- FreeBSD portinstall completion
- Slackware Linux removepkg completion
- look(1) completion
- ypcat(1) and ypmatch(1) completion
- mplayer(1) completion
- KDE dcop completion
- wvdial(1) completion
- gpg(1) completion
- iconv(1) completion
- dict(1) completion
- cdrecord(1) completion
- mkisofs(8) completion
- mc(1) completion
- yum(8) completion
- yum-arch(8) completion
- ImageMagick completion
Previously we showed how to add basic completion to commands, using facilities which were already provided by the bash completion routines. In this second part we'll demonstrate how to add completely new custom completion to commands.In part one we looked at adding hostname completion to arbitrary commands by executing:
complete -F _known_hosts xvncviewerThis uses the complete command to tell bash that the function _known_hosts should be used to handle the completion of arguments to the xvncviewer.
If we wish to add custom completion to a command we will instead write our own function, and bind that to the command.
A Basic ExampleAs a basic example we'll first look at adding some simple completions to the binary foo. This hypothetical command takes three arguments:
- --help
- Shows the help options for foo, and exits.
- --version
- Shows the version of the foo command, and exits.
- --verbose
- Runs foo with extra verbosity
To handle these arguments we'll create a new file /etc/bash_completion.d/foo. This file will be automatically sourced (or loaded) when the bash completion code is loaded.
Inside that file save the following text:
_foo() { local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" opts="--help --verbose --version" if [[ ${cur} == -* ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 fi } complete -F _foo fooTo test it you can now source the file:
skx@lappy:~$ . /etc/bash_completion.d/foo skx@lappy:~$ foo --[TAB] --help --verbose --versionIf you experiment you'll see that it successfully completes the arguments as expected. Type "foo --h[TAB]" and the --help argument is completed. Press [TAB] a few times and you'll see all the options. (In this case it doesn't actually matter if you don't have a binary called foo installed upon your system.)
So now that we have something working we should look at how it actually works!
May 08, 2006 | Linux.com
The auto complete feature of the Bourne Again SHell makes bash one of the most loved and newbie-friendly Linux shells. Just by pressing theTab key you can complete commands and filenames. Press theTab key twice and all files in the directory get displayed. But you can do more with autocomplete -- such as associating file types with applications, and automatically designating whether you're looking for directories, text, or MP3 files. With simple commands such as
You can use the dollar signcomplete
and the use of Escape sequences, you can save time and have fun on the command line.
($)
, tilde(~)
, and at(@)
characters along with theTab key to get quick results in autocomplete.For instance, if you want to switch to the testing subdirectory of your home directory, you can either type
cd /ho[Tab]/tes[Tab]
to get there, or use the tilde --cd ~tes[Tab]
. If the partial text -- that is, the portion before you pressTab -- begins with a dollar sign, bash looks for a matching environment variable. The tilde tells bash to look for a matching user name, and the at-sign tells it to look for a matching hostname.Escaping is good
TheTab key can complete the names of commands, files, directories, users, and hosts. Sometimes, it is overkill to use theTab key. If you know that you are looking for a file, or only user names, then use the Escape key instead for completion, as it limits bash's completion field.
You can use several Escape key combinations to tell bash what you are looking for. Invoke Escape key combinations by pressing a key while keeping the Escape key pressed. When looking for a file, you can use the Esc-/ (press / along with Escape) key combination. This will attempt filename completion only. If you have one file and one directory beginning with the letter 'i,' you will have to press theTab key twice to see all the files:
$ less i <tab><tab>
ideas im articles/When you type
less i
and press'/'
while keeping the Escape key pressed, bash completes the filename to 'ideas.'While Control key combinations work no matter how long you keep the Ctrl key pressed before pressing the second key, this is not the case with Escape key sequences. The Esc-/ sequence will print out a slash if you delay in pressing the / key after you press the Escape key.
You can also use Escape along with the previously discussed
$
,~
, and@
keys.Esc-$
, for example, completes only variable names. You can useEsc-!
when you wish to complete command names. Of course you need to press the Shift key in order to use any of the "upper order" characters.Even smarter completion
By default,Tab completion is quite dim-witted. This is because when you have already typed
cd down
before pressing Tab, you'd expect bash to complete only directory names. But bash goes ahead and displays all possible files and directories that begin with 'down.'You can, however, convert bash into a brilliant command-reading whiz. As root, edit the /etc/bash.bashrc file. Scroll down to the end of the file till you see the section:
# enable bash completion in interactive shells #if [ -f /etc/bash_completion ]; then # . /etc/bash_completion #fiUncomment this section and voilà, you have given bash powers far beyond your imagination! Not only is bash now smart enough to know when to complete only directory names, it can also complete man pages and even some command arguments.
Don't despair if you don't have root previleges. Just edit the last section of your ~/.bashrc file.
Associating application with file types
The
complete
command in bash lets you associate file types with certain applications. If after associating a file type to an application you were to write the name of the application and press Tab, only files with associated file types would be displayed.
complete -G "*.txt" gedit
would associate .txt files with gedit. The downfall of using complete is that it overwrites bash's regular completion. That is, if you have two files named invoice.txt and ideas.txt,gedit [Tab][Tab]
displays both the files, butgedit inv[Tab]
, which should complete to invoice.txt, no longer works.
complete
associations last only for the current bash session. If you exit and open a console, gedit will no longer be associated with .txt files. You need to associate file types to applications each time you start a new console session.For permanent associations, you need to add the command to one of the bash startup scripts, such as ~/.bashrc. Then, whenever you are at the console, gedit will be associated with .txt files.
Shashank Sharma is studying for a degree in computer science. He specializes in writing about free and open source software for new users.
Shashank Sharma is studying for a degree in computer science. He specializes in writing about free and open source software for new users. He is the co-author of Beginning Fedora, published by Apress.
No more worrying about cases
The best bash tip I can share is very helpful when working on systems that don't allow filenames to differ only in case (like OSX and Windows):
create a file called .inputrc in your home directory and put this line in it:set completion-ignore-case on
Now bash tab-completion won't worry about case in filenames. Thus 'cd sit[tab]' would complete to 'cd Sites/'
> I was wondering if anyone knows if there is software (or built in
> functionality) for the korn shell in UWin which allows for the following two
> functions available in the Unix Cshell:
>
> 1.)the ability to complete the path/filename from the first few letters
> typed
Yes, ksh supports both command and filename completion. In emacs
mode use, <ESC><ESC> to complete a command or pathname up to the
point of uniqueness. If the complete the first word on the line,
then this indicates command completion and it will uses functions,
builtins, and path search to complete the argument. You can use
<ESC>= to get the matching list.
In vi-mode use <ESC> to go to control mode and then \ to
complete or = to list.
U/WIN provides functions emacs_keybind and vi_keybind to allow
theTab key to be used for completion, but there is a bug in
the emacs_keybind function in which a $ is missing in front of the '\E\E".
> 2.)the ability to use the arguments of previous commands (in the history)
In vi-mode you can use _ from control mode to get the last argument
of the previous command, or n_ to get the n-th argument of the
pervious command. With emacs you can use <ESC>_ or <ESC>.
>
>
David Korn
research!dgk
[email protected]
Please allow user to revert to standard bash completion at any time (a must-have).
by Stéphane Gourichon - Oct 4th 2004 07:59:13Currently, the arguably interesting features of bash_completion actually interfere with some completion
patterns that bash had for years, (for example completing a path stopping at cursor, when the cursor is in the middle
of the line, but there are other cases in previous comments).Generally, until it can be proven that a change makes the situation better at all times without any (even minor)
downside, the change should be reversible and never imposed.So, any user should be able to turn it off. The simplest idea is to unset the involved environment variables.
But BASH_COMPLETION and BASH_COMPLETION_DIR
are declared as read-only. Why ?
This prevents a particular user to turn it off... :-(On a system with many users, there's currently no other choice than to ask the administrator to remove the
package for all users (or make it not activated by default, which is not what we need either).Is it currently possible for a user to revert to standard bash completion ? If not, please consider changing
something in the package (even something as simple as checking for some ~/.bash_completionrc for a hint should
be fine).The risk is that, on any big site, new users don't even know what comes from your package or even that it
exists, but people that used normal bash completion completion in ways *you* don't use will dislike the package
(becauses it causes less efficient work) and have it removed for all users.A last suggestion : use savannah.nongnu.org or sourceforge.net to have real forums. Freshmeat comments
aren't structured enough so that contributors can make a good job of checking if a request was already issued
before. User feedback quality depends on this.Regards,
--
"J'y gagne, répondit le renard, à cause de la couleur du blé."["] Re: Please allow user to revert to standard bash completion at any time (a must-have).
by Ian Macdonald - Oct 8th 2004 17:20:08
> So, any user should be able to turn it> off. The simplest
> idea is to unset the involved
> environment variables.
>
> But BASH_COMPLETION and
> BASH_COMPLETION_DIR
> are declared as read-only. Why ?
> This prevents a particular user to turn
> it off... :-(
These are set read-only, because it's bad to change them once they've been set. They are used later on and it's important that the value doesn't change. They can be set before the bash_completion script is run, however, and the original value will be honoured.> On a system with many users, there's
> currently no other
> choice than to ask the administrator to
> remove the
> package for all users (or make it not
> activated by default,
> which is not what we need either).
>
> Is it currently possible for a user to
> revert to standard
> bash completion ?
Yes, just run 'complete -r' and all completions will be removed, leaving just the default. However, I agree that this isn't the most useful way of achieving this, so I will consider the implementation of a better mechanism.
> A last suggestion : use> savannah.nongnu.org or
> sourceforge.net to have real forums.
> Freshmeat comments
> aren't structured enough so that
> contributors can make a
> good job of checking if a request was
> already issued
> before. User feedback quality depends on
> this.
Well, e-mail works well, too. I agree that this forum isn't very efficient or convenient, so just e-mail me your comments instead. It would be nice to have a real mailing list, though. I'll consider setting one up.
["] Wonderful... but...
by GaelicWizard - Oct 5th 2003 02:14:11I LOVE bash_completion, but I think that it is growing
just a tad too big... and a little unmanageable.
Spesific gripes:
1) If $UNAME isn't tested explicitly for an OS that
doesn't return xyz then feature abc which worx, is not
completed upon. I'm not sure how this is fixable, its just
a comment. :-)
2) some of the functions and completions seem to be
slightly more complex than neccessary. What I mean is
that I don't see the need to redefine the builtin
completions if the builtin ones work.
3) It seems to be very linux spesific, although almost all
worx on freeBSD it checks vigorously for linux in
$UNAME.Thanx, keep up the good work!
["] Re: Automatic change directory
by Ian Macdonald - Apr 18th 2003 18:37:42
> Would it be possible to add the
> automatic change directory feature to
> Bash Completion?
>
> If a directory called /usr/local/lib/foo
> exists and the command line is:
> $ /usr/local/lib/foo <return>
>
> Then the action is to change to that
> directory instead of reporting that
> "/usr/local/lib/foo" is a
> directory.
>
> I've used this feature in other shells.
> Can this be done at the command
> completion level or does it call for a
> more fundamental change in bash
> itself?
>bash can't really do this, since it has no pre-execution hook for you to tap into with code.
Nevertheless, to my surprise, I managed to botch together the following hack:trap '{ d=$_; [ -d "$d" ] && cd $d; unset d; }' ERR
This does what you want, but won't stop the attempt to run a directory from displaying an error before changing to the directory.
Google matched content |
Please visit Heiner Steven SHELLdorado the best shell scripting site on the Internet |
Bash Reference Manual - Commands For Completion
An introduction to bash completion part 1
An introduction to bash completion part 2
Working more productively with bash 2.x by Ian Macdonald . See below his bash programmable completion package
Bash Reference Manual Command Line Editing
BASHISH - the good stuff.Advanced Bash-Scripting HOWTO - A guide to shell scripting, using Bash
freshmeat.net Project details for bash programmable completion project by Ian Macdonald
Since v2.04, bash has allowed you to intelligently program and extend its standard completion behavior to achieve complex command lines with just a few keystrokes. Imagine typing ssh [Tab] and being able to complete on hosts from your ~/.ssh/known_hosts files. Or typing man 3 str [Tab] and getting a list of all string handling functions in the UNIX manual. mount system: [Tab] would complete on all exported file-systems from the host called system, while make [Tab] would complete on all targets in Makefile. This project was conceived to produce programmable completion routines for the most common Linux/UNIX commands, reducing the amount of typing sysadmins and programmers need to do on a daily basis.
Society
Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers : Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism : The Iron Law of Oligarchy : Libertarian Philosophy
Quotes
War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda : SE quotes : Language Design and Programming Quotes : Random IT-related quotes : Somerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose Bierce : Bernard Shaw : Mark Twain Quotes
Bulletin:
Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 : Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law
History:
Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds : Larry Wall : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOS : Programming Languages History : PL/1 : Simula 67 : C : History of GCC development : Scripting Languages : Perl history : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history
Classic books:
The Peter Principle : Parkinson Law : 1984 : The Mythical Man-Month : How to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite
Most popular humor pages:
Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor
The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D
Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.
FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.
This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...
|
You can use PayPal to to buy a cup of coffee for authors of this site |
Disclaimer:
The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.
Last modified: April 26, 2018