Zsh
我正在尝试修改(或) shell的行为,以在执行之前Bash
自动在所有输入中添加一个自定义命令(例如命名) 。myapp
本质上,我想拦截并修改用户的输入,当他们按下 时ENTER_KEY
,应该执行修改后的命令。
我在 shell 中输入的任何命令,例如:
grep -rn hello
应该像我输入一样进行处理
$ myapp grep -rn hello
另一个例子,如果我输入ls
,它应该被执行为myapp ls
。
目标
我想尝试使用 vim 自动作为某些 cli 工具的查看器:
# myapp
vim -c "term $*"
答案1
考虑到目标,最简单的解决方案是将命令的结果通过管道传递给 vim,如下所示。
$ yourcommand | vim -
例如,
$ grep -rn hello | vim -
答案2
我假设您想要进入和退出这种安排,因此我做了以下操作。对于 zsh,DEBUG 陷阱处理程序可以通过设置 ERR_EXIT 选项来跳过已提交命令的执行,而是运行您的自定义命令
# this is run before every command
debug_trap() {
# get last submitted command
cmd="${history[$HISTCMD]}";
if [ "$cmd" ]; then
# catch the unwrap command and remove the trap
if [ "$cmd" = "unwrap" ]; then
print 'Unwrapping command-line';
trap - DEBUG;
return;
fi
# make sure multiple trap triggers only handle this once
if [ "$handled" != "$HISTCMD;$cmd" ]; then
# when either history index or command text
# changes, we can assume its a new command
handled="$HISTCMD;$cmd";
# do whatever with $cmd
myapp $cmd;
fi
# optionally skip the raw execution
setopt ERR_EXIT;
fi
}
# start the debug trap
wrap() {
print 'Wrapping command-line';
trap 'debug_trap' DEBUG;
}
# this is just defined in order to avoid errors
# the unwrapping happens in the trap handler
unwrap() {}
bash 中的等效内容:
# bash requires this option in order to skip execution
# inside the debug trap
shopt -s extdebug;
# this is run before every command
debug_trap() {
cmd="$BASH_COMMAND";
# catch the unwrap command and remove the trap
# notice how the alias is expanded here and
# the command is no longer 'unwrap'
if [[ "$cmd" == 'trap - DEBUG' ]]; then
echo 'Unwrapping command-line';
# the trap is unset by the submitted command
else
# do whatever with $cmd
myapp $cmd;
# optionally skip the raw execution
return 1;
fi
}
# start the debug trap
wrap() {
echo 'Wrapping command-line';
trap debug_trap DEBUG;
}
# we can't unset global traps inside a function
# so we use an alias instead
alias unwrap='trap - DEBUG';
使用示例:
> myapp() { echo "### $1"; }
> wrap
Wrapping command-line
> echo 123
### echo 123
> unwrap
Unwrapping command-line
> echo 123
123
要实现 vim 功能,请相应地在 myapp 函数中使用“vim -c”或更改“myapp $cmd;” trap 函数中的行。
然而,使用前的警告。调试陷阱非常挑剔,我尝试使用 zsh 版本来减少错误。使用像 oh-my-*sh 这样的插件可能会引入钩子、陷阱和其他机制,从而大大增加实现稳定实现的难度。 zsh 版本针对 oh-my-zsh 进行了测试,应该可以工作。 bash 版本仅在没有修饰的 bash v4.2 上进行了测试。
zsh 中的其他潜在实现:您可以覆盖绑定到返回键的默认 zle 小部件“accept-line”,该返回键可以在提交执行之前操作您的文本缓冲区,这可能是一个更干净的解决方案。还有“preexec”挂钩函数可能很有用,但它似乎没有自行更改或跳过命令的方法。
其他使用思路:您可以使用它来将命令发送(ssh)到一台或多台远程计算机,将它们写入脚本文件并推迟执行,在执行前进行静态分析,要求确认或要求修复拼写错误。