Merge pull request #8 from charmbracelet/fish

Fish shell completion script
This commit is contained in:
Maas Lalani 2022-07-25 16:46:25 -04:00 committed by GitHub
commit d643c54db2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 122 additions and 28 deletions

View file

@ -1,6 +1,6 @@
includes:
- from_url:
url: charmbracelet/meta/main/goreleaser.yaml
url: charmbracelet/meta/main/goreleaser-full.yaml
variables:
main: "."
@ -9,5 +9,3 @@ variables:
maintainer: "Maas Lalani <maas@charm.sh>"
brew_commit_author_name: "Maas Lalani"
brew_commit_author_email: "maas@charm.sh"

View file

@ -11,9 +11,10 @@ import (
"github.com/alecthomas/kong"
)
// Bash is a bash completion generator.
type Bash struct{}
// Run generates bash shell completion.
// Run generates bash completion script.
func (b Bash) Run(ctx *kong.Context) error {
buf := new(bytes.Buffer)
writePreamble(buf, ctx.Model.Name)

View file

@ -12,7 +12,7 @@ import (
type Completion struct {
Bash Bash `cmd:"" help:"Generate the autocompletion script for bash"`
Zsh Zsh `cmd:"" help:"Generate the autocompletion script for zsh"`
// Fish Fish `cmd:"" help:"Generate the autocompletion script for fish"`
Fish Fish `cmd:"" help:"Generate the autocompletion script for fish"`
}
func commandName(cmd *kong.Node) string {
@ -47,3 +47,13 @@ func writeString(b io.StringWriter, s string) {
func nonCompletableFlag(flag *kong.Flag) bool {
return flag.Hidden
}
func flagPossibleValues(flag *kong.Flag) []string {
values := make([]string, 0)
for _, enum := range flag.EnumSlice() {
if strings.TrimSpace(enum) != "" {
values = append(values, enum)
}
}
return values
}

90
completion/fish.go Normal file
View file

@ -0,0 +1,90 @@
package completion
import (
"fmt"
"io"
"strings"
"github.com/alecthomas/kong"
)
// Fish is a fish shell completion generator.
type Fish struct{}
// Run generates fish completion script.
func (f Fish) Run(ctx *kong.Context) error {
var buf strings.Builder
buf.WriteString(`# Fish shell completion for gum
# Generated by gum completion
# disable file completion unless explicitly enabled
complete -c gum -f
`)
node := ctx.Model.Node
f.gen(&buf, node)
_, err := fmt.Fprint(ctx.Stdout, buf.String())
return err
}
func (f Fish) gen(buf io.StringWriter, cmd *kong.Node) {
root := cmd
for root.Parent != nil {
root = root.Parent
}
rootName := root.Name
if cmd.Parent == nil {
buf.WriteString(fmt.Sprintf("# %s\n", rootName))
} else {
buf.WriteString(fmt.Sprintf("# %s\n", cmd.Path()))
buf.WriteString(
fmt.Sprintf("complete -c %s -f -n '__fish_use_subcommand' -a %s -d '%s'\n",
rootName,
cmd.Name,
cmd.Help,
),
)
}
for _, f := range cmd.Flags {
if f.Hidden {
continue
}
if cmd.Parent == nil {
buf.WriteString(
fmt.Sprintf("complete -c %s -f",
rootName,
),
)
} else {
buf.WriteString(
fmt.Sprintf("complete -c %s -f -n '__fish_seen_subcommand_from %s'",
rootName,
cmd.Name,
),
)
}
if !f.IsBool() {
enums := flagPossibleValues(f)
if len(enums) > 0 {
buf.WriteString(fmt.Sprintf(" -xa '%s'", strings.Join(enums, " ")))
} else {
buf.WriteString(" -x")
}
}
if f.Short != 0 {
buf.WriteString(fmt.Sprintf(" -s %c", f.Short))
}
buf.WriteString(fmt.Sprintf(" -l %s", f.Name))
buf.WriteString(fmt.Sprintf(" -d '%s'", f.Help))
buf.WriteString("\n")
}
buf.WriteString("\n")
for _, c := range cmd.Children {
if c == nil || c.Hidden {
continue
}
f.gen(buf, c)
}
}

View file

@ -8,8 +8,23 @@ import (
"github.com/alecthomas/kong"
)
// Zsh is zsh completion generator.
type Zsh struct{}
// Run generates zsh completion script.
func (z Zsh) Run(ctx *kong.Context) error {
var out strings.Builder
format := `#compdef %[1]s
# zsh completion for %[1]s
# generated by gum completion
`
fmt.Fprintf(&out, format, ctx.Model.Name)
z.gen(&out, ctx.Model.Node)
_, err := fmt.Fprint(ctx.Stdout, out.String())
return err
}
func (z Zsh) writeFlag(buf io.StringWriter, f *kong.Flag) {
var str strings.Builder
str.WriteString(" ")
@ -40,17 +55,12 @@ func (z Zsh) writeFlag(buf io.StringWriter, f *kong.Flag) {
str.WriteString(strings.ToLower(f.Help))
str.WriteString(":")
}
enumSlice := make([]string, 0)
for _, enum := range f.EnumSlice() {
if strings.TrimSpace(enum) != "" {
enumSlice = append(enumSlice, enum)
}
}
if len(enumSlice) > 0 {
values := flagPossibleValues(f)
if len(values) > 0 {
str.WriteString("(")
for i, v := range f.EnumSlice() {
str.WriteString(v)
if i < len(enumSlice)-1 {
if i < len(values)-1 {
str.WriteString(" ")
}
}
@ -131,17 +141,3 @@ func (z Zsh) gen(buf io.StringWriter, cmd *kong.Node) {
writeString(buf, "\n")
writeString(buf, "}\n\n")
}
// Run generates zsh shell completion.
func (z Zsh) Run(ctx *kong.Context) error {
var out strings.Builder
format := `#compdef %[1]s
# zsh completion for %[1]s
# generated by gum completion
`
fmt.Fprintf(&out, format, ctx.Model.Name)
z.gen(&out, ctx.Model.Node)
_, err := fmt.Fprint(ctx.Stdout, out.String())
return err
}

1
go.sum
View file

@ -16,7 +16,6 @@ github.com/charmbracelet/bubbles v0.13.1-0.20220708023448-746ec595c3d1/go.mod h1
github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4=
github.com/charmbracelet/bubbletea v0.22.0 h1:E1BTNSE3iIrq0G0X6TjGAmrQ32cGCbFDPcIuImikrUc=
github.com/charmbracelet/bubbletea v0.22.0/go.mod h1:aoVIwlNlr5wbCB26KhxfrqAn0bMp4YpJcoOelbxApjs=
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8=
github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs=