Categorygithub.com/youta-t/flarc
repositorypackage
0.0.3
Repository: https://github.com/youta-t/flarc.git
Documentation: pkg.go.dev

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# README

flarc -- commandline parser, supports flag, arg, subcommands

flarc is a commandline parser. With flarc, you can

  • declare flags, gnu style (short option -f and long option --flag)
  • declare positional arguments, and
  • declare subcommands
  • get generated help texts

Install

go get github.com/youta-t/flarc

flarc needs go1.21+.

Usage

Define command

// ...
import "github.com/youta-t/flarc"
// ...

// declare struct for flags.
// Flag options can be set with tag.
//
// Recognized tag keys are:
//
// - flag:    flag name. by default, field-name-in-kebab-case.
// - alias:   aliases of the flag.
// - help:    help message.
// - metavar: value example in Usage section in help.
//            By default, the default value of the flag is used.
//
type Flag struct {
    Foo string  `alias:"f" help:"flag foo" metavar:"FOO"`
    Bar int     // when no tag, assumed as `flag:"${field-name-in-kebab-case}"` is given.
    Fizz bool   `flag:"F"`  // flag name is case sensitive
    Bazz time.Duration  `metavar:"DURATION"`
}

func main() {

// ...

	cmd, err := flarc.NewCommand(
		"short description...",

		// declare default values for flags
		Flag{
			Foo:  "default foo",
			Bar:  42,
			Fizz: false,
			Bazz: 3 * time.Second,
		},

		// declare positional args
		flarc.Args{
			{
				Name:       "SOURCE", // positional arg name
				Repeatable: true,     // set true if this arg takes many items
				Required:   true,     // require at least 1 item
				Help:       "help message of SOURCE",
			},
			{
				Name: "DEST", Required: true,
				Help: "help message of DEST",
			},
		},

		func(
			ctx context.Context,
			commandline flarc.Commandline[Flag],
			param []any,
		) error {
			// parsed flag
			var flag Flag = commandline.Flags()

			// key is arg's name. values are assigned commandline
			var args map[string][]string = commandline.Args()

			buf := make([]byte, 1024)
			io.ReadAtLeast(commandline.Stdin(), buf, 0)

			fmt.Fprintf(commandline.Stdout(), "passed flag: %+v\n\n", flag)
			fmt.Fprintf(commandline.Stdout(), "passed arg: %+v\n\n", args)
			fmt.Fprintf(commandline.Stdout(), "passed params: %+v\n\n", param)

			return nil
		},

		// Description is template.
		// Placeholder {{ .Command }} will be replaced with command name at runtime.
		flarc.WithDescription(`this is example command.

To show how to declare flags and args, also genereatad help message.

This command is called "{{ .Command }}"
`),
	)

	if err != nil {
		fmt.Fprintln(os.Stderr, "unexpected error:", err)
		os.Exit(1)
	}

	// ...
}

Run command

func main() {
	// ...

	ctx, cancel := signal.NotifyContext(
		context.Background(), os.Interrupt,
	)
	defer cancel()

	type param struct {
		ParamValue string
	}

	os.Exit(flarc.Run(
		ctx, cmd,

		// (optional) extra params.
		//
		// For example, loggers can be injected with this.
		flarc.WithParams([]any{param{ParamValue: "this is param value"}}),
	))
}

Return status is selected by flarc.

If the task of command returns,

  • nil: success! exits with 0.
  • flarc.ErrUsage: prints help message and exits with 2.
  • other error: exits with 1.
$ go run ./example/example_command -f foo -F false source1 source2 dest1
passed flag: {Foo:foo Bar:42 Fizz:false Bazz:3s}

passed arg: map[DEST:[dest1] SOURCE:[source1 source2]]

passed params: [{ParamValue:this is param value}]

By default, flarc provides --help, -h flag to show help message.

$ go run ./example/example_command --help
example_command -- short description...

Usage:

    example_command --foo=FOO --bar=0 --fizz=false --bazz=DURATION --help=false SOURCE[, ...] DEST

Description:

    this is example command.
    
    To show how to declare flags and args, also genereatad help message.
    
    This command is called "example_command"
    

Flags:

    --foo, -f   flag foo
    --bar
    --fizz, -F
    --bazz
    --help, -h  show help message

Args:

    SOURCE      help message of SOURCE
    DEST        help message of DEST

Define Command Group and Subcommand

// ...

type GroupFlag struct {
	Qux  string `alias:"q" help:"help for command group flag"`
	Quux string `alias:"Q"`
}

//...

func main() {

	// ...

	grp, err := flarc.NewCommandGroup(
		"description of command group",
		GroupFlag{
			Qux:  "qux",
			Quux: "QUUX",
		},
		flarc.WithGroupDescription(`command group description.

This command is called as "{{ .Command }}".
`),
		flarc.WithSubcommand("sub", cmd),
	)

	if err != nil {
		fmt.Fprintln(os.Stderr, "unexpected error:", err)
		os.Exit(1)
	}

	// ...
}

run it

Help for command group:

$ go run ./example/example_subcommand --help
example_subcommand -- description of command group

Usage:

    example_subcommand --qux --quux --help=false

Description:

    command group description.
    
    This command is called as "example_subcommand".
    

Flags:

    --qux, -q   help for command group flag
    --quux, -Q
    --help, -h  show help message

Subcommands:

    sub         short description...

Help for subcommand:

$ go run ./example/example_subcommand sub --help
example_subcommand sub -- short description...

Usage:

    example_subcommand sub --foo=FOO --bar=0 --fizz=false --bazz=DURATION --qux --quux --help=false SOURCE[, ...] DEST

Description:

    this is example command.
    
    To show how to declare flags and args, also genereatad help message.
    

Flags:

    --foo, -f   flag foo
    --bar
    --fizz, -F
    --bazz
    --qux, -q   help for command group flag
    --quux, -Q
    --help, -h  show help message

Args:

    SOURCE      help message of SOURCE
    DEST        help message of DEST
$ go run ./example/example_subcommand sub -f foo -F false -q "queue" -Q "Queue" source1 source2 dest1
passed flag: {Foo:foo Bar:42 Fizz:false Bazz:3s}

passed arg: map[DEST:[dest1] SOURCE:[source1 source2]]

passed params: [{ParamValue:this is param value} {Qux:queue Quux:Queue}]