Bash/Zsh 在完成过程中如何识别相关命令?

Bash/Zsh 在完成过程中如何识别相关命令?

当我开始在交互式登录 shell(zsh 或 bash)中输入内容并单击标签,shell 为我提供自动完成建议。

我大致了解完成规范是如何定义的。作为参考,这里概述了:

我不明白的是,当用户按下 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 可能会有类似的实现。

流程也有很好的解释这里

相关内容