cli / cli

GitHub’s official command line tool
https://cli.github.com
MIT License
37.17k stars 5.76k forks source link

Better completions for repos, issues, PRs, etc. in commands #360

Open eugene-babichenko opened 4 years ago

eugene-babichenko commented 4 years ago

Editing to clarify for people who come upon this issue that:

It would be great to have completions for different shell environments. Not only for commands, but, for example, cycling through open pull request when checking out a PR branch or something like that.

whi-tw commented 4 years ago

You can generate command completion as-is:

gh completion -s fish
gh completion -s zsh
gh completion -s bash

This is standard behaviour when using (recent) spf13/cobra! (This may not actually be true. gh seems to follow the standard form that cobra itself uses, but appears to have been implemented specifically.)

nesl247 commented 4 years ago

It would be much better if these were installed as part of the homebrew installation, same for other systems.

Also, I did try it with fish and it did not work. Apparently the version of gh available in the tap is not updated as I'm only on 0.5.2.

Update: Now that 0.5.4 is available in homebrew it worked.

cbrnr commented 4 years ago

This should already work with Homebrew. When installing I get the following notification:

==> Caveats
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
eugene-babichenko commented 4 years ago

@whi-tw

This is standard behaviour when using (recent) spf13/cobra

I know about them, but those completions work only for subcommands and flags names. What I want is something like git completions, where you can, for example, select files to add to commit from completions. Or select the branch to checkout in the same way. Something more intelligent overall.

whi-tw commented 4 years ago

@eugene-babichenko

I know about them, but those completions work only for subcommands and flags names.

Sure, I misunderstood what you meant by 'Not only for commands' at first: that you were unaware that command completion already existed. I've tried to edit my reply to acknowledge that. Hopefully the discussion helps people when looking for 'standard' completion, and that I haven't diluted the discussion about the other context-aware completions - I agree, git style completions for PRs / branches etc would be really useful!

cmur2 commented 4 years ago

Would it be possible to show the availability of the gh completion subcommand in gh help? I tend to forget the specific syntax and have to search for this issue again then.

AjayKMehta commented 4 years ago

Is there any plan to add support for Powershell to gh completion?

mislav commented 4 years ago

@AjayKMehta https://github.com/cli/cli/pull/591

rsteube commented 4 years ago

asciicast

https://github.com/rsteube/gh

mislav commented 4 years ago

@rsteube That is pretty cool!

rsteube commented 4 years ago

asciicast

added completions for the new commands - still some minor issues but otherwise works pretty well so far

rsteube commented 3 years ago

@mislav got this pretty much working by now. Could either

mislav commented 3 years ago

@rsteube We would be open to contributions around this ❤️ but I wouldn't want to inherit the set of the dependencies that I currently see in your branch. Could this not be achieved with the completion functionality in Cobra?

rsteube commented 3 years ago

@mislav Yes, that's more than there should be (duh). I added chroma/diff just for the tests, a bit annoying that this affects dependent modules. Really needed at the moment should only be spf13/pflag, spf13/cobra and mitchellh/go-ps (to auto-detect current shell). Should be pretty easy to get rid of all those though and have just spf13/pflag and spf13/cobra (almost done).

AFAIK cobra has no support for elvish and xonsh yet and the completion is still a bit limited (like powershell). This is actually initially forked from cobra's completion due to those limitations and has simply grown since.

No worries if a PR is not an option, just wanted at least offer it.

(updated the branch)

rsteube commented 3 years ago

Dependencies are clean now. Rebased and added completion for the new secret command.

joelostblom commented 3 years ago

Just watched the videos. AMAZING! :exploding_head: Thank you so much for developing this functionality for the gh cli @rsteube !

rsteube commented 3 years ago

asciicast

rsteube commented 3 years ago

So anyone following this: i moved the completion to carapace-bin. Not much difference other than that the completion is provided by a separate binary. This simply means that whenever you invoke completion for gh with <TAB> it is executed with the current command line instead of gh (you can try this out by calling it directly carapace gh elvish _ gh issue view '').

