fix: satisfy all linters

This commit is contained in:
Maas Lalani 2022-08-04 18:45:19 -04:00
parent 2d5ef98037
commit 1479184f3f
31 changed files with 137 additions and 115 deletions

View File

@ -7,8 +7,7 @@
//
// Let's pick from a list of gum flavors:
//
// $ gum choose "Strawberry" "Banana" "Cherry"
//
// $ gum choose "Strawberry" "Banana" "Cherry"
package choose
import (

View File

@ -9,10 +9,11 @@ import (
"github.com/alecthomas/kong"
"github.com/charmbracelet/bubbles/paginator"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/gum/internal/exit"
"github.com/charmbracelet/gum/internal/stdin"
"github.com/charmbracelet/gum/style"
"github.com/charmbracelet/lipgloss"
)
var (
@ -31,9 +32,9 @@ func (o Options) Run() error {
o.Options = strings.Split(strings.TrimSpace(input), "\n")
}
var items []item
for _, option := range o.Options {
items = append(items, item{text: option, selected: false})
var items = make([]item, len(o.Options))
for i, option := range o.Options {
items[i] = item{text: option, selected: false}
}
// We don't need to display prefixes if we are only picking one option.
@ -79,6 +80,10 @@ func (o Options) Run() error {
selectedItemStyle: o.SelectedItemStyle.ToLipgloss(),
}, tea.WithOutput(os.Stderr)).StartReturningModel()
if err != nil {
return fmt.Errorf("failed to start tea program: %w", err)
}
m := tm.(model)
if m.aborted {
return exit.ErrAborted
@ -95,10 +100,11 @@ func (o Options) Run() error {
fmt.Println(strings.TrimSuffix(s.String(), "\n"))
return err
return nil
}
// BeforeReset hook. Used to unclutter style flags.
func (o Options) BeforeReset(ctx *kong.Context) error {
return style.HideFlags(ctx)
style.HideFlags(ctx)
return nil
}

View File

@ -3,7 +3,6 @@ package choose
import "github.com/charmbracelet/gum/style"
// Options is the customization options for the choose command.
// nolint:staticcheck
type Options struct {
Options []string `arg:"" optional:"" help:"Options to choose from."`

View File

@ -21,7 +21,10 @@ func (b Bash) Run(ctx *kong.Context) error {
writePostscript(buf, ctx.Model.Name)
_, err := fmt.Fprint(ctx.Stdout, buf.String())
return err
if err != nil {
return fmt.Errorf("unable to generate bash completion: %v", err)
}
return nil
}
// ShellCompDirective is a bit map representing the different behaviors the shell

View File

@ -24,7 +24,10 @@ complete -c gum -f
node := ctx.Model.Node
f.gen(&buf, node)
_, err := fmt.Fprint(ctx.Stdout, buf.String())
return err
if err != nil {
return fmt.Errorf("unable to generate fish completion: %w", err)
}
return nil
}
func (f Fish) gen(buf io.StringWriter, cmd *kong.Node) {

View File

@ -22,7 +22,10 @@ func (z Zsh) Run(ctx *kong.Context) error {
fmt.Fprintf(&out, format, ctx.Model.Name)
z.gen(&out, ctx.Model.Node)
_, err := fmt.Fprint(ctx.Stdout, out.String())
return err
if err != nil {
return fmt.Errorf("unable to generate zsh completion: %w", err)
}
return nil
}
func (z Zsh) writeFlag(buf io.StringWriter, f *kong.Flag) {

View File

@ -1,10 +1,12 @@
package confirm
import (
"fmt"
"os"
"github.com/alecthomas/kong"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/gum/style"
)
@ -22,7 +24,7 @@ func (o Options) Run() error {
}, tea.WithOutput(os.Stderr)).StartReturningModel()
if err != nil {
return err
return fmt.Errorf("unable to run confirm: %w", err)
}
if m.(model).confirmation {
@ -36,5 +38,6 @@ func (o Options) Run() error {
// BeforeReset hook. Used to unclutter style flags.
func (o Options) BeforeReset(ctx *kong.Context) error {
return style.HideFlags(ctx)
style.HideFlags(ctx)
return nil
}

View File

@ -7,8 +7,7 @@
//
// I.e. confirm if the user wants to delete a file
//
// $ gum confirm "Are you sure?" && rm file.txt
//
// $ gum confirm "Are you sure?" && rm file.txt
package confirm
import (

View File

@ -3,13 +3,14 @@ package confirm
import "github.com/charmbracelet/gum/style"
// Options is the customization options for the confirm command.
// nolint:staticcheck
type Options struct {
Affirmative string `help:"The title of the affirmative action" default:"Yes"`
Negative string `help:"The title of the negative action" default:"No"`
Default bool `help:"Default confirmation action" default:"true"`
Prompt string `arg:"" help:"Prompt to display." default:"Are you sure?"`
PromptStyle style.Styles `embed:"" prefix:"prompt." help:"The style of the prompt" set:"defaultMargin=1 0 0 0" envprefix:"GUM_CONFIRM_PROMPT_"`
SelectedStyle style.Styles `embed:"" prefix:"selected." help:"The style of the selected action" set:"defaultBackground=212" set:"defaultForeground=230" set:"defaultPadding=0 3" set:"defaultMargin=1 1" envprefix:"GUM_CONFIRM_SELECTED_"`
Affirmative string `help:"The title of the affirmative action" default:"Yes"`
Negative string `help:"The title of the negative action" default:"No"`
Default bool `help:"Default confirmation action" default:"true"`
Prompt string `arg:"" help:"Prompt to display." default:"Are you sure?"`
PromptStyle style.Styles `embed:"" prefix:"prompt." help:"The style of the prompt" set:"defaultMargin=1 0 0 0" envprefix:"GUM_CONFIRM_PROMPT_"`
//nolint:staticcheck
SelectedStyle style.Styles `embed:"" prefix:"selected." help:"The style of the selected action" set:"defaultBackground=212" set:"defaultForeground=230" set:"defaultPadding=0 3" set:"defaultMargin=1 1" envprefix:"GUM_CONFIRM_SELECTED_"`
//nolint:staticcheck
UnselectedStyle style.Styles `embed:"" prefix:"unselected." help:"The style of the unselected action" set:"defaultBackground=235" set:"defaultForeground=254" set:"defaultPadding=0 3" set:"defaultMargin=1 1" envprefix:"GUM_CONFIRM_UNSELECTED_"`
}

View File

@ -9,6 +9,7 @@ import (
"github.com/charmbracelet/bubbles/textinput"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/gum/internal/exit"
"github.com/charmbracelet/gum/internal/files"
"github.com/charmbracelet/gum/internal/stdin"
@ -53,6 +54,9 @@ func (o Options) Run() error {
}, options...)
tm, err := p.StartReturningModel()
if err != nil {
return fmt.Errorf("unable to run filter: %w", err)
}
m := tm.(model)
if m.aborted {
@ -62,10 +66,11 @@ func (o Options) Run() error {
fmt.Println(m.matches[m.selected].Str)
}
return err
return nil
}
// BeforeReset hook. Used to unclutter style flags.
func (o Options) BeforeReset(ctx *kong.Context) error {
return style.HideFlags(ctx)
style.HideFlags(ctx)
return nil
}

View File

@ -7,8 +7,7 @@
//
// I.e. let's pick from a list of gum flavors:
//
// $ cat flavors.text | gum filter
//
// $ cat flavors.text | gum filter
package filter
import (
@ -136,6 +135,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
func matchAll(options []string) []fuzzy.Match {
//nolint:prealloc
var matches []fuzzy.Match
for _, option := range options {
matches = append(matches, fuzzy.Match{Str: option})

View File

@ -3,7 +3,6 @@ package filter
import "github.com/charmbracelet/gum/style"
// Options is the customization options for the filter command.
// nolint:staticcheck
type Options struct {
Indicator string `help:"Character for selection" default:"•" env:"GUM_FILTER_INDICATOR"`
IndicatorStyle style.Styles `embed:"" prefix:"indicator." set:"defaultForeground=212" envprefix:"GUM_FILTER_INDICATOR_"`

View File

@ -2,13 +2,12 @@
//
// It supports the following types:
//
// 1. Markdown
// 2. Code
// 3. Emoji
// 4. Template
// 1. Markdown
// 2. Code
// 3. Emoji
// 4. Template
//
// For more information, see the format/README.md file.
//
package format
import (

View File

@ -15,9 +15,13 @@ var code Func = func(input string) (string, error) {
glamour.WithWordWrap(0),
)
if err != nil {
return "", err
return "", fmt.Errorf("unable to create renderer: %w", err)
}
return renderer.Render(fmt.Sprintf("```\n%s\n```", input))
output, err := renderer.Render(fmt.Sprintf("```\n%s\n```", input))
if err != nil {
return "", fmt.Errorf("unable to render: %w", err)
}
return output, nil
}
var emoji Func = func(input string) (string, error) {
@ -25,9 +29,13 @@ var emoji Func = func(input string) (string, error) {
glamour.WithEmoji(),
)
if err != nil {
return "", err
return "", fmt.Errorf("unable to create renderer: %w", err)
}
return renderer.Render(input)
output, err := renderer.Render(input)
if err != nil {
return "", fmt.Errorf("unable to render: %w", err)
}
return output, nil
}
var markdown Func = func(input string) (string, error) {
@ -36,16 +44,20 @@ var markdown Func = func(input string) (string, error) {
glamour.WithWordWrap(0),
)
if err != nil {
return "", err
return "", fmt.Errorf("unable to create renderer: %w", err)
}
return renderer.Render(input)
output, err := renderer.Render(input)
if err != nil {
return "", fmt.Errorf("unable to render: %w", err)
}
return output, nil
}
var template Func = func(input string) (string, error) {
f := termenv.TemplateFuncs(termenv.ColorProfile())
t, err := tpl.New("tpl").Funcs(f).Parse(input)
if err != nil {
return "", err
return "", fmt.Errorf("unable to parse template: %w", err)
}
var buf bytes.Buffer

4
go.sum
View File

@ -11,10 +11,6 @@ github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/charmbracelet/bubbles v0.13.1-0.20220708023448-746ec595c3d1 h1:2iHkYbnXv+7i5pp/dIJa/IhM+hE6EckujhOQWLzGMP4=
github.com/charmbracelet/bubbles v0.13.1-0.20220708023448-746ec595c3d1/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc=
github.com/charmbracelet/bubbles v0.13.1-0.20220731172002-8f6516082803 h1:+XxHUDsn8N5dvaLgAiCK04B+xe+gKW0pDG39T476ztM=
github.com/charmbracelet/bubbles v0.13.1-0.20220731172002-8f6516082803/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc=
github.com/charmbracelet/bubbles v0.13.1-0.20220804185250-84eacf535a81 h1:iQZnv9OkOx/jhBSVNn5bIhH3PdJgVk82dVCIVJg9jik=
github.com/charmbracelet/bubbles v0.13.1-0.20220804185250-84eacf535a81/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc=
github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4=

17
gum.go
View File

@ -2,6 +2,7 @@ package main
import (
"github.com/alecthomas/kong"
"github.com/charmbracelet/gum/choose"
"github.com/charmbracelet/gum/completion"
"github.com/charmbracelet/gum/confirm"
@ -35,7 +36,7 @@ type Gum struct {
//
// Let's pick from a list of gum flavors:
//
// $ gum choose "Strawberry" "Banana" "Cherry"
// $ gum choose "Strawberry" "Banana" "Cherry"
//
Choose choose.Options `cmd:"" help:"Choose an option from a list of choices"`
@ -49,7 +50,7 @@ type Gum struct {
//
// I.e. confirm if the user wants to delete a file
//
// $ gum confirm "Are you sure?" && rm file.txt
// $ gum confirm "Are you sure?" && rm file.txt
//
Confirm confirm.Options `cmd:"" help:"Ask a user to confirm an action"`
@ -62,7 +63,7 @@ type Gum struct {
//
// I.e. let's pick from a list of gum flavors:
//
// $ cat flavors.text | gum filter
// $ cat flavors.text | gum filter
//
Filter filter.Options `cmd:"" help:"Filter items from a list"`
@ -77,7 +78,7 @@ type Gum struct {
// It can be used to prompt the user for some input. The text the user
// entered will be sent to stdout.
//
// $ gum input --placeholder "What's your favorite gum?" > answer.text
// $ gum input --placeholder "What's your favorite gum?" > answer.text
//
Input input.Options `cmd:"" help:"Prompt for some input"`
@ -89,7 +90,7 @@ type Gum struct {
// Note: We wrap the variable in quotes to ensure the new lines are part of a
// single argument. Otherwise, the command won't work as expected.
//
// $ gum join --horizontal "$BUBBLE_BOX" "$GUM_BOX"
// $ gum join --horizontal "$BUBBLE_BOX" "$GUM_BOX"
//
// ╔══════════════════════╗╔═════════════╗
// ║ ║║ ║
@ -110,7 +111,7 @@ type Gum struct {
// We can simply prepend a spinner to this task to show it to the user,
// while performing the task / command in the background.
//
// $ gum spin -t "Taking a nap..." -- sleep 5
// $ gum spin -t "Taking a nap..." -- sleep 5
//
// The spinner will automatically exit when the task is complete.
//
@ -124,7 +125,7 @@ type Gum struct {
//
// Let's make some text glamorous using bash:
//
// $ gum style \
// $ gum style \
// --foreground 212 --border double --align center \
// --width 50 --margin 2 --padding "2 4" \
// "Bubble Gum (1¢)" "So sweet and so fresh\!"
@ -147,7 +148,7 @@ type Gum struct {
// It can be used to ask the user to write some long form of text
// (multi-line) input. The text the user entered will be sent to stdout.
//
// $ gum write > output.text
// $ gum write > output.text
//
Write write.Options `cmd:"" help:"Prompt for long-form text"`
}

View File

@ -7,6 +7,7 @@ import (
"github.com/alecthomas/kong"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/gum/internal/exit"
"github.com/charmbracelet/gum/internal/stdin"
"github.com/charmbracelet/gum/style"
@ -40,6 +41,9 @@ func (o Options) Run() error {
aborted: false,
}, tea.WithOutput(os.Stderr))
tm, err := p.StartReturningModel()
if err != nil {
return fmt.Errorf("failed to run input: %w", err)
}
m := tm.(model)
if m.aborted {
@ -47,10 +51,11 @@ func (o Options) Run() error {
}
fmt.Println(m.textinput.Value())
return err
return nil
}
// BeforeReset hook. Used to unclutter style flags.
func (o Options) BeforeReset(ctx *kong.Context) error {
return style.HideFlags(ctx)
style.HideFlags(ctx)
return nil
}

View File

@ -4,8 +4,7 @@
// It can be used to prompt the user for some input. The text the user entered
// will be sent to stdout.
//
// $ gum input --placeholder "What's your favorite gum?" > answer.text
//
// $ gum input --placeholder "What's your favorite gum?" > answer.text
package input
import (
@ -23,11 +22,11 @@ func (m model) View() string { return m.textinput.View() }
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyEscape, tea.KeyCtrlC:
switch msg.String() {
case "ctrl+c", "esc":
m.aborted = true
fallthrough
case tea.KeyEnter:
return m, tea.Quit
case "enter":
return m, tea.Quit
}
}

View File

@ -3,7 +3,6 @@ package input
import "github.com/charmbracelet/gum/style"
// Options are the customization options for the input.
// nolint:staticcheck
type Options struct {
Placeholder string `help:"Placeholder value" default:"Type something..." env:"GUM_INPUT_PLACEHOLDER"`
Prompt string `help:"Prompt to display" default:"> " env:"GUM_INPUT_PROMPT"`

View File

@ -2,7 +2,7 @@ package stdin
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"strings"
@ -12,7 +12,7 @@ import (
func Read() (string, error) {
stat, err := os.Stdin.Stat()
if err != nil {
return "", errors.New("failed to get stdin stat")
return "", fmt.Errorf("failed to stat stdin: %w", err)
}
if stat.Mode()&os.ModeNamedPipe == 0 && stat.Size() == 0 {
@ -29,7 +29,7 @@ func Read() (string, error) {
}
_, err = b.WriteRune(r)
if err != nil {
return "", err
return "", fmt.Errorf("failed to write rune: %w", err)
}
}

View File

@ -6,21 +6,21 @@
// wrap the variable in quotes to ensure the new lines are part of a single
// argument. Otherwise, the command won't work as expected.
//
// $ gum join --horizontal "$BUBBLE_BOX" "$GUM_BOX"
//
// ╔══════════════════════╗╔═════════════╗
// ║ ║║ ║
// ║ Bubble ║║ Gum ║
// ║ ║║ ║
// ╚══════════════════════╝╚═════════════╝
// $ gum join --horizontal "$BUBBLE_BOX" "$GUM_BOX"
//
// ╔══════════════════════╗╔═════════════╗
// ║ ║║ ║
// ║ Bubble ║║ Gum ║
// ║ ║║ ║
// ╚══════════════════════╝╚═════════════╝
package join
import (
"fmt"
"github.com/charmbracelet/gum/internal/decode"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/gum/internal/decode"
)
// Run is the command-line interface for the joining strings through lipgloss.

View File

@ -7,11 +7,14 @@ import (
"runtime/debug"
"github.com/alecthomas/kong"
"github.com/charmbracelet/gum/internal/exit"
"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
"github.com/charmbracelet/gum/internal/exit"
)
const shaLen = 7
var (
// Version contains the application version number. It's set via ldflags
// when building.
@ -35,8 +38,8 @@ func main() {
}
}
version := fmt.Sprintf("gum version %s", Version)
if len(CommitSHA) >= 7 {
version += " (" + CommitSHA[:7] + ")"
if len(CommitSHA) >= shaLen {
version += " (" + CommitSHA[:shaLen] + ")"
}
gum := &Gum{}

View File

@ -7,6 +7,7 @@ import (
"github.com/alecthomas/kong"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/gum/internal/exit"
"github.com/charmbracelet/gum/style"
)
@ -27,7 +28,7 @@ func (o Options) Run() error {
m = mm.(model)
if err != nil {
return err
return fmt.Errorf("failed to run spin: %w", err)
}
if o.ShowOutput {
@ -45,5 +46,6 @@ func (o Options) Run() error {
// BeforeReset hook. Used to unclutter style flags.
func (o Options) BeforeReset(ctx *kong.Context) error {
return style.HideFlags(ctx)
style.HideFlags(ctx)
return nil
}

View File

@ -3,7 +3,6 @@ package spin
import "github.com/charmbracelet/gum/style"
// Options is the customization options for the spin command.
// nolint:staticcheck
type Options struct {
Command []string `arg:"" help:"Command to run"`

View File

@ -9,10 +9,9 @@
// We can simply prepend a spinner to this task to show it to the user, while
// performing the task / command in the background.
//
// $ gum spin -t "Taking a nap..." -- sleep 5
// $ gum spin -t "Taking a nap..." -- sleep 5
//
// The spinner will automatically exit when the task is complete.
//
package spin
import (

View File

@ -3,24 +3,6 @@
//
// It allows you to use Lip Gloss to style text without needing to use Go. All
// of the styling options are available as flags.
//
// Let's make some text glamorous using bash:
//
// $ gum style \
// --foreground 212 --border double --align center \
// --width 50 --margin 2 --padding "2 4" \
// "Bubble Gum (1¢)" "So sweet and so fresh\!"
//
//
// ╔══════════════════════════════════════════════════╗
// ║ ║
// ║ ║
// ║ Bubble Gum (1¢) ║
// ║ So sweet and so fresh! ║
// ║ ║
// ║ ║
// ╚══════════════════════════════════════════════════╝
//
package style
import (
@ -40,10 +22,10 @@ func (o Options) Run() error {
// HideFlags hides the flags from the usage output. This is used in conjunction
// with BeforeReset hook.
func HideFlags(ctx *kong.Context) error {
func HideFlags(ctx *kong.Context) {
n := ctx.Selected()
if n == nil {
return nil
return
}
for _, f := range n.Flags {
if g := f.Group; g != nil && g.Key == groupName {
@ -52,5 +34,4 @@ func HideFlags(ctx *kong.Context) error {
}
}
}
return nil
}

View File

@ -1,8 +1,9 @@
package style
import (
"github.com/charmbracelet/gum/internal/decode"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/gum/internal/decode"
)
// ToLipgloss takes a Styles flag set and returns the corresponding

View File

@ -5,6 +5,8 @@ import (
"strings"
)
const minTokens = 1
const halfTokens = 2
const maxTokens = 4
// parsePadding parses 1 - 4 integers from a string and returns them in a top,
@ -27,11 +29,11 @@ func parsePadding(s string) (int, int, int, int) {
ints[i] = parsed
}
if len(tokens) == 1 {
if len(tokens) == minTokens {
return ints[0], ints[0], ints[0], ints[0]
}
if len(tokens) == 2 {
if len(tokens) == halfTokens {
return ints[0], ints[1], ints[0], ints[1]
}

View File

@ -7,6 +7,7 @@ import (
"github.com/alecthomas/kong"
"github.com/charmbracelet/bubbles/textarea"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/gum/internal/exit"
"github.com/charmbracelet/gum/internal/stdin"
"github.com/charmbracelet/gum/style"
@ -48,16 +49,20 @@ func (o Options) Run() error {
p := tea.NewProgram(model{textarea: a}, tea.WithOutput(os.Stderr))
tm, err := p.StartReturningModel()
if err != nil {
return fmt.Errorf("failed to run write: %w", err)
}
m := tm.(model)
if m.aborted {
return exit.ErrAborted
}
fmt.Println(m.textarea.Value())
return err
return nil
}
// BeforeReset hook. Used to unclutter style flags.
func (o Options) BeforeReset(ctx *kong.Context) error {
return style.HideFlags(ctx)
style.HideFlags(ctx)
return nil
}

View File

@ -3,7 +3,6 @@ package write
import "github.com/charmbracelet/gum/style"
// Options are the customization options for the textarea.
// nolint:staticcheck
type Options struct {
Width int `help:"Text area width" default:"50" env:"GUM_WRITE_WIDTH"`
Height int `help:"Text area height" default:"5" env:"GUM_WRITE_HEIGHT"`

View File

@ -1,11 +1,10 @@
// Package write provides a shell script interface for the text area bubble.
// https://github.com/charmbracelet/bubbles/tree/master/textarea
//
// It can be used to ask the user to write some long form of text
// (multi-line) input. The text the user entered will be sent to stdout.
//
// $ gum write > output.text
// It can be used to ask the user to write some long form of text (multi-line)
// input. The text the user entered will be sent to stdout.
//
// $ gum write > output.text
package write
import (
@ -29,11 +28,12 @@ func (m model) View() string {
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyCtrlC:
switch msg.String() {
case "ctrl+c":
m.aborted = true
fallthrough
case tea.KeyEscape, tea.KeyCtrlD:
m.quitting = true
return m, tea.Quit
case "esc", "ctrl+d":
m.quitting = true
return m, tea.Quit
}