报价问题

报价问题

我正在尝试编写自己的完整命令。完成需要使用键入命令的一部分来进行路径搜索。

我试图获得以下行为

当我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 测试

相关内容