我正在使用 SaltStack。我想在调用salt
命令时自动完成小兵名称。
以下行已添加到~/.bashrc
:
complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt
然后输入→ ;我可以看到它按预期工作:salt inTab
salt integration-Tab
$ 盐集成-TabTab 集成-c 集成-u 集成-u2
为了与 一起使用sudo
,我添加了complete -cf sudo
into ~/.bashrc
,但它不起作用:
须藤盐Tab
什么也没返回。
我还尝试安装bash_completion
并将以下行添加到~/.bash_profile
:
if [ -f $(brew --prefix)/etc/bash_completion ]; then
. $(brew --prefix)/etc/bash_completion
fi
但没有运气。
我错过了什么?
更新
哦,我首先想说的是有时它是有效的:
$ sudo salt 集成TabTab -集成-c 集成-u 集成-u2
有时却并非如此。
首先,让我们看看 bash_completion 包做了多少事情。
我该如何检查?这是我的功能:
# a wrapper method for the next one, when the offset is unknown
_command()
{
local offset i
# find actual offset, as position of the first non-option
offset=1
for (( i=1; i <= COMP_CWORD; i++ )); do
if [[ "${COMP_WORDS[i]}" != -* ]]; then
offset=$i
break
fi
done
_command_offset $offset
}
# A meta-command completion function for commands like sudo(8), which need to
# first complete on a command, then complete according to that command's own
# completion definition - currently not quite foolproof (e.g. mount and umount
# don't work properly), but still quite useful.
#
_command_offset()
{
local cur func cline cspec noglob cmd i char_offset word_offset \
_COMMAND_FUNC _COMMAND_FUNC_ARGS
word_offset=$1
# rewrite current completion context before invoking
# actual command completion
# find new first word position, then
# rewrite COMP_LINE and adjust COMP_POINT
local first_word=${COMP_WORDS[$word_offset]}
for (( i=0; i <= ${#COMP_LINE}; i++ )); do
if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
char_offset=$i
break
fi
done
COMP_LINE=${COMP_LINE:$char_offset}
COMP_POINT=$(( COMP_POINT - $char_offset ))
# shift COMP_WORDS elements and adjust COMP_CWORD
for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
done
for (( i; i <= COMP_CWORD; i++ )); do
unset COMP_WORDS[i];
done
COMP_CWORD=$(( $COMP_CWORD - $word_offset ))
COMPREPLY=()
_get_comp_words_by_ref cur
if [[ $COMP_CWORD -eq 0 ]]; then
_compopt_o_filenames
COMPREPLY=( $( compgen -c -- "$cur" ) )
else
cmd=${COMP_WORDS[0]}
if complete -p ${cmd##*/} &>/dev/null; then
cspec=$( complete -p ${cmd##*/} )
if [ "${cspec#* -F }" != "$cspec" ]; then
# complete -F <function>
# get function name
func=${cspec#*-F }
func=${func%% *}
if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
$func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
else
$func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
fi
# remove any \: generated by a command that doesn't
# default to filenames or dirnames (e.g. sudo chown)
# FIXME: I'm pretty sure this does not work!
if [ "${cspec#*-o }" != "$cspec" ]; then
cspec=${cspec#*-o }
cspec=${cspec%% *}
if [[ "$cspec" != @(dir|file)names ]]; then
COMPREPLY=("${COMPREPLY[@]//\\\\:/:}")
else
_compopt_o_filenames
fi
fi
elif [ -n "$cspec" ]; then
cspec=${cspec#complete};
cspec=${cspec%%${cmd##*/}};
COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
fi
elif [ ${#COMPREPLY[@]} -eq 0 ]; then
_filedir
fi
fi
}
如果您输入
sudo mkdir
TabTab,它会显示目录列表吗?
是的:
$ sudo mkdir TabTab .FontForge/ .djangopypi2/ .ievms/ .ssh/ .wireshark-etc/
答案1
检查set -o
是否posix
启用了可能的模式。如果是这样,请禁用set +o posix
在“posix”模式下,由于某种原因,bash 的制表符补全在“vi 模式”下被禁用。我没有看到任何解释为什么会出现这种行为,也没有看到为什么它特定于 vi 模式,所以我没有费心解释。
PS:这个答案更适合通过搜索引擎偶然发现问题的人......而不适合您的特定设置。
更新:
切特·雷米说:
在POSIX模式下,vi编辑模式不应该通过映射tab来完成。这是因为 POSIX.2 完全规定了 vi 编辑模式的行为,并且标准要求 tab 默认映射到 self insert。
答案2
快速回答:
- 安装
bash-completion
- 来源
bash_completion
Bash
启动时 Bash
在启动时添加您的 compspec- 不要
sudo
用以下内容覆盖 compspeccomplete -cf sudo
我想你用的MacOSX
是brew
.
尝试:
brew update
brew install bash-completion
brew info bash-completion
# bash-completion: stable 1.3
. $(brew --prefix)/etc/bash_completion
complete -p sudo
你应该看到这样的东西:
complete -F _root_command sudo
测试:
function _comp_foo() { COMPREPLY=($(compgen -W 'a b c' -- "$2")); }
complete -F _comp_foo foo
类型foo
SpaceTabTab
您应该看到a b c
类型sudo foo
SpaceTabTab
您应该看到a b c
complete -fc sudo
然后从初始化文件中删除~/.bash_profile
(~/.bashrc
等)
将以下行添加到初始化文件中:
if [ -f $(brew --prefix)/etc/bash_completion ]; then
. $(brew --prefix)/etc/bash_completion
fi
# Your compspec here
complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt
重新打开终端。
类型complete -p sudo
。
你应该看看complete -F _root_command sudo
。
类型complete -p salt
。
你应该看到这样的东西:
complete -o default -o nospace -W 'a
b
c' salt
bash-completion2.* 注意:
您可以安装bash-completion2
:https://github.com/Homebrew/homebrew/issues/19258
但:
2.*
与Bash 4.*
2.*
使用-D
compspecs 延迟加载选项。因此,complete -p sudo
输出complete: sudo: no completion specification
直到您键入sudo
SpaceTab
答案3
sudo
除非您使用 请求,否则不会为您提供登录 shell -i
。所以你会发现没有它你需要加载系统的补全:
. /etc/bash_completion
如果您使用 运行-i
,则将$HOME
为~root
,因此写入用户的任何内容~/.bashrc
都不会被读取。如果您可以将完成的内容与其余部分分开~/.bashrc
,请使用 和 来获取它.
,这应该可以工作。