以下是我想要的。当制表符补全不明确时,bash 会打印可能性列表。我希望它为我应该在列表中的每个单词中按下的下一个字符着色。
以下是我到目前为止所做的事情。在我的 .bashrc 中,我定义了以下函数并调用了完整的命令
_colourunique() {
local word=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($(compgen -f -- "${word}"))
if [[ "$word" ]] && [[ ${#COMPREPLY[@]} -gt 1 ]]; then
local w
local i=0
for ((i=0;i<${#COMPREPLY[@]};i++)) ; do
w=${COMPREPLY[$i]}
n=${#word}
COMPREPLY[$i]="${w:0:n}\033[91m${w:n:1}\033[0m${w:$((n+1))}"
done
fi
}
complete -D -F _colourunique
但它不起作用......当我打字时
ls D[TAB]
它自动完成为
ls D\033[91m
而不是列出文档、桌面等的可能性。这里可能出了什么问题?或者还有其他直接的方法来实现这一点吗?
更新1:
我想我明白这里发生了什么。由于我将 \033[91m 添加到 COMPREPLY 中的每个单词中,bash 认为这部分对所有人来说都是通用的,并且会将该通用术语自动补全到命令提示符本身中。 (而不是简单地打印列表)
所以我不认为这种编辑 COMPREPLY 数组的方法是正确的方法。还有其他方法吗?
更新2:
为了保持唯一性,我尝试在字符串中添加 $i 和 \b 。
COMPREPLY[$i]="${w:0:n}$i\b\033[91m${w:n:1}\033[0m${w:$((n+1))}"
现在它会打印可能的制表符补全,如下所示。
D0\b\033[91mo\033[0mwnloads D1\b\033[91me\033[0msktop
这意味着列表会照原样打印。没有对 \b 或 \033[91m 个字符进行求值。:-(
更新3:
由于回复看起来像这样,因此无法在 bash 中完成我想要的任务(除非我转向 zsh)。我决定接受另一种选择。我将尝试将下一个唯一的击键附加到每个单词的末尾,以便它脱颖而出。
以下是到目前为止的代码。
SanitiseString () {
local String="$1"
local j
for j in \\ \! \@ \# \$ \% \^ \& \* \( \) \+ \{ \[ \] \} \| \; \: \" \' \, \? \ ; do
String=${String//"$j"/\\"$j"}
done
echo "$String"
}
_colourunique() {
saveIFS=$IFS
IFS=$'\n'
local word=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($(compgen -f -- "${word}"))
if [[ "$word" ]] ; then
local w
local i=0
for ((i=0;i<${#COMPREPLY[@]};i++)) ; do
w="${COMPREPLY[$i]}"
n=${#word}
w=$(SanitiseString "$w")
if [[ ${#COMPREPLY[@]} -gt 1 ]] ; then
COMPREPLY[$i]="$w :${w:n:1}"
else
COMPREPLY[$i]="$w"
fi
done
fi
IFS=$saveIFS
}
complete -D -F _colourunique
这将打印下一个唯一击键的选项,并用 分隔:
但该代码仍然存在两个令人恼火的问题。我必须解决这个问题
- 它不再在自动完成目录的末尾附加 /
- 自动完成后不再执行智能间距。
有什么建议么?
答案1
虽然这不完全是你要求的,但我决定发布这个答案,因为最初我和你有同样的想法,但最终我这样解决了,我发现它比着色更好。
可以将此选项设置为GNU 读行库:
完成前缀显示长度 未经修改显示的可能完成列表的公共前缀的字符长度。当设置为大于零的值时,在显示可能的补全时,长于该值的公共前缀将被替换为省略号。
例如这一行〜/.inputrc:
set completion-prefix-display-length 2
也成功了(当公共前缀长于两个字符时)。
答案2
我的 .c 不是那么热,但是从内部阅读http://git.savannah.gnu.org/cgit/bash.git/snapshot/bash-master.tar.gz,在我看来 COMPREPLY 只不过是非操作文本数据。 iow,即使在那里正确地得到一个转义符,最终也会被打印为我们用来表达它们的字符的非魔法/非特殊表示。
类似\033
or\e
不是单个字符“Escape”,而是四个或两个反斜杠字符以及零、三和 Es。
在深入 .c 看看它实际上是如何的之前,我研究了printf
//echo
的各种迭代eval
处理过COMPREPLY 中的值。
可能是错误的,但签入strlist_print()
看起来lib/sh/stringlist.c
像 COMPREPLY 是 STRINGLIST 类型的结构(如 中所定义externs.h
)。