Cache is written to {os.TempDir()}/carapace (e.g. /tmp/carapace). Did a couple of tests and so far seems to work alright, but there might be some minor issues with different environments.

So if you want to try it out either grab the release and source the completion for gh:

# bash (~/.bashrc)
source <(carapace gh bash)

# elvish (~/.elvish/rc.elv)
eval (carapace gh elvish|slurp)

# fish (~/.config/fish/config.fish)
mkdir -p ~/.config/fish/completions
carapace --list | awk '{print $1}' | xargs -I{} touch ~/.config/fish/completions/{}.fish # disable auto-loaded completions (https://github.com/rsteube/carapace-bin/issues/185)
carapace gh fish | source

# oil (~/.config/oil/oshrc)
source <(carapace gh oil)

# powershell (~/.config/powershell/Microsoft.PowerShell_profile.ps1)
Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete
carapace gh powershell | Out-String | Invoke-Expression

# xonsh (~/.config/xonsh/rc.xsh)
COMPLETIONS_CONFIRM=True
exec($(carapace gh xonsh))

# zsh (~/.zshrc)
source <(carapace gh zsh)

Or build just the completer for gh:

cd completers/gh_completer
go install --ldflags="-s -w"

# bash (~/.bashrc)
source <(gh_completer _carapace bash)

# elvish (~/.elvish/rc.elv)
eval (gh_completer _carapace elvish|slurp)

# fish (~/.config/fish/config.fish)
mkdir -p ~/.config/fish/completions
touch ~/.config/fish/completions/gh.fish # disable auto-loaded completions (https://github.com/rsteube/carapace-bin/issues/185)
gh_completer _carapace | source

# oil (~/.config/oil/oshrc)
source <(gh_completer _carapace oil)

# powershell (~/.config/powershell/Microsoft.PowerShell_profile.ps1)
Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete
gh_completer _carapace powershell | Out-String | Invoke-Expression

# xonsh (~/.config/xonsh/rc.xsh)
COMPLETIONS_CONFIRM=True
exec($(gh_completer _carapace xonsh))

# zsh (~/.zshrc)
source <(gh_completer _carapace zsh)
JonParton commented 3 years ago

just a note @rsteube; I couldn't get the above to work with fish autocompletions using the method of registering suggested:

# fish (~/.config/fish/config.fish)
gh_completer _carapace | source

instead, I had to put the output in a completion's config file:

# fish
gh_completer _carapace > ~/.config/fish/completions/gh.fish

Hope that might help others if they hit the same problem!

Working fantastically once I got over that hiccup though! 👍🏼👍🏼 Thanks so much for putting all the work into this and it's a shame it won't be part of core! (Although I understand the reluctance from the maintainers!).

rsteube commented 3 years ago

Oh yes @JonParton , that might be because of https://github.com/fish-shell/fish-shell/issues/6716 as system completions (so the one installed by the package) are still being autoloaded even if one is already registered (so it overwrites it at first <TAB>). An empty user completion would prevent it as well but your solution is better anyway as it omits the delay of invoking gh_completer at shell startup:

touch ~/.config/fish/completions/gh.fish
cmoog commented 3 years ago

So isn't this achievable by adding the following to each appropriate command spec

ValidArgsFunction: func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)

For example, the valid args function for gh issue close would return each open issue number. https://github.com/cli/cli/blob/6b49e21295c992f5159384cda4c3dd930bb56d19/pkg/cmd/issue/close/close.go#L35-L35

rsteube commented 3 years ago

@cmoog yes?

mislav commented 3 years ago

@cmoog This is achievable using Cobra like you've outlined, yes. We've started to add some completions to core gh already, e.g. https://github.com/cli/cli/blob/e2973453b5cd77df1b246a6147bbed6b47e4ce1c/cmd/gh/main.go#L168-L169 https://github.com/cli/cli/blob/e2973453b5cd77df1b246a6147bbed6b47e4ce1c/pkg/cmd/repo/create/create.go#L139-L139

