0

I have created a zsh completion script. It works as expected if I hardcode the options list, but if I try to generate that same hardcoded value using a bash command, my results are unexpected. For the purposes of this question, I have combined both methods into the same completion script. "silly" is the strange one. "silly2" behaves as expected.

#compdef silly

_silly() {
    local -a options
    options=($(cat in_file.txt))
    _describe 'silly command' options && ret=0
    return ret
}

_silly2() {
    local -a options
    options=("one:Does the 1 thing" "two:Does the 2 thing")
    _describe 'silly2 command' options && ret=0
    return ret
}

compdef _silly silly
compdef _silly2 silly2

#contents of in_file.txt
#"one:Does the 1 thing" "two:Does the 2 thing"

As you can see, the second method (hardcoded) takes the input string "one:Does..." while the first method (dynamic) generates the exact same output via a cat call to the file in_file.txt, which has identical text.

Ideally, the result looks like this:

one  -- Does the 1 thing
two  -- Does the 2 thing

The second one does indeed produce this result. The first one, however, produces a result like so:

"two  "one  -- Does
1                          2             the            thing"

I cannot for the life of me figure out what the difference is here!

Brian Mego
  • 1,439
  • 11
  • 10

1 Answers1

0

And here I am answering my own question. The answer comes from a related question: How to pass the contents of a file using `cat` to `_values` (zsh completion)

Basically, the spaces are treated differently if they come from the result of a bash command rather than a string literal. The solution is to change the bash internal field separator for the duration of the command, then change it back.

OLD_IFS=$IFS
IFS=$'\n'
options=($(cat in_file.txt))
_describe 'silly command' options && ret=0
IFS=$OLD_IFS

This makes the two command behave the same way.

Brian Mego
  • 1,439
  • 11
  • 10