3

Is it possible to pass the contents of a file using cat to _values (zsh completion)?

If I uncomment the line _values cat .test_tasks~ and comment _values below, it doesn't work, I get: _values:compvalues:10: invalid value definition: 1test[1.

#compdef test
#autoload

local curcontext="$curcontext" state line ret=1
local -a _configs

_arguments -C \
  '1: :->cmds' \
  '2:: :->args' && ret=0

_test_tasks() {
  # _values "test" $(cat .test_tasks~)

  _values "test" \
      "1test[1 test test]" \
      "2test[2 test test]"
}

case $state in
  cmds)
        _test_tasks
    ret=0
    ;;
  args)
        _test_tasks
    ret=0
    ;;
esac

return ret

.test_tasks~

1test[1 test test]
2test[2 test test]

It seems to be a problem with whitespaces. If I remove the whitespaces:

1test[1testtest]
2test[2testtest]

it works.

Any ideas?

Solution:

OLD_IFS=$IFS
IFS=$'\n'
_values $(< .cap_tasks~)
IFS=$OLD_IFS

Reference: Bash cat command space issue explained.

Pablo Cantero
  • 6,239
  • 4
  • 33
  • 44

1 Answers1

1

You can use the mapfile module:

zmodload zsh/mapfile
_values ${(f)mapfile[.test_tasks~]}

The mapfile associative array provides access to the contents of external files. The parameter expansion flag (f) splits the resulting expansion on newlines, so that each line of the file will form a separate argument to _values.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • Awesome! It worked, thanks. What do you think about the Solution in the answer? I'm just wondering if load a module can be expensive for the completion code. – Pablo Cantero Jan 26 '14 at 00:10
  • A module isn't a shell script; it's just '.so' file linked at runtime, so it should be fast enough. You can also move the `zmodload` command to the top of the file; it doesn't need to be in the function where `mapfile` is actually used. – chepner Jan 26 '14 at 00:36