File: completion.go

package info (click to toggle)
wormhole-william 1.0.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 400 kB
  • sloc: makefile: 10
file content (145 lines) | stat: -rw-r--r-- 3,819 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package cmd

import (
	"context"
	"os"
	"strings"
	"time"

	"github.com/psanford/wormhole-william/internal/crypto"
	"github.com/psanford/wormhole-william/rendezvous"
	"github.com/psanford/wormhole-william/wordlist"
	"github.com/psanford/wormhole-william/wormhole"
	"github.com/spf13/cobra"
)

func completionCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "shell-completion [bash|zsh|fish|powershell]",
		Short: "Generate shell completion script",
		Long: `To load completions:

Bash:

  $ source <(wormhole-william shell-completion bash)

  # To configure your bash shell to load completions for each session add to your bashrc

# ~/.bashrc or ~/.profile
if which wormhole-william &>/dev/null ; then
  . <(wormhole-william shell-completion bash)
fi

Zsh:

  # If shell completion is not already enabled in your environment,
  # you will need to enable it.  You can execute the following once:

  $ echo "autoload -U compinit; compinit" >> ~/.zshrc

  # To load completions for each session, execute once:
  $ wormhole-william shell-completion zsh > "${fpath[1]}/_wormhole-william"

  # You will need to start a new shell for this setup to take effect.

fish:

  $ wormhole-william shell-completion fish | source

  # To load completions for each session, execute once:
  $ wormhole-william shell-completion fish > ~/.config/fish/completions/wormhole-william.fish

PowerShell:

  PS> wormhole-william shell-completion powershell | Out-String | Invoke-Expression

  # To load completions for every new session, run:
  PS> wormhole-william shell-completion powershell > wormhole-william.ps1
  # and source this file from your PowerShell profile.
`,
		DisableFlagsInUseLine: true,
		ValidArgs:             []string{"bash", "zsh", "fish", "powershell"},
		Args:                  cobra.ExactValidArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			switch args[0] {
			case "bash":
				cmd.Root().GenBashCompletion(os.Stdout)
			case "zsh":
				cmd.Root().GenZshCompletion(os.Stdout)
			case "fish":
				cmd.Root().GenFishCompletion(os.Stdout, true)
			case "powershell":
				cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
			}
		},
	}

	return cmd
}

func recvCodeCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
	flags := cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace
	parts := strings.Split(toComplete, "-")
	if len(parts) < 2 {
		nameplates, err := activeNameplates()
		if err != nil {
			return nil, flags
		}
		if len(parts) == 0 {
			return nameplates, flags
		}

		var candidates []string
		for _, nameplate := range nameplates {
			if strings.HasPrefix(nameplate, parts[0]) {
				candidates = append(candidates, nameplate+"-")
			}
		}

		return candidates, flags
	}

	currentCompletion := parts[len(parts)-1]
	prefix := parts[:len(parts)-1]

	// even odd is based on just the number of words so slice off the mailbox
	parts = parts[1:]
	even := len(parts)%2 == 0

	var candidates []string
	for _, pair := range wordlist.RawWords {
		var candidateWord string
		if even {
			candidateWord = pair.Even
		} else {
			candidateWord = pair.Odd
		}
		if strings.HasPrefix(candidateWord, currentCompletion) {
			guessParts := append(prefix, candidateWord)
			candidates = append(candidates, strings.Join(guessParts, "-"))
		}
	}

	return candidates, flags
}

func activeNameplates() ([]string, error) {
	url := wormhole.DefaultRendezvousURL
	sideID := crypto.RandSideID()
	appID := wormhole.WormholeCLIAppID

	ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)
	defer cancel()

	client := rendezvous.NewClient(url, sideID, appID)

	mood := rendezvous.Happy
	defer client.Close(ctx, mood)

	_, err := client.Connect(ctx)
	if err != nil {
		return nil, err
	}

	return client.ListNameplates(ctx)
}