1Password / shell-plugins

Seamless authentication for every tool in your terminal.
https://developer.1password.com/docs/cli/shell-plugins/
MIT License
527 stars 174 forks source link

ZSH completions when using glab plugin #122

Open jmccure opened 1 year ago

jmccure commented 1 year ago

Platform or tool

GitLab

Desired or expected behavior

Hi team, really enjoying the GitLab 1password plugin. https://developer.1password.com/docs/cli/shell-plugins/gitlab

One thing I noticed once I installed the glab shell plugin is that my completions stopped working, since op aliases glab

I had to add setopt completealiases to my ~/.zshrc file so zsh does not expand aliases before performing completion.

I was thinking if it would be worth mentioning here: https://developer.1password.com/docs/cli/shell-plugins/gitlab ?

Current behavior

Completions don't work by default with zsh + op

Relevant log output

No response

op CLI version

2.8.0-beta.10

mrjones2014 commented 1 year ago

Have not tested, but I would guess this is the same for all shells (except maybe Fish, Fish shell is pretty good about doing that kind of stuff by default) and all Shell Plugins.

Maybe plugins.sh should set the correct equivalent of completealiases in all shells, or otherwise mention it somewhere in the docs that applies to all shell plugins.

mrjones2014 commented 1 year ago

Some findings from looking into this a bit:

For these reasons, I think the best approach is to document it, rather than trying to set it automatically, because the plugins.sh file has no shebang line (e.g. #!/usr/bin/env bash) and so it runs in the user's own shell environment. Trying to set it automatically would mean adding some shell detection, in a syntax that is compatible with all of zsh, bash, and fish, which might be complex; fish syntax is mostly compatible with bash/zsh but not fully.

Options for bash completions: \ Disclaimer: I've not validated these, we'll need to audit them before we can officially recommend them. For now, use at your own risk.

jrpedrianes commented 1 year ago

For ZSH we can do the following:

function _glab_command () {
  op plugin run -- glab $@
}

alias glab="_glab_command"
compdef _glab _glab_command

I no tested it yet for glab, but I did it for "doctl" and it works well

aaronkollasch commented 1 year ago

I'd prefer not to setopt completealiases in zsh as that would mess up completions of other aliases that include command line args.

I tried this for gh and while @jrpedrianes solution worked, it asked for authentication on every completion, unless I switched the security settings from "ask approval for each new application and terminal session" to "ask approval for each new application". I think this is because a new subshell is spawned for each function call?

My interim solution has been to update the op completion functions to call _gh directly – see this gist for the changes. In particular, within _op_plugin_run:

  case "$line[1]" in
  gh)
    _gh
    ;;
  esac

This should work for _glab as well. There's probably a better way to make it work for all completions, but I haven't found it yet.


Edit: the general solution for zsh looks to be as simple as replacing the lines above with:

_dispatch "$curcontext" "$line[1]"
Forst commented 1 year ago

@aaronkollasch's solution above works for me for op plugin run glab:

% op plugin run glab #TAB
alias         -- Create, list and delete aliases
api           -- Make an authenticated request to GitLab API
...

However op's aliases default to including the -- separator, e.g. op plugin run -- glab, which doesn't work and autocompletes files/dirs instead:

% op plugin run -- glab #TAB
bin/               Desktop/           Downloads/
...

zsh 5.9. op autogenerates the aliases, I'd prefer not to mess with those manually. Any idea what could be the issue here? Thank you!

aaronkollasch commented 9 months ago

@Forst I finally found the problem – there was an extra -- hanging around before the command in the zsh variable $words.

Adding the following lines before _dispatch "$curcontext" "$line[1]" fixes the issue:

  if [[ "$words[1]" == "--" ]]; then
    shift words
  fi

I've also updated the gist. This should get things to work properly with op's autogenerated aliases, i.e. op plugin run -- glab

mrjones2014 commented 7 months ago

Related: #433

punk-dev-robot commented 5 months ago

The thing that works reliably for me is also monkey patching op completion function with:

function _op_plugin_run_fix() {
    for (( i=2; i < CURRENT; i++ )); do
        if [[ ${words[i]} == -- ]]; then
            shift $i words
            (( CURRENT -= i ))
            _normal
            return
        fi
    done

    # run original op completion
    _op
}

function __load_op_completion() {
  local op_completion_fn="$(op completion zsh)"
  local fix_fn="$(which _op_plugin_run_fix)"

  # replace all references to _op with _op_plugin_run_fix (except for the function definition)
  local patched_op=$(sed -E -e 's/\b_op\b([^()]|$)/_op_plugin_run_fix\1/g' <<< $op_completion_fn)

  echo -e "$patched_op\n\n$fix_fn"
}

eval "$(__load_op_completion)"

The only problem with it is that I need to use eval instead of keeping it on fpath. With fpath the guard in _op on $funcstack means that when loading completion for the first time I have to press <TAB> twice.