From ab4a596f106a1ae124ad065eeabc7527e5263d5e Mon Sep 17 00:00:00 2001 From: rsteube Date: Mon, 7 Sep 2020 00:03:54 +0200 Subject: [PATCH] added git branch subcommand --- completers/git_completer/cmd/action/action.go | 88 +++++++++++++++++ completers/git_completer/cmd/branch.go | 99 +++++++++++++++++++ .../git_completer/cmd/branch_generated.go | 45 --------- 3 files changed, 187 insertions(+), 45 deletions(-) create mode 100644 completers/git_completer/cmd/branch.go delete mode 100644 completers/git_completer/cmd/branch_generated.go diff --git a/completers/git_completer/cmd/action/action.go b/completers/git_completer/cmd/action/action.go index 09868b67b7..e30fff9400 100644 --- a/completers/git_completer/cmd/action/action.go +++ b/completers/git_completer/cmd/action/action.go @@ -27,6 +27,55 @@ func ActionRemotes() carapace.Action { }) } +// TODO combine with ActionRemoteBranches +func ActionLocalBranches() carapace.Action { + return carapace.ActionCallback(func(args []string) carapace.Action { + if output, err := exec.Command("git", "branch", "--format", "%(refname)").Output(); err != nil { + return carapace.ActionMessage(err.Error()) + } else { + refs := make([]string, 0) + for _, line := range strings.Split(string(output), "\n") { + if len(line) > 12 { + refs = append(refs, line[11:]) + } + } + return carapace.ActionValues(refs...) + } + }) +} + +func ActionRemoteBranches() carapace.Action { + return carapace.ActionCallback(func(args []string) carapace.Action { + if output, err := exec.Command("git", "branch", "--remote", "--format", "%(refname)").Output(); err != nil { + return carapace.ActionMessage(err.Error()) + } else { + refs := make([]string, 0) + for _, line := range strings.Split(string(output), "\n") { + if len(line) > 14 { + refs = append(refs, line[13:]) + } + } + return carapace.ActionValues(refs...) + } + }) +} + +func ActionCommits() carapace.Action { + return carapace.ActionCallback(func(args []string) carapace.Action { + if output, err := exec.Command("git", "log", "--pretty=tformat:%H %<(64,trunc)%s", "--all", "--max-count", "1000").Output(); err != nil { + return carapace.ActionMessage(err.Error()) + } else { + refs := make([]string, 0) + for _, line := range strings.Split(string(output), "\n") { + if len(line) > 14 { + refs = append(refs, line[:40], strings.TrimSpace(line[43:])) + } + } + return carapace.ActionValuesDescribed(refs...) + } + }) +} + // TODO multiparts action to complete step by step func ActionUnstagedChanges() carapace.Action { return carapace.ActionCallback(func(args []string) carapace.Action { @@ -55,3 +104,42 @@ func ActionUnstagedChanges() carapace.Action { } }) } + +func ActionFieldNames() carapace.Action { + return carapace.ActionValuesDescribed( + "authordate", "the date component of the author header-field", + "authoremail", "the email component of the author header-field", + "authorname", "the name component of the author header-field", + "author", "the author header-field", + "body", "the body of the message", + "committerdate", "the date component of the committer header-field", + "committeremail", "the email component of the committer header-field", + "committername", "the name component of the committer header-field", + "committer", "the committer header-field", + "contents", "complete message", + "creatordate", "the date component of the creator header-field", + "creator", "the creator header-field", + "deltabase", "object name of the delta base of the object", + "HEAD", "* if HEAD matches ref or space otherwise", + "numparent", "number of parent objects", + "objectname", "object name (SHA-1)", + "objectsize", "the size of the object", + "object", "the object header-field", + "objecttype", "the type of the object", + "parent", "the parent header-field", + "push", "name of a local ref which represents the @{push} location for the displayed ref", + "refname", "name of the ref", + "subject", "the subject of the message", + "symref", "the ref which the given symbolic ref refers to", + "taggerdate", "the date component of the tagger header-field", + "taggeremail", "the email component of the tagger header-field", + "taggername", "the name component of the tagger header-field", + "tagger", "the tagger header-field", + "tag", "the tag header-field", + "trailers", "structured information in commit messages", + "tree", "the tree header-field", + "type", "the type header-field", + "upstream", "name of a local ref which can be considered “upstream” from the displayed ref", + "version:refname", "sort by versions", + ) +} diff --git a/completers/git_completer/cmd/branch.go b/completers/git_completer/cmd/branch.go new file mode 100644 index 0000000000..a828f68c66 --- /dev/null +++ b/completers/git_completer/cmd/branch.go @@ -0,0 +1,99 @@ +package cmd + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/completers/git_completer/cmd/action" + "github.com/spf13/cobra" +) + +var branchCmd = &cobra.Command{ + Use: "branch", + Short: "List, create, or delete branches", + Run: func(cmd *cobra.Command, args []string) {}, +} + +func init() { + carapace.Gen(branchCmd).Standalone() + + branchCmd.Flags().BoolS("D", "D", false, "Shortcut for --delete --force.") + branchCmd.Flags().BoolS("M", "M", false, "Shortcut for --move --force.") + branchCmd.Flags().BoolS("C", "C", false, "Shortcut for --copy --force.") + branchCmd.Flags().String("abbrev", "", "Alter the sha1s minimum display length in the output listing.") + branchCmd.Flags().BoolP("all", "a", false, "List both remote-tracking branches and local branches.") + branchCmd.Flags().String("color", "", "Color branches to highlight current, local, and remote-tracking branches.") + branchCmd.Flags().String("contains", "", "Only list branches which contain the specified commit (HEAD if not specified).") + branchCmd.Flags().BoolP("copy", "c", false, "Copy a branch and the corresponding reflog.") + branchCmd.Flags().Bool("create-reflog", false, "Create the branchs reflog.") + branchCmd.Flags().BoolP("delete", "d", false, "Delete a branch.") + branchCmd.Flags().Bool("edit-description", false, "Open an editor and edit the text to explain what the branch is for.") + branchCmd.Flags().BoolP("force", "f", false, "Reset to , even if exists already.") + branchCmd.Flags().String("format", "", "A string that interpolates %(fieldname) from a branch ref being shown and the object it points at.") + branchCmd.Flags().BoolP("ignore-case", "i", false, "Sorting and filtering branches are case insensitive.") + branchCmd.Flags().BoolP("list", "l", false, "List branches.") + branchCmd.Flags().String("merged", "", "Only list branches whose tips are reachable from the specified commit (HEAD if not specified).") + branchCmd.Flags().BoolP("move", "m", false, "Move/rename a branch and the corresponding reflog.") + branchCmd.Flags().Bool("no-abbrev", false, "Display the full sha1s in the output listing rather than abbreviating them.") + branchCmd.Flags().Bool("no-color", false, "Turn off branch colors, even when the configuration file gives the default to color output.") + branchCmd.Flags().String("no-contains", "", "Only list branches which dont contain the specified commit (HEAD if not specified).") + branchCmd.Flags().String("no-merged", "", "Only list branches whose tips are not reachable from the specified commit (HEAD if not specified).") + branchCmd.Flags().Bool("no-track", false, "Do not set up upstream configuration, even if the branch.autoSetupMerge configuration variable is true.") + branchCmd.Flags().String("points-at", "", "Only list branches of the given object.") + branchCmd.Flags().BoolP("quiet", "q", false, "Be more quiet when creating or deleting a branch, suppressing non-error messages.") + branchCmd.Flags().BoolP("remotes", "r", false, "List or delete (if used with -d) the remote-tracking branches.") + branchCmd.Flags().String("set-upstream-to", "", "Set up s tracking information so is considered s upstream branch.") + branchCmd.Flags().Bool("show-current", false, "Print the name of the current branch.") + branchCmd.Flags().String("sort", "", "Sort based on the key given.") + branchCmd.Flags().BoolP("track", "t", false, "When creating a new branch, set up branch..remote and branch..merge configuration entries to mark the start-point branch as upstream from the new branch.") + branchCmd.Flags().Bool("unset-upstream", false, "Remove the upstream information for .") + rootCmd.AddCommand(branchCmd) + + carapace.Gen(branchCmd).FlagCompletion(carapace.ActionMap{ + "color": carapace.ActionValues("always", "auto", "never"), + "contains": action.ActionCommits(), + "D": action.ActionLocalBranches(), + "delete": action.ActionLocalBranches(), + "merged": action.ActionCommits(), + "no-contains": action.ActionCommits(), + "no-merged": action.ActionCommits(), + "points-at": action.ActionRemoteBranches(), + "set-upstream-to": action.ActionRemoteBranches(), + "sort": action.ActionFieldNames(), + }) + + carapace.Gen(branchCmd).PositionalAnyCompletion( + carapace.ActionCallback(func(args []string) carapace.Action { + switch len(args) { + case 0: + if branchCmd.Flag("set-upstream-to").Changed || + branchCmd.Flag("track").Changed || + branchCmd.Flag("no-track").Changed || + branchCmd.Flag("unset-upstream").Changed || + branchCmd.Flag("M").Changed || + branchCmd.Flag("C").Changed || + branchCmd.Flag("D").Changed || + branchCmd.Flag("move").Changed || + branchCmd.Flag("copy").Changed || + branchCmd.Flag("delete").Changed || + branchCmd.Flag("edit-description").Changed { + return action.ActionLocalBranches() + } + case 1: + if branchCmd.Flag("M").Changed || + branchCmd.Flag("C").Changed || + branchCmd.Flag("D").Changed || + branchCmd.Flag("move").Changed || + branchCmd.Flag("copy").Changed || + branchCmd.Flag("delete").Changed { + return action.ActionLocalBranches() + } + default: + if branchCmd.Flag("D").Changed || + branchCmd.Flag("delete").Changed { + return action.ActionLocalBranches() + } + } + return carapace.ActionValues() + }), + ) + +} diff --git a/completers/git_completer/cmd/branch_generated.go b/completers/git_completer/cmd/branch_generated.go deleted file mode 100644 index 1c05cd4408..0000000000 --- a/completers/git_completer/cmd/branch_generated.go +++ /dev/null @@ -1,45 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -var branchCmd = &cobra.Command{ - Use: "branch", - Short: "List, create, or delete branches", - Run: func(cmd *cobra.Command, args []string) { - }, -} - -func init() { - branchCmd.Flags().BoolP("all", "a", false, "list both remote-tracking and local branches") - branchCmd.Flags().String("abbrev", "", "use digits to display SHA-1s") - branchCmd.Flags().BoolP("C", "C", false, "copy a branch, even if target exists") - branchCmd.Flags().BoolP("copy", "c", false, "copy a branch and its reflog") - branchCmd.Flags().String("color", "", "use colored output") - branchCmd.Flags().String("column", "", "list branches in columns") - branchCmd.Flags().String("contains", "", "print only branches that contain the commit") - branchCmd.Flags().Bool("create-reflog", false, "create the branch's reflog") - branchCmd.Flags().BoolP("D", "D", false, "delete branch (even if not merged)") - branchCmd.Flags().BoolP("delete", "d", false, "delete fully merged branch") - branchCmd.Flags().Bool("edit-description", false, "edit the description for the branch") - branchCmd.Flags().BoolP("force", "f", false, "force creation, move/rename, deletion") - branchCmd.Flags().String("format", "", "format to use for the output") - branchCmd.Flags().BoolP("ignore-case", "i", false, "sorting and filtering are case insensitive") - branchCmd.Flags().BoolP("list", "l", false, "list branch names") - branchCmd.Flags().String("merged", "", "print only branches that are merged") - branchCmd.Flags().BoolP("move", "m", false, "move/rename a branch and its reflog") - branchCmd.Flags().BoolP("M", "M", false, "move/rename a branch, even if target exists") - branchCmd.Flags().String("no-contains", "", "print only branches that don't contain the commit") - branchCmd.Flags().String("no-merged", "", "print only branches that are not merged") - branchCmd.Flags().String("points-at", "", "print only branches of the object") - branchCmd.Flags().BoolP("quiet", "q", false, "suppress informational messages") - branchCmd.Flags().BoolP("remotes", "r", false, "act on remote-tracking branches") - branchCmd.Flags().Bool("show-current", false, "show current branch name") - branchCmd.Flags().String("sort", "", "field name to sort on") - branchCmd.Flags().BoolP("track", "t", false, "set up tracking mode (see git-pull(1))") - branchCmd.Flags().Bool("unset-upstream", false, "unset the upstream info") - branchCmd.Flags().BoolP("set-upstream-to", "u", false, " change the upstream info") - branchCmd.Flags().BoolP("verbose", "v", false, "show hash and subject, give twice for upstream branch") - rootCmd.AddCommand(branchCmd) -}