mcli

package module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2022 License: MIT Imports: 15 Imported by: 6

README

mcli

GoDoc Go Report Card Issues GitHub release MIT License

mcli is a minimal but powerful cli library for Go. m stands for minimal and magic.

It is extremely easy to use, it makes you love writing cli programs in Go.

Disclaimer: the original idea is inspired by shafreeck/cortana, which is licensed under the Apache License 2.0.

Features

  • Easy to use, dead simple yet very powerful API to define commands, flags and arguments.
  • Add arbitrary nested sub-command with single line code.
  • Define command flags and arguments inside the command processor using struct tag.
  • Define global flags apply to all commands.
  • Read environment variables for flags and arguments.
  • Set default value for flags and arguments.
  • Work with slice, map out of box, of course the basic types bool, string, integer, unsigned integer, float, duration are also supported.
  • Mark commands, flags as hidden, hidden commands and flags won't be showed in help, except that when a special flag --mcli-show-hidden is provided.
  • Mark flags, arguments as required, it reports error when not given.
  • Mark flags as deprecated.
  • Automatic suggestions like git.
  • Automatic help generation for commands, flags and arguments.
  • Automatic help flag recognition of -h, --help, etc.
  • Compatible with the standard library's flag.FlagSet.
  • Optional posix-style single token multiple options command line parsing.
  • Alias command, so you can reorganize commands without breaking them.
  • Flexibility to define your own usage messages.
  • Minimal dependency.
  • Makes you love writing cli programs in Go.

Usage

Use in main function:

func main() {
    var args struct {
        Name string `cli:"-n, --name, Who do you want to say to" default:"tom"`

        // This argument is required.
        Text string `cli:"#R, text, The 'message' you want to send"`
    }
    mcli.Parse(&args)
    fmt.Printf("Say to %s: %s\n", args.Name, args.Text)
}
$ go run say.go
argument is required but not given: text
USAGE:
  say [flags] <text>

FLAGS:
  -n, --name string    Who do you want to say to (default "tom")

ARGUMENTS:
  text message (REQUIRED)    The message you want to send

exit status 2

$ go run say.go hello
Say to tom: hello

Use sub-commands:

func main() {
    mcli.Add("cmd1", runCmd1, "An awesome command cmd1")

    mcli.AddGroup("cmd2", "This is a command group called cmd2")
    mcli.Add("cmd2 sub1", runCmd2Sub1, "Do something with cmd2 sub1")
    mcli.Add("cmd2 sub2", runCmd2Sub2, "Brief description about cmd2 sub2")

    // A sub-command can also be registered without registering the group.
    mcli.Add("group3 sub1 subsub1", runGroup3Sub1Subsub1, "Blah blah Blah")

    // This is a hidden command, it won't be showed in help,
    // except that when flag "--mcli-show-hidden" is given.
    mcli.AddHiden("secret-cmd", secretCmd, "An secret command won't be showed in help")

    mcli.Run()
}

func runCmd1() {
    var args struct {
        Branch    string `cli:"-b, --branch, Select another branch by passing in the branch name"`
        Commit    bool   `cli:"-c, --commit, Open the last commit"`
        NoBrowser bool   `cli:"-n, --no-browser, Print destination URL instead of opening the browser"`
        Projects  bool   `cli:"-p, --projects, Open repository projects"`
        Repo      string `cli:"-R, --repo, Select another repository using the '[HOST/]OWNER/REPO' format"`
        Settings  bool   `cli:"-s, --settings, Open repository settings"`
        Wiki      bool   `cli:"-w, --wiki, Open repository wiki"`

        Location  string `cli:"location, A browser location can be specified using arguments in the following format:\n- by number for issue or pull request, e.g. \"123\"; or\n- by path for opening folders and files, e.g. \"cmd/gh/main.go\""`
    }
    mcli.Parse(&args)

    // Do something
}

type Cmd2CommonArgs struct {
    Repo string `cli:"-R, --repo, Select another repository using the '[HOST/]OWNER/REPO' format"`
}