However, we are going light on this approach because we don't want too many API-powered completions before we build a good foundation for performing those with proper caching in place. Otherwise the experience of using them is going to be slow and potentially frustrating.

rsteube commented 3 years ago

Anyone here already got access to codespaces and can check if this works?

gh codespace ssh --codespace [name] -- ls -1 -p /

It should output files/folder from the codespace vm (replace [name]).

rsteube commented 2 years ago

@mislav just been working on completer reusage and the same thing should work for you to provide completions for the extensions (at least the go based ones).

Basically you just have to add a subcommand for each extension with flag parsing disabled (probably already being done) like here. Then in the ValidArgsFunction invoke the __complete subcommand of the extension with args and toComplete as arguments similar to this (you can ignore the directive handling as this is not needed for you).

It outputs:

value
value\twithDescription
:4
# empty line

So just return lines[:len(lines)-2] and :4 parsed as integer (ShellCompDirecive) and it might already work.

chmouel commented 1 year ago

Here is a POC using Cobra builtin ValidArgs on zsh (should work as well on bash and any shells cobra completions support) :

https://user-images.githubusercontent.com/98980/203340289-4d81b84f-1896-4579-9615-462afbdf867a.mov

implementation is not ideal (it use gh binary to generate the pr list and title when it could just use graphql directly) but good enough for what we want to do..

let me know what do you think and i can clean this up and submit it...

diff --git a/pkg/cmd/pr/view/view.go b/pkg/cmd/pr/view/view.go
index 10300a23..c896b589 100644
--- a/pkg/cmd/pr/view/view.go
+++ b/pkg/cmd/pr/view/view.go
@@ -2,6 +2,7 @@ package view

 import (
    "fmt"
+   "os/exec"
    "sort"
    "strconv"
    "strings"
@@ -51,6 +52,18 @@ func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Comman
            With '--web', open the pull request in a web browser instead.
        `),
        Args: cobra.MaximumNArgs(1),
+       ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+           if len(args) != 0 {
+               return nil, cobra.ShellCompDirectiveNoFileComp
+           }
+           c := exec.Command("gh", "pr", "list", "--jq", ".[] | ((.number|tostring)+\"\\t\"+.title)",
+               "--json", "number,title")
+           out, err := c.Output()
+           if err != nil {
+               return nil, cobra.ShellCompDirectiveNoFileComp
+           }
+           return strings.Split(string(out), "\n"), cobra.ShellCompDirectiveNoFileComp
+       },
        RunE: func(cmd *cobra.Command, args []string) error {
            opts.Finder = shared.NewFinder(f)
chmouel commented 1 year ago

I thought it would be neat to wrap around the gh binary for generating the completion cobra expect....

here is a shell script adding completion (only for pr and issue the rest is an exercise for the rider) to gh by wrapping around it.

Just save this script in your $PATH before the path of where the real gh binary is and just tab on the issue and pr to get the a completion of the pr and title (as per my video in the above comment) :

#!/usr/bin/env bash
# Copyright 2022 Chmouel Boudjnah <chmouel@chmouel.com>
# will look better on zsh if you set : 
# zstyle ':completion:*:*:gh:*' menu yes select
# to have a nice interactive menu to select the prnumber
set -eufo pipefail
shopt -s extglob

[[ -n ${BASH_COMP_DEBUG_FILE:-""} ]] && echo "$@" >> $BASH_COMP_DEBUG_FILE

ghbins=($(command which -a gh))
ghbin=${ghbins[1]}
[[ -z ${ghbin} ]] && { echo "cannot find real gh bin in path"; exit 1 ;}

get_obj_title() {
    local obj=$1
    exec ${ghbin} $obj list -q '.[] | ((.number|tostring)+"\t"+.title)' --json "number,title"
}

case $@ in
    *__complete\ pr\ +(checks|close|comment|ready|review|status|view|diff|edit|merge|view|checkout)*) get_obj_title pr;;
    *__complete\ issue\ +(comment|view|delete|develop|edit|list|pin|status)*) get_obj_title issue;;
   *) exec ${ghbin} "$@";;
esac