我正在使用 zsh普雷斯托配置框架。我希望能够输入类似的术语1 + 2 * (3 / 4)
并从中得到“2.5”。
这些术语可以被识别,因为它们仅包含某些字符:0123456789 +-*/()
。对于更复杂的事情,我可以打开一个专用程序(如 python shell)。
解决方案不够好
- 使用程序:我不想
python -c
在我的术语之前输入或将其输入到bc
.打字太多了,希望能做得更好。 - 使用函数或别名: 有一些解决方案那里允许在使用
c
or=
或 时进行这些计算calc
,就像在= 1 + 2 * (3 / 4)
.这很好,但基本上与第 1 点相同。 - 使用另一个外壳: 我知道克森什我确信还有其他 shell 可以做到这一点。但我喜欢 zsh 并且不想换 shell。
什么可能有效
- zsh 插件:我可以想象一个 zsh 插件,它可以查找命令是否与某个正则表达式匹配,然后将其通过管道传输到 python/bc/whatever 中。有点类似于当您仅输入目录名称时自动 cd 的作用。我不知道这是否可能。我很想听到一些提示,这样我就可以写下来。
- 截距
command not found
:与4类似。也许可以拦截zsh在未找到命令时的行为。但我又不知道该怎么做。 - 所有号码的别名:我想您可以为所有数字编写一个别名,以便它们成为将数学字符串的其余部分作为参数的命令。这可能有用,但看起来很老套。此外,“所有数字”是相当多的别名,即使在自动生成代码时也是如此。
我想听听关于如何解决这个问题的想法。我并不害怕编写代码,但我更喜欢干净的解决方案而不是黑客的解决方案。
答案1
在命令执行之前拦截它是可能的,但为时已晚:该命令已经被解析并且别名已经被扩展。例如,2 * 3
将显示为未找到命令2
(假设没有该名称的命令),后跟当前目录中的文件列表。
相反,您需要在命令提交后(甚至在解析它之前)立即拦截该命令。因此,您需要挂接到命令行界面,而不是挂接到命令执行引擎。我认为没有通用的方法可以做到这一点:我能想到的唯一方法是覆盖 Enter 键命令及其兄弟命令,并让它们重写命令行。这不太漂亮,但它满足您的要求。
主要的回车键命令是accept-line
,绑定到^J
和^M
。您可以按如下方式覆盖它(您需要对您使用的其他类似小部件执行此操作,例如accept-and-hold
、accept-line-and-down-history
等):
function my-accept-line {
my-rewrite-accepted-line "$@"
zle accept-line "$@"
}
zle -N my-accept-line
bindkey '^J' my-accept-line
bindkey '^M' my-accept-line
现在,让函数重写接受的行。该行内容位于BUFFER
。唯一的困难是重写的逻辑。也许是这样的,它要求该行以数字(不是变量,这太不明确了)开头,可选地在前面加上一元运算符和括号,后面跟着一个二元运算符:
function my-rewrite-accepted-line {
emulate -L zsh
setopt extended_glob
if [[ ${BUFFER// /} == [\(+\-]#([0-9]##(|.[0-9]#)(|e(-|+|)[0-9]##)|0x[0-9A-Fa-f]##)[-+*/%\&\|\^]* ]]; then
BUFFER="echo \$(($BUFFER))"
fi
}
请注意,我仅使用裸 zsh 进行了最少的测试。我还没有调查这是否会干扰 Prezto。