func runCmd2Sub1() {
    // Note that the flag/argument description can be seperated either
    // by a comma or spaces, and can be mixed.
    var args struct {
        Body     string `cli:"-b, --body        Supply a body. Will prompt for one otherwise."`
        BodyFile string `cli:"-F, --body-file   Read body text from 'file' (use \"-\" to read from standard input)"`
        Editor   bool   `cli:"-e, --editor,     Add body using editor"`
        Web      bool   `cli:"-w, --web,        Add body in browser"`

        // Can embed other structs.
        CommonIssueArgs
    }
    mcli.Parse(&args)

    // Do something
}

Also, there are some sophisticated examples:

  • github-cli mimics Github's cli command gh
  • lego mimics Lego's command lego

API

  • SetOptions sets optional options for App.
  • SetGlobalFlags sets global flags, global flags are available to all commands.
  • Add adds a command.
  • AddAlias adds an alias name for a command.
  • AddHidden adds a hidden command.
  • AddGroup adds a group explicitly. A group is a common prefix for some commands. It's not required to add group before adding sub commands, but user can use this function to add a description to a group, which will be showed in help.
  • AddHelp enables the "help" command.
  • Parse parses the command line for flags and arguments.
  • Run runs the program, it will parse the command line, search for a registered command and run it.
  • PrintHelp prints usage doc of the current command to stderr.
Custom parsing options
  • WithArgs tells Parse to parse from the given args, instead of parsing from the command line arguments.
  • WithErrorHandling tells Parse to use the given ErrorHandling. By default, it exits the program when an error happens.
  • WithName specifies the command name to use when printing usage doc.
  • DisableGlobalFlags tells Parse to don't parse and print global flags in help.
  • ReplaceUsage tells Parse to use a custom usage function instead of the default.
  • WithFooter adds a footer message after the default help.

Tag syntax

Struct tag is a powerful feature in Go, mcli uses struct tag to define flags and arguments.

  • tag cli defines the name and description for flags and arguments
  • tag env optionally tells Parse to lookup environment variables when user doesn't provide a value on the command line
  • tag default optionally provides a default value to a flag or argument, which will be used when the value is not available from both command line and env

The syntax is

/* cli tag, only Name is required.
 * Short name and long name are both optional, but at least one must be given.
 * See below for details about modifiers.
 * e.g.
 * - `cli:"-c, Open the last commit"`
 * - `cli:"#R, -b, --branch, Select another branch by passing in the branch name"`
 * - `cli:"--an-obvious-flag-dont-need-description"`
 */
CliTag       <-  ( Modifiers ',' Space? )? Name ( ( ',' | Space ) Description )?
Modifiers    <-  '#' [DHR]+
Name         <-  ( ShortName LongName? ) | LongName
Description  <-  ( ![\r\n] . )*

/* env tag, optional.
 * Multiple environment names can be specified, the first non-empty value
 * will be used.
 * e.g.
 * - `env:"SOME_ENV"`
 * - `env:"ANOTHER_ENV_1, ANOTHER_ENV_2"`
 */
EnvTag  <-  ( EnvName ',' Space? )* EnvName

/* default value tag, optional.
 * e.g.
 * - `default:"1.5s"` // duration
 * - `default:"true"` // bool
 */
DefaultValueTag  <-  ( ![\r\n] . )*

Modifiers

Modifier represents an option to a flag, it sets the flag to be deprecated, hidden, or required. In a cli tag, modifiers appears as the first segment, starting with a # character.

Fow now the following modifiers are available:

  • D - marks a flag or argument as deprecated, "DEPRECATED" will be showed in help
  • R - marks a flag or argument as required, "REQUIRED" will be showed in help
  • H - marks a flag as hidden, see below for more about hidden flags

Hidden flags won't be showed in help, except that when a special flag "--mcli-show-hidden" is provided.

Modifier H shall not be used for an argument, else it panics. An argument must be showed in help to tell user how to use the program correctly.

Some modifiers cannot be used together, else it panics, e.g.

  • H & R - a required flag must appear in help to tell user to set it
  • D & R - a required flag must not be deprecated, it does not make sense, but makes user confused

Compatibility with package flag

Parse returns a *flag.FlagSet if success, all defined flags are available with the flag set, including both short and long names.

Note that the package flag requires command line flags must present before arguments, this package does not have this requirement. Positional arguments can present either before flags or after flags, even both before and after flags, in which case, the args will be reordered and all arguments can be accessed by calling flagSet.Args() and flagSet.Arg(i).

