diff --git a/command/alias.go b/command/alias.go index 839c8047e..26272d3b0 100644 --- a/command/alias.go +++ b/command/alias.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "sort" "strings" "github.com/cli/cli/utils" @@ -12,6 +13,7 @@ import ( func init() { RootCmd.AddCommand(aliasCmd) aliasCmd.AddCommand(aliasSetCmd) + aliasCmd.AddCommand(aliasListCmd) } var aliasCmd = &cobra.Command{ @@ -112,3 +114,55 @@ func processArgs(args []string) []string { return newArgs } + +var aliasListCmd = &cobra.Command{ + Use: "list", + Short: "List your aliases", + Long: `This command prints out all of the aliases gh is configured to use.`, + Args: cobra.ExactArgs(0), + RunE: aliasList, +} + +func aliasList(cmd *cobra.Command, args []string) error { + ctx := contextForCommand(cmd) + cfg, err := ctx.Config() + if err != nil { + return fmt.Errorf("couldn't read config: %w", err) + } + + aliasCfg, err := cfg.Aliases() + if err != nil { + return fmt.Errorf("couldn't read aliases config: %w", err) + } + + stderr := colorableErr(cmd) + + if aliasCfg.Empty() { + fmt.Fprintf(stderr, "no aliases configured\n") + return nil + } + + stdout := colorableOut(cmd) + + tp := utils.NewTablePrinter(stdout) + + aliasMap := aliasCfg.All() + keys := []string{} + for alias := range aliasMap { + keys = append(keys, alias) + } + sort.Strings(keys) + + for _, alias := range keys { + if tp.IsTTY() { + // ensure that screen readers pause + tp.AddField(alias+":", nil, nil) + } else { + tp.AddField(alias, nil, nil) + } + tp.AddField(aliasMap[alias], nil, nil) + tp.EndRow() + } + + return tp.Render() +} diff --git a/command/alias_test.go b/command/alias_test.go index 666d74589..e8c5f8877 100644 --- a/command/alias_test.go +++ b/command/alias_test.go @@ -241,3 +241,42 @@ func TestAliasSet_invalid_command(t *testing.T) { eq(t, err.Error(), "could not create alias: pe checkout does not correspond to a gh command") } + +func TestAliasList_empty(t *testing.T) { + initBlankContext("", "OWNER/REPO", "trunk") + + output, err := RunCommand("alias list") + + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + eq(t, output.String(), "") +} + +func TestAliasList(t *testing.T) { + cfg := `--- +aliases: + co: pr checkout + il: issue list --author=$1 --label=$2 + clone: repo clone + prs: pr status + cs: config set editor 'quoted path' +` + initBlankContext(cfg, "OWNER/REPO", "trunk") + + output, err := RunCommand("alias list") + + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + expected := `clone repo clone +co pr checkout +cs config set editor 'quoted path' +il issue list --author=$1 --label=$2 +prs pr status +` + + eq(t, output.String(), expected) +} diff --git a/internal/config/alias_config.go b/internal/config/alias_config.go index 434b74f20..979ab3b9a 100644 --- a/internal/config/alias_config.go +++ b/internal/config/alias_config.go @@ -42,3 +42,19 @@ func (a *AliasConfig) Delete(alias string) error { // TODO when we get to gh alias delete return nil } + +func (a *AliasConfig) All() map[string]string { + out := map[string]string{} + + if a.Empty() { + return out + } + + for i := 0; i < len(a.Root.Content)-1; i += 2 { + key := a.Root.Content[i].Value + value := a.Root.Content[i+1].Value + out[key] = value + } + + return out +}