可以更改 fish shell 中的制表符完成行为吗?

Possible to change tab completion behavior in fish shell?

更新此投诉与旧版本的鱼有关——请参阅下面一位鱼开发者的评论,描述了鱼的出色改进使此投诉无效的寻呼机行为。

鱼 shell 很酷 -- 但是我讨厌制表符补全的功能之一。

我经常——几乎就像一个紧张的滴答声——在更改目录时输入路径时会点击{tab}{tab}。这让我可以使用 {tab} 检查某些路径的内容,同时解决我当前击键允许解决的大部分路径消歧问题。这提供了一种快速发现到达文件系统中特定位置的最快组合键的好方法,而无需考虑太多或不必事先知道各种目录的内容。

另一方面,Fish 以我认为非常烦人的方式解释 {tab} {tab}。第一个 {tab} 列出了可能的补全,这很好。按下下一个选项卡,fish 选择列表中的第一个完成项,并将当前在该行中输入的路径的最后一部分替换为完整的第一个完成项——无论消歧状态如何。随后的选项卡循环显示下一个可能性。它类似于 windows 命令 shell 的作用。

这比正常的 bash 行为要糟糕得多...

考虑一个深度嵌套的目录结构foo/bar/baz/a/b/c/

其中一些 foo、bar、baz 是空目录。 Bash tab 补全让我可以键入 cd foo/{tab}{tab}{tab}{tab}{tab}{tab} -- 无需考虑我按了多少次 tab,无需提前考虑在我的命令行条目的当前状态下点击选项卡的效果。

正常情况下,所有这些目录都不会为空——但上面的方法仍然可以非常快速地发现我需要输入的最少字符数,才能进入某个深度嵌套的路径。

具有 bash 行为: cd some/unknown/dir/{tab}{tab} 保证

(1) 我看到了目录dir/的内容 (2) 到目前为止,我的命令可以明确表达的内容已经完成,但仅此而已。

点击上面的两个选项卡后,我可能会看到如下内容:

abc123 酒吧123 baz123 bcd123 mnop123

可以执行以下操作:

a{TAB}{TAB}(给我 abc123,如果这是一个目录,则列出其内容)

m{tab}{tab}(给我 mnop123,如果它的目录列出了它的内容)

假设我想到达路径 bcd123: b -- 告诉我我打字太快了,现在只显示了 3 个选项,我很容易得出结论,我只需要点击 'c' 来消除我的目标

的歧义

b{tab}{tab}c{tab}{tab}(获取我想要的路径,如果是目录则列出 bcd123 的内容)

fish 的模型更糟糕。 b{tab}{tab} 会完成到 bar123,我必须按未知次数的 Tab 键才能获得我想要的值,此外,我无法将输入上下文恢复为我输入的字母到目前为止,我实际上已经打字了(除了多次按退格键)。如果这个目录中碰巧有一大堆以 ba 开头的东西怎么办——我完全搞砸了会发生什么......

总的来说鱼的模型比较差:

有人请告诉我这里有一种方法可以改变鱼的行为,使其更像 bash ...鱼很酷,但这种行为不可用——我将不得不回到 bash 如果没有办法改变这个 ...

我赞扬你写了这篇详细而周到的文章 post,它值得同样详细而周到的回复!

tab 完成行为已在 fish top-of-tree(尚未发布)中重写,并被称为 "new pager." 您可以查看设计目标和讨论 here。我在这个回复的底部写了一个说明如何获得它。

贝壳是个人的,就像任何个人的东西一样,合理化和辩护一文不值:你要么喜欢,要么不喜欢,我们甚至可能没有意识到影响我们感受的因素。所以我能说的就是试一试,看看你的感受,然后(请)反馈。

我在 YouTube 上发布了 short little screencast 新寻呼机。注意事项:1. 只需键入更多内容即可关闭菜单,2. 它 "unfurls" 渐进(需要几个选项卡才能完全可见),即使有大量完成,也不会以模式方式接管您的屏幕,并且易于搜索和导航,并且 3. escape 将始终关闭它并将命令行恢复为您键入的内容。

让我逐一解决您的问题:

"I have to hit tab an unknown number of times to get the value I wanted"。使用新的寻呼机,所选项目在菜单中突出显示。这听起来微不足道,但我个人认为这会带来巨大的不同:点击 Tab 的额外次数变得 已知 ,并且由于您的手指在 Tab 上方,因此通常更容易点击它比键入其他字母多几次。您也可以使用箭头键进行导航。

"I have no way of getting the entry context back to only the letters that I've actually typed up to this point"。对于新的寻呼机,转义键正是这样做的。很容易按下,因为转义符就在标签的正上方,你的手指就在那里。

"What if there happen to be a whole bunch of things that start with ba in this directory -- I'm totally screwed is what happens"。 bash 和 old-pager-fish 都不能很好地处理大量完成。 fish 会让你进入这个模态分页环境,而 bash 使用模态 "Display all 1002 possibilities? (y or n)" 对话框打断你的流程,迫使你停止你正在做的事情并点击 'n'.

我想您会喜欢新寻呼机的处理方式。最初你会得到一个简短的菜单,它在你的提示 下方 下最多填充五行(不是上面,也不是替换)。这个菜单是非模态的,可以通过输入更多或点击退出来关闭。如果您再次点击 Tab,菜单会增长以显示更多完成,但仍然是非模态的。从来没有不和谐的过渡。

"it does not allow using tab to complete nested paths" 抱歉,我不确定您的意思。 bash 和 fish 在选项卡完成目录时附加一个 /。

"much more difficult to discover disambiguation sequences when in large directories" 使用新的寻呼机,您可以按 Esc 键,再输入一些内容,然后再次按 Tab 键。或者您可以 搜索 菜单:将焦点放在菜单中并键入内容,它会被过滤。请参阅上面的截屏视频。

"in general requires you to 'be careful' before you hit tab which makes you hit it less often and decreases its utility" 一个非常有效的观点,新寻呼机以几种方式解决了这一点。首先,它使用了渐进式披露的概念,这意味着需要 "work" 才能输出大量数据。其次,它永远不会 "takes over your screen" 像旧的模态寻呼机。最后,您可以按 escape 返回到您键入的内容,并且由于寻呼机出现在提示下方,它不会像 bash 那样在您的回滚中留下小粪便。

如果您使用的是自制软件,则可以通过 brew install fish --HEAD 从 master 安装。还有 nightly builds for Linux. And lastly, feel free to open an issue at https://github.com/fish-shell/fish-shell/issues 以及您的任何改进想法。