If there is slice or map arguments, it will match all following arguments.

Changelog

v0.5.0 @ 2022-06-22
  • New: validate non-flag arguments for invalid usage.
  • New: support value implementing encoding.TextUnmarshaler, allowing command-line flags and arguments to have types such as big.Int, netip.Addr, and time.Time.
  • New: add type Context to allow using func(*Context) as command action, making it easier to use manually created App.
  • Change: drop support for Go < 1.17.
v0.4.0 @ 2022-06-18
  • Fix: reflect.Pointer not exists when using with Go below 1.18.
  • Fix: error handling for invalid command.
  • New: add options ReplaceUsage and WithFooter to customize usage help.
  • New: add option to allow parsing posix-style single token multiple options.
  • New: support alias commands.
  • Change: remove api KeepCommandOrder, replaced by SetOptions.
  • Change: optimize help padding.
  • Change: refactor code for better maintainability.
v0.2.1 @ 2022-06-11
  • Support alternative 'mcli' tag.
  • Support global flags.
  • Support keep command order in help.
  • Improve compatibility with flag.FlagSet.
  • Improve examples and docs.
v0.1.1 @ 2022-03-17

Initial public release.

Documentation

Overview

Example (GithubCliCommandBrowse)
args := struct {
	Branch    string `cli:"-b, --branch, Select another branch by passing in the branch name"`
	Commit    bool   `cli:"-c, --commit, Open the last commit"`
	NoBrowser bool   `cli:"-n, --no-browser, Print destination URL instead of opening the browser"`
	Projects  bool   `cli:"-p, --projects, Open repository projects"`
	Repo      string "cli:\"-R, --repo, Select another repository using the `[HOST/]OWNER/REPO` format\""
	Settings  bool   `cli:"-s, --settings, Open repository settings"`
	Wiki      bool   `cli:"-w, --wiki, Open repository wiki"`

	Location string `cli:"location, A browser location can be specified using arguments in the following format:\n- by number for issue or pull request, e.g. \"123\"; or\n- by path for opening folders and files, e.g. \"cmd/gh/main.go\""`
}{}
_, err := Parse(&args, WithErrorHandling(flag.ContinueOnError))
if err != nil && err != flag.ErrHelp {
	panic(err)
}
Output:

Example (GithubCliCommandIssueClose)
var args struct {
	CommonIssueArgs
}
_, err := Parse(&args, WithErrorHandling(flag.ContinueOnError))
if err != nil && err != flag.ErrHelp {
	panic(err)
}
Output:

Example (GithubCliCommandIssueComment)
var args struct {
	Body     string `cli:"-b, --body        Supply a body. Will prompt for one otherwise."`
	BodyFile string `cli:"-F, --body-file   Read body text from 'file' (use \"-\" to read from standard input)"`
	Editor   bool   `cli:"-e, --editor,     Add body using editor"`
	Web      bool   `cli:"-w, --web,        Add body in browser"`
	CommonIssueArgs
}
_, err := Parse(&args, WithErrorHandling(flag.ContinueOnError))
if err != nil && err != flag.ErrHelp {
	panic(err)
}
Output:

Example (GithubCliCommandIssueCreate)
var args struct {
	Assignee  string `cli:"-a, --assignee    Assign people by their 'login'. Use \"@me\" to self-assign."`
	Body      string `cli:"-b, --body        Supply a body. Will prompt for one otherwise."`
	BodyFile  string `cli:"-F, --body-file   Read body text from 'file' (use \"-\" to read from standard input)"`
	Label     string `cli:"-l, --label       Add labels by 'name'"`
	Milestone string `cli:"-m, --milestone   Add the issue to a milestone by 'name'"`
	Project   string `cli:"-p, --project     Add the issue to projects by 'name'"`
	Recover   string `cli:"    --recover     Recover input from a failed run of create"`
	Title     string `cli:"-t, --title       Supply a title. Will prompt for one otherwise."`
	Web       bool   `cli:"-w, --web         Open the browser to create an issue"`
	CommonIssueArgs
}
_, err := Parse(&args, WithErrorHandling(flag.ContinueOnError))
if err != nil && err != flag.ErrHelp {
	panic(err)
}
Output:

Example (GithubCliCommandIssueEdit)
// The description don't need to be aligned.
var args struct {
	AddAssignee    bool   `cli:"--add-assignee      Add assigned users by their 'login'. Use \"@me\" to assign yourself."`
	AddLabel       string `cli:"--add-label          Add labels by 'name'"`
	AddProject     string `cli:"--add-project        Add the issue to projects by 'name'"`
	Body           string `cli:"-b, --body             Set the new body."`
	BodyFile       string `cli:"-F, --body-file          Read body text from 'file' (use \"-\" to read from standard input)"`
	Milestone      string `cli:"-m, --milestone          Edit the milestone the issue belongs to by 'name'"`
	RemoveAssignee string `cli:"--remove-assignee   Remove assigned users by their 'login'. Use \"@me\" to unassign yourself."`
	RemoveLabel    string `cli:"--remove-label       Remove labels by 'name'"`
	RemoveProject  string `cli:"--remove-project     Remove the issue from projects by 'name'"`
	Title          string `cli:"-t, --title            Set the new title."`
	CommonIssueArgs
}
_, err := Parse(&args, WithErrorHandling(flag.ContinueOnError))
if err != nil && err != flag.ErrHelp {
	panic(err)
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Add

func Add(name string, f interface{}, description string)

Add adds a command. f must be a function of signature `func()` or `func(*Context)`, else it panics.

Example (AddCommands)
Add("browse", Example_githubCliCommandBrowse, "Open the repository in the browser")
Add("actions", dummyCmd, "Learn about working with GitHub Actions")

AddGroup("issue", "Manage issues")
Add("issue close", Example_githubCliCommandIssueClose, "Close issue")
Add("issue comment", Example_githubCliCommandIssueComment, "Create a new issue comment")
Add("issue create", Example_githubCliCommandIssueCreate, "Create a new issue")
Add("issue delete", dummyCmd, "Delete issue")
Add("issue edit", Example_githubCliCommandIssueEdit, "Edit an issue")
Add("issue list", dummyCmd, "List and filter issues in this repository")
Add("issue reopen", dummyCmd, "Reopen issue")
Add("issue status", dummyCmd, "Show status of relevant issues")
Add("issue transfer", dummyCmd, "Transfer issue to another repository")
Add("issue view", dummyCmd, "View an issue")

AddGroup("codespace", "Connect to and manage your codespaces")
Add("codespace code", dummyCmd, "Open a codespace in Visual Studio Code")
Add("codespace cp", dummyCmd, "Copy files between local and remote file systems")
Add("codespace create", dummyCmd, "Create a codespace")
Add("codespace delete", dummyCmd, "Delete a codespace")
Add("codespace list", dummyCmd, "List your codespaces")
Add("codespace logs", dummyCmd, "Access codespace logs")
Add("codespace ports", dummyCmd, "List ports in a codespace")
Add("codespace ssh", dummyCmd, "SSH into a codespace")
Add("codespace stop", dummyCmd, "Stop a running codespace")

AddGroup("gist", "Manage gists")
Add("gist clone", dummyCmd, "Clone a gist locally")
Add("gist create", dummyCmd, "Create a new gist")
Add("gist delete", dummyCmd, "Delete a gist")
Add("gist edit", dummyCmd, "Edit one of your gists")
Add("gist list", dummyCmd, "List your gists")
Add("gist view", dummyCmd, "View a gist")

AddGroup("pr", "Manage pull requests")
Add("pr checkout", dummyCmd, "Check out a pull request in git")
Add("pr checks", dummyCmd, "Show CI status for a single pull request")
Add("pr close", dummyCmd, "Close a pull request")
Add("pr comment", dummyCmd, "Create a new pr comment")
Add("pr create", dummyCmd, "Create a pull request")
Add("pr diff", dummyCmd, "View changes in a pull request")
Add("pr edit", dummyCmd, "Edit a pull request")
Add("pr list", dummyCmd, "List and filter pull requests in this repository")
Add("pr merge", dummyCmd, "Merge a pull request")
Add("pr ready", dummyCmd, "Mark a pull request as ready for review")
Add("pr reopen", dummyCmd, "Reopen a pull request")
Add("pr review", dummyCmd, "Add a review to a pull request")
Add("pr status", dummyCmd, "Show status of relevant pull requests")
Add("pr view", dummyCmd, "View a pull request")

AddGroup("release", "Manage GitHub releases")
Add("release create", dummyCmd, "Create a new release")
Add("release delete", dummyCmd, "Delete a release")
Add("release download", dummyCmd, "Download release assets")
Add("release list", dummyCmd, "List releases in a repository")
Add("release upload", dummyCmd, "Upload assets to a release")
Add("release view", dummyCmd, "View information about a release")

AddGroup("repo", "Create, clone, fork, and view repositories")
Add("repo archive", dummyCmd, "Archive a repository")
Add("repo clone", dummyCmd, "Clone a repository locally")
Add("repo create", dummyCmd, "Create a new repository")
Add("repo delete", dummyCmd, "Delete a repository")
Add("repo edit", dummyCmd, "Edit repository settings")
Add("repo fork", dummyCmd, "Create a fork of a repository")
Add("repo list", dummyCmd, "List repositories owned by user or organization")
Add("repo rename", dummyCmd, "Rename a repository")
Add("repo sync", dummyCmd, "Sync a repository")
Add("repo view", dummyCmd, "View a repository")

AddGroup("run", "View details about workflow runs")
Add("run cancel", dummyCmd, "Cancel a workflow run")
Add("run download", dummyCmd, "Download artifacts generated by a workflow run")
Add("run list", dummyCmd, "List recent workflow runs")
Add("run rerun", dummyCmd, "Rerun a failed run")
Add("run view", dummyCmd, "View a summary of a workflow run")
Add("run watch", dummyCmd, "Watch a run until it completes, showing its progress")

AddGroup("workflow", "View details about GitHub Actions workflows")
Add("workflow disable", dummyCmd, "Disable a workflow")
Add("workflow enable", dummyCmd, "Enable a workflow")
Add("workflow list", dummyCmd, "List workflows")
Add("workflow run", dummyCmd, "Run a workflow by creating a workflow_dispatch event")
Add("workflow view", dummyCmd, "View the summary of a workflow")

AddGroup("alias", "Create command shortcuts")
Add("alias delete", dummyCmd, "Delete an alias")
Add("alias list", dummyCmd, "List your aliases")
Add("alias set", dummyCmd, "Create a shortcut for a gh command")

Add("api", dummyCmd, "Make an authenticated GitHub API request")

AddGroup("auth", "Login, logout, and refresh your authentication")
Add("auth login", dummyCmd, "Authenticate with a GitHub host")
Add("auth logout", dummyCmd, "Log out of a GitHub host")
Add("auth refresh", dummyCmd, "Refresh stored authentication credentials")
Add("auth setup-git", dummyCmd, "Configure git to use GitHub CLI as a credential helper")
Add("auth status", dummyCmd, "View authentication status")

Add("completion", dummyCmd, "Generate shell completion scripts")

AddGroup("config", "Manage configuration for gh")
Add("config get", dummyCmd, "Print the value of a given configuration key")
Add("config list", dummyCmd, "Print a list of configuration keys and values")
Add("config set", dummyCmd, "Update configuration with a value for the given key")

AddGroup("extension", "Manage gh extensions")
Add("extension create", dummyCmd, "Create a new extension")
Add("extension install", dummyCmd, "Install a gh extension from a repository")
Add("extension list", dummyCmd, "List installed extension commands")
Add("extension remove", dummyCmd, "Remove an installed extension")
Add("extension upgrade", dummyCmd, "Upgrade installed extensions")

AddGroup("gpg-key", "Manage GPG keys")
Add("gpg-key add", dummyCmd, "Add a GPG key to your GitHub account")
Add("gpg-key list", dummyCmd, "Lists GPG keys in your GitHub account")

AddGroup("secret", "Manage GitHub secrets")
Add("secret list", dummyCmd, "List secrets")
Add("secret remove", dummyCmd, "Remove secrets")
Add("secret set", dummyCmd, "Create or update secrets")

AddGroup("ssh-key", "Manage SSH keys")
Add("ssh-key add", dummyCmd, "Add an SSH key to your GitHub account")
Add("ssh-key list", dummyCmd, "Lists SSH keys in your GitHub account")

// Enable the "help" command.
AddHelp()
Output:

func AddAlias added in v0.4.0

func AddAlias(aliasName, target string)

AddAlias adds an alias name for a command.

Example
defer markExampleTest()()

var addCommands = func() {
	Add("cmda", dummyCmd, "A description for cmda")
	Add("cmdb", dummyCmd, "Do something with this cmdb command")
	AddAlias("cmd alias", "cmdb")
}

resetDefaultApp()
addCommands()
os.Args = []string{"demo", "cmd", "alias"}
Run()
Output:

Alias of command "cmdb"
Do something with this cmdb command

USAGE:
  demo cmdb

func AddGroup

func AddGroup(name string, description string)

AddGroup adds a group explicitly. A group is a common prefix for some commands. It's not required to add group before adding sub commands, but user can use this function to add a description to a group, which will be showed in help.

func AddHelp

func AddHelp()

AddHelp enables the "help" command to print help about any command.

func AddHidden

func AddHidden(name string, f interface{}, description string)

AddHidden adds a hidden command. f must be a function of signature `func()` or `func(*Context)`, else it panics.

A hidden command won't be showed in help, except that when a special flag "--mcli-show-hidden" is provided.

func Parse

func Parse(v interface{}, opts ...ParseOpt) (fs *flag.FlagSet, err error)

Parse parses the command line for flags and arguments. v must be a pointer to a struct, else it panics.

func PrintHelp

func PrintHelp()

PrintHelp prints usage doc of the current command to stderr.

func Run

func Run(args ...string)

Run runs the program, it parses the command line and searches for a registered command, it runs the command if a command is found, else it will report an error and exit the program.

Optionally you may specify args to parse, by default it parses the command line arguments os.Args[1:].

Example (GroupCommand)
resetDefaultApp()
defer markExampleTest()()

ExampleAdd_addCommands()
os.Args = []string{"gh", "issue"}
Run()
Output:

Manage issues

USAGE:
  gh issue <command> ...

COMMANDS:
  issue close       Close issue
  issue comment     Create a new issue comment
  issue create      Create a new issue
  issue delete      Delete issue
  issue edit        Edit an issue
  issue list        List and filter issues in this repository
  issue reopen      Reopen issue
  issue status      Show status of relevant issues
  issue transfer    Transfer issue to another repository
  issue view        View an issue
Example (HelpCommand)
resetDefaultApp()
defer markExampleTest()()

ExampleAdd_addCommands()
os.Args = []string{"gh", "help"}
Run()
Output:

USAGE:
  gh <command> ...

COMMANDS:
  actions       Learn about working with GitHub Actions
  alias         Create command shortcuts
  api           Make an authenticated GitHub API request
  auth          Login, logout, and refresh your authentication
  browse        Open the repository in the browser
  codespace     Connect to and manage your codespaces
  completion    Generate shell completion scripts
  config        Manage configuration for gh
  extension     Manage gh extensions
  gist          Manage gists
  gpg-key       Manage GPG keys
  help          Help about any command
  issue         Manage issues
  pr            Manage pull requests
  release       Manage GitHub releases
  repo          Create, clone, fork, and view repositories
  run           View details about workflow runs
  secret        Manage GitHub secrets
  ssh-key       Manage SSH keys
  workflow      View details about GitHub Actions workflows
Example (HelpIssueCreate)
resetDefaultApp()
defer markExampleTest()()

ExampleAdd_addCommands()
os.Args = []string{"gh", "help", "issue", "create"}
Run()
Output:

Create a new issue

USAGE:
  gh issue create [flags]

FLAGS:
  -a, --assignee string           Assign people by their 'login'. Use "@me" to self-assign.
  -b, --body string               Supply a body. Will prompt for one otherwise.
  -F, --body-file string          Read body text from 'file' (use "-" to read from standard input)
  -l, --label string              Add labels by 'name'
  -m, --milestone string          Add the issue to a milestone by 'name'
  -p, --project string            Add the issue to projects by 'name'
      --recover string            Recover input from a failed run of create
  -R, --repo [HOST/]OWNER/REPO    Select another repository using the [HOST/]OWNER/REPO format
  -t, --title string              Supply a title. Will prompt for one otherwise.
  -w, --web                       Open the browser to create an issue
Example (MainCommand)
resetDefaultApp()
defer markExampleTest()()

ExampleAdd_addCommands()
os.Args = []string{"gh", "-h"}
Run()
Output:

USAGE:
  gh <command> ...

COMMANDS:
  actions       Learn about working with GitHub Actions
  alias         Create command shortcuts
  api           Make an authenticated GitHub API request
  auth          Login, logout, and refresh your authentication
  browse        Open the repository in the browser
  codespace     Connect to and manage your codespaces
  completion    Generate shell completion scripts
  config        Manage configuration for gh
  extension     Manage gh extensions
  gist          Manage gists
  gpg-key       Manage GPG keys
  help          Help about any command
  issue         Manage issues
  pr            Manage pull requests
  release       Manage GitHub releases
  repo          Create, clone, fork, and view repositories
  run           View details about workflow runs
  secret        Manage GitHub secrets
  ssh-key       Manage SSH keys
  workflow      View details about GitHub Actions workflows
Example (SubCommandBrowse)
resetDefaultApp()
defer markExampleTest()()

ExampleAdd_addCommands()
os.Args = []string{"gh", "browse", "-h"}
Run()
Output:

Open the repository in the browser

USAGE:
  gh browse [flags] [location]

FLAGS:
  -b, --branch string             Select another branch by passing in the branch name
  -c, --commit                    Open the last commit
  -n, --no-browser                Print destination URL instead of opening the browser
  -p, --projects                  Open repository projects
  -R, --repo [HOST/]OWNER/REPO    Select another repository using the [HOST/]OWNER/REPO format
  -s, --settings                  Open repository settings
  -w, --wiki                      Open repository wiki

ARGUMENTS:
  location string    A browser location can be specified using arguments in the following format:
                     - by number for issue or pull request, e.g. "123"; or
                     - by path for opening folders and files, e.g. "cmd/gh/main.go"
Example (SubCommandIssueCreate)
resetDefaultApp()
defer markExampleTest()()

ExampleAdd_addCommands()
os.Args = []string{"gh", "issue", "create", "-h"}
Run()
Output:

Create a new issue

USAGE:
  gh issue create [flags]

FLAGS:
  -a, --assignee string           Assign people by their 'login'. Use "@me" to self-assign.
  -b, --body string               Supply a body. Will prompt for one otherwise.
  -F, --body-file string          Read body text from 'file' (use "-" to read from standard input)
  -l, --label string              Add labels by 'name'
  -m, --milestone string          Add the issue to a milestone by 'name'
  -p, --project string            Add the issue to projects by 'name'
      --recover string            Recover input from a failed run of create
  -R, --repo [HOST/]OWNER/REPO    Select another repository using the [HOST/]OWNER/REPO format
  -t, --title string              Supply a title. Will prompt for one otherwise.
  -w, --web                       Open the browser to create an issue

func SetGlobalFlags added in v0.2.0

func SetGlobalFlags(v interface{})

SetGlobalFlags sets global flags, global flags are available to all commands. DisableGlobalFlags may be used to disable global flags for a specific command when calling Parse.

func SetOptions added in v0.4.0

func SetOptions(opts Options)

SetOptions sets optional options for App.

Types

type App added in v0.3.0

type App struct {
	// contains filtered or unexported fields
}

App holds the state of a cli application.

func NewApp added in v0.3.0

func NewApp() *App

NewApp creates a new cli application instance. Typically, there is no need to manually create an application, using the package-level functions with the default application is preferred.

func (*App) Add added in v0.3.0

func (p *App) Add(name string, f interface{}, description string)

Add adds a command. f must be a function of signature `func()` or `func(*Context)`, else it panics.

func (*App) AddAlias added in v0.4.0

func (p *App) AddAlias(aliasName, target string)

AddAlias adds an alias name for a command.

func (*App) AddGroup added in v0.3.0

func (p *App) AddGroup(name string, description string)

AddGroup adds a group explicitly. A group is a common prefix for some commands. It's not required to add group before adding sub commands, but user can use this function to add a description to a group, which will be showed in help.

func (*App) AddHelp added in v0.3.0

func (p *App) AddHelp()

AddHelp enables the "help" command to print help about any command.

func (*App) AddHidden added in v0.3.0

func (p *App) AddHidden(name string, f interface{}, description string)

AddHidden adds a hidden command. f must be a function of signature `func()` or `func(*Context)`, else it panics.

A hidden command won't be showed in help, except that when a special flag "--mcli-show-hidden" is provided.

func (*App) Run added in v0.3.0

func (p *App) Run(args ...string)

Run is the entry point to an application, it parses the command line and searches for a registered command, it runs the command if a command is found, else it will report an error and exit the program.

Optionally you may specify args to parse, by default it parses the command line arguments os.Args[1:].

func (*App) SetGlobalFlags added in v0.3.0

func (p *App) SetGlobalFlags(v interface{})

SetGlobalFlags sets global flags, global flags are available to all commands. DisableGlobalFlags may be used to disable global flags for a specific command when calling Parse.

func (*App) SetOptions added in v0.4.0

func (p *App) SetOptions(opts Options)

SetOptions sets optional options for App.

type Command

type Command struct {
	Name        string
	Description string
	Hidden      bool

	AliasOf string
	// contains filtered or unexported fields
}

Command holds the information of a command.

type Context added in v0.5.0

type Context struct {
	context.Context

	App     *App
	Command *Command
}

Context holds context-specific information, which is passed to a Command when executing it. Context embeds context.Context, it can be passed to functions which take context.Context as parameter.

func (*Context) Parse added in v0.5.0

func (ctx *Context) Parse(v interface{}, opts ...ParseOpt) (*flag.FlagSet, error)

Parse parses the command line for flags and arguments. v must be a pointer to a struct, else it panics.

func (*Context) PrintHelp added in v0.5.0

func (ctx *Context) PrintHelp()

PrintHelp prints usage doc of the current command to stderr.

type Modifier

type Modifier byte

Modifier represents an option to a flag, it sets the flag to be deprecated, hidden, or required. In a `cli` tag, modifiers appears as the first segment, starting with a `#` character.

Fow now the following modifiers are available:

D - marks a flag or argument as deprecated, "DEPRECATED" will be showed in help
R - marks a flag or argument as required, "REQUIRED" will be showed in help
H - marks a flag as hidden, see below for more about hidden flags

Hidden flags won't be showed in help, except that when a special flag "--mcli-show-hidden" is provided.

Modifier `H` shall not be used for an argument, else it panics. An argument must be showed in help to tell user how to use the program correctly.

Some modifiers cannot be used together, else it panics, e.g.

H & R - a required flag must appear in help to tell user to set it
D & R - a required flag must not be deprecated, it does not make sense,
        but makes user confused

type Options added in v0.4.0

type Options struct {

	// KeepCommandOrder makes Parse to print commands in the order of
	// adding the commands.
	// By default, it prints commands in lexicographic order.
	KeepCommandOrder bool

	// AllowPosixSTMO enables using the posix-style single token to specify
	// multiple boolean options. e.g. ‘-abc’ is equivalent to ‘-a -b -c’.
	AllowPosixSTMO bool
}

Options specifies optional options for an App.

type ParseOpt

type ParseOpt struct {
	// contains filtered or unexported fields
}

ParseOpt specifies options to customize the behavior of Parse.

func DisableGlobalFlags added in v0.2.0

func DisableGlobalFlags() ParseOpt

DisableGlobalFlags tells Parse to don't parse and print global flags in help.

func ReplaceUsage added in v0.3.0

func ReplaceUsage(f func() string) ParseOpt

ReplaceUsage specifies a function to generate a usage help to replace the default help.

func WithArgs

func WithArgs(args []string) ParseOpt

WithArgs tells Parse to parse from the given args, instead of parsing from the command line arguments.

func WithErrorHandling

func WithErrorHandling(h flag.ErrorHandling) ParseOpt

WithErrorHandling tells Parse to use the given ErrorHandling. By default, Parse exits the program when an error happens.

func WithFooter added in v0.3.0

func WithFooter(f func() string) ParseOpt

WithFooter specifies a function to generate extra help text to print after the default help.

func WithName

func WithName(name string) ParseOpt

WithName specifies the command name to use when printing usage doc.

Directories

Path Synopsis
examples
say

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL