aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/go.yml2
-rw-r--r--commands/bridge_auth_addtoken.go2
-rw-r--r--commands/bridge_auth_rm.go3
-rw-r--r--commands/bridge_auth_show.go3
-rw-r--r--commands/bridge_configure.go1
-rw-r--r--commands/bridge_pull.go3
-rw-r--r--commands/bridge_push.go3
-rw-r--r--commands/bridge_rm.go3
-rw-r--r--commands/comment.go1
-rw-r--r--commands/comment_add.go1
-rw-r--r--commands/helper_completion.go342
-rw-r--r--commands/label.go1
-rw-r--r--commands/label_add.go1
-rw-r--r--commands/label_rm.go1
-rw-r--r--commands/ls.go34
-rw-r--r--commands/ls_test.go43
-rw-r--r--commands/pull.go1
-rw-r--r--commands/push.go1
-rw-r--r--commands/rm.go1
-rw-r--r--commands/root.go8
-rw-r--r--commands/select.go1
-rw-r--r--commands/show.go6
-rw-r--r--commands/status.go1
-rw-r--r--commands/title.go1
-rw-r--r--commands/title_edit.go1
-rw-r--r--commands/user.go6
-rw-r--r--commands/user_adopt.go1
-rw-r--r--commands/user_ls.go1
-rw-r--r--entity/dag/operation_pack.go2
-rw-r--r--misc/bash_completion/git-bug1569
-rw-r--r--misc/gen_completion.go73
-rw-r--r--util/text/validate.go2
32 files changed, 709 insertions, 1410 deletions
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 21fff7dc..27353e90 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -51,5 +51,5 @@ jobs:
- name: Checkout code
uses: actions/checkout@v2
- - name: Check Code Formation
+ - name: Check Code Formatting
run: find . -name "*.go" | while read line; do [ -z "$(gofmt -d "$line" | head)" ] || exit 1; done
diff --git a/commands/bridge_auth_addtoken.go b/commands/bridge_auth_addtoken.go
index c0458fda..dfdc66b6 100644
--- a/commands/bridge_auth_addtoken.go
+++ b/commands/bridge_auth_addtoken.go
@@ -41,10 +41,12 @@ func newBridgeAuthAddTokenCommand() *cobra.Command {
flags.StringVarP(&options.target, "target", "t", "",
fmt.Sprintf("The target of the bridge. Valid values are [%s]", strings.Join(bridge.Targets(), ",")))
+ cmd.RegisterFlagCompletionFunc("target", completeFrom(bridge.Targets()))
flags.StringVarP(&options.login,
"login", "l", "", "The login in the remote bug-tracker")
flags.StringVarP(&options.user,
"user", "u", "", "The user to add the token to. Default is the current user")
+ cmd.RegisterFlagCompletionFunc("user", completeUser(env))
return cmd
}
diff --git a/commands/bridge_auth_rm.go b/commands/bridge_auth_rm.go
index fa73ad11..a28057de 100644
--- a/commands/bridge_auth_rm.go
+++ b/commands/bridge_auth_rm.go
@@ -16,7 +16,8 @@ func newBridgeAuthRm() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
return runBridgeAuthRm(env, args)
},
- Args: cobra.ExactArgs(1),
+ Args: cobra.ExactArgs(1),
+ ValidArgsFunction: completeBridgeAuth(env),
}
return cmd
diff --git a/commands/bridge_auth_show.go b/commands/bridge_auth_show.go
index f174cdb7..7233bb51 100644
--- a/commands/bridge_auth_show.go
+++ b/commands/bridge_auth_show.go
@@ -21,7 +21,8 @@ func newBridgeAuthShow() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runBridgeAuthShow(env, args)
}),
- Args: cobra.ExactArgs(1),
+ Args: cobra.ExactArgs(1),
+ ValidArgsFunction: completeBridgeAuth(env),
}
return cmd
diff --git a/commands/bridge_configure.go b/commands/bridge_configure.go
index 6533e497..bbfc13be 100644
--- a/commands/bridge_configure.go
+++ b/commands/bridge_configure.go
@@ -97,6 +97,7 @@ git bug bridge configure \
flags.StringVarP(&options.name, "name", "n", "", "A distinctive name to identify the bridge")
flags.StringVarP(&options.target, "target", "t", "",
fmt.Sprintf("The target of the bridge. Valid values are [%s]", strings.Join(bridge.Targets(), ",")))
+ cmd.RegisterFlagCompletionFunc("target", completeFrom(bridge.Targets()))
flags.StringVarP(&options.params.URL, "url", "u", "", "The URL of the remote repository")
flags.StringVarP(&options.params.BaseURL, "base-url", "b", "", "The base URL of your remote issue tracker")
flags.StringVarP(&options.params.Login, "login", "l", "", "The login on your remote issue tracker")
diff --git a/commands/bridge_pull.go b/commands/bridge_pull.go
index 3155ebf4..9370e088 100644
--- a/commands/bridge_pull.go
+++ b/commands/bridge_pull.go
@@ -32,7 +32,8 @@ func newBridgePullCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runBridgePull(env, options, args)
}),
- Args: cobra.MaximumNArgs(1),
+ Args: cobra.MaximumNArgs(1),
+ ValidArgsFunction: completeBridge(env),
}
flags := cmd.Flags()
diff --git a/commands/bridge_push.go b/commands/bridge_push.go
index a232f0f0..ef1f2d3e 100644
--- a/commands/bridge_push.go
+++ b/commands/bridge_push.go
@@ -23,7 +23,8 @@ func newBridgePushCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runBridgePush(env, args)
}),
- Args: cobra.MaximumNArgs(1),
+ Args: cobra.MaximumNArgs(1),
+ ValidArgsFunction: completeBridge(env),
}
return cmd
diff --git a/commands/bridge_rm.go b/commands/bridge_rm.go
index 121a35ad..0306944e 100644
--- a/commands/bridge_rm.go
+++ b/commands/bridge_rm.go
@@ -16,7 +16,8 @@ func newBridgeRm() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runBridgeRm(env, args)
}),
- Args: cobra.ExactArgs(1),
+ Args: cobra.ExactArgs(1),
+ ValidArgsFunction: completeBridge(env),
}
return cmd
diff --git a/commands/comment.go b/commands/comment.go
index 90657e4a..b4b4628b 100644
--- a/commands/comment.go
+++ b/commands/comment.go
@@ -18,6 +18,7 @@ func newCommentCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runComment(env, args)
}),
+ ValidArgsFunction: completeBug(env),
}
cmd.AddCommand(newCommentAddCommand())
diff --git a/commands/comment_add.go b/commands/comment_add.go
index 11ba5ad3..f308428c 100644
--- a/commands/comment_add.go
+++ b/commands/comment_add.go
@@ -25,6 +25,7 @@ func newCommentAddCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runCommentAdd(env, options, args)
}),
+ ValidArgsFunction: completeBug(env),
}
flags := cmd.Flags()
diff --git a/commands/helper_completion.go b/commands/helper_completion.go
new file mode 100644
index 00000000..3a089e35
--- /dev/null
+++ b/commands/helper_completion.go
@@ -0,0 +1,342 @@
+package commands
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "github.com/spf13/cobra"
+
+ "github.com/MichaelMure/git-bug/bridge"
+ "github.com/MichaelMure/git-bug/bridge/core/auth"
+ "github.com/MichaelMure/git-bug/bug"
+ "github.com/MichaelMure/git-bug/cache"
+ _select "github.com/MichaelMure/git-bug/commands/select"
+)
+
+type validArgsFunction func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective)
+
+func completionHandlerError(err error) (completions []string, directives cobra.ShellCompDirective) {
+ return nil, cobra.ShellCompDirectiveError
+}
+
+func completeBridge(env *Env) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+
+ bridges, err := bridge.ConfiguredBridges(env.backend)
+ if err != nil {
+ return completionHandlerError(err)
+ }
+
+ completions = make([]string, len(bridges))
+ for i, bridge := range bridges {
+ completions[i] = bridge + "\t" + "Bridge"
+ }
+
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+}
+
+func completeBridgeAuth(env *Env) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+
+ creds, err := auth.List(env.backend)
+ if err != nil {
+ return completionHandlerError(err)
+ }
+
+ completions = make([]string, len(creds))
+ for i, cred := range creds {
+ meta := make([]string, 0, len(cred.Metadata()))
+ for k, v := range cred.Metadata() {
+ meta = append(meta, k+":"+v)
+ }
+ sort.Strings(meta)
+ metaFmt := strings.Join(meta, ",")
+
+ completions[i] = cred.ID().Human() + "\t" + cred.Target() + " " + string(cred.Kind()) + " " + metaFmt
+ }
+
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+}
+
+func completeBug(env *Env) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+
+ return completeBugWithBackend(env.backend, toComplete)
+ }
+}
+
+func completeBugWithBackend(backend *cache.RepoCache, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ allIds := backend.AllBugsIds()
+ bugExcerpt := make([]*cache.BugExcerpt, len(allIds))
+ for i, id := range allIds {
+ var err error
+ bugExcerpt[i], err = backend.ResolveBugExcerpt(id)
+ if err != nil {
+ return completionHandlerError(err)
+ }
+ }
+
+ for i, id := range allIds {
+ if strings.Contains(id.String(), strings.TrimSpace(toComplete)) {
+ completions = append(completions, id.Human()+"\t"+bugExcerpt[i].Title)
+ }
+ }
+
+ return completions, cobra.ShellCompDirectiveNoFileComp
+}
+
+func completeBugAndLabels(env *Env, addOrRemove bool) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+
+ b, args, err := _select.ResolveBug(env.backend, args)
+ if err == _select.ErrNoValidId {
+ // we need a bug first to complete labels
+ return completeBugWithBackend(env.backend, toComplete)
+ }
+ if err != nil {
+ return completionHandlerError(err)
+ }
+
+ snap := b.Snapshot()
+
+ seenLabels := map[bug.Label]bool{}
+ for _, label := range args {
+ seenLabels[bug.Label(label)] = addOrRemove
+ }
+
+ var labels []bug.Label
+ if addOrRemove {
+ for _, label := range snap.Labels {
+ seenLabels[label] = true
+ }
+
+ allLabels := env.backend.ValidLabels()
+ labels = make([]bug.Label, 0, len(allLabels))
+ for _, label := range allLabels {
+ if !seenLabels[label] {
+ labels = append(labels, label)
+ }
+ }
+ } else {
+ labels = make([]bug.Label, 0, len(snap.Labels))
+ for _, label := range snap.Labels {
+ if seenLabels[label] {
+ labels = append(labels, label)
+ }
+ }
+ }
+
+ completions = make([]string, len(labels))
+ for i, label := range labels {
+ completions[i] = string(label) + "\t" + "Label"
+ }
+
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+}
+
+func completeFrom(choices []string) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+ return choices, cobra.ShellCompDirectiveNoFileComp
+ }
+}
+
+func completeGitRemote(env *Env) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+
+ remoteMap, err := env.backend.GetRemotes()
+ if err != nil {
+ return completionHandlerError(err)
+ }
+ completions = make([]string, 0, len(remoteMap))
+ for remote, url := range remoteMap {
+ completions = append(completions, remote+"\t"+"Remote: "+url)
+ }
+ sort.Strings(completions)
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+}
+
+func completeLabel(env *Env) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+
+ labels := env.backend.ValidLabels()
+ completions = make([]string, len(labels))
+ for i, label := range labels {
+ if strings.Contains(label.String(), " ") {
+ completions[i] = fmt.Sprintf("\"%s\"\tLabel", label.String())
+ } else {
+ completions[i] = fmt.Sprintf("%s\tLabel", label.String())
+ }
+ }
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+}
+
+func completeLs(env *Env) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if strings.HasPrefix(toComplete, "status:") {
+ completions = append(completions, "status:open\tOpen bugs")
+ completions = append(completions, "status:closed\tClosed bugs")
+ return completions, cobra.ShellCompDirectiveDefault
+ }
+
+ byPerson := []string{"author:", "participant:", "actor:"}
+ byLabel := []string{"label:", "no:"}
+ needBackend := false
+ for _, key := range append(byPerson, byLabel...) {
+ if strings.HasPrefix(toComplete, key) {
+ needBackend = true
+ }
+ }
+
+ if needBackend {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+ }
+
+ for _, key := range byPerson {
+ if !strings.HasPrefix(toComplete, key) {
+ continue
+ }
+ ids := env.backend.AllIdentityIds()
+ completions = make([]string, len(ids))
+ for i, id := range ids {
+ user, err := env.backend.ResolveIdentityExcerpt(id)
+ if err != nil {
+ return completionHandlerError(err)
+ }
+ var handle string
+ if user.Login != "" {
+ handle = user.Login
+ } else {
+ // "author:John Doe" does not work yet, so use the first name.
+ handle = strings.Split(user.Name, " ")[0]
+ }
+ completions[i] = key + handle + "\t" + user.DisplayName()
+ }
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+
+ for _, key := range byLabel {
+ if !strings.HasPrefix(toComplete, key) {
+ continue
+ }
+ labels := env.backend.ValidLabels()
+ completions = make([]string, len(labels))
+ for i, label := range labels {
+ if strings.Contains(label.String(), " ") {
+ completions[i] = key + "\"" + string(label) + "\""
+ } else {
+ completions[i] = key + string(label)
+ }
+ }
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+
+ completions = []string{
+ "actor:\tFilter by actor",
+ "author:\tFilter by author",
+ "label:\tFilter by label",
+ "no:\tExclude bugs by label",
+ "participant:\tFilter by participant",
+ "status:\tFilter by open/close status",
+ "title:\tFilter by title",
+ }
+ return completions, cobra.ShellCompDirectiveNoSpace
+ }
+}
+
+func completeUser(env *Env) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+
+ ids := env.backend.AllIdentityIds()
+ completions = make([]string, len(ids))
+ for i, id := range ids {
+ user, err := env.backend.ResolveIdentityExcerpt(id)
+ if err != nil {
+ return completionHandlerError(err)
+ }
+ completions[i] = user.Id.Human() + "\t" + user.DisplayName()
+ }
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+}
+
+func completeUserForQuery(env *Env) validArgsFunction {
+ return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
+ if err := loadBackend(env)(cmd, args); err != nil {
+ return completionHandlerError(err)
+ }
+ defer func() {
+ _ = env.backend.Close()
+ }()
+
+ ids := env.backend.AllIdentityIds()
+ completions = make([]string, len(ids))
+ for i, id := range ids {
+ user, err := env.backend.ResolveIdentityExcerpt(id)
+ if err != nil {
+ return completionHandlerError(err)
+ }
+ var handle string
+ if user.Login != "" {
+ handle = user.Login
+ } else {
+ // "author:John Doe" does not work yet, so use the first name.
+ handle = strings.Split(user.Name, " ")[0]
+ }
+ completions[i] = handle + "\t" + user.DisplayName()
+ }
+ return completions, cobra.ShellCompDirectiveNoFileComp
+ }
+}
diff --git a/commands/label.go b/commands/label.go
index d108b089..906974a5 100644
--- a/commands/label.go
+++ b/commands/label.go
@@ -16,6 +16,7 @@ func newLabelCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runLabel(env, args)
}),
+ ValidArgsFunction: completeBug(env),
}
cmd.AddCommand(newLabelAddCommand())
diff --git a/commands/label_add.go b/commands/label_add.go
index c60ecfeb..65439a4a 100644
--- a/commands/label_add.go
+++ b/commands/label_add.go
@@ -17,6 +17,7 @@ func newLabelAddCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runLabelAdd(env, args)
}),
+ ValidArgsFunction: completeBugAndLabels(env, true),
}
return cmd
diff --git a/commands/label_rm.go b/commands/label_rm.go
index 1cdcd248..3f4e1958 100644
--- a/commands/label_rm.go
+++ b/commands/label_rm.go
@@ -17,6 +17,7 @@ func newLabelRmCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runLabelRm(env, args)
}),
+ ValidArgsFunction: completeBugAndLabels(env, false),
}
return cmd
diff --git a/commands/ls.go b/commands/ls.go
index db4145d0..da5ea8ce 100644
--- a/commands/ls.go
+++ b/commands/ls.go
@@ -56,6 +56,7 @@ git bug ls status:open --by creation "foo bar" baz
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runLs(env, options, args)
}),
+ ValidArgsFunction: completeLs(env),
}
flags := cmd.Flags()
@@ -63,26 +64,36 @@ git bug ls status:open --by creation "foo bar" baz
flags.StringSliceVarP(&options.statusQuery, "status", "s", nil,
"Filter by status. Valid values are [open,closed]")
+ cmd.RegisterFlagCompletionFunc("status", completeFrom([]string{"open", "closed"}))
flags.StringSliceVarP(&options.authorQuery, "author", "a", nil,
"Filter by author")
flags.StringSliceVarP(&options.metadataQuery, "metadata", "m", nil,
"Filter by metadata. Example: github-url=URL")
+ cmd.RegisterFlagCompletionFunc("author", completeUserForQuery(env))
flags.StringSliceVarP(&options.participantQuery, "participant", "p", nil,
"Filter by participant")
+ cmd.RegisterFlagCompletionFunc("participant", completeUserForQuery(env))
flags.StringSliceVarP(&options.actorQuery, "actor", "A", nil,
"Filter by actor")
+ cmd.RegisterFlagCompletionFunc("actor", completeUserForQuery(env))
flags.StringSliceVarP(&options.labelQuery, "label", "l", nil,
"Filter by label")
+ cmd.RegisterFlagCompletionFunc("label", completeLabel(env))
flags.StringSliceVarP(&options.titleQuery, "title", "t", nil,
"Filter by title")
flags.StringSliceVarP(&options.noQuery, "no", "n", nil,
"Filter by absence of something. Valid values are [label]")
+ cmd.RegisterFlagCompletionFunc("no", completeLabel(env))
flags.StringVarP(&options.sortBy, "by", "b", "creation",
"Sort the results by a characteristic. Valid values are [id,creation,edit]")
+ cmd.RegisterFlagCompletionFunc("by", completeFrom([]string{"id", "creation", "edit"}))
flags.StringVarP(&options.sortDirection, "direction", "d", "asc",
"Select the sorting direction. Valid values are [asc,desc]")
+ cmd.RegisterFlagCompletionFunc("direction", completeFrom([]string{"asc", "desc"}))
flags.StringVarP(&options.outputFormat, "format", "f", "default",
"Select the output formatting style. Valid values are [default,plain,json,org-mode]")
+ cmd.RegisterFlagCompletionFunc("format",
+ completeFrom([]string{"default", "plain", "json", "org-mode"}))
return cmd
}
@@ -92,13 +103,9 @@ func runLs(env *Env, opts lsOptions, args []string) error {
var err error
if len(args) >= 1 {
- // either the shell or cobra remove the quotes, we need them back for the parsing
- for i, arg := range args {
- if strings.Contains(arg, " ") {
- args[i] = fmt.Sprintf("\"%s\"", arg)
- }
- }
- assembled := strings.Join(args, " ")
+ // either the shell or cobra remove the quotes, we need them back for the query parsing
+ assembled := repairQuery(args)
+
q, err = query.Parse(assembled)
if err != nil {
return err
@@ -142,6 +149,19 @@ func runLs(env *Env, opts lsOptions, args []string) error {
}
}
+func repairQuery(args []string) string {
+ for i, arg := range args {
+ split := strings.Split(arg, ":")
+ for j, s := range split {
+ if strings.Contains(s, " ") {
+ split[j] = fmt.Sprintf("\"%s\"", s)
+ }
+ }
+ args[i] = strings.Join(split, ":")
+ }
+ return strings.Join(args, " ")
+}
+
type JSONBugExcerpt struct {
Id string `json:"id"`
HumanId string `json:"human_id"`
diff --git a/commands/ls_test.go b/commands/ls_test.go
new file mode 100644
index 00000000..aff94e03
--- /dev/null
+++ b/commands/ls_test.go
@@ -0,0 +1,43 @@
+package commands
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func Test_repairQuery(t *testing.T) {
+ cases := []struct {
+ args []string
+ output string
+ }{
+ {
+ []string{""},
+ "",
+ },
+ {
+ []string{"foo"},
+ "foo",
+ },
+ {
+ []string{"foo", "bar"},
+ "foo bar",
+ },
+ {
+ []string{"foo bar", "baz"},
+ "\"foo bar\" baz",
+ },
+ {
+ []string{"foo:bar", "baz"},
+ "foo:bar baz",
+ },
+ {
+ []string{"foo:bar boo", "baz"},
+ "foo:\"bar boo\" baz",
+ },
+ }
+
+ for _, tc := range cases {
+ require.Equal(t, tc.output, repairQuery(tc.args))
+ }
+}
diff --git a/commands/pull.go b/commands/pull.go
index f3a31414..29c9f034 100644
--- a/commands/pull.go
+++ b/commands/pull.go
@@ -18,6 +18,7 @@ func newPullCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runPull(env, args)
}),
+ ValidArgsFunction: completeGitRemote(env),
}
return cmd
diff --git a/commands/push.go b/commands/push.go
index 9d6ca7df..adba6bef 100644
--- a/commands/push.go
+++ b/commands/push.go
@@ -16,6 +16,7 @@ func newPushCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runPush(env, args)
}),
+ ValidArgsFunction: completeGitRemote(env),
}
return cmd
diff --git a/commands/rm.go b/commands/rm.go
index 8205c128..2e1d924d 100644
--- a/commands/rm.go
+++ b/commands/rm.go
@@ -17,6 +17,7 @@ func newRmCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runRm(env, args)
}),
+ ValidArgsFunction: completeBug(env),
}
flags := cmd.Flags()
diff --git a/commands/root.go b/commands/root.go
index e7848363..e012bd83 100644
--- a/commands/root.go
+++ b/commands/root.go
@@ -50,14 +50,6 @@ the same git remote you are already using to collaborate with other people.
SilenceUsage: true,
DisableAutoGenTag: true,
-
- // Custom bash code to connect the git completion for "git bug" to the
- // git-bug completion for "git-bug"
- BashCompletionFunction: `
-_git_bug() {
- __start_git-bug "$@"
-}
-`,
}
cmd.AddCommand(newAddCommand())
diff --git a/commands/select.go b/commands/select.go
index 34d00a32..f9e6ece7 100644
--- a/commands/select.go
+++ b/commands/select.go
@@ -31,6 +31,7 @@ The complementary command is "git bug deselect" performing the opposite operatio
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runSelect(env, args)
}),
+ ValidArgsFunction: completeBug(env),
}
return cmd
diff --git a/commands/show.go b/commands/show.go
index 55140357..16747214 100644
--- a/commands/show.go
+++ b/commands/show.go
@@ -29,13 +29,17 @@ func newShowCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runShow(env, options, args)
}),
+ ValidArgsFunction: completeBug(env),
}
flags := cmd.Flags()
flags.SortFlags = false
+ fields := []string{"author", "authorEmail", "createTime", "lastEdit", "humanId",
+ "id", "labels", "shortId", "status", "title", "actors", "participants"}
flags.StringVarP(&options.fields, "field", "", "",
- "Select field to display. Valid values are [author,authorEmail,createTime,lastEdit,humanId,id,labels,shortId,status,title,actors,participants]")
+ "Select field to display. Valid values are ["+strings.Join(fields, ",")+"]")
+ cmd.RegisterFlagCompletionFunc("by", completeFrom(fields))
flags.StringVarP(&options.format, "format", "f", "default",
"Select the output formatting style. Valid values are [default,json,org-mode]")
diff --git a/commands/status.go b/commands/status.go
index c1e45c5f..c3e860b6 100644
--- a/commands/status.go
+++ b/commands/status.go
@@ -15,6 +15,7 @@ func newStatusCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runStatus(env, args)
}),
+ ValidArgsFunction: completeBug(env),
}
cmd.AddCommand(newStatusCloseCommand())
diff --git a/commands/title.go b/commands/title.go
index c4293530..f99c6eff 100644
--- a/commands/title.go
+++ b/commands/title.go
@@ -15,6 +15,7 @@ func newTitleCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runTitle(env, args)
}),
+ ValidArgsFunction: completeBug(env),
}
cmd.AddCommand(newTitleEditCommand())
diff --git a/commands/title_edit.go b/commands/title_edit.go
index 810c5e62..a9e7fe4b 100644
--- a/commands/title_edit.go
+++ b/commands/title_edit.go
@@ -24,6 +24,7 @@ func newTitleEditCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runTitleEdit(env, options, args)
}),
+ ValidArgsFunction: completeBug(env),
}
flags := cmd.Flags()
diff --git a/commands/user.go b/commands/user.go
index b6a2e485..0fe3be4d 100644
--- a/commands/user.go
+++ b/commands/user.go
@@ -3,6 +3,7 @@ package commands
import (
"errors"
"fmt"
+ "strings"
"github.com/spf13/cobra"
@@ -24,6 +25,7 @@ func newUserCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runUser(env, options, args)
}),
+ ValidArgsFunction: completeUser(env),
}
cmd.AddCommand(newUserAdoptCommand())
@@ -33,8 +35,10 @@ func newUserCommand() *cobra.Command {
flags := cmd.Flags()
flags.SortFlags = false
+ fields := []string{"email", "humanId", "id", "lastModification", "lastModificationLamports", "login", "metadata", "name"}
flags.StringVarP(&options.fields, "field", "f", "",
- "Select field to display. Valid values are [email,humanId,id,lastModification,lastModificationLamports,login,metadata,name]")
+ "Select field to display. Valid values are ["+strings.Join(fields, ",")+"]")
+ cmd.RegisterFlagCompletionFunc("field", completeFrom(fields))
return cmd
}
diff --git a/commands/user_adopt.go b/commands/user_adopt.go
index 166063ae..afef94ea 100644
--- a/commands/user_adopt.go
+++ b/commands/user_adopt.go
@@ -15,6 +15,7 @@ func newUserAdoptCommand() *cobra.Command {
RunE: closeBackend(env, func(cmd *cobra.Command, args []string) error {
return runUserAdopt(env, args)
}),
+ ValidArgsFunction: completeUser(env),
}
return cmd
diff --git a/commands/user_ls.go b/commands/user_ls.go
index 98800b87..341f0dc1 100644
--- a/commands/user_ls.go
+++ b/commands/user_ls.go
@@ -32,6 +32,7 @@ func newUserLsCommand() *cobra.Command {
flags.StringVarP(&options.format, "format", "f", "default",
"Select the output formatting style. Valid values are [default,json]")
+ cmd.RegisterFlagCompletionFunc("format", completeFrom([]string{"default", "json"}))
return cmd
}
diff --git a/entity/dag/operation_pack.go b/entity/dag/operation_pack.go
index 8ca2ff56..9b42f9bf 100644
--- a/entity/dag/operation_pack.go
+++ b/entity/dag/operation_pack.go
@@ -359,5 +359,5 @@ func (pk PGPKeyring) DecryptionKeys() []openpgp.Key {
// }
// }
// return result
- return nil
+ panic("not implemented")
}
diff --git a/misc/bash_completion/git-bug b/misc/bash_completion/git-bug
index 2320c1c0..85d2a15b 100644
--- a/misc/bash_completion/git-bug
+++ b/misc/bash_completion/git-bug
@@ -1,4 +1,4 @@
-# bash completion for git-bug -*- shell-script -*-
+# bash completion V2 for git-bug -*- shell-script -*-
__git-bug_debug()
{
@@ -7,64 +7,43 @@ __git-bug_debug()
fi
}
-# Homebrew on Macs have version 1.3 of bash-completion which doesn't include
-# _init_completion. This is a very minimal version of that function.
+# Macs have bash3 for which the bash-completion package doesn't include
+# _init_completion. This is a minimal version of that function.
__git-bug_init_completion()
{
COMPREPLY=()
_get_comp_words_by_ref "$@" cur prev words cword
}
-__git-bug_index_of_word()
-{
- local w word=$1
- shift
- index=0
- for w in "$@"; do
- [[ $w = "$word" ]] && return
- index=$((index+1))
- done
- index=-1
-}
-
-__git-bug_contains_word()
-{
- local w word=$1; shift
- for w in "$@"; do
- [[ $w = "$word" ]] && return
- done
- return 1
-}
-
-__git-bug_handle_go_custom_completion()
-{
- __git-bug_debug "${FUNCNAME[0]}: cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}"
-
- local shellCompDirectiveError=1
- local shellCompDirectiveNoSpace=2
- local shellCompDirectiveNoFileComp=4
- local shellCompDirectiveFilterFileExt=8
- local shellCompDirectiveFilterDirs=16
-
- local out requestComp lastParam lastChar comp directive args
+# This function calls the git-bug program to obtain the completion
+# results and the directive. It fills the 'out' and 'directive' vars.
+__git-bug_get_completion_results() {
+ local requestComp lastParam lastChar args
# Prepare the command to request completions for the program.
# Calling ${words[0]} instead of directly git-bug allows to handle aliases
args=("${words[@]:1}")
- requestComp="${words[0]} __completeNoDesc ${args[*]}"
+ requestComp="${words[0]} __complete ${args[*]}"
lastParam=${words[$((${#words[@]}-1))]}
lastChar=${lastParam:$((${#lastParam}-1)):1}
- __git-bug_debug "${FUNCNAME[0]}: lastParam ${lastParam}, lastChar ${lastChar}"
+ __git-bug_debug "lastParam ${lastParam}, lastChar ${lastChar}"
if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
# If the last parameter is complete (there is a space following it)
# We add an extra empty parameter so we can indicate this to the go method.
- __git-bug_debug "${FUNCNAME[0]}: Adding extra empty parameter"
- requestComp="${requestComp} \"\""
+ __git-bug_debug "Adding extra empty parameter"
+ requestComp="${requestComp} ''"
fi
- __git-bug_debug "${FUNCNAME[0]}: calling ${requestComp}"
+ # When completing a flag with an = (e.g., git-bug -n=<TAB>)
+ # bash focuses on the part after the =, so we need to remove
+ # the flag part from $cur
+ if [[ "${cur}" == -*=* ]]; then
+ cur="${cur#*=}"
+ fi
+
+ __git-bug_debug "Calling ${requestComp}"
# Use eval to handle any environment variables and such
out=$(eval "${requestComp}" 2>/dev/null)
@@ -76,24 +55,36 @@ __git-bug_handle_go_custom_completion()
# There is not directive specified
directive=0
fi
- __git-bug_debug "${FUNCNAME[0]}: the completion directive is: ${directive}"
- __git-bug_debug "${FUNCNAME[0]}: the completions are: ${out[*]}"
+ __git-bug_debug "The completion directive is: ${directive}"
+ __git-bug_debug "The completions are: ${out[*]}"
+}
+
+__git-bug_process_completion_results() {
+ local shellCompDirectiveError=1
+ local shellCompDirectiveNoSpace=2
+ local shellCompDirectiveNoFileComp=4
+ local shellCompDirectiveFilterFileExt=8
+ local shellCompDirectiveFilterDirs=16
if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
# Error code. No completion.
- __git-bug_debug "${FUNCNAME[0]}: received error from custom completion go code"
+ __git-bug_debug "Received error from custom completion go code"
return
else
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
if [[ $(type -t compopt) = "builtin" ]]; then
- __git-bug_debug "${FUNCNAME[0]}: activating no space"
+ __git-bug_debug "Activating no space"
compopt -o nospace
+ else
+ __git-bug_debug "No space directive not supported in this version of bash"
fi
fi
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
if [[ $(type -t compopt) = "builtin" ]]; then
- __git-bug_debug "${FUNCNAME[0]}: activating no file completion"
+ __git-bug_debug "Activating no file completion"
compopt +o default
+ else
+ __git-bug_debug "No file completion directive not supported in this version of bash"
fi
fi
fi
@@ -101,6 +92,7 @@ __git-bug_handle_go_custom_completion()
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
# File extension filtering
local fullFilter filter filteringCmd
+
# Do not use quotes around the $out variable or else newline
# characters will be kept.
for filter in ${out[*]}; do
@@ -112,1400 +104,219 @@ __git-bug_handle_go_custom_completion()
$filteringCmd
elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
# File completion for directories only
- local subdir
+
# Use printf to strip any trailing newline
+ local subdir
subdir=$(printf "%s" "${out[0]}")
if [ -n "$subdir" ]; then
__git-bug_debug "Listing directories in $subdir"
- __git-bug_handle_subdirs_in_dir_flag "$subdir"
+ pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
else
__git-bug_debug "Listing directories in ."
_filedir -d
fi
else
- while IFS='' read -r comp; do
- COMPREPLY+=("$comp")
- done < <(compgen -W "${out[*]}" -- "$cur")
+ __git-bug_handle_completion_types
fi
+
+ __git-bug_handle_special_char "$cur" :
+ __git-bug_handle_special_char "$cur" =
}
-__git-bug_handle_reply()
-{
- __git-bug_debug "${FUNCNAME[0]}"
- local comp
- case $cur in
- -*)
- if [[ $(type -t compopt) = "builtin" ]]; then
- compopt -o nospace
- fi
- local allflags
- if [ ${#must_have_one_flag[@]} -ne 0 ]; then
- allflags=("${must_have_one_flag[@]}")
- else
- allflags=("${flags[*]} ${two_word_flags[*]}")
- fi
- while IFS='' read -r comp; do
+__git-bug_handle_completion_types() {
+ __git-bug_debug "__git-bug_handle_completion_types: COMP_TYPE is $COMP_TYPE"
+
+ case $COMP_TYPE in
+ 37|42)
+ # Type: menu-complete/menu-complete-backward and insert-completions
+ # If the user requested inserting one completion at a time, or all
+ # completions at once on the command-line we must remove the descriptions.
+ # https://github.com/spf13/cobra/issues/1508
+ local tab comp
+ tab=$(printf '\t')
+ while IFS='' read -r comp; do
+ # Strip any description
+ comp=${comp%%$tab*}
+ # Only consider the completions that match
+ comp=$(compgen -W "$comp" -- "$cur")
+ if [ -n "$comp" ]; then
COMPREPLY+=("$comp")
- done < <(compgen -W "${allflags[*]}" -- "$cur")
- if [[ $(type -t compopt) = "builtin" ]]; then
- [[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace
fi
+ done < <(printf "%s\n" "${out[@]}")
+ ;;
- # complete after --flag=abc
- if [[ $cur == *=* ]]; then
- if [[ $(type -t compopt) = "builtin" ]]; then
- compopt +o nospace
- fi
+ *)
+ # Type: complete (normal completion)
+ __git-bug_handle_standard_completion_case
+ ;;
+ esac
+}
- local index flag
- flag="${cur%=*}"
- __git-bug_index_of_word "${flag}" "${flags_with_completion[@]}"
- COMPREPLY=()
- if [[ ${index} -ge 0 ]]; then
- PREFIX=""
- cur="${cur#*=}"
- ${flags_completion[${index}]}
- if [ -n "${ZSH_VERSION:-}" ]; then
- # zsh completion needs --flag= prefix
- eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
- fi
- fi
- fi
+__git-bug_handle_standard_completion_case() {
+ local tab comp
+ tab=$(printf '\t')
- if [[ -z "${flag_parsing_disabled}" ]]; then
- # If flag parsing is enabled, we have completed the flags and can return.
- # If flag parsing is disabled, we may not know all (or any) of the flags, so we fallthrough
- # to possibly call handle_go_custom_completion.
- return 0;
- fi
- ;;
- esac
+ local longest=0
+ # Look for the longest completion so that we can format things nicely
+ while IFS='' read -r comp; do
+ # Strip any description before checking the length
+ comp=${comp%%$tab*}
+ # Only consider the completions that match
+ comp=$(compgen -W "$comp" -- "$cur")
+ if ((${#comp}>longest)); then
+ longest=${#comp}
+ fi
+ done < <(printf "%s\n" "${out[@]}")
- # check if we are handling a flag with special work handling
- local index
- __git-bug_index_of_word "${prev}" "${flags_with_completion[@]}"
- if [[ ${index} -ge 0 ]]; then
- ${flags_completion[${index}]}
- return
- fi
+ local completions=()
+ while IFS='' read -r comp; do
+ if [ -z "$comp" ]; then
+ continue
+ fi
- # we are parsing a flag and don't have a special handler, no completion
- if [[ ${cur} != "${words[cword]}" ]]; then
- return
- fi
+ __git-bug_debug "Original comp: $comp"
+ comp="$(__git-bug_format_comp_descriptions "$comp" "$longest")"
+ __git-bug_debug "Final comp: $comp"
+ completions+=("$comp")
+ done < <(printf "%s\n" "${out[@]}")
- local completions
- completions=("${commands[@]}")
- if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then
- completions+=("${must_have_one_noun[@]}")
- elif [[ -n "${has_completion_function}" ]]; then
- # if a go completion function is provided, defer to that function
- __git-bug_handle_go_custom_completion
- fi
- if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
- completions+=("${must_have_one_flag[@]}")
- fi
while IFS='' read -r comp; do
COMPREPLY+=("$comp")
done < <(compgen -W "${completions[*]}" -- "$cur")
- if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then
- while IFS='' read -r comp; do
- COMPREPLY+=("$comp")
- done < <(compgen -W "${noun_aliases[*]}" -- "$cur")
- fi
-
- if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
- if declare -F __git-bug_custom_func >/dev/null; then
- # try command name qualified custom func
- __git-bug_custom_func
- else
- # otherwise fall back to unqualified for compatibility
- declare -F __custom_func >/dev/null && __custom_func
- fi
- fi
-
- # available in bash-completion >= 2, not always present on macOS
- if declare -F __ltrim_colon_completions >/dev/null; then
- __ltrim_colon_completions "$cur"
- fi
-
- # If there is only 1 completion and it is a flag with an = it will be completed
- # but we don't want a space after the =
- if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then
- compopt -o nospace
+ # If there is a single completion left, remove the description text
+ if [ ${#COMPREPLY[*]} -eq 1 ]; then
+ __git-bug_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
+ comp="${COMPREPLY[0]%% *}"
+ __git-bug_debug "Removed description from single completion, which is now: ${comp}"
+ COMPREPLY=()
+ COMPREPLY+=("$comp")
fi
}
-# The arguments should be in the form "ext1|ext2|extn"
-__git-bug_handle_filename_extension_flag()
-{
- local ext="$1"
- _filedir "@(${ext})"
-}
-
-__git-bug_handle_subdirs_in_dir_flag()
+__git-bug_handle_special_char()
{
- local dir="$1"
- pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
+ local comp="$1"
+ local char=$2
+ if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
+ local word=${comp%"${comp##*${char}}"}
+ local idx=${#COMPREPLY[*]}
+ while [[ $((--idx)) -ge 0 ]]; do
+ COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
+ done
+ fi
}
-__git-bug_handle_flag()
+__git-bug_format_comp_descriptions()
{
- __git-bug_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
+ local tab
+ tab=$(printf '\t')
+ local comp="$1"
+ local longest=$2
- # if a command required a flag, and we found it, unset must_have_one_flag()
- local flagname=${words[c]}
- local flagvalue=""
- # if the word contained an =
- if [[ ${words[c]} == *"="* ]]; then
- flagvalue=${flagname#*=} # take in as flagvalue after the =
- flagname=${flagname%=*} # strip everything after the =
- flagname="${flagname}=" # but put the = back
- fi
- __git-bug_debug "${FUNCNAME[0]}: looking for ${flagname}"
- if __git-bug_contains_word "${flagname}" "${must_have_one_flag[@]}"; then
- must_have_one_flag=()
- fi
+ # Properly format the description string which follows a tab character if there is one
+ if [[ "$comp" == *$tab* ]]; then
+ desc=${comp#*$tab}
+ comp=${comp%%$tab*}
- # if you set a flag which only applies to this command, don't show subcommands
- if __git-bug_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then
- commands=()
- fi
+ # $COLUMNS stores the current shell width.
+ # Remove an extra 4 because we add 2 spaces and 2 parentheses.
+ maxdesclength=$(( COLUMNS - longest - 4 ))
- # keep flag value with flagname as flaghash
- # flaghash variable is an associative array which is only supported in bash > 3.
- if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then
- if [ -n "${flagvalue}" ] ; then
- flaghash[${flagname}]=${flagvalue}
- elif [ -n "${words[ $((c+1)) ]}" ] ; then
- flaghash[${flagname}]=${words[ $((c+1)) ]}
+ # Make sure we can fit a description of at least 8 characters
+ # if we are to align the descriptions.
+ if [[ $maxdesclength -gt 8 ]]; then
+ # Add the proper number of spaces to align the descriptions
+ for ((i = ${#comp} ; i < longest ; i++)); do
+ comp+=" "
+ done
else
- flaghash[${flagname}]="true" # pad "true" for bool flag
+ # Don't pad the descriptions so we can fit more text after the completion
+ maxdesclength=$(( COLUMNS - ${#comp} - 4 ))
fi
- fi
- # skip the argument to a two word flag
- if [[ ${words[c]} != *"="* ]] && __git-bug_contains_word "${words[c]}" "${two_word_flags[@]}"; then
- __git-bug_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument"
- c=$((c+1))
- # if we are looking for a flags value, don't show commands
- if [[ $c -eq $cword ]]; then
- commands=()
+ # If there is enough space for any description text,
+ # truncate the descriptions that are too long for the shell width
+ if [ $maxdesclength -gt 0 ]; then
+ if [ ${#desc} -gt $maxdesclength ]; then
+ desc=${desc:0:$(( maxdesclength - 1 ))}
+ desc+="…"
+ fi
+ comp+=" ($desc)"
fi
fi
- c=$((c+1))
-
+ # Must use printf to escape all special characters
+ printf "%q" "${comp}"
}
-__git-bug_handle_noun()
-{
- __git-bug_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
-
- if __git-bug_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
- must_have_one_noun=()
- elif __git-bug_contains_word "${words[c]}" "${noun_aliases[@]}"; then
- must_have_one_noun=()
- fi
-
- nouns+=("${words[c]}")
- c=$((c+1))
-}
-
-__git-bug_handle_command()
+__start_git-bug()
{
- __git-bug_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
+ local cur prev words cword split
- local next_command
- if [[ -n ${last_command} ]]; then
- next_command="_${last_command}_${words[c]//:/__}"
- else
- if [[ $c -eq 0 ]]; then
- next_command="_git-bug_root_command"
- else
- next_command="_${words[c]//:/__}"
- fi
- fi
- c=$((c+1))
- __git-bug_debug "${FUNCNAME[0]}: looking for ${next_command}"
- declare -F "$next_command" >/dev/null && $next_command
-}
+ COMPREPLY=()
-__git-bug_handle_word()
-{
- if [[ $c -ge $cword ]]; then
- __git-bug_handle_reply
- return
- fi
- __git-bug_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
- if [[ "${words[c]}" == -* ]]; then
- __git-bug_handle_flag
- elif __git-bug_contains_word "${words[c]}" "${commands[@]}"; then
- __git-bug_handle_command
- elif [[ $c -eq 0 ]]; then
- __git-bug_handle_command
- elif __git-bug_contains_word "${words[c]}" "${command_aliases[@]}"; then
- # aliashash variable is an associative array which is only supported in bash > 3.
- if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then
- words[c]=${aliashash[${words[c]}]}
- __git-bug_handle_command
- else
- __git-bug_handle_noun
- fi
+ # Call _init_completion from the bash-completion package
+ # to prepare the arguments properly
+ if declare -F _init_completion >/dev/null 2>&1; then
+ _init_completion -n "=:" || return
else
- __git-bug_handle_noun
+ __git-bug_init_completion -n "=:" || return
fi
- __git-bug_handle_word
-}
-
-
-_git_bug() {
- __start_git-bug "$@"
-}
-
-_git-bug_add()
-{
- last_command="git-bug_add"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--title=")
- two_word_flags+=("--title")
- two_word_flags+=("-t")
- local_nonpersistent_flags+=("--title")
- local_nonpersistent_flags+=("--title=")
- local_nonpersistent_flags+=("-t")
- flags+=("--message=")
- two_word_flags+=("--message")
- two_word_flags+=("-m")
- local_nonpersistent_flags+=("--message")
- local_nonpersistent_flags+=("--message=")
- local_nonpersistent_flags+=("-m")
- flags+=("--file=")
- two_word_flags+=("--file")
- two_word_flags+=("-F")
- local_nonpersistent_flags+=("--file")
- local_nonpersistent_flags+=("--file=")
- local_nonpersistent_flags+=("-F")
- flags+=("--non-interactive")
- local_nonpersistent_flags+=("--non-interactive")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge_auth_add-token()
-{
- last_command="git-bug_bridge_auth_add-token"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--target=")
- two_word_flags+=("--target")
- two_word_flags+=("-t")
- local_nonpersistent_flags+=("--target")
- local_nonpersistent_flags+=("--target=")
- local_nonpersistent_flags+=("-t")
- flags+=("--login=")
- two_word_flags+=("--login")
- two_word_flags+=("-l")
- local_nonpersistent_flags+=("--login")
- local_nonpersistent_flags+=("--login=")
- local_nonpersistent_flags+=("-l")
- flags+=("--user=")
- two_word_flags+=("--user")
- two_word_flags+=("-u")
- local_nonpersistent_flags+=("--user")
- local_nonpersistent_flags+=("--user=")
- local_nonpersistent_flags+=("-u")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge_auth_rm()
-{
- last_command="git-bug_bridge_auth_rm"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge_auth_show()
-{
- last_command="git-bug_bridge_auth_show"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge_auth()
-{
- last_command="git-bug_bridge_auth"
-
- command_aliases=()
-
- commands=()
- commands+=("add-token")
- commands+=("rm")
- commands+=("show")
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge_configure()
-{
- last_command="git-bug_bridge_configure"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--name=")
- two_word_flags+=("--name")
- two_word_flags+=("-n")
- local_nonpersistent_flags+=("--name")
- local_nonpersistent_flags+=("--name=")
- local_nonpersistent_flags+=("-n")
- flags+=("--target=")
- two_word_flags+=("--target")
- two_word_flags+=("-t")
- local_nonpersistent_flags+=("--target")
- local_nonpersistent_flags+=("--target=")
- local_nonpersistent_flags+=("-t")
- flags+=("--url=")
- two_word_flags+=("--url")
- two_word_flags+=("-u")
- local_nonpersistent_flags+=("--url")
- local_nonpersistent_flags+=("--url=")
- local_nonpersistent_flags+=("-u")
- flags+=("--base-url=")
- two_word_flags+=("--base-url")
- two_word_flags+=("-b")
- local_nonpersistent_flags+=("--base-url")
- local_nonpersistent_flags+=("--base-url=")
- local_nonpersistent_flags+=("-b")
- flags+=("--login=")
- two_word_flags+=("--login")
- two_word_flags+=("-l")
- local_nonpersistent_flags+=("--login")
- local_nonpersistent_flags+=("--login=")
- local_nonpersistent_flags+=("-l")
- flags+=("--credential=")
- two_word_flags+=("--credential")
- two_word_flags+=("-c")
- local_nonpersistent_flags+=("--credential")
- local_nonpersistent_flags+=("--credential=")
- local_nonpersistent_flags+=("-c")
- flags+=("--token=")
- two_word_flags+=("--token")
- local_nonpersistent_flags+=("--token")
- local_nonpersistent_flags+=("--token=")
- flags+=("--token-stdin")
- local_nonpersistent_flags+=("--token-stdin")
- flags+=("--owner=")
- two_word_flags+=("--owner")
- two_word_flags+=("-o")
- local_nonpersistent_flags+=("--owner")
- local_nonpersistent_flags+=("--owner=")
- local_nonpersistent_flags+=("-o")
- flags+=("--project=")
- two_word_flags+=("--project")
- two_word_flags+=("-p")
- local_nonpersistent_flags+=("--project")
- local_nonpersistent_flags+=("--project=")
- local_nonpersistent_flags+=("-p")
- flags+=("--non-interactive")
- local_nonpersistent_flags+=("--non-interactive")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge_pull()
-{
- last_command="git-bug_bridge_pull"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--no-resume")
- flags+=("-n")
- local_nonpersistent_flags+=("--no-resume")
- local_nonpersistent_flags+=("-n")
- flags+=("--since=")
- two_word_flags+=("--since")
- two_word_flags+=("-s")
- local_nonpersistent_flags+=("--since")
- local_nonpersistent_flags+=("--since=")
- local_nonpersistent_flags+=("-s")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge_push()
-{
- last_command="git-bug_bridge_push"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge_rm()
-{
- last_command="git-bug_bridge_rm"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_bridge()
-{
- last_command="git-bug_bridge"
-
- command_aliases=()
-
- commands=()
- commands+=("auth")
- commands+=("configure")
- commands+=("pull")
- commands+=("push")
- commands+=("rm")
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_commands()
-{
- last_command="git-bug_commands"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--pretty")
- flags+=("-p")
- local_nonpersistent_flags+=("--pretty")
- local_nonpersistent_flags+=("-p")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_comment_add()
-{
- last_command="git-bug_comment_add"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--file=")
- two_word_flags+=("--file")
- two_word_flags+=("-F")
- local_nonpersistent_flags+=("--file")
- local_nonpersistent_flags+=("--file=")
- local_nonpersistent_flags+=("-F")
- flags+=("--message=")
- two_word_flags+=("--message")
- two_word_flags+=("-m")
- local_nonpersistent_flags+=("--message")
- local_nonpersistent_flags+=("--message=")
- local_nonpersistent_flags+=("-m")
- flags+=("--non-interactive")
- local_nonpersistent_flags+=("--non-interactive")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_comment_edit()
-{
- last_command="git-bug_comment_edit"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--file=")
- two_word_flags+=("--file")
- two_word_flags+=("-F")
- local_nonpersistent_flags+=("--file")
- local_nonpersistent_flags+=("--file=")
- local_nonpersistent_flags+=("-F")
- flags+=("--message=")
- two_word_flags+=("--message")
- two_word_flags+=("-m")
- local_nonpersistent_flags+=("--message")
- local_nonpersistent_flags+=("--message=")
- local_nonpersistent_flags+=("-m")
- flags+=("--non-interactive")
- local_nonpersistent_flags+=("--non-interactive")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_comment()
-{
- last_command="git-bug_comment"
-
- command_aliases=()
-
- commands=()
- commands+=("add")
- commands+=("edit")
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-_git-bug_deselect()
-{
- last_command="git-bug_deselect"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_label_add()
-{
- last_command="git-bug_label_add"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_label_rm()
-{
- last_command="git-bug_label_rm"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_label()
-{
- last_command="git-bug_label"
-
- command_aliases=()
-
- commands=()
- commands+=("add")
- commands+=("rm")
+ __git-bug_debug
+ __git-bug_debug "========= starting completion logic =========="
+ __git-bug_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword"
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
+ # The user could have moved the cursor backwards on the command-line.
+ # We need to trigger completion from the $cword location, so we need
+ # to truncate the command-line ($words) up to the $cword location.
+ words=("${words[@]:0:$cword+1}")
+ __git-bug_debug "Truncated words[*]: ${words[*]},"
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_ls()
-{
- last_command="git-bug_ls"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--status=")
- two_word_flags+=("--status")
- two_word_flags+=("-s")
- local_nonpersistent_flags+=("--status")
- local_nonpersistent_flags+=("--status=")
- local_nonpersistent_flags+=("-s")
- flags+=("--author=")
- two_word_flags+=("--author")
- two_word_flags+=("-a")
- local_nonpersistent_flags+=("--author")
- local_nonpersistent_flags+=("--author=")
- local_nonpersistent_flags+=("-a")
- flags+=("--metadata=")
- two_word_flags+=("--metadata")
- two_word_flags+=("-m")
- local_nonpersistent_flags+=("--metadata")
- local_nonpersistent_flags+=("--metadata=")
- local_nonpersistent_flags+=("-m")
- flags+=("--participant=")
- two_word_flags+=("--participant")
- two_word_flags+=("-p")
- local_nonpersistent_flags+=("--participant")
- local_nonpersistent_flags+=("--participant=")
- local_nonpersistent_flags+=("-p")
- flags+=("--actor=")
- two_word_flags+=("--actor")
- two_word_flags+=("-A")
- local_nonpersistent_flags+=("--actor")
- local_nonpersistent_flags+=("--actor=")
- local_nonpersistent_flags+=("-A")
- flags+=("--label=")
- two_word_flags+=("--label")
- two_word_flags+=("-l")
- local_nonpersistent_flags+=("--label")
- local_nonpersistent_flags+=("--label=")
- local_nonpersistent_flags+=("-l")
- flags+=("--title=")
- two_word_flags+=("--title")
- two_word_flags+=("-t")
- local_nonpersistent_flags+=("--title")
- local_nonpersistent_flags+=("--title=")
- local_nonpersistent_flags+=("-t")
- flags+=("--no=")
- two_word_flags+=("--no")
- two_word_flags+=("-n")
- local_nonpersistent_flags+=("--no")
- local_nonpersistent_flags+=("--no=")
- local_nonpersistent_flags+=("-n")
- flags+=("--by=")
- two_word_flags+=("--by")
- two_word_flags+=("-b")
- local_nonpersistent_flags+=("--by")
- local_nonpersistent_flags+=("--by=")
- local_nonpersistent_flags+=("-b")
- flags+=("--direction=")
- two_word_flags+=("--direction")
- two_word_flags+=("-d")
- local_nonpersistent_flags+=("--direction")
- local_nonpersistent_flags+=("--direction=")
- local_nonpersistent_flags+=("-d")
- flags+=("--format=")
- two_word_flags+=("--format")
- two_word_flags+=("-f")
- local_nonpersistent_flags+=("--format")
- local_nonpersistent_flags+=("--format=")
- local_nonpersistent_flags+=("-f")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
+ local out directive
+ __git-bug_get_completion_results
+ __git-bug_process_completion_results
}
-_git-bug_ls-id()
-{
- last_command="git-bug_ls-id"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_ls-label()
-{
- last_command="git-bug_ls-label"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_pull()
-{
- last_command="git-bug_pull"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_push()
-{
- last_command="git-bug_push"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_rm()
-{
- last_command="git-bug_rm"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_select()
-{
- last_command="git-bug_select"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_show()
-{
- last_command="git-bug_show"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--field=")
- two_word_flags+=("--field")
- local_nonpersistent_flags+=("--field")
- local_nonpersistent_flags+=("--field=")
- flags+=("--format=")
- two_word_flags+=("--format")
- two_word_flags+=("-f")
- local_nonpersistent_flags+=("--format")
- local_nonpersistent_flags+=("--format=")
- local_nonpersistent_flags+=("-f")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_status_close()
-{
- last_command="git-bug_status_close"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_status_open()
-{
- last_command="git-bug_status_open"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_status()
-{
- last_command="git-bug_status"
-
- command_aliases=()
-
- commands=()
- commands+=("close")
- commands+=("open")
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_termui()
-{
- last_command="git-bug_termui"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_title_edit()
-{
- last_command="git-bug_title_edit"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--title=")
- two_word_flags+=("--title")
- two_word_flags+=("-t")
- local_nonpersistent_flags+=("--title")
- local_nonpersistent_flags+=("--title=")
- local_nonpersistent_flags+=("-t")
- flags+=("--non-interactive")
- local_nonpersistent_flags+=("--non-interactive")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_title()
-{
- last_command="git-bug_title"
-
- command_aliases=()
-
- commands=()
- commands+=("edit")
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_user_adopt()
-{
- last_command="git-bug_user_adopt"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_user_create()
-{
- last_command="git-bug_user_create"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--avatar=")
- two_word_flags+=("--avatar")
- two_word_flags+=("-a")
- local_nonpersistent_flags+=("--avatar")
- local_nonpersistent_flags+=("--avatar=")
- local_nonpersistent_flags+=("-a")
- flags+=("--email=")
- two_word_flags+=("--email")
- two_word_flags+=("-e")
- local_nonpersistent_flags+=("--email")
- local_nonpersistent_flags+=("--email=")
- local_nonpersistent_flags+=("-e")
- flags+=("--name=")
- two_word_flags+=("--name")
- two_word_flags+=("-n")
- local_nonpersistent_flags+=("--name")
- local_nonpersistent_flags+=("--name=")
- local_nonpersistent_flags+=("-n")
- flags+=("--non-interactive")
- local_nonpersistent_flags+=("--non-interactive")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_user_ls()
-{
- last_command="git-bug_user_ls"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--format=")
- two_word_flags+=("--format")
- two_word_flags+=("-f")
- local_nonpersistent_flags+=("--format")
- local_nonpersistent_flags+=("--format=")
- local_nonpersistent_flags+=("-f")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_user()
-{
- last_command="git-bug_user"
-
- command_aliases=()
-
- commands=()
- commands+=("adopt")
- commands+=("create")
- commands+=("ls")
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--field=")
- two_word_flags+=("--field")
- two_word_flags+=("-f")
- local_nonpersistent_flags+=("--field")
- local_nonpersistent_flags+=("--field=")
- local_nonpersistent_flags+=("-f")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_version()
-{
- last_command="git-bug_version"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--number")
- flags+=("-n")
- local_nonpersistent_flags+=("--number")
- local_nonpersistent_flags+=("-n")
- flags+=("--commit")
- flags+=("-c")
- local_nonpersistent_flags+=("--commit")
- local_nonpersistent_flags+=("-c")
- flags+=("--all")
- flags+=("-a")
- local_nonpersistent_flags+=("--all")
- local_nonpersistent_flags+=("-a")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_webui()
-{
- last_command="git-bug_webui"
-
- command_aliases=()
-
- commands=()
-
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
-
- flags+=("--host=")
- two_word_flags+=("--host")
- local_nonpersistent_flags+=("--host")
- local_nonpersistent_flags+=("--host=")
- flags+=("--open")
- local_nonpersistent_flags+=("--open")
- flags+=("--no-open")
- local_nonpersistent_flags+=("--no-open")
- flags+=("--port=")
- two_word_flags+=("--port")
- two_word_flags+=("-p")
- local_nonpersistent_flags+=("--port")
- local_nonpersistent_flags+=("--port=")
- local_nonpersistent_flags+=("-p")
- flags+=("--read-only")
- local_nonpersistent_flags+=("--read-only")
- flags+=("--query=")
- two_word_flags+=("--query")
- two_word_flags+=("-q")
- local_nonpersistent_flags+=("--query")
- local_nonpersistent_flags+=("--query=")
- local_nonpersistent_flags+=("-q")
-
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
-
-_git-bug_root_command()
-{
- last_command="git-bug"
-
- command_aliases=()
-
- commands=()
- commands+=("add")
- commands+=("bridge")
- commands+=("commands")
- commands+=("comment")
- commands+=("deselect")
- commands+=("label")
- commands+=("ls")
- commands+=("ls-id")
- commands+=("ls-label")
- commands+=("pull")
- commands+=("push")
- commands+=("rm")
- commands+=("select")
- commands+=("show")
- commands+=("status")
- commands+=("termui")
- if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then
- command_aliases+=("tui")
- aliashash["tui"]="termui"
- fi
- commands+=("title")
- commands+=("user")
- commands+=("version")
- commands+=("webui")
+if [[ $(type -t compopt) = "builtin" ]]; then
+ complete -o default -F __start_git-bug git-bug
+else
+ complete -o default -o nospace -F __start_git-bug git-bug
+fi
- flags=()
- two_word_flags=()
- local_nonpersistent_flags=()
- flags_with_completion=()
- flags_completion=()
+# ex: ts=4 sw=4 et filetype=sh
+_git_bug() {
+ local cur prev words cword split
- must_have_one_flag=()
- must_have_one_noun=()
- noun_aliases=()
-}
+ COMPREPLY=()
-__start_git-bug()
-{
- local cur prev words cword split
- declare -A flaghash 2>/dev/null || :
- declare -A aliashash 2>/dev/null || :
+ # Call _init_completion from the bash-completion package
+ # to prepare the arguments properly
if declare -F _init_completion >/dev/null 2>&1; then
- _init_completion -s || return
+ _init_completion -n "=:" || return
else
- __git-bug_init_completion -n "=" || return
+ __git-bug_init_completion -n "=:" || return
fi
- local c=0
- local flag_parsing_disabled=
- local flags=()
- local two_word_flags=()
- local local_nonpersistent_flags=()
- local flags_with_completion=()
- local flags_completion=()
- local commands=("git-bug")
- local command_aliases=()
- local must_have_one_flag=()
- local must_have_one_noun=()
- local has_completion_function=""
- local last_command=""
- local nouns=()
- local noun_aliases=()
+ # START PATCH
+ # replace in the array ("git","bug", ...) to ("git-bug", ...) and adjust the index in cword
+ words=("git-bug" "${words[@]:2}")
+ cword=$(($cword-1))
+ # END PATCH
- __git-bug_handle_word
-}
+ __git-bug_debug
+ __git-bug_debug "========= starting completion logic =========="
+ __git-bug_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword"
-if [[ $(type -t compopt) = "builtin" ]]; then
- complete -o default -F __start_git-bug git-bug
-else
- complete -o default -o nospace -F __start_git-bug git-bug
-fi
+ # The user could have moved the cursor backwards on the command-line.
+ # We need to trigger completion from the $cword location, so we need
+ # to truncate the command-line ($words) up to the $cword location.
+ words=("${words[@]:0:$cword+1}")
+ __git-bug_debug "Truncated words[*]: ${words[*]},"
-# ex: ts=4 sw=4 et filetype=sh
+ local out directive
+ __git-bug_get_completion_results
+ __git-bug_process_completion_results
+}
diff --git a/misc/gen_completion.go b/misc/gen_completion.go
index c073e67e..1f86124d 100644
--- a/misc/gen_completion.go
+++ b/misc/gen_completion.go
@@ -40,25 +40,86 @@ func main() {
}
func genBash(root *cobra.Command) error {
- cwd, _ := os.Getwd()
- dir := filepath.Join(cwd, "misc", "bash_completion", "git-bug")
- return root.GenBashCompletionFile(dir)
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+ f, err := os.Create(filepath.Join(cwd, "misc", "bash_completion", "git-bug"))
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ const patch = `
+_git_bug() {
+ local cur prev words cword split
+
+ COMPREPLY=()
+
+ # Call _init_completion from the bash-completion package
+ # to prepare the arguments properly
+ if declare -F _init_completion >/dev/null 2>&1; then
+ _init_completion -n "=:" || return
+ else
+ __git-bug_init_completion -n "=:" || return
+ fi
+
+ # START PATCH
+ # replace in the array ("git","bug", ...) to ("git-bug", ...) and adjust the index in cword
+ words=("git-bug" "${words[@]:2}")
+ cword=$(($cword-1))
+ # END PATCH
+
+ __git-bug_debug
+ __git-bug_debug "========= starting completion logic =========="
+ __git-bug_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword"
+
+ # The user could have moved the cursor backwards on the command-line.
+ # We need to trigger completion from the $cword location, so we need
+ # to truncate the command-line ($words) up to the $cword location.
+ words=("${words[@]:0:$cword+1}")
+ __git-bug_debug "Truncated words[*]: ${words[*]},"
+
+ local out directive
+ __git-bug_get_completion_results
+ __git-bug_process_completion_results
+}
+`
+ err = root.GenBashCompletionV2(f, true)
+ if err != nil {
+ return err
+ }
+
+ // Custom bash code to connect the git completion for "git bug" to the
+ // git-bug completion for "git-bug"
+ _, err = f.WriteString(patch)
+
+ return err
}
func genFish(root *cobra.Command) error {
- cwd, _ := os.Getwd()
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
dir := filepath.Join(cwd, "misc", "fish_completion", "git-bug")
return root.GenFishCompletionFile(dir, true)
}
func genPowerShell(root *cobra.Command) error {
- cwd, _ := os.Getwd()
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
path := filepath.Join(cwd, "misc", "powershell_completion", "git-bug")
return root.GenPowerShellCompletionFile(path)
}
func genZsh(root *cobra.Command) error {
- cwd, _ := os.Getwd()
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
path := filepath.Join(cwd, "misc", "zsh_completion", "git-bug")
return root.GenZshCompletionFile(path)
}
diff --git a/util/text/validate.go b/util/text/validate.go
index 4c3f7065..f25a56b4 100644
--- a/util/text/validate.go
+++ b/util/text/validate.go
@@ -33,7 +33,7 @@ func Safe(s string) bool {
return true
}
-// Safe will tell if a character in the string is considered unsafe
+// SafeOneLine will tell if a character in the string is considered unsafe
// Currently trigger on all unicode control character
func SafeOneLine(s string) bool {
for _, r := range s {