目前的情况是,我在.zshrc
中定义了一些别名,比如:
alias gco='git checkout'
alias cdp='cd ..'
还有很多类似的东西。我的问题是如何在我键入别名并按下回车时每次打印出该命令?
例如:
$> gco master
> Command: git checkout master
> Git process ...
如果这个解决方案也能在Bash中运行,那就更好了!谢谢!
目前的情况是,我在.zshrc
中定义了一些别名,比如:
alias gco='git checkout'
alias cdp='cd ..'
还有很多类似的东西。我的问题是如何在我键入别名并按下回车时每次打印出该命令?
例如:
$> gco master
> Command: git checkout master
> Git process ...
如果这个解决方案也能在Bash中运行,那就更好了!谢谢!
这是一个不错的问题。我们可以通过定义几个函数来扩展别名,然后使用 preexec
钩子在执行之前运行这些函数。
我从这里获取了答案。
_aliases="$(alias -Lr 2>/dev/null || alias)"
alias_for() {
[[ $1 =~ '[[:punct:]]' ]] && return
local found="$( echo "$_aliases" | sed -nE "/^alias ${1}='?(.+)/s//\\1/p" )"
[[ -n $found ]] && echo "${found%\'}"
}
首先,将所有的别名存储在一个变量中。alias -r
打印所有的常规
别名(不是全局或后缀),而alias -L
以“适合在启动脚本中使用的方式”打印它们。
alias_for()
函数做了一些清理工作,删除引号并将alias
放在行的前面。当我们执行echo ${_aliases}
时,会得到类似于以下内容:
alias history='fc -l 1'
alias ls='ls -F -G'
alias lsdf='ls -1l ~/.*(@)'
alias mv='mv -v'
将此与 alias
的输出进行比较:
history='fc -l 1'
ls='ls -F -G'
lsdf='ls -1l ~/.*(@)'
mv='mv -v'
如果输入了别名,我们现在可以检测到并打印出来:
expand_command_line() {
[[ $# -eq 0 ]] && return # If there's no input, return. Else...
local found_alias="$(alias_for $1)" # Check if there's an alias for the comand.
if [[ -n $found_alias ]]; then # If there was
echo ${found_alias} # Print it.
fi
}
preexec
函数非常适合这个任务。它是一个函数,会在以下情况下被执行:
在读取并即将执行一条命令后执行。如果历史机制处于活动状态(并且该行未从历史缓冲区中舍弃),则用户键入的字符串将作为第一个参数传递,否则它是一个空字符串。将要被执行的实际命令(包括扩展的别名)以两种不同的形式传递:第二个参数是一个单行、大小限制版本的命令(类似于省略了函数体的东西);第三个参数包含正在执行的完整文本。
引自zsh手册的第9章。
请注意,我们可以使用preeexec函数来显示正在运行的命令信息。
为了将我们的函数添加到preexec中,我们使用此示例中的钩子进行操作。
autoload -U add-zsh-hook # Load the zsh hook module.
add-zsh-hook preexec expand_command_line # Adds the hook
稍后要移除钩子时,可以使用:
# add-zsh-hook -d preexec expand_command_line # Remove it for this hook.
当我运行它时,这是我的Shell的样子:
$ 1
cd -
$ rake
bundle exec rake
^C
$ chmod
usage: chmod [-fhv] [-R [-H | -L | -P]] [-a | +a | =a [i][# [ n]]] mode|entry file ...
chmod [-fhv] [-R [-H | -L | -P]] [-E | -C | -N | -i | -I] file ...
$ git lg1
fatal: Not a git repository (or any of the parent directories): .git
从我的shell示例中可以看出,运行未别名化的命令(如chmod
)时,并不会显示完整命令。但是当运行别名命令(如1
或rake
)时,将显示完整命令。
当运行git
别名命令(例如git lg1
)时,不会展开git
别名。如果您查看我的第一个链接,那里的完整示例确实使用了git
别名展开-如果git别名对您至关重要,则应采用该示例并进行修改。
alias obp="explorer.exe \".\\build\""
存在一个错误。它运行得很好,但是在控制台中显示的命令是eplorer.exe "uild"
,路径上缺少.\\
。 - equiman