An alternative solution is to paste those commands into a text file instead of a function block. Something like:
## This is needed to make the sourced aliases available
## within the script.
shopt -s expand_aliases
source /some/environment/setup/script.sh
aliasToSetupSomeSoftwareVersion
anotherAliasForOtherSoftware
source /maybe/theres/another/script.sh
runSomeOtherSetup
Save that as setup1.sh
wherever you like. The trick is to then source this file, not execute it:
$ source setup1.sh
That will run the aliases that are in the script and also make them available to your current shell.
You can further simplify the process by adding this to your .bashrc
:
alias setupLotsOfThings="source setup1.sh"
Now you can simply run setupLotsOfThings
and get the behavior you wanted from the function.
Explanation
There are two issues here. First, aliases are not available to the function they are declared in but only once that function has exited and second that aliases are not available within scripts. Both are explained in the same section of man bash
:
Aliases are not expanded when the shell is not interactive, unless
the expand_aliases shell option is set using shopt (see the
description of shopt under SHELL BUILTIN COMMANDS below).
The rules concerning the definition and use of aliases are
somewhat confusing. Bash always reads at least one complete
line of input before executing any of the commands on that
line. Aliases are expanded when a command is read, not when it
is executed. Therefore, an alias definition appearing on the same
line as another command does not take effect until the next
line of input is read. The commands following the alias definition
on that line are not affected by the new alias. This behavior
is also an issue when functions are executed. Aliases are expanded
when a function definition is read, not when the function is
executed, because a function definition is itself a compound
command. As a consequence, aliases defined in a function are not
available until after that function is executed. To be safe,
always put alias definitions on a separate line, and do not use
alias in com‐ pound commands.
Then, there is the difference between executing and sourcing a file. Basically, running a script makes it run in a separate shell while sourcing it makes it run in the current shell. So, sourcing setup.sh
makes the aliases available to the parent shell while executing it as a script would not.
Completion and where it comes from can be rather confusing. Take a Ubuntu 14.04 system as an example:
$ dpkg -L zsh-common | grep git
/usr/share/zsh/functions/Completion/Debian/_git-buildpackage
/usr/share/zsh/functions/Completion/Unix/_stgit
/usr/share/zsh/functions/Completion/Unix/_git
/usr/share/zsh/functions/Completion/Unix/_topgit
/usr/share/zsh/functions/VCS_Info/Backends/VCS_INFO_get_data_git
/usr/share/zsh/functions/VCS_Info/Backends/VCS_INFO_detect_git
/usr/share/zsh/functions/Misc/run-help-git
The zsh-common
package ships git completion functions. On the other hand, the git
package also comes with completion files for bash and zsh:
$ dpkg -L git | grep compl
/etc/bash_completion.d
/etc/bash_completion.d/git-prompt
/usr/share/bash-completion
/usr/share/bash-completion/completions
/usr/share/bash-completion/completions/git
/usr/share/bash-completion/completions/gitk
Which contains files such as
$ head -n 5 /usr/share/bash-completion/completions/gitk
# bash/zsh completion support for core Git.
#
# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
# Distributed under the GNU General Public License, version 2.0.
The git package even provides a git aware prompt which can be enabled, all without fancy addons such as oh-my-zsh.
To summarize, git subcommand completion can come from your shell (zsh):
https://github.com/zsh-users/zsh/blob/master/Completion/Unix/Command/_git
from git
https://github.com/git/git/tree/master/contrib/completion
or from plugins such as oh-my-zsh.
To get back to your question: The old behavior of completing git chec
that you describe is actually buggy. chec
is still ambiguous and a proper completion script should not complete it to checkout
, since there are multiple subcommands that begin with chec
. If you want that behavior, find out which of the many completion scripts out there you were using before, disable the oh-my-zsh git plugin and continue to use your old completion script.
Alternatively, I'd recommend to set up an alias and get used to it. You can use
git config --global alias.co checkout
to make git co
your new git checkout
- the oh-my-zsh plugin is aware of these aliases and will still complete branch and tag names next!
Best Answer
The following code, adapted from this Stack Overflow answer and this Ubuntu Forums discussion thread will add completions for all your defined aliases:
For simple (command only, no arguments) aliases it will assign the original completion function to the alias; for aliases with arguments, it creates a wrapper function that inserts the extra arguments into the original completion function.
Unlike the scripts it has evolved from, the function respects quotes both for the alias command and its arguments (but the former have to be matched by the completion command, and cannot be nested), and it should reliably filter out aliases to command lists and pipes (which are skipped, as it is impossible to find out what to complete in them without re-creating the complete shell command line parsing logic).
Usage
Either save the code as a shell script file and source that in, or copy the function wholesale into,
.bashrc
(or your pertinent dot file). The important thing is to call the function after both bash completion and alias definitions have been set up (the code above calls the function right after its definition, in a “source and forget” spirit, but you can move the call anywhere downstream if that suits you better). If you don’t want the function in your environment after it exits, you can addunset -f alias_completion
after calling it.Notes
If you are using
bash
4.1 or above and use dynamically-loaded completions, the script will attempt to load completions for all of your aliased commands so that it can build the wrapper functions for your aliases.