diff --git a/.github/workflows/lint-soft.yml b/.github/workflows/lint-soft.yml new file mode 100644 index 0000000..77348b9 --- /dev/null +++ b/.github/workflows/lint-soft.yml @@ -0,0 +1,28 @@ +name: lint-soft +on: + push: + pull_request: + +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + pull-requests: read + +jobs: + golangci: + name: lint-soft + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: ^1 + + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + # Optional: golangci-lint command line arguments. + args: --config .golangci-soft.yml --issues-exit-code=0 + # Optional: show only new issues if it's a pull request. The default value is `false`. + only-new-issues: true diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..1129ece --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,28 @@ +name: lint +on: + push: + pull_request: + +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + pull-requests: read + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: ^1 + + - uses: actions/checkout@v3 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + # Optional: golangci-lint command line arguments. + #args: + # Optional: show only new issues if it's a pull request. The default value is `false`. + only-new-issues: true diff --git a/.golangci-soft.yml b/.golangci-soft.yml new file mode 100644 index 0000000..ef456e0 --- /dev/null +++ b/.golangci-soft.yml @@ -0,0 +1,47 @@ +run: + tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + # - dupl + - exhaustive + # - exhaustivestruct + - goconst + - godot + - godox + - gomnd + - gomoddirectives + - goprintffuncname + - ifshort + # - lll + - misspell + - nakedret + - nestif + - noctx + - nolintlint + - prealloc + - wrapcheck + + # disable default linters, they are already enabled in .golangci.yml + disable: + - deadcode + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - structcheck + - typecheck + - unused + - varcheck diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..a5a91d0 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,29 @@ +run: + tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - bodyclose + - exportloopref + - goimports + - gosec + - nilerr + - predeclared + - revive + - rowserrcheck + - sqlclosecheck + - tparallel + - unconvert + - unparam + - whitespace diff --git a/choose/choose.go b/choose/choose.go index 9f2e9c1..a6b669f 100644 --- a/choose/choose.go +++ b/choose/choose.go @@ -139,6 +139,7 @@ func (m model) View() string { return s.String() } +//nolint:unparam func clamp(x, min, max int) int { if x < min { return min diff --git a/choose/options.go b/choose/options.go index f5edf23..8359e91 100644 --- a/choose/options.go +++ b/choose/options.go @@ -3,6 +3,7 @@ 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."` diff --git a/completion/bash.go b/completion/bash.go index 5f06deb..f8756db 100644 --- a/completion/bash.go +++ b/completion/bash.go @@ -1,4 +1,3 @@ -// TODO implement our own gum bash completion package completion import ( @@ -59,7 +58,7 @@ const ( // All directives using iota should be above this one. // For internal use. - shellCompDirectiveMaxValue + shellCompDirectiveMaxValue //nolint:deadcode,unused,varcheck // ShellCompDirectiveDefault indicates to let the shell perform its default // behavior after completions have been provided. @@ -576,6 +575,7 @@ func writeFlag(buf io.StringWriter, flag *kong.Flag, cmd *kong.Node) { writeFlagHandler(buf, "--"+name, map[string][]string{}, cmd) } +//nolint:deadcode,unused func writeLocalNonPersistentFlag(buf io.StringWriter, flag *kong.Flag) { name := flag.Name format := " local_nonpersistent_flags+=(\"--%[1]s" + cbn diff --git a/completion/command.go b/completion/command.go index 95d501b..ebc552f 100644 --- a/completion/command.go +++ b/completion/command.go @@ -9,6 +9,7 @@ import ( "github.com/alecthomas/kong" ) +// Completion command. type Completion struct { Bash Bash `cmd:"" help:"Generate the autocompletion script for bash"` Zsh Zsh `cmd:"" help:"Generate the autocompletion script for zsh"` @@ -31,6 +32,7 @@ func hasCommands(cmd *kong.Node) bool { return false } +//nolint:deadcode,unused func isArgument(cmd *kong.Node) bool { return cmd.Type == kong.ArgumentNode } diff --git a/completion/fish.go b/completion/fish.go index b7c978e..362f0fe 100644 --- a/completion/fish.go +++ b/completion/fish.go @@ -34,10 +34,10 @@ func (f Fish) gen(buf io.StringWriter, cmd *kong.Node) { } rootName := root.Name if cmd.Parent == nil { - buf.WriteString(fmt.Sprintf("# %s\n", rootName)) + _, _ = buf.WriteString(fmt.Sprintf("# %s\n", rootName)) } else { - buf.WriteString(fmt.Sprintf("# %s\n", cmd.Path())) - buf.WriteString( + _, _ = 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, @@ -51,13 +51,13 @@ func (f Fish) gen(buf io.StringWriter, cmd *kong.Node) { continue } if cmd.Parent == nil { - buf.WriteString( + _, _ = buf.WriteString( fmt.Sprintf("complete -c %s -f", rootName, ), ) } else { - buf.WriteString( + _, _ = buf.WriteString( fmt.Sprintf("complete -c %s -f -n '__fish_seen_subcommand_from %s'", rootName, cmd.Name, @@ -67,19 +67,19 @@ func (f Fish) gen(buf io.StringWriter, cmd *kong.Node) { if !f.IsBool() { enums := flagPossibleValues(f) if len(enums) > 0 { - buf.WriteString(fmt.Sprintf(" -xa '%s'", strings.Join(enums, " "))) + _, _ = buf.WriteString(fmt.Sprintf(" -xa '%s'", strings.Join(enums, " "))) } else { - buf.WriteString(" -x") + _, _ = buf.WriteString(" -x") } } if f.Short != 0 { - buf.WriteString(fmt.Sprintf(" -s %c", f.Short)) + _, _ = 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(fmt.Sprintf(" -l %s", f.Name)) + _, _ = buf.WriteString(fmt.Sprintf(" -d '%s'", f.Help)) + _, _ = buf.WriteString("\n") } - buf.WriteString("\n") + _, _ = buf.WriteString("\n") for _, c := range cmd.Children { if c == nil || c.Hidden { diff --git a/completion/zsh.go b/completion/zsh.go index bd73715..0e7c40f 100644 --- a/completion/zsh.go +++ b/completion/zsh.go @@ -93,7 +93,7 @@ func (z Zsh) writeCommands(buf io.StringWriter, cmd *kong.Node) { } z.writeCommand(buf, c) if i < len(cmd.Children)-1 { - buf.WriteString(" \\") + _, _ = buf.WriteString(" \\") } writeString(buf, "\n") } diff --git a/confirm/options.go b/confirm/options.go index 94650c1..bbf4b98 100644 --- a/confirm/options.go +++ b/confirm/options.go @@ -3,6 +3,7 @@ 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"` diff --git a/filter/command.go b/filter/command.go index cf452ee..6a5701e 100644 --- a/filter/command.go +++ b/filter/command.go @@ -27,7 +27,7 @@ func (o Options) Run() error { input, _ := stdin.Read() var choices []string if input != "" { - choices = strings.Split(string(input), "\n") + choices = strings.Split(input, "\n") } else { choices = files.List() } diff --git a/filter/filter.go b/filter/filter.go index d61b05e..79fa619 100644 --- a/filter/filter.go +++ b/filter/filter.go @@ -45,7 +45,6 @@ func (m model) View() string { // Since there are matches, display them so that the user can see, in real // time, what they are searching for. for i, match := range m.matches { - // If this is the current selected index, we add a small indicator to // represent it. Otherwise, simply pad the string. if i == m.selected { diff --git a/filter/options.go b/filter/options.go index d29078f..102fdae 100644 --- a/filter/options.go +++ b/filter/options.go @@ -3,6 +3,7 @@ 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:"•"` IndicatorStyle style.Styles `embed:"" prefix:"indicator." set:"defaultForeground=212" set:"name=indicator"` diff --git a/format/command.go b/format/command.go index d3db6b0..293b347 100644 --- a/format/command.go +++ b/format/command.go @@ -19,7 +19,7 @@ import ( ) // Func is a function that formats some text -type Func func(string) string +type Func func(string) (string, error) var formatType = map[string]Func{ "code": code, @@ -37,6 +37,11 @@ func (o Options) Run() error { input, _ = stdin.Read() } - fmt.Println(formatType[o.Type](input)) + v, err := formatType[o.Type](input) + if err != nil { + return err + } + + fmt.Println(v) return nil } diff --git a/format/formats.go b/format/formats.go index 5d6c596..648eefa 100644 --- a/format/formats.go +++ b/format/formats.go @@ -9,57 +9,46 @@ import ( "github.com/muesli/termenv" ) -var code Func = func(input string) string { +var code Func = func(input string) (string, error) { renderer, err := glamour.NewTermRenderer( glamour.WithAutoStyle(), glamour.WithWordWrap(0), ) if err != nil { - return "" + return "", err } - out, err := renderer.Render(fmt.Sprintf("```\n%s\n```", input)) - if err != nil { - return "" - } - return out + return renderer.Render(fmt.Sprintf("```\n%s\n```", input)) } -var emoji Func = func(input string) string { +var emoji Func = func(input string) (string, error) { renderer, err := glamour.NewTermRenderer( glamour.WithEmoji(), ) if err != nil { - return "" + return "", err } - out, err := renderer.Render(input) - if err != nil { - return "" - } - return out + return renderer.Render(input) } -var markdown Func = func(input string) string { +var markdown Func = func(input string) (string, error) { renderer, err := glamour.NewTermRenderer( glamour.WithStandardStyle("pink"), glamour.WithWordWrap(0), ) if err != nil { - return "" + return "", err } - out, err := renderer.Render(input) - if err != nil { - return "" - } - return out + return renderer.Render(input) } -var template Func = func(input string) string { +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 "" + return "", err } + var buf bytes.Buffer - t.Execute(&buf, nil) - return buf.String() + err = t.Execute(&buf, nil) + return buf.String(), err } diff --git a/input/options.go b/input/options.go index 5d3d50f..ede3dc3 100644 --- a/input/options.go +++ b/input/options.go @@ -3,6 +3,7 @@ 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..."` Prompt string `help:"Prompt to display" default:"> "` diff --git a/internal/files/files.go b/internal/files/files.go index fd40517..51e6950 100644 --- a/internal/files/files.go +++ b/internal/files/files.go @@ -13,7 +13,7 @@ func List() []string { err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error { if shouldIgnore(path) || info.IsDir() || err != nil { - return nil + return nil //nolint:nilerr } files = append(files, path) return nil @@ -23,7 +23,6 @@ func List() []string { return []string{} } return files - } var defaultIgnorePatterns = []string{"node_modules", ".git", "."} diff --git a/main.go b/main.go index 3214a83..ddd9aa6 100644 --- a/main.go +++ b/main.go @@ -54,5 +54,5 @@ func main() { "defaultUnderline": "false", }, ) - ctx.Run() + _ = ctx.Run() } diff --git a/spin/options.go b/spin/options.go index 8323ac6..f5995c8 100644 --- a/spin/options.go +++ b/spin/options.go @@ -3,6 +3,7 @@ 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"` diff --git a/spin/spin.go b/spin/spin.go index 7ec4586..571faa3 100644 --- a/spin/spin.go +++ b/spin/spin.go @@ -36,7 +36,7 @@ func commandStart(command []string) tea.Cmd { if len(command) > 1 { args = command[1:] } - out, _ := exec.Command(command[0], args...).Output() + out, _ := exec.Command(command[0], args...).Output() //nolint:gosec return finishCommandMsg{output: string(out)} } } diff --git a/write/options.go b/write/options.go index 54099d0..b8c96bb 100644 --- a/write/options.go +++ b/write/options.go @@ -3,6 +3,7 @@ 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"` Height int `help:"Text area height" default:"5"`