Bash TAB完成双引号字符串

时间:2022-11-07 22:28:40

Problem

I'm writing a Twitter client for the command line (in C). I'm currently working on doing TAB-completion for Twitter screen names, like so:

我正在为命令行编写一个Twitter客户端(在C中)。我正在为Twitter屏幕名称做TAB完成,如下所示:

tweet "@s<TAB>
@sourcebits @spolsky

推特“@s @sourcebits @spolsky

However, I can't get it to work mid-string, e.g.:

但是,我不能让它在mid-string中工作,例如:

tweet "Foo bar @s<TAB>

推特“Foo bar @s

since Bash treats the string as one word. I couldn't find anything in the Bash man page suggesting a simple fix, so I decided to hack around it. Below is my half-done solution to the problem. I simply split the incoming string by spaces, take the last word (simplification, for now) and send it to compgen (the variable $last_word below). However, I need to append $prefix to the beginning of the string that the TAB-completion produces, as it replaces the whole input string (remember: it's treated as one word). That's where I'm stuck.

因为Bash将字符串视为一个单词。我在Bash手册页中找不到任何建议简单修复的东西,所以我决定破解它。以下是我对该问题的半成品解决方案。我只是按空格分割传入的字符串,取最后一个字(简化,现在)并将其发送到compgen(下面的变量$ last_word)。但是,我需要将$前缀附加到TAB完成产生的字符串的开头,因为它替换了整个输入字符串(记住:它被视为一个单词)。那就是我被困住的地方。

Question

How can this be done?

如何才能做到这一点?

Code etc.

__cltwitter_complete () {
  local cache="$HOME/.cltwitter_users.cache"
  local string=${COMP_WORDS[COMP_CWORD]}
  local last_word=${string##* }
  local prefix=${string% *}

  COMPREPLY=()

  #if [ ! -f ${cache} ] || [ "`find ${cache} -mmin +60`" != "" ]; then
  #  cltwitter-update-cache
  #fi

  if [[ "$last_word" == \"@* ]]; then  # if word is beginning of a quotation
    last_word=${last_word:2}
  elif [[ "$last_word" == @* ]]; then  # if user put '@' in front
    last_word=${last_word:1}
  fi

  COMPREPLY=( $( compgen -W "`cat $cache`" -P @ -- $last_word ) )
}

complete -F __cltwitter_complete tweet

Relevant section from the Bash man page:

Bash手册页的相关部分:

COMP_WORDS

An array variable (see Arrays below) consisting of the individual words in the current command line. The words are split on shell metacharacters as the shell parser would separate them. This variable is available only in shell functions invoked by the programmable completion facilities.

一个数组变量(参见下面的数组),由当前命令行中的各个单词组成。这些单词在shell元字符上被拆分,因为shell解析器会将它们分开。此变量仅在可编程完成工具调用的shell函数中可用。

2 个解决方案

#1


Look at programmable completion: http://www.faqs.org/docs/bashman/bashref_103.html

查看可编程完成情况:http://www.faqs.org/docs/bashman/bashref_103.html

#2


Do you really need the quotes?

你真的需要报价吗?

For example, your command could be:

例如,您的命令可能是:

tweet Foo bar @s<TAB>

Then @s would simply be the word you are trying to complete, and you can search for that. Inside the script, you can still get at the entire string with $*.

那么@s就是你要完成的单词,你可以搜索它。在脚本内部,您仍然可以使用$ *获取整个字符串。

You'll have to be more careful invoking now, though, as you can't use special characters such as ! and ( ) anymore without having to escape them with a backslash.

但是,你现在必须更加小心地调用,因为你不能使用特殊的字符,比如!和()不再需要用反斜杠来逃避它们。

#1


Look at programmable completion: http://www.faqs.org/docs/bashman/bashref_103.html

查看可编程完成情况:http://www.faqs.org/docs/bashman/bashref_103.html

#2


Do you really need the quotes?

你真的需要报价吗?

For example, your command could be:

例如,您的命令可能是:

tweet Foo bar @s<TAB>

Then @s would simply be the word you are trying to complete, and you can search for that. Inside the script, you can still get at the entire string with $*.

那么@s就是你要完成的单词,你可以搜索它。在脚本内部,您仍然可以使用$ *获取整个字符串。

You'll have to be more careful invoking now, though, as you can't use special characters such as ! and ( ) anymore without having to escape them with a backslash.

但是,你现在必须更加小心地调用,因为你不能使用特殊的字符,比如!和()不再需要用反斜杠来逃避它们。