• Stars
    star
    41
  • Rank 668,415 (Top 14 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created about 5 years ago
  • Updated about 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The standard library flag package with its missing features

cmd

codecov GoDoc

Package cmd is a minimalistic library that enables easy sub commands with the standard flag library.

This library extends the standard library flag package to support sub commands and more features in a minimalistic and idiomatic API.

Features:

  • Sub commands.

  • Automatic bash completion.

  • Flag values definition and check.

  • Explicit positional arguments definition.

  • Automatic usage text.

Usage

Define a root command object using the New function. This object exposes the standard library's flag.FlagSet API, which enables adding flags in the standard way. Additionally, this object exposes the SubCommand method, which returns another command object. This objects also exposing the same API, enabling definition of flags and nested sub commands. The root object then have to be called with the Parse method, similarly to the flag.Parse call.

Principles

  • Minimalistic and flag-like.

  • Any flag that is defined in the base command will be reflected in all of its sub commands.

  • When user types the command, it starts from the command and sub commands, only then types the flags and then the positional arguments:

[command] [sub commands...] [flags...] [positional args...]
  • When a command defines positional arguments, all its sub commands has these positional arguments and thus can't define their own positional arguments.

  • When flag configuration is wrong, the program will panic.

Examples

Definition and usage of sub commands and sub commands flags.

package main

import (
	"fmt"

	"github.com/posener/cmd"
)

var (
	// Define root command with a single string flag. This object the familiar standard library
	// `*flag.FlagSet` API, so it can be used similarly.
	root  = cmd.New()
	flag0 = root.String("flag0", "", "root string flag")

	// Define a sub command from the root command with a single string flag. The sub command object
	// also have the same API as the root command object.
	sub1  = root.SubCommand("sub1", "first sub command")
	flag1 = sub1.String("flag1", "", "sub1 string flag")

	// Define a second sub command from the root command with an int flag.
	sub2  = root.SubCommand("sub2", "second sub command")
	flag2 = sub1.Int("flag2", 0, "sub2 int flag")
)

// Definition and usage of sub commands and sub commands flags.
func main() {
	// Parse command line arguments.
	root.ParseArgs("cmd", "sub1", "-flag1", "value")

	// Check which sub command was choses by the user.
	switch {
	case sub1.Parsed():
		fmt.Printf("Called sub1 with flag: %s", *flag1)
	case sub2.Parsed():
		fmt.Printf("Called sub2 with flag: %d", *flag2)
	}
}

Values

An example that shows how to use advanced configuration of flags and positional arguments using the predict package.

package main

import (
	"fmt"
	"github.com/posener/cmd"
	"github.com/posener/complete/v2/predict"
)

func main() {
	// Should be defined in global `var`.
	var (
		root = cmd.New()
		// Define a flag with valid values 'foo' and 'bar', and enforce the values by `OptCheck()`.
		// The defined values will be used for bash completion, and since the OptCheck was set, the
		// flag value will be checked during the parse call.
		flag1 = root.String("flag1", "", "first flag", predict.OptValues("foo", "bar"), predict.OptCheck())
		// Define a flag to accept a valid Go file path. Choose to enforce the valid path using the
		// `OptCheck` function. The file name will also be completed in the bash completion
		// processes.
		file = root.String("file", "", "file path", predict.OptPredictor(predict.Files("*.go")), predict.OptCheck())
		// Positional arguments should be explicitly defined. Define positional arguments with valid
		// values of 'baz' and 'buzz', and choose not to enforce these values by not calling
		// `OptCheck`. These values will also be completed in the bash completion process.
		args = root.Args("[args...]", "positional arguments", predict.OptValues("baz", "buzz"))
	)

	// Parse fake command line arguments.
	root.ParseArgs("cmd", "-flag1", "foo", "-file", "cmd.go", "buz", "bazz")

	// Test:

	fmt.Println(*flag1, *file, *args)
}

Output:

foo cmd.go [buz bazz]

Args

In the cmd package, positional arguments should be explicitly defined. They are defined using the Args or ArgsVar methods.

package main

import (
	"fmt"
	"github.com/posener/cmd"
)

func main() {
	// Should be defined in global `var`.
	var (
		root = cmd.New()
		// Positional arguments should be defined as any other flag.
		args = root.Args("[args...]", "positional arguments for command line")
	)

	// Parse fake command line arguments.
	root.ParseArgs("cmd", "v1", "v2", "v3")

	// Test:

	fmt.Println(*args)
}

Output:

[v1 v2 v3]

ArgsFn

An example of how to parse positional arguments using a custom function. It enables the advantage of using named variables such as src and dst as opposed to args[0] and args[1].

package main

import (
	"fmt"
	"github.com/posener/cmd"
)

func main() {
	// Should be defined in global `var`.
	var (
		root = cmd.New()
		// Define variables that will hold the command line positional arguments.
		src, dst string
	)

	// Define an `ArgsFn` that converts a list of positional arguments to the named variables. It
	// should return an error when the arguments are invalid.
	argsFn := cmd.ArgsFn(func(args []string) error {
		if len(args) != 2 {
			return fmt.Errorf("expected src and dst, got %d arguments", len(args))
		}
		src, dst = args[0], args[1]
		return nil
	})

	// Should be in `init()`.
	// Register the function in the root command using the `ArgsVar` method.
	root.ArgsVar(argsFn, "[src] [dst]", "positional arguments for command line")

	// Should be in `main()`.
	root.ParseArgs("cmd", "from.txt", "to.txt")

	// Test:

	fmt.Println(src, dst)
}

Output:

from.txt to.txt

ArgsInt

An example of defining int positional arguments.

package main

import (
	"fmt"
	"github.com/posener/cmd"
)

func main() {
	// Should be defined in global `var`.
	var (
		root = cmd.New()
		// Define a variable that will hold the positional arguments values. Use the `ArgsInt` type
		// to parse them as int.
		args cmd.ArgsInt
	)

	// Should be in `init()`.
	// Register the positional argument variable in the root command using the `ArgsVar` method.
	root.ArgsVar(&args, "[int...]", "numbers to sum")

	// Should be in `main()`.
	// Parse fake command line arguments.
	root.ParseArgs("cmd", "10", "20", "30")

	// Test:

	sum := 0
	for _, n := range args {
		sum += n
	}
	fmt.Println(sum)
}

Output:

60

ArgsN

An example of defining an exact number of positional arguments.

package main

import (
	"fmt"
	"github.com/posener/cmd"
)

func main() {
	// Should be defined in global `var`.
	var (
		root = cmd.New()
		// Define a variable that will hold positional arguments. Create the `ArgsStr` object with
		// cap=2 to ensure that the number of arguments is exactly 2.
		args = make(cmd.ArgsStr, 2)
	)

	// Should be in `init()`.
	// Register the positional argument variable in the root command using the `ArgsVar` method
	// (similar to the Var methods of the standard library).
	root.ArgsVar(&args, "[src] [dst]", "positional arguments for command line")

	// Should be in `main()`.
	// Parse fake command line arguments.
	root.ParseArgs("cmd", "from.txt", "to.txt")

	// Test:

	fmt.Println(args)
}

Output:

[from.txt to.txt]

Readme created from Go doc with goreadme

More Repositories

1

complete

bash completion written in go + bash completion for go command
Go
925
star
2

goreadme

Generate readme file from Go doc. Now available as a Github action!
Go
213
star
3

goaction

Write Github actions in Go
Go
210
star
4

h2conn

HTTP2 client-server full-duplex connection
Go
129
star
5

gitfs

A complete solution for static files in Go code
Go
127
star
6

wstest

go websocket client for unit testing of a websocket handler
Go
101
star
7

sharedsecret

Implementation of Shamir's Secret Sharing algorithm.
Go
69
star
8

tarfs

An implementation of the FileSystem interface for tar files.
Go
58
star
9

ctxutil

utils for Go context
Go
25
star
10

client-timing

An HTTP client for go-server-timing middleware. Enables automatic timing propagation through HTTP calls between servers.
Go
24
star
11

order

More readable and easier ordering and comparison tasks
Go
21
star
12

mock-import

A helper mocking function to mask ImportErrors
Python
17
star
13

orm

Go Typed ORM
Go
16
star
14

context

A proof of concept implementation of scoped context
Go
16
star
15

h2demo

Code examples for blog post
Go
15
star
16

script

Easily write scripts with Go. Improvements for https://github.com/bitfield/script.
Go
14
star
17

fuzzing

Easy fuzzing with go-fuzz
Go
14
star
18

eztables

iptables in web browser
Go
11
star
19

fcontext

Go Context with (pseudo) constant access-time
Go
10
star
20

auth

Painless OAuth authentication middleware
Go
8
star
21

dont

A towel, is about the most massively useful thing an interstellar hitchhiker can have
Go
6
star
22

tiler

A Go port of https://github.com/nuno-faria/tiler.
Go
6
star
23

goaction-example

Simplest goaction example
Go
5
star
24

flag

Like the flag package, but with bash completion support!
Go
5
star
25

goreadme-server

Github App for goreadme package
Go
4
star
26

formatter

A library for formatting text - indenting and line wrapping
Go
3
star
27

wsbeam

WebSocket HTTP handler that can be used to beam (broadcast) data to all connections
Go
3
star
28

contexttest

Test package for context implementations
Go
3
star
29

chrome-github-godoc

Chrome extension that replaces Github view of git commit messages with useful godoc.org synopsis
JavaScript
3
star
30

tmplt

A small wrapper around Go templates for handling simple templates
Go
2
star
31

learn

Go
2
star
32

goaction-issues-example

Goaction example for using Github APIs
Go
2
star
33

meetups

An archive of my meetup lectures
Go
1
star
34

grpcgw

Convenience comes with grpc-ecosystem/grpc-gateway
Go
1
star
35

go

Go
1
star
36

fsutil

Go
1
star
37

state-logger

A logging tool to log on state changes
Go
1
star
38

ps1

A lightweight script that sets a nice shell prompt
Shell
1
star
39

githubapp

oauth2 Github app authentication client
Go
1
star
40

autogen

Automatically generate files
Go
1
star