当我开始在交互式登录 shell(zsh 或 bash)中输入内容并单击标签,shell 为我提供自动完成建议。
我大致了解完成规范是如何定义的。作为参考,这里概述了:
- 重击:https://www.gnu.org/software/bash/manual/bash.html#Programmable-Completion
- 兹什:http://zsh.sourceforge.net/Doc/Release/Completion-System.html
我不明白的是,当用户按下 Tab 时,bash/zsh 如何识别要完成哪个命令,即如果我这样做ls [tab]
,bash/zsh 如何识别ls
。换句话说,bash/zsh 如何知道使用ls
补全规范生成补全。
更多一些具有更复杂解析的示例,Bash/Zsh 仍然正确:
ls [tab]
-> 完成于ls
echo $( echo $(ls [tab]
-> 完成于ls
echo hi; git a[tab]
-> 完成于git
echo 'cd [tab]
-> 未完成于cd
echo "$(ls [tab]
-> 完成于ls
echo $( echo hi | ls [tab]
-> 完成ls
(我知道ls
不接受 stdin,但这个例子仍然说明了 bash/zsh 的解析能力)
我假设 bash/zsh 正在使用某种解析器。然而,它不是一个普通的解析器。它无需结构正确的命令即可完成。它知道某些内容在引号或 shell 扩展中,即使它们没有关闭。
bash/zsh 运行什么函数来“识别”相关命令或确定是否有命令需要完成?
答案1
bash/zsh 运行什么函数来“识别”相关命令或确定是否有命令需要完成?
当您按下 时tab
,readline 会执行该complete
函数。
您可以在以下位置覆盖它~/.inputrc
:
"\t": complete
complete
定义为lib/readline/funmap.c
:
static const FUNMAP default_funmap[] = {
[..]
{ "complete", rl_complete },
rl_complete
可以在lib/readline/complete.c
(浏览源码):
/* Complete the word at or before point. You have supplied the function
that does the initial simple matching selection algorithm (see
rl_completion_matches ()). The default is to do filename completion. */
int
rl_complete (int ignore, int invoking_key)
{
..
这是起点。它分解单词,检查注册了哪些补全,然后查找相关的补全。
zsh 可能会有类似的实现。
流程也有很好的解释这里。