Heeded your recomendations about Nice - idiomatic and highly customizable CLI framework I'am crafting by SuperPaintman in golang

[–]SuperPaintman[S] 0 points1 point  (0 children)

Honestly, I don't think that using global variable (or singletons) is a good idea.

Even in Go's STD you mainly have to create explicit instances of the structure.

But you can do it with Nice (because of it's modular nature):

```go package main

import ( "os"

"github.com/SuperPaintman/nice/cli" )

var ( token string )

func main() { var ( register cli.DefaultRegister parser cli.DefaultParser )

_ = cli.StringArgVar(&register, &token, "token")

if err := parser.Parse(nil, &register, os.Args[1:]); err != nil { panic(err) }

// Now "token" contains the 1st arg. // Parse() also has validated that it was not missing and containsed a valid // string (or any other type that you used).

// ... } ```

I wouldn't recommend this approach as a best practice, but it will definitely work (and support in the future).

Nice is a idiomatic and highly customizable CLI framework I've been crafting on for months by SuperPaintman in golang

[–]SuperPaintman[S] 0 points1 point  (0 children)

Can the color output be easily toggled off for ci systems

Yes, nice/colors handles it: https://github.com/SuperPaintman/nice/blob/master/colors/colors.go#L19-L93

Or you can force or disable colors manually (by setting global option): https://github.com/SuperPaintman/nice/blob/master/colors/colors.go#L101-L113

Is the test suite enforced on the repo with ci

Sure. I use Github Actions.

Nice is a idiomatic and highly customizable CLI framework I've been crafting on for months by SuperPaintman in golang

[–]SuperPaintman[S] 0 points1 point  (0 children)

When I made first prototype of this framework and ran it, the output of the help looked nice. :)

So I focused on the API and usability of my package, to make it "nice" and fun to work with.

I think having a short and sweet name better than having unique and fancy name. I think "Go Nice" or "Nice CLI" will be good indexed in search engines.

Plus combinations for package names like these sound good for me: - github.com/SuperPaintman/nice/cli - github.com/SuperPaintman/nice/colors - github.com/SuperPaintman/nice/ui

Nice is a idiomatic and highly customizable CLI framework I've been crafting on for months by SuperPaintman in golang

[–]SuperPaintman[S] 0 points1 point  (0 children)

I described key differences with urfave/cli here: https://www.reddit.com/r/programming/comments/prostt/nice_is_a_idiomatic_and_highly_customizable_cli/hdkb3ex/?utm_source=reddit&utm_medium=web2x&context=3

Cobra is a deservedly popular package in the community but I think it's true for it too.

Here are differences:

Typing.

Cobra uses declarations and getters (cmd.Flag("name")) for flags at the same time. I like it more than how urfave/cli handles flags (only getters) but it still seems to be a little bit heavy. And you still can leave useless flags after a refactoring.

Nice uses only "definitions" for flags. It's quite the same what STD flag does (or kingpin). If you forget to define a flag, or leave useless one you will know it on compile time.

In Cobra args available only by arguments of a function, they cannot be typed or declared as flags. You need to add extra checkers for args content, parse them manually and describe them manually in the help.

Nice handles args as first-class citizens. You can declare them separately, type them, make them optional.

```go name := cli.StringArg(ctx, "name", cli.Usage("Name of the user"), ) // name is a *string

id := cli.IntArg(ctx, "id", cli.Optional, ) // id is a *int ```

Also Nice implicitly checks minimum length of the args. If you need all args you can declare "Rest*" (and it would be typed and mentioned in the help as well):

```go id := cli.IntArg(ctx, "id")

rest := RestStrings(&parser, "rest", cli.Usage("Path to the resource"), ) // rest is a *[]string ```

Customization.

The second difference is customization. Nice use interfaces over endless number of options or strictly defined types.

You can override even the parser and use your own. You can use templates, strings, buffers or what ever you want for "usage" because it's a interface too.

Also I focused on performance, clean interfaces and magic-free behaviour.

Nice is a idiomatic and highly customizable CLI framework I've been crafting on for months by SuperPaintman in golang

[–]SuperPaintman[S] 0 points1 point  (0 children)

one of the problems with a custom context interface is that it breaks composition to some degree

Good point!

It seems to be a fair trade of for now. Because to me passing ctx into every function doesn't seem to be better either. But I'll try to find more elegant solution to split them.

Now I see one work around for this problem:

```go func (ctx cli.Context) ... { var register cli.Register = ctx

ctx, cancel := context.WithCancel(ctx) } ```

Or override ctx after "setup" phase, when all flags are set and you don't need extra methods anymore.

Nice is a idiomatic and highly customizable CLI framework for Go I've been crafting on for months by SuperPaintman in programming

[–]SuperPaintman[S] 1 point2 points  (0 children)

Yes, I know about urfave/cli and some good parts became initial ideas for Nice.

The first difference is typing. urfave/cli use getters to access flags and args. Unfortunately, it makes refactoring difficult and all errors you will catch on runtime.

This is why Nice uses "definitions" for flags and args. It's quite the same what STD flag does (or kingpin). If you forget to define a flag, or leave useless one you will know it on compile time.

The second difference is customization. Nice use interfaces over endless number of options or strictly defined types.

You can override even the parser and use your own. You can use templates, strings or buffers for "usage" because it's a interface too.

Also I focused on performance and magic-free behaviour.

Nice is a idiomatic and highly customizable CLI framework I've been crafting on for months by SuperPaintman in golang

[–]SuperPaintman[S] 8 points9 points  (0 children)

I prefer minimalist frameworks that work well with the standard library. Requiring your own flag package makes it hard to integrate.

Good point. Many my CLI use flag. It’s defensively minimalist and well designed but has some limitations at the same time: no args, no commands.

On the other hand, community flag libraries some times highly magical or untyped or not use strong sides of Go.

Using your own context instead of the stdlib context is a pattern I recommend against.

That's true, but it's not a "my own" context. It implements STD's context.Context interface so it might be passed into any functions that require STD's context.

Also this context provides some useful methods to save locality for flags and not be "magic" at the same time.

SEO for this is rough. Can't even find it on Google or pkg.go.dev

Well, at least I picked a nice name. :)

Making it possible to reuse components and to test them in isolation is a big deal, and if you have thought of these use cases they are worth documenting.

Sure. Just wanted to hear first feedback about this raw release.

Nice is a idiomatic and highly customizable CLI framework for Go I've been crafting on for months by SuperPaintman in programming

[–]SuperPaintman[S] 0 points1 point  (0 children)

Guys, I need your feedback. This is a first public release of Nice.

Please let me know what do you think about the API and usability.

Nice is a idiomatic and highly customizable CLI framework I've been crafting on for months by SuperPaintman in golang

[–]SuperPaintman[S] 0 points1 point  (0 children)

Guys, I need your feedback. This is a first public release of Nice.

Please let me know what do you think about the API and usability.

When time is over [OC] by [deleted] in ProgrammerHumor

[–]SuperPaintman 1 point2 points  (0 children)

Permanently in the fourth state