我正在尝试编写自己的完整命令。完成需要使用键入命令的一部分来进行路径搜索。
我试图获得以下行为
当我my_commad -ws my_ws -t[TAB]
在 my_ws/tests 下编写文件夹列表时,它显示为完成列表,我不知道如何打破它
我尝试了以下操作,但由于引号问题而失败,我猜
complete my_command 'n@-t@`echo $COMMAND_LINE | perl -ne '/-ws (\w+)/; print $1'`@'
答案1
报价问题
正如您所提到的,您的命令的问题在于单引号内有单引号,您需要将其转义。有几种方法可以做到这一点。
如果backslash_quote
设置了 shell 变量,则可以使用反斜杠转义内部单引号。
complete my_command 'n@-t@`echo $COMMAND_LINE | perl -ne \'/-ws (\w+)/; print $1\'`@'
- 可以通过运行来检查是否
echo $?backslash_quote
为1。 - 如果没有设置,可以通过运行来设置
set backslash_quote
或者,如果您的backslash_quote
未设置并且您不想更改它,您可以将内部单引号替换为'"'"'
。
complete my_command 'n@-t@`echo $COMMAND_LINE | perl -ne '"'"'/-ws (\w+)/; print $1'"'"'`@'
两种解决方案都可以解决您的引号问题,结果将是后面的参数-t
将由您的参数完成-ws
。
$ my_command -ws my_ws -t TABmy_ws
无论如何,这不是您想要实现的目标。您希望它由“my_ws/tests 下的文件夹列表”。
回答您的实际需求
对于更复杂的完成,您可能会考虑创建一个包装器脚本来解析$COMMAND_LINE
变量并执行其他操作。
例如,如果您希望-t
$WS/tests 下的子目录完成后面的参数,您可以在主目录中编写类似于以下内容的脚本:
$ cat $HOME/findtest.sh
#!/bin/sh
ws=$(perl -ne '/-ws (\S+)/; print $1' <<< $@)
find $ws/tests -mindepth 1 -maxdepth 1 -type d 2>/dev/null
然后在您的complete
命令中,您将findtest.sh
使用$COMMAND_LINE
变量作为参数来调用脚本:
complete my_command 'n@-t@`$HOME/findtest.sh $COMMAND_LINE`@'
结果:
假设my_ws/tests
你下面有以下文件夹:
ls -1 my_ws/tests
test1
test2
test3
然后尝试完成参数 for-t
将导致:
$ my_command -ws my_ws -tTAB my_ws/测试/test1 my_ws/测试/test2 my_ws/测试/test3 $ my_command -ws my_ws -t my_ws/测试/测试
如果您不想显示完整路径,而只想显示下面的目录my_ws/tests
而不显示前导路径,您可以将find
脚本中的命令更改为:
find $ws/tests -mindepth 1 -maxdepth 1 -type d -printf "%f\n" 2>/dev/null
结果:
$ my_command -ws my_ws -tTAB 测试1 测试2 测试3 $ my_command -ws my_ws -t 测试
其他建议
您可以添加其他功能来完成。例如:
complete my_command 'n@-t@`$HOME/findtest.sh $COMMAND_LINE`@' 'N/-ws/(-t)/' 'n/-ws/d/' 'p/*/(-ws)/'
或者更具可读性:
complete my_command \
'n@-t@`$HOME/findtest.sh $COMMAND_LINE`@' \
'N/-ws/(-t)/' \
'n/-ws/d/' \
'p/*/(-ws)/'
解释:
'p/*/(-ws)/'
- 在您之后的任何地方,my_command
它都会尝试完成-ws
。'n/-ws/d/'
- 之后-ws
它将尝试仅完成目录。'N/-ws/(-t)/'
- 如果在行中当前位置之前的两个单词是-ws
,则它期望的下一个参数是-t
。
请注意,此处的顺序很重要,因为tcsh
将尝试根据单词在complete
命令中出现的顺序来完成。例如,如果您将 移至'p/*/(-ws)/'
开头,它将始终尝试完成 to-ws
而不会尝试该行的其余部分。
结果:
$ my_command TAB # 将完成-ws $ my_command -ws $ my_command -ws m TAB # 将完成以以下开头的目录列表米 $ my_command -ws my_ws/ $ my_command -ws my_ws/ TAB # 将完成到-t $ my_command -ws my_ws/ -t $ my_command -ws my_ws/ -t TAB # 将完成以下文件夹列表my_ws/测试 测试1 测试2 测试3 $ my_command -ws my_ws/ -t 测试