mirror of
https://github.com/charmbracelet/gum
synced 2024-05-25 09:52:24 +02:00
Add soft & hard linter configs & workflows (#44)
* chore: add linter configs & workflows * fix: ignore certain linter warnings * fix: mark errors as intentionally ignored * fix: avoid unnecessary conversion * fix: handle template/renderer errors * fix: mark intentionally unused code
This commit is contained in:
parent
e4fc0c2e74
commit
66993d8ef1
28
.github/workflows/lint-soft.yml
vendored
Normal file
28
.github/workflows/lint-soft.yml
vendored
Normal file
|
@ -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
|
28
.github/workflows/lint.yml
vendored
Normal file
28
.github/workflows/lint.yml
vendored
Normal file
|
@ -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
|
47
.golangci-soft.yml
Normal file
47
.golangci-soft.yml
Normal file
|
@ -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
|
29
.golangci.yml
Normal file
29
.golangci.yml
Normal file
|
@ -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
|
|
@ -139,6 +139,7 @@ func (m model) View() string {
|
||||||
return s.String()
|
return s.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:unparam
|
||||||
func clamp(x, min, max int) int {
|
func clamp(x, min, max int) int {
|
||||||
if x < min {
|
if x < min {
|
||||||
return min
|
return min
|
||||||
|
|
|
@ -3,6 +3,7 @@ package choose
|
||||||
import "github.com/charmbracelet/gum/style"
|
import "github.com/charmbracelet/gum/style"
|
||||||
|
|
||||||
// Options is the customization options for the choose command.
|
// Options is the customization options for the choose command.
|
||||||
|
// nolint:staticcheck
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Options []string `arg:"" optional:"" help:"Options to choose from."`
|
Options []string `arg:"" optional:"" help:"Options to choose from."`
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// TODO implement our own gum bash completion
|
|
||||||
package completion
|
package completion
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -59,7 +58,7 @@ const (
|
||||||
|
|
||||||
// All directives using iota should be above this one.
|
// All directives using iota should be above this one.
|
||||||
// For internal use.
|
// For internal use.
|
||||||
shellCompDirectiveMaxValue
|
shellCompDirectiveMaxValue //nolint:deadcode,unused,varcheck
|
||||||
|
|
||||||
// ShellCompDirectiveDefault indicates to let the shell perform its default
|
// ShellCompDirectiveDefault indicates to let the shell perform its default
|
||||||
// behavior after completions have been provided.
|
// 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)
|
writeFlagHandler(buf, "--"+name, map[string][]string{}, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:deadcode,unused
|
||||||
func writeLocalNonPersistentFlag(buf io.StringWriter, flag *kong.Flag) {
|
func writeLocalNonPersistentFlag(buf io.StringWriter, flag *kong.Flag) {
|
||||||
name := flag.Name
|
name := flag.Name
|
||||||
format := " local_nonpersistent_flags+=(\"--%[1]s" + cbn
|
format := " local_nonpersistent_flags+=(\"--%[1]s" + cbn
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Completion command.
|
||||||
type Completion struct {
|
type Completion struct {
|
||||||
Bash Bash `cmd:"" help:"Generate the autocompletion script for bash"`
|
Bash Bash `cmd:"" help:"Generate the autocompletion script for bash"`
|
||||||
Zsh Zsh `cmd:"" help:"Generate the autocompletion script for zsh"`
|
Zsh Zsh `cmd:"" help:"Generate the autocompletion script for zsh"`
|
||||||
|
@ -31,6 +32,7 @@ func hasCommands(cmd *kong.Node) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:deadcode,unused
|
||||||
func isArgument(cmd *kong.Node) bool {
|
func isArgument(cmd *kong.Node) bool {
|
||||||
return cmd.Type == kong.ArgumentNode
|
return cmd.Type == kong.ArgumentNode
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,10 @@ func (f Fish) gen(buf io.StringWriter, cmd *kong.Node) {
|
||||||
}
|
}
|
||||||
rootName := root.Name
|
rootName := root.Name
|
||||||
if cmd.Parent == nil {
|
if cmd.Parent == nil {
|
||||||
buf.WriteString(fmt.Sprintf("# %s\n", rootName))
|
_, _ = buf.WriteString(fmt.Sprintf("# %s\n", rootName))
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString(fmt.Sprintf("# %s\n", cmd.Path()))
|
_, _ = buf.WriteString(fmt.Sprintf("# %s\n", cmd.Path()))
|
||||||
buf.WriteString(
|
_, _ = buf.WriteString(
|
||||||
fmt.Sprintf("complete -c %s -f -n '__fish_use_subcommand' -a %s -d '%s'\n",
|
fmt.Sprintf("complete -c %s -f -n '__fish_use_subcommand' -a %s -d '%s'\n",
|
||||||
rootName,
|
rootName,
|
||||||
cmd.Name,
|
cmd.Name,
|
||||||
|
@ -51,13 +51,13 @@ func (f Fish) gen(buf io.StringWriter, cmd *kong.Node) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if cmd.Parent == nil {
|
if cmd.Parent == nil {
|
||||||
buf.WriteString(
|
_, _ = buf.WriteString(
|
||||||
fmt.Sprintf("complete -c %s -f",
|
fmt.Sprintf("complete -c %s -f",
|
||||||
rootName,
|
rootName,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString(
|
_, _ = buf.WriteString(
|
||||||
fmt.Sprintf("complete -c %s -f -n '__fish_seen_subcommand_from %s'",
|
fmt.Sprintf("complete -c %s -f -n '__fish_seen_subcommand_from %s'",
|
||||||
rootName,
|
rootName,
|
||||||
cmd.Name,
|
cmd.Name,
|
||||||
|
@ -67,19 +67,19 @@ func (f Fish) gen(buf io.StringWriter, cmd *kong.Node) {
|
||||||
if !f.IsBool() {
|
if !f.IsBool() {
|
||||||
enums := flagPossibleValues(f)
|
enums := flagPossibleValues(f)
|
||||||
if len(enums) > 0 {
|
if len(enums) > 0 {
|
||||||
buf.WriteString(fmt.Sprintf(" -xa '%s'", strings.Join(enums, " ")))
|
_, _ = buf.WriteString(fmt.Sprintf(" -xa '%s'", strings.Join(enums, " ")))
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString(" -x")
|
_, _ = buf.WriteString(" -x")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.Short != 0 {
|
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(" -l %s", f.Name))
|
||||||
buf.WriteString(fmt.Sprintf(" -d '%s'", f.Help))
|
_, _ = buf.WriteString(fmt.Sprintf(" -d '%s'", f.Help))
|
||||||
buf.WriteString("\n")
|
_, _ = buf.WriteString("\n")
|
||||||
}
|
}
|
||||||
buf.WriteString("\n")
|
_, _ = buf.WriteString("\n")
|
||||||
|
|
||||||
for _, c := range cmd.Children {
|
for _, c := range cmd.Children {
|
||||||
if c == nil || c.Hidden {
|
if c == nil || c.Hidden {
|
||||||
|
|
|
@ -93,7 +93,7 @@ func (z Zsh) writeCommands(buf io.StringWriter, cmd *kong.Node) {
|
||||||
}
|
}
|
||||||
z.writeCommand(buf, c)
|
z.writeCommand(buf, c)
|
||||||
if i < len(cmd.Children)-1 {
|
if i < len(cmd.Children)-1 {
|
||||||
buf.WriteString(" \\")
|
_, _ = buf.WriteString(" \\")
|
||||||
}
|
}
|
||||||
writeString(buf, "\n")
|
writeString(buf, "\n")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package confirm
|
||||||
import "github.com/charmbracelet/gum/style"
|
import "github.com/charmbracelet/gum/style"
|
||||||
|
|
||||||
// Options is the customization options for the confirm command.
|
// Options is the customization options for the confirm command.
|
||||||
|
// nolint:staticcheck
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Affirmative string `help:"The title of the affirmative action" default:"Yes"`
|
Affirmative string `help:"The title of the affirmative action" default:"Yes"`
|
||||||
Negative string `help:"The title of the negative action" default:"No"`
|
Negative string `help:"The title of the negative action" default:"No"`
|
||||||
|
|
|
@ -27,7 +27,7 @@ func (o Options) Run() error {
|
||||||
input, _ := stdin.Read()
|
input, _ := stdin.Read()
|
||||||
var choices []string
|
var choices []string
|
||||||
if input != "" {
|
if input != "" {
|
||||||
choices = strings.Split(string(input), "\n")
|
choices = strings.Split(input, "\n")
|
||||||
} else {
|
} else {
|
||||||
choices = files.List()
|
choices = files.List()
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ func (m model) View() string {
|
||||||
// Since there are matches, display them so that the user can see, in real
|
// Since there are matches, display them so that the user can see, in real
|
||||||
// time, what they are searching for.
|
// time, what they are searching for.
|
||||||
for i, match := range m.matches {
|
for i, match := range m.matches {
|
||||||
|
|
||||||
// If this is the current selected index, we add a small indicator to
|
// If this is the current selected index, we add a small indicator to
|
||||||
// represent it. Otherwise, simply pad the string.
|
// represent it. Otherwise, simply pad the string.
|
||||||
if i == m.selected {
|
if i == m.selected {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package filter
|
||||||
import "github.com/charmbracelet/gum/style"
|
import "github.com/charmbracelet/gum/style"
|
||||||
|
|
||||||
// Options is the customization options for the filter command.
|
// Options is the customization options for the filter command.
|
||||||
|
// nolint:staticcheck
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Indicator string `help:"Character for selection" default:"•"`
|
Indicator string `help:"Character for selection" default:"•"`
|
||||||
IndicatorStyle style.Styles `embed:"" prefix:"indicator." set:"defaultForeground=212" set:"name=indicator"`
|
IndicatorStyle style.Styles `embed:"" prefix:"indicator." set:"defaultForeground=212" set:"name=indicator"`
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Func is a function that formats some text
|
// Func is a function that formats some text
|
||||||
type Func func(string) string
|
type Func func(string) (string, error)
|
||||||
|
|
||||||
var formatType = map[string]Func{
|
var formatType = map[string]Func{
|
||||||
"code": code,
|
"code": code,
|
||||||
|
@ -37,6 +37,11 @@ func (o Options) Run() error {
|
||||||
input, _ = stdin.Read()
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,57 +9,46 @@ import (
|
||||||
"github.com/muesli/termenv"
|
"github.com/muesli/termenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var code Func = func(input string) string {
|
var code Func = func(input string) (string, error) {
|
||||||
renderer, err := glamour.NewTermRenderer(
|
renderer, err := glamour.NewTermRenderer(
|
||||||
glamour.WithAutoStyle(),
|
glamour.WithAutoStyle(),
|
||||||
glamour.WithWordWrap(0),
|
glamour.WithWordWrap(0),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return "", err
|
||||||
}
|
}
|
||||||
out, err := renderer.Render(fmt.Sprintf("```\n%s\n```", input))
|
return renderer.Render(fmt.Sprintf("```\n%s\n```", input))
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var emoji Func = func(input string) string {
|
var emoji Func = func(input string) (string, error) {
|
||||||
renderer, err := glamour.NewTermRenderer(
|
renderer, err := glamour.NewTermRenderer(
|
||||||
glamour.WithEmoji(),
|
glamour.WithEmoji(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return "", err
|
||||||
}
|
}
|
||||||
out, err := renderer.Render(input)
|
return renderer.Render(input)
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var markdown Func = func(input string) string {
|
var markdown Func = func(input string) (string, error) {
|
||||||
renderer, err := glamour.NewTermRenderer(
|
renderer, err := glamour.NewTermRenderer(
|
||||||
glamour.WithStandardStyle("pink"),
|
glamour.WithStandardStyle("pink"),
|
||||||
glamour.WithWordWrap(0),
|
glamour.WithWordWrap(0),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return "", err
|
||||||
}
|
}
|
||||||
out, err := renderer.Render(input)
|
return renderer.Render(input)
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var template Func = func(input string) string {
|
var template Func = func(input string) (string, error) {
|
||||||
f := termenv.TemplateFuncs(termenv.ColorProfile())
|
f := termenv.TemplateFuncs(termenv.ColorProfile())
|
||||||
t, err := tpl.New("tpl").Funcs(f).Parse(input)
|
t, err := tpl.New("tpl").Funcs(f).Parse(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
t.Execute(&buf, nil)
|
err = t.Execute(&buf, nil)
|
||||||
return buf.String()
|
return buf.String(), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package input
|
||||||
import "github.com/charmbracelet/gum/style"
|
import "github.com/charmbracelet/gum/style"
|
||||||
|
|
||||||
// Options are the customization options for the input.
|
// Options are the customization options for the input.
|
||||||
|
// nolint:staticcheck
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Placeholder string `help:"Placeholder value" default:"Type something..."`
|
Placeholder string `help:"Placeholder value" default:"Type something..."`
|
||||||
Prompt string `help:"Prompt to display" default:"> "`
|
Prompt string `help:"Prompt to display" default:"> "`
|
||||||
|
|
|
@ -13,7 +13,7 @@ func List() []string {
|
||||||
err := filepath.Walk(".",
|
err := filepath.Walk(".",
|
||||||
func(path string, info os.FileInfo, err error) error {
|
func(path string, info os.FileInfo, err error) error {
|
||||||
if shouldIgnore(path) || info.IsDir() || err != nil {
|
if shouldIgnore(path) || info.IsDir() || err != nil {
|
||||||
return nil
|
return nil //nolint:nilerr
|
||||||
}
|
}
|
||||||
files = append(files, path)
|
files = append(files, path)
|
||||||
return nil
|
return nil
|
||||||
|
@ -23,7 +23,6 @@ func List() []string {
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
return files
|
return files
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultIgnorePatterns = []string{"node_modules", ".git", "."}
|
var defaultIgnorePatterns = []string{"node_modules", ".git", "."}
|
||||||
|
|
2
main.go
2
main.go
|
@ -54,5 +54,5 @@ func main() {
|
||||||
"defaultUnderline": "false",
|
"defaultUnderline": "false",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
ctx.Run()
|
_ = ctx.Run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package spin
|
||||||
import "github.com/charmbracelet/gum/style"
|
import "github.com/charmbracelet/gum/style"
|
||||||
|
|
||||||
// Options is the customization options for the spin command.
|
// Options is the customization options for the spin command.
|
||||||
|
// nolint:staticcheck
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Command []string `arg:"" help:"Command to run"`
|
Command []string `arg:"" help:"Command to run"`
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ func commandStart(command []string) tea.Cmd {
|
||||||
if len(command) > 1 {
|
if len(command) > 1 {
|
||||||
args = 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)}
|
return finishCommandMsg{output: string(out)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package write
|
||||||
import "github.com/charmbracelet/gum/style"
|
import "github.com/charmbracelet/gum/style"
|
||||||
|
|
||||||
// Options are the customization options for the textarea.
|
// Options are the customization options for the textarea.
|
||||||
|
// nolint:staticcheck
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Width int `help:"Text area width" default:"50"`
|
Width int `help:"Text area width" default:"50"`
|
||||||
Height int `help:"Text area height" default:"5"`
|
Height int `help:"Text area height" default:"5"`
|
||||||
|
|
Loading…
Reference in a new issue