Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
eugene-babichenko opened this issue Feb 12, 2020 · 27 comments
Open

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

eugene-babichenko opened this issue Feb 12, 2020 · 27 comments
Labels
enhancement a request to improve CLI help wanted Contributions welcome

Comments

@eugene-babichenko
Copy link

eugene-babichenko commented Feb 12, 2020

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

  • Shell completion of commands is already supported in gh
  • This issue is about shell completion for particular GitHub objects (for example, easily cycling through possible PRs to checkout or view)

Original issue content:

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
Copy link
Contributor

whi-tw commented Feb 12, 2020

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
Copy link

nesl247 commented Feb 12, 2020

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
Copy link

cbrnr commented Feb 13, 2020

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
Copy link
Author

@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
Copy link
Contributor

whi-tw commented Feb 13, 2020

@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!

@mislav mislav changed the title Completions for bash, zsh, etc Better completions for bash, zsh, etc Feb 20, 2020
@cmur2
Copy link

cmur2 commented Feb 28, 2020

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
Copy link

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

@mislav
Copy link
Contributor

mislav commented Mar 5, 2020

@AjayKMehta #591

@billygriffin billygriffin changed the title Better completions for bash, zsh, etc Better completions for repos, issues, PRs, etc. in commands Apr 20, 2020
@billygriffin billygriffin added the enhancement a request to improve CLI label Apr 20, 2020
@rsteube
Copy link
Contributor

rsteube commented Sep 9, 2020

asciicast

https://github.com/rsteube/gh

@mislav
Copy link
Contributor

mislav commented Sep 14, 2020

@rsteube That is pretty cool!

@vilmibm vilmibm added the core This issue is not accepting PRs from outside contributors label Oct 7, 2020
@rsteube
Copy link
Contributor

rsteube commented Oct 29, 2020

asciicast

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

@rsteube
Copy link
Contributor

rsteube commented Nov 27, 2020

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

  • prepare a PR (diff) if you're interested
    this would introduce a dependency to carapace though (which is still a bit young)
  • migrate it to carapace-bin
    which would provide the completion as external binary (thus no impact on cli/cli, just needs to be kept up to date)

@mislav
Copy link
Contributor

mislav commented Dec 10, 2020

@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?

@mislav mislav added help wanted Contributions welcome and removed core This issue is not accepting PRs from outside contributors labels Dec 10, 2020
@rsteube
Copy link
Contributor

rsteube commented Dec 10, 2020

@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
Copy link
Contributor

rsteube commented Dec 15, 2020

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

@joelostblom
Copy link

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

@rsteube
Copy link
Contributor

rsteube commented May 9, 2021

asciicast

@rsteube
Copy link
Contributor

rsteube commented May 27, 2021

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
Copy link

JonParton commented Aug 13, 2021

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
Copy link
Contributor

rsteube commented Aug 13, 2021

Oh yes @JonParton , that might be because of fish-shell/fish-shell#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
Copy link

cmoog commented Aug 24, 2021

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.

Args: cobra.ExactArgs(1),

@rsteube
Copy link
Contributor

rsteube commented Aug 24, 2021

@cmoog yes?

@mislav
Copy link
Contributor

mislav commented Aug 24, 2021

@cmoog This is achievable using Cobra like you've outlined, yes. We've started to add some completions to core gh already, e.g.

cli/cmd/gh/main.go

Lines 168 to 169 in e297345

// provide completions for aliases and extensions
rootCmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
_ = cmd.RegisterFlagCompletionFunc("gitignore", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {

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
Copy link
Contributor

rsteube commented Oct 27, 2021

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
Copy link
Contributor

rsteube commented Feb 14, 2022

@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
Copy link

chmouel commented Nov 22, 2022

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

recording-20221122-15.23.06.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
Copy link

chmouel commented Nov 22, 2022

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 <[email protected]>
# 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement a request to improve CLI help wanted Contributions welcome
Projects
None yet
Development

Successfully merging a pull request may close this issue.

15 participants