diff --git a/.gitignore b/.gitignore index ee1b1c1..6b01183 100755 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,9 @@ coverage.html # Taskfile .task +# rumdl +.rumdl-cache + # Comparative benchmarks before.txt after.txt diff --git a/.rumdl.toml b/.rumdl.toml new file mode 100644 index 0000000..509c326 --- /dev/null +++ b/.rumdl.toml @@ -0,0 +1,34 @@ +# rumdl configuration file + +# Global configuration options +[global] +# List of rules to disable (uncomment and modify as needed) +disable = [ + "MD033", # No inline html + "MD013", # Line length +] + +# List of rules to enable exclusively (if provided, only these rules will run) +# enable = ["MD001", "MD003", "MD004"] + +# List of file/directory patterns to include for linting (if provided, only these will be linted) +# include = [ +# "docs/*.md", +# "src/**/*.md", +# "README.md" +# ] + +# List of file/directory patterns to exclude from linting +exclude = [ + # Common directories to exclude + ".git", + ".github", + "node_modules", + "vendor", + "dist", + "build", + + # Specific files or patterns + "CHANGELOG.md", + "LICENSE.md", +] diff --git a/README.md b/README.md index 0bd327f..916c5f1 100644 --- a/README.md +++ b/README.md @@ -255,8 +255,12 @@ cli.New( ) ``` -And just like [Flags](#flags), your argument types are all inferred and parsed automatically ✨, and you get nicer `--help` output too! Have a look at the [`./examples`](https://github.com/FollowTheProcess/cli/tree/main/examples) -to see more! +And just like [Flags](#flags), your argument types are all inferred and parsed automatically ✨, and you get nicer `--help` output too! + +Have a look at the [`./examples`](https://github.com/FollowTheProcess/cli/tree/main/examples) to see more! + +Other CLI libraries that do this sort of thing rely heavily on reflection and struct tags, `cli` does things differently! We prefer Go code +to be 100% type safe and statically checkable, so all this is implemented using generics and compile time checks 🚀 > [!NOTE] > Just like flags, you can't really get this wrong. The types you can use for arguments are part of a generic constraint so using the wrong type results in a compiler error diff --git a/Taskfile.yml b/Taskfile.yml index 7910bc1..348bd36 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -23,11 +23,19 @@ tasks: fmt: desc: Run go fmt on all source files + preconditions: + - sh: command -v golangci-lint + msg: golangci-lint not installed, see https://golangci-lint.run/usage/install/#local-installation + + - sh: command -v rumdl + msg: rumdl not installed, see https://github.com/rvben/rumdl#installation sources: - "**/*.go" - .golangci.yml + - "**/*.md" cmds: - golangci-lint fmt ./... + - rumdl fmt --fix . test: desc: Run the test suite @@ -65,8 +73,12 @@ tasks: - sh: command -v typos msg: requires typos-cli, run `brew install typos-cli` + + - sh: command -v rumdl + msg: rumdl not installed, see https://github.com/rvben/rumdl#installation cmds: - golangci-lint run --fix + - rumdl check --fix . - typos - nilaway ./... diff --git a/command.go b/command.go index e5ce7ac..7d1ceb3 100644 --- a/command.go +++ b/command.go @@ -13,8 +13,6 @@ import ( "go.followtheprocess.codes/cli/internal/arg" "go.followtheprocess.codes/cli/internal/flag" "go.followtheprocess.codes/cli/internal/style" - - "go.followtheprocess.codes/hue/tabwriter" ) const ( @@ -581,7 +579,7 @@ func writeArgumentsSection(cmd *Command, s *strings.Builder) error { s.WriteString("\n\n") s.WriteString(style.Title.Text("Arguments")) s.WriteString(":\n\n") - tw := tabwriter.NewWriter(s, style.MinWidth, style.TabWidth, style.Padding, style.PadChar, style.Flags) + tw := style.Tabwriter(s) for _, arg := range cmd.args { switch arg.Default() { @@ -646,7 +644,7 @@ func writeSubcommands(cmd *Command, s *strings.Builder) error { s.WriteByte(':') s.WriteString("\n\n") - tw := tabwriter.NewWriter(s, style.MinWidth, style.TabWidth, style.Padding, style.PadChar, style.Flags) + tw := style.Tabwriter(s) for _, subcommand := range cmd.subcommands { fmt.Fprintf(tw, " %s\t%s\n", style.Bold.Text(subcommand.name), subcommand.short) } diff --git a/internal/flag/set.go b/internal/flag/set.go index 0c2dadb..e2da64f 100644 --- a/internal/flag/set.go +++ b/internal/flag/set.go @@ -10,7 +10,6 @@ import ( "go.followtheprocess.codes/cli/flag" "go.followtheprocess.codes/cli/internal/format" "go.followtheprocess.codes/cli/internal/style" - "go.followtheprocess.codes/hue/tabwriter" ) // usageBufferSize is sufficient to hold most commands flag usage text. @@ -201,7 +200,7 @@ func (s *Set) Usage() (string, error) { slices.Sort(names) - tw := tabwriter.NewWriter(buf, style.MinWidth, style.TabWidth, style.Padding, style.PadChar, style.Flags) + tw := style.Tabwriter(buf) for _, name := range names { f := s.flags[name] diff --git a/internal/style/style.go b/internal/style/style.go index 74aad7f..0397324 100644 --- a/internal/style/style.go +++ b/internal/style/style.go @@ -4,7 +4,12 @@ // [hue]: https://github.com/FollowTheProcess/hue package style -import "go.followtheprocess.codes/hue" +import ( + "io" + + "go.followtheprocess.codes/hue" + "go.followtheprocess.codes/hue/tabwriter" +) const ( // Title is the style for titles of help text sections like arguments or commands. @@ -13,18 +18,23 @@ const ( // Bold is simply plain bold text. Bold = hue.Bold - // MinWidth is the minimum cell width for hue's colour-enabled tabwriter. - MinWidth = 1 + // minWidth is the minimum cell width for hue's colour-enabled tabwriter. + minWidth = 1 - // TabWidth is the width of tabs in spaces for tabwriter. - TabWidth = 8 + // tabWidth is the width of tabs in spaces for tabwriter. + tabWidth = 8 - // Padding is the number of PadChars to pad table cells with. - Padding = 2 + // padding is the number of PadChars to pad table cells with. + padding = 2 - // PadChar is the character with which to pad table cells. - PadChar = ' ' + // padChar is the character with which to pad table cells. + padChar = ' ' - // Flags is the tabwriter config flags. - Flags = 0 + // flags is the tabwriter config flags. + flags = 0 ) + +// Tabwriter returns a [hue.Tabwriter] configured with cli house style. +func Tabwriter(w io.Writer) *tabwriter.Writer { + return tabwriter.NewWriter(w, minWidth, tabWidth, padding, padChar, flags) +}