In Ubuntu 10.04 it works out of the box for me. In bash:
$ hg c
cat checkout clone commit copy
Or in zsh:
$ hg c
cat checkout ci clone co commit copy cp
Perhaps you have a package missing (or you hit a bug).
On my system the completion file is provided by the mercurial package:
$ dpkg -S /etc/bash_completion.d/mercurial
mercurial: /etc/bash_completion.d/mercurial
Edit: OK. Seems like I might have misread the situation. Thought you meant program options as in:
$ mplayer_alias -pla<tab><tab>
-playing-msg -playlist
$
but guess it is file completion. I don't know, but give it a go.
As a quick fix this should work:
complete -f -o default ee
Giving:
$ ee<tab><tab>
file1 file2 file3
$
as of Programmable Completion Builtins. E.g. the -X pattern
can be useful. E.g. to exclude .swp
and .swo
files:
complete -f -X '*.sw[op]' ee
only show .zip
, .ZIP
:
complete -f -o default -X '!*.+(zip|ZIP)' my_unzip_alias
some might need you to add shopt -s extglob
in configuration file.
OLD Answer:
You could try out something like this in your .bash_completion
.
At least as a starter.
The core idea is to simply add complete
for the alias using the existing
complete script for the real program. Here I assume that they are all in the format:
complete -F _complete_function_from_original program_name
You can get what it is by executing: complete -p program_name
. Best to check first.
For some methods like apt-get
one can use only alias + load:
_load_comp_hack apt-get myalias
For others like mplayer
one need a function wrapper, as in e.g.:
myalias() { mplayer "$@"; }
|
+--- Could be messy
It is quite possible there is a better way to solve this, but has worked fine for my use. I mostly use it for wrapper scripts where I extend the functionality of the original program. Have not used it on aliases.
I do not feel to safe on this hack, but you could see if it works.
_load_comp_hack()
{
local cc=
# Make sure completion scripts are sourced.
# Report error if source fail.
if . "/usr/share/bash-completion/completions/$1" >/dev/null 2>&1; then
# Extract the completion function used by the "real" program.
if cc="$(complete -p "$1" | cut -d' ' -f3)"; then
# Add it to the alias
complete -F "$cc" "$2"
return 0
fi
fi
echo "bash-completion '$1' for '$2' not found."
}
_load_comp_hack mplayer mplad
_load_comp_hack apt-get z
| |
| +----- Alias, script or function
+------------- Real function
Some programs use more general completion like _longopt
, by which the
source file won't be located. Usually it is no need to source either, so a
simpler variant could be:
_load_comp_hack()
{
local cc=
if cc=$(complete -p "$1" | cut -d' ' -f3); then
complete -F "$cc" "$2"
fi
}
One problem here, IIRC, is that some completion scripts are not loaded until first run, as in first:
prog
tabtab. As an alternative perhaps add it as an else
if sourcing of file fails.
Best Answer
There are two ways to interpret the question: you want the completion while you are typing the names before the closing
}
(in effect performing completion of files in another directory); or, you want the completion to expand and substitute the (valid) names after the closing}
.{ }
expansion expands all the options, unlike globbing which expands existing file names, though using "," rather than space.With bash, the expected way to use
{}
to create a list of words is:There are two options: associating a readline key binding with a shell function, or programmable completion.
The readline approach gives you a free hand to completely rewrite the current command, but the problem is that it doesn't tokenise the current command line, so you have a non-trivial parsing problem.
Programmable completion does tokenise the command line, but you can only modify/replace the current word, which means you can't (easily) preserve the
path/{
prefix during editing.The only related native bash capability is the
readline
functionshell-expand-line
for bash purports to do "all of the shell word expansions", this is bound by default to\M-\C-e
(Esc\C-e
). One might reasonably expect this expansion to be all of the seven types of expansion indicated in the man page (bash-4.3):You can experiment with by typing (without hitting Return)
And then MetaCtrlE (or ESC + CtrlE if you are using a Meta-impaired keyboard).
Neither the first nor last (brace and path) expansions work for me, so the documentation and implementation don't quite match IMHO.
What follows is a work-around, rather than complete solution using tab for expansion. You need to make sure to use the correct syntax for brace expansion though, specifically with a comma to separate the items, not a space.
This binds Ctrl_ to a bash function which uses
eval
to populate an array, causing all the normal expansions (as above, and not including history) to occur, and then rebuilds the command line.Start typing, hit Ctrl_ when you want something expanded, and Return as normal when ready.
This is more powerful than tab, but less precise in that it expands the complete input line. There are a few cases where this won't expand as hoped, specifically where various shell metacharacters confuse the simple
eval
logic.Rather than over-engineer a bash solution, Gille's suggestion of
zsh
is worth a look.