【问题标题】:Sdkman Incorrect zsh completion script outputSdkman 不正确的 zsh 完成脚本输出
【发布时间】:2018-11-18 21:17:24
【问题描述】:

我正在使用 oh-my-zsh,并且一直在尝试为 sdkman 开发自定义完成脚本。

但是我在尝试使某些命令相互化时遇到了一个小问题。

下面是完成脚本的开始。使用 _describe 方法输出完成帮助的三个函数。

#compdef sdk

zstyle ':completion:*:descriptions' format '%B%d%b'

# Gets candidate lists and removes all unecessery things just to get candidate names
__get_candidate_list() {
  echo `sdk list | grep --color=never  "$ sdk install" | sed 's/\$ sdk install //g' | sed -e 's/[\t ]//g;/^$/d'`
}

__get_current_installed_list() {
  echo `sdk current | sed "s/Using://g" | sed "s/\:.*//g"  | sed -e "s/[\t ]//g;/^$/d"`
}

__describe_commands() {
  local -a commands
  commands=(
    'install: install a program'
    'uninstall: uninstal an existing program'
  )

  _describe -t commands "Commands" commands && ret=0
}

__describe_install() {
  local -a candidate_list
  candidate_list=( $( __get_candidate_list ) )
  _describe -t candidate_list "Candidates available" candidate_list && ret=0
}

__describe_uninstall() { # FIXME THis is not working, it only displays candidate list
  local -a candidates_to_uninstall
  candidates_to_uninstall=( $( __get_current_installed_list ) )
  _describe -t candidates_to_uninstall "Uninstallable candidates" candidates_to_uninstall && ret=0
}

__get_candidate_list 与以下值相呼应:

ant asciidoctorj bpipe ceylon crash cuba cxf gaiden glide gradle grails groovy groovyserv infrastructor java jbake kotlin kscript lazybones leiningen maven micronaut sbt scala spark springboot sshoogr vertx visualvm

__get_current_installed_list 与以下值相呼应:

gradle java kotlin maven sbt scala

下面脚本的第二部分是我们调用所有内容的地方,以便 zsh 正确使用完成脚本:

function _sdk() {
  local ret=1
  local target=$words[2]

  _arguments -C \
    '1: :->first_arg' \
    '2: :->second_arg' \
    && ret=0

    case $state in
      first_arg)
        __describe_commands
        ;;
      second_arg)
        case $target in
          install)
            __describe_install
            ;;
          uninstall)
            __describe_uninstall
            ;;
          *)
            ;;
        esac
        ;;
    esac

    return $ret
}

_sdk "$@"

问题如下:当我输入 sdk install 时,我得到了正确的输出,来自 __get_candidate_list 方法的输出,但是当我使用 sdk uninstall 时,它仍然给我 __get_candidate_list 虽然我期待 __get_current_installed_list 输出。

编辑: 经过一番调试,似乎 zsh 没有错。我不知道为什么,但是 sdkman 从完成脚本内部给了我与 sdk listsdk current (在 sed 命令之后)相同的输出。在我的 shell 中,这两个命令都可以在 shell 中正常工作。

我使用 _describe 方法的方式有问题吗? 还有什么我没看到的吗?

感谢您的帮助。

【问题讨论】:

    标签: zsh oh-my-zsh sdkman


    【解决方案1】:

    所以我终于找到了解决此问题的解决方法,但这并不理想。

    我选择在启动插件时在后台启动命令,并用结果填充文本文件,以便完成脚本之后可以使用这些。 下面是我在 zsh-sdkman.plugin.zsh 文件中使用的代码,以防我的 github 存储库消失:

    # --------------------------
    # -------- Executed on shell launch for completion help
    # --------------------------
    # NOTE: Sdkman seems to always output the candidate list rather than the currently installted list when we do this through the completion script
    # There are two goals in the code below:
    #   - Optimization: the _sdkman_get_candidate_list command can take time, so it is done once and in background
    #   - Bug correction: correct the problem with sdkman command output explained above
    
    # WARNING: We are setting this as a local variable because we don't have it yet at the time of initialization
    # A better approach would be welcome
    SDKMAN_DIR_LOCAL=~/.sdkman
    
    # Custom variables for later
    export ZSH_SDKMAN_CANDIDATE_LIST_HOME=~/.zsh-sdkman.candidate-list
    export ZSH_SDKMAN_INSTALLED_LIST_HOME=~/.zsh-sdkman.current-installed-list
    
    _sdkman_get_candidate_list() {
      (sdk list | grep --color=never  "$ sdk install" | sed 's/\$ sdk install //g' | sed -e 's/[\t ]//g;/^$/d' > $ZSH_SDKMAN_CANDIDATE_LIST_HOME &)
    }
    
    _sdkman_get_current_installed_list() {
      (sdk current | sed "s/Using://g" | sed "s/\:.*//g"  | sed -e "s/[\t ]//g;/^$/d" > $ZSH_SDKMAN_INSTALLED_LIST_HOME &)
    }
    
    # "sdk" command is not found if we don't do this
    source "$SDKMAN_DIR_LOCAL/bin/sdkman-init.sh"
    
    # Initialize files with available candidate list and currently installted candidates
    _sdkman_get_candidate_list "$@"
    _sdkman_get_current_installed_list "$@"
    

    更多信息可以查看我插件的完整仓库:https://github.com/matthieusb/zsh-sdkman

    如果您有其他更简洁的解决方案,我愿意进行必要的修改,或者毫不犹豫地对项目提出拉取请求。

    【讨论】:

    • 我也不得不在其他情况下使用这种方法,所以我必须在 zsh 插件启动时生成文件。我在别处见过这个(参见 rustup zsh 插件)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 2023-02-15
    • 1970-01-01
    相关资源
    最近更新 更多