【发布时间】:2020-07-15 21:19:24
【问题描述】:
我编写了一个 bash 补全脚本来完成文件/目录补全,但使用 . 作为分隔符而不是 /。但是,它的行为不像我预期的那样。
在我进一步深入之前,有没有人知道这方面的任何选择,或者已经写好的可以做到这一点的东西?这样做的动机是在使用 -m 标志调用 python 时启用完成。这似乎很疯狂,这还不存在,但我找不到任何相关的东西。
我的问题是 bash 无法将 . 识别为完成选项的分隔符,并且在我在当前命令的末尾添加一个额外的空格之前不会显示下一个选项。
这里有几个具体的例子,给定这个目录结构。
/module
/script1.py
/script2.py
例如,当我使用ls 命令时,它的工作原理是这样的
$ ls mo<TAB>
$ ls module/<TAB><TAB>
script1.py script2.py
但是,使用我的函数,它的工作方式如下:
$ python -m mod<TAB>
$ python -m module.<TAB><TAB>
module.
因此,它不再显示下一个条目,而是再次显示完成的字符串。但是,如果我添加一个空格,它就会起作用,但我不希望它包含空格:
$ python -m mod<TAB>
$ python -m module. <TAB><TAB> # (note the space here after the dot)
script1 script2 # (Note, I'm intentionally removing the file extension here).
我希望补全功能与底部示例一样,但不强制包含转到下一组选项的空间
我打开了大约 50 个标签,并尝试了很多建议,但似乎没有什么能够按照我的意愿解决这个问题。这里还有一些其他警告需要花费大量时间才能完成,所以如果我跳过了一些重要的内容,我很乐意扩展任何其他点。我在下面附上了我的代码,任何帮助将不胜感激。谢谢!
#!/bin/bash
_python_target() {
local cur opts cur_path
# Retrieving the current typed argument
cur="${COMP_WORDS[COMP_CWORD]}"
# Preparing an array to store available list for completions
# COMREPLY will be checked to suggest the list
COMPREPLY=()
# Here, we'll only handle the case of "-m"
# Hence, the classic autocompletion is disabled
# (ie COMREPLY stays an empty array)
if [[ "${COMP_WORDS[1]}" != "-m" ]]
then
return 0
fi
# add each path component to the current path to check for additional files
cur_path=""
for word in ${COMP_WORDS[@]:2:COMP_CWORD-2}; do
path_component=$(echo ${word} | sed 's/\./\//g')
cur_path="${cur_path}${path_component}"
done
cur_path="./${cur_path}"
if [[ ! -f "$cur_path" && ! -d "$cur_path" ]]; then
return 0
fi
# this is not very pretty, but it works. Open to comments on this too
file_opts="$(find ${cur_path} -name "*.py" -type f -maxdepth 1 -print0 | xargs -0 basename -a | sed 's/\.[^.]*$//')"
dir_opts="$(find ${cur_path} ! -path ${cur_path} -type d -maxdepth 1 -print0 | xargs -0 basename -a | xargs -I {} echo {}.)"
opts="${file_opts} ${dir_opts}"
# We store the whole list by invoking "compgen" and filling
# COMREPLY with its output content.
COMPREPLY=($(compgen -W "$opts" -- "$cur"))
[[ $COMPREPLY == *\. ]] && compopt -o nospace
}
complete -F _python_target python
【问题讨论】: