目前的情况是,我在.zshrc
中定义了一些别名
alias gco='git checkout'
alias cdp='cd ..'
并且很多。 我的问题是每次输入别名时如何打印命令并按Enter键?
例如:
$> gco master
> Command: git checkout master
> Git process ...
类似的东西,如果解决方案也适用于bash会更好! 谢谢!
答案 0 :(得分:7)
这是一个很好的问题。我们可以通过定义几个函数来扩展别名,然后在执行它们之前使用preexec
钩子来运行它们。
我从here得到了答案。
_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
打印所有regular
别名(不是全局或后缀),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
功能非常适用于此。这是一个功能:
在读取命令后即将执行并执行。如果历史记录机制处于活动状态(并且未从历史缓冲区中删除该行),则用户键入的字符串将作为第一个参数传递,否则它将为空字符串。将要执行的实际命令(包括扩展别名)以两种不同的形式传递:第二个参数是命令的单行大小限制版本(函数体之类的东西被省略);第三个参数包含正在执行的全文。
from the zsh Manual, chapter 9。
注意,我们可能只是使用preeexec函数来显示正在运行的内容。
要将我们的函数添加到preexec,我们使用钩子using this example:
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
)时,完整命令 not 显示。运行别名命令(如1
或rake
)时,将显示完整命令。
运行git
别名(例如git lg1
)时, git
别名未展开。如果你查看我的first link,那么完整的例子确实使用git
别名扩展 - 你应该接受并修改git别名对你来说至关重要。