当你输入内容时,你经常使用bash自动完成:例如,你开始编写一个命令,然后输入TAB
来获得剩下的单词。
正如您可能已经注意到的,当多个选项与您的命令匹配时,bash会显示如下:
foobar@myserv:~$ admin-
admin-addrsync admin-adduser admin-delrsync admin-deluser admin-listsvn
admin-addsvn admin-chmod admin-delsvn admin-listrsync
我正在寻找一种解决方案,在新行上显示每个可能的解决方案,类似于ls -l
上的最后一列。如果我可以应用这样的规则,那么会更好 "如果您发现少于10条建议,请逐行显示,如果更多=>实际显示" 。
答案 0 :(得分:10)
bash
不允许对完成的输出格式进行任何控制。
Bash 4.2+允许切换到1-suggestion-per-line output global ,如Grisha Levit's helpful answer中所述,它也链接到clever workaround来实现 per-completion-function 解决方案。
以下是 自定义完成的棘手解决方法。
解决此问题一般,对于所有定义的完成,将更难(如果有办法直接调用readline
函数,它可能更容易,但我还没有办法做到这一点。)
测试下面的概念验证:
. file
) - 这将:
foo
的命令(shell函数)foo
时,它只是以诊断形式打印其参数。)foo [fileNamePrefix]
,然后按标签:
<强>限制强>:
$PS1
中存储的提示定义字符串的扩展版本,解决方法(受https://stackoverflow.com/a/24006864/45375启发),它应该在典型< / em>案件,但并非万无一失。<强>方法强>:
>/dev/tty
,然后手动提示和命令行重新绘制&#34;模仿标准完成行为。# Define the command (function) for which to establish custom command completion.
# The command simply prints out all its arguments in diagnostic form.
foo() { local a i=0; for a; do echo "\$$((i+=1))=[$a]"; done; }
# Define the completion function that will generate the set of completions
# when <tab> is pressed.
# CAVEAT:
# Only works properly if <tab> is pressed at the END of the command line,
# i.e., if completion is applied to the LAST argument.
_complete_foo() {
local currToken="${COMP_WORDS[COMP_CWORD]}" matches matchCount
# Collect matches, providing the current command-line token as input.
IFS=$'\n' read -d '' -ra matches <<<"$(compgen -A file "$currToken")"
# Count matches.
matchCount=${#matches[@]}
# Output in custom format, depending on the number of matches.
if (( matchCount > 1 && matchCount < 10 )); then
# Output matches in CUSTOM format:
# print the matches line by line, directly to the terminal.
printf '\n%s' "${matches[@]}" >/dev/tty
# !! We actually *must* pass out the current token as the result,
# !! as it will otherwise be *removed* from the redrawn line,
# !! even though $COMP_LINE *includes* that token.
# !! Also, by passing out a nonempty result, we avoid the bell
# !! signal that normally indicates a failed completion.
# !! However, by passing out a single result, a *space* will
# !! be appended to the last token - unless the compspec
# !! (mapping established via `complete`) was defined with
# !! `-o nospace`.
COMPREPLY=( "$currToken" )
# Finally, simulate redrawing the command line.
# Obtain an *expanded version* of `$PS1` using a trick
# inspired by https://stackoverflow.com/a/24006864/45375.
# !! This is NOT foolproof, but hopefully works in most cases.
expandedPrompt=$(PS1="$PS1" debian_chroot="$debian_chroot" "$BASH" --norc -i </dev/null 2>&1 | sed -n '${s/^\(.*\)exit$/\1/p;}')
printf '\n%s%s' "$expandedPrompt" "$COMP_LINE" >/dev/tty
else # Just 1 match or 10 or more matches?
# Perform NORMAL completion: let bash handle it by
# reporting matches via array variable `$COMPREPLY`.
COMPREPLY=( "${matches[@]}" )
fi
}
# Map the completion function (`_complete_foo`) to the command (`foo`).
# `-o nospace` ensures that no space is appended after a completion,
# which is needed for our workaround.
complete -o nospace -F _complete_foo -- foo
答案 1 :(得分:5)
bash
4.2+(更常见的是,使用readline
6.2+的应用程序)通过使用completion-display-width
变量来支持此功能。
执行完成时用于显示可能匹配项的屏幕列数。如果该值小于0或大于终端屏幕宽度,则忽略该值。 值为0将导致每行显示一个匹配项。默认值为-1。
运行以下命令为当前会话设置所有完成 1 的行为:
bind 'set completion-display-width 0'
或修改您的~/.inputrc
2 文件:
set completion-display-width 0
更改所有新shell的行为。
1 有关控制各个自定义完成函数的此行为的方法,请参阅here。
2 readline init文件的搜索路径为$INPUTRC
,~/.inputrc
,/etc/inputrc
,因此请修改适合您的文件。