【问题标题】:Unit testing Zsh completion script单元测试 Zsh 完成脚本
【发布时间】:2020-12-21 00:02:07
【问题描述】:

我正在尝试为 Zsh 编写完成脚本。我想对完成脚本进行单元测试。例如,我想测试 my-command --h 的完成是否包括 --help

对于 Fish,我可以使用 complete -C 'my-command --h',然后输出 --help 和任何其他有效的补全。

我似乎找不到 Zsh 的等效命令。一个存在吗?我尝试过_main_complete_complete_normal 之类的方法,但要么他们不支持这一点,要么我没有以正确的方式调用它们(我收到很多can only be called from completion function 错误)。

【问题讨论】:

    标签: zsh


    【解决方案1】:

    我收到了很多can only be called from completion function errors

    这是因为 Zsh 的补全命令只能从补全小部件内部运行,而补全小部件只能在 Zsh 行编辑器处于活动状态时调用。我们可以通过在所谓的pseudo terminal 内的活动命令行上激活完成小部件来解决此问题:

    # Set up your completions as you would normally.
    compdef _my-command my-command
    _my-command () {
            _arguments '--help[display help text]'  # Just an example.
    }
    
    # Define our test function.
    comptest () {
            # Gather all matching completions in this array.
            # -U discards duplicates.
            typeset -aU completions=()  
    
            # Override the builtin compadd command.
            compadd () {
                    # Gather all matching completions for this call in $reply.
                    # Note that this call overwrites the specified array.
                    # Therefore we cannot use $completions directly.
                    builtin compadd -O reply "$@"
    
                    completions+=("$reply[@]") # Collect them.
                    builtin compadd "$@"       # Run the actual command.
            }
    
            # Bind a custom widget to TAB.
            bindkey "^I" complete-word
            zle -C {,,}complete-word
            complete-word () {
                    # Make the completion system believe we're on a normal 
                    # command line, not in vared.
                    unset 'compstate[vared]'
    
                    _main_complete "$@"  # Generate completions.
    
                    # Print out our completions.
                    # Use of ^B and ^C as delimiters here is arbitrary.
                    # Just use something that won't normally be printed.
                    print -n $'\C-B'
                    print -nlr -- "$completions[@]"  # Print one per line.
                    print -n $'\C-C'
                    exit
            }
    
            vared -c tmp
    }
    
    zmodload zsh/zpty  # Load the pseudo terminal module.
    zpty {,}comptest   # Create a new pty and run our function in it.
    
    # Simulate a command being typed, ending with TAB to get completions.
    zpty -w comptest $'my-command --h\t'
    
    # Read up to the first delimiter. Discard all of this.
    zpty -r comptest REPLY $'*\C-B'
    
    zpty -r comptest REPLY $'*\C-C'  # Read up to the second delimiter.
    
    # Print out the results.
    print -r -- "${REPLY%$'\C-C'}"   # Trim off the ^C, just in case.
    
    zpty -d comptest  # Delete the pty.
    

    运行上面的例子会打印出来:

    --help
    

    如果您想测试整个完成输出,而不仅仅是要在命令行中插入的字符串,请参阅https://unix.stackexchange.com/questions/668618/how-to-write-automated-tests-for-zsh-completion/668827#668827

    【讨论】:

      猜你喜欢
      • 2012-02-26
      • 1970-01-01
      • 2010-11-23
      • 2019-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-01
      • 1970-01-01
      相关资源
      最近更新 更多