Merge pull request #531 from krobelus/complete-bug-ids

Complete bug IDs where appropriate
This commit is contained in:
Michael Muré 2022-05-01 12:54:40 +02:00 committed by GitHub
commit 547d626c25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 721 additions and 1422 deletions

View File

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

View File

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

View File

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

View File

@ -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")

View File

@ -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()

View File

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

View File

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

View File

@ -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())

View File

@ -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()

View File

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

View File

@ -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())

View File

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

View File

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

View File

@ -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"`

43
commands/ls_test.go Normal file
View File

@ -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))
}
}

View File

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

View File

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

View File

@ -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()

View File

@ -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())

View File

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

View File

@ -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]")

View File

@ -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())

View File

@ -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())

View File

@ -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()

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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)
}