console

package module
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2022 License: MIT Imports: 17 Imported by: 2

README

Console

Build Status Go Report Card GoDoc

Creating a Command

Commands are defined in struct extending pkg/command/create_user.go. For example, you may want a command to create a user:

package command

import (
	"context"

	"gitoa.ru/go-4devs/console"
	"gitoa.ru/go-4devs/console/input"
	"gitoa.ru/go-4devs/console/output"
)

func CreateUser() *console.Command {
	return &console.Command{
		Name: "app:create-user",
		Execute: func(ctx context.Context, in input.Input, out output.Output) error {
			return nil
		},
	}
}

Configure command

func CreateUser() *console.Command {
	return &console.Command{
        //...
		Description: "Creates a new user.",
		Help:        "This command allows you to create a user...",
	}
}

Add arguments

func CreateUser(required bool) *console.Command {
	return &console.Command{
        //....
		Configure: func(ctx context.Context, cfg *input.Definition) error {
			var opts []func(*input.Argument)
			if required {
				opts = append(opts, argument.Required)
			}
			cfg.SetArgument("password", "User password", opts...)

			return nil
		},
	}
}

Registering the Command

cmd/console/main.go

package main

import (
	"context"

	"gitoa.ru/go-4devs/console"
	"gitoa.ru/go-4devs/console/example/pkg/command"
)

func main() {
	console.
		New().
		Add(
			command.CreateUser(false),
		).
		Execute(context.Background())
}

Executing the Command

build command go build -o bin/console cmd/console/main.go run command `bin/console app:create-user``

Console Output

The Execute field has access to the output stream to write messages to the console:

func CreateUser(required bool) *console.Command {
	return &console.Command{
        // ....
		Execute: func(ctx context.Context, in input.Input, out output.Output) error {
			// outputs a message followed by a "\n"
			out.Println(ctx, "User Creator")
			out.Println(ctx, "Whoa!")

			// outputs a message without adding a "\n" at the end of the line
			out.Print(ctx, "You are about to ", "create a user.")

			return nil
		},
	}
}

Now, try build and executing the command:

bin/console app:create-user
User Creator
Whoa!
You are about to create a user.

Console Input

Use input options or arguments to pass information to the command:

func CreateUser(required bool) *console.Command {
	return &console.Command{
		Configure: func(ctx context.Context, cfg *input.Definition) error {
			var opts []func(*input.Argument)
			if required {
				opts = append(opts, argument.Required)
			}
			cfg.
				SetArgument("username", "The username of the user.", argument.Required).
				SetArgument("password", "User password", opts...)

			return nil
		},
		Execute: func(ctx context.Context, in input.Input, out output.Output) error {
			// outputs a message followed by a "\n"
			out.Println(ctx, "User Creator")
			out.Println(ctx, "Username: ", in.Argument(ctx, "username").String())

			return nil
		},
	}
}

Now, you can pass the username to the command:

bin/console app:create-user AwesomeUsername
User Creator
Username: AwesomeUsername

Testing Commands

package command_test

import (
	"bytes"
	"context"
	"testing"

	"gitoa.ru/go-4devs/console"
	"gitoa.ru/go-4devs/console/example/pkg/command"
	"gitoa.ru/go-4devs/console/input/array"
	"gitoa.ru/go-4devs/console/output"
)

func TestCreateUser(t *testing.T) {
	ctx := context.Background()
	in := input.Array{}
    in.SetArgument("username","andrey")
	buf := bytes.Buffer{}
	out := output.Buffer(&buf)

	console.Run(ctx, command.CreateUser(false), in, out)

	expect := `User Creator
Username: andrey
`

	if expect != buf.String() {
		t.Errorf("expect: %s, got:%s", expect, buf.String())
	}
}

Documentation

Overview

Package console eases the creation of beautiful and testable command line interfaces. The Console package allows you to create command-line commands. Your console commands can be used for any recurring task, such as cronjobs, imports, or other batch jobs. console application can be written as follows:

//cmd/console/main.go
func main() {
  console.New().Execute(context.Background())
}

Then, you can register the commands using Add():

package main

import (
  "context"

  "gitoa.ru/go-4devs/console"
  "gitoa.ru/go-4devs/console/example/pkg/command"
)

func main() {
  console.
    New().
      Add(
        command.Hello(),
        command.Args(),
        command.Hidden(),
        command.Namespace(),
     ).
     Execute(context.Background())
}

Index

Examples

Constants

View Source
const (
	OptionHelp    = "help"
	OptionVersion = "version"
	OptionAnsi    = "ansi"
	OptionNoAnsi  = "no-ansi"
	OptionQuiet   = "quiet"
	OptionVerbose = "verbose"
)
View Source
const (
	ArgumentCommandName = "command_name"
	OptionFormat        = "format"
)
View Source
const (
	CommandHelp = "help"
	CommandList = "list"
)
View Source
const (
	ArgumentNamespace = "namespace"
)

Variables

View Source
var (
	ErrNotFound         = errors.New("command not found")
	ErrCommandNil       = errors.New("console: Register command is nil")
	ErrExecuteNil       = errors.New("console: execute is nil")
	ErrCommandDuplicate = errors.New("console: duplicate command")
)

Functions

func Commands

func Commands() []string

Commands returns a sorted list of the names of the registered commands.

func Default

func Default(d *input.Definition) *input.Definition

Default options and argument command.

func Execute

func Execute(ctx context.Context, cmd *Command, opts ...func(*App))

Execute the current command with option.

Example
cmd := Command()
ctx := context.Background()
in := &input.Array{}

// Run command: ./bin "argument value" -b --string="same value" --string="other value"
in.SetOption("bool", value.New(true))
in.SetOption("string", value.New([]string{"same value", "other value"}))
in.SetArgument("test_argument", value.New("argument value"))

console.Execute(ctx, cmd, console.WithInput(in), console.WithExit(func(int) {}))
Output:

test argument:argument value
bool option:true
duration option with default:1s
array string:[same value,other value]

func MustRegister

func MustRegister(cmd *Command)

MustRegister register command or panic if err.

func Register

func Register(cmd *Command) error

Register makes a command available execute in app. If Register is called twice with the same name or if driver is nil, return error.

func Run

func Run(ctx context.Context, cmd *Command, in input.Input, out output.Output) error

Run current command by input and output.

Example
cmd := Command()
ctx := context.Background()
out := output.Stdout()
in := &input.Array{}

err := console.Run(ctx, cmd, in, out)
fmt.Println("err:", err)
Output:

test argument:
bool option:false
duration option with default:1s
array string:[]
err: <nil>

func WithExit

func WithExit(f func(int)) func(*App)

WithExit sets exit callback by default os.Exit.

func WithInput

func WithInput(in input.Input) func(*App)

WithInput sets input, by default creates inpur by os.Args.

func WithOutput

func WithOutput(out output.Output) func(*App)

WithOutput sets outpu,^ by default output os.Stdout.

func WithSkipArgs

func WithSkipArgs(l int) func(*App)

WithSkipArgs sets how many arguments are passed. For example, you don't need to pass the name of a single command.

Types

type Action

type Action func(ctx context.Context, input input.Input, output output.Output) error

type AlternativesError added in v0.1.0

type AlternativesError struct {
	Alt []string
	Err error
}

func (AlternativesError) Error added in v0.1.0

func (e AlternativesError) Error() string

func (AlternativesError) Is added in v0.1.0

func (e AlternativesError) Is(err error) bool

func (AlternativesError) Unwrap added in v0.1.0

func (e AlternativesError) Unwrap() error

type App

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

App is collection of command and configure env.

func New

func New(opts ...func(*App)) *App

New creates and configure new console app.

Example (Help)
ctx := context.Background()
os.Args = []string{
	"bin/console",
	"test:command",
	"-h",
	"--no-ansi",
}

console.New(console.WithExit(func(int) {})).
	Add(
		Command(),
	).
	Execute(ctx)
Output:

Description:
  test command

Usage:
  test:command [options] [--] [<test_argument>]

Arguments:
  test_argument                  test argument

Options:
      --duration[=DURATION]        test duration with default [default: 1s]
      --bool                       test bool option
      --string[=STRING]            array string (multiple values allowed)
  -q, --quiet                      Do not output any message
  -v, --verbose                    Increase the verbosity of messages: -v for info output, -vv for debug and -vvv for trace (multiple values allowed)
  -h, --help                       Display this help message
  -V, --version                    Display this application version
      --ansi                       Do not ask any interactive question
      --no-ansi                    Disable ANSI output
Example (List)
ctx := context.Background()

os.Args = []string{
	"bin/console",
	"--no-ansi",
}

console.New(console.WithExit(func(int) {})).
	Add(
		Command(),
		&console.Command{
			Name:        "fdevs:console:arg",
			Description: "Understanding how Console Arguments and Options Are Handled",
		},
		&console.Command{
			Name:        "fdevs:console:hello",
			Description: "example hello command",
		},
		&console.Command{
			Name:        "app:start",
			Description: "example command in other namespace",
		},
	).
	Execute(ctx)
Output:

Usage:
  command [options] [arguments]

Options:
  -q, --quiet    Do not output any message
  -v, --verbose  Increase the verbosity of messages: -v for info output, -vv for debug and -vvv for trace (multiple values allowed)
  -h, --help     Display this help message
  -V, --version  Display this application version
      --ansi     Do not ask any interactive question
      --no-ansi  Disable ANSI output

Available commands:
  help                 Displays help for a command
  list                 Lists commands
app
  app:start            example command in other namespace
fdevs
  fdevs:console:arg    Understanding how Console Arguments and Options Are Handled
  fdevs:console:hello  example hello command
  fdevs:console:test   test command
test
  test:command         test command

func (*App) Add

func (a *App) Add(cmds ...*Command) *App

Add add or replace command.

func (*App) Execute

func (a *App) Execute(ctx context.Context)

Execute run the command by name and arguments.

type Command

type Command struct {
	// The name of the command.
	Name string
	// A short description of the usage of this command.
	Description string
	// A longer explanation of how the command works.
	Help string
	// Vervion command.
	Version string
	// Boolean to hide this command from help or completion.
	Hidden bool
	// Configures the current command.
	Configure Configure
	// The middleware for configures current command.
	Prepare Prepare
	// The function to call when this command is invoked.
	Execute Action
	// The middleware for executes current command.
	Handle Handle
}

func Find

func Find(name string) (*Command, error)

Find command by name, tries to find the best match if you give it an abbreviation of a name.

func (*Command) Init

func (c *Command) Init(ctx context.Context, cfg *input.Definition) error

Init configures command.

func (*Command) Run

func (c *Command) Run(ctx context.Context, in input.Input, out output.Output) error

Run run command with input and output.

func (*Command) String

func (c *Command) String() string

func (*Command) With

func (c *Command) With(opts ...Option) *Command

With creates new command by parent and options.

type Configure

type Configure func(ctx context.Context, cfg *input.Definition) error

type Handle

type Handle func(ctx context.Context, in input.Input, out output.Output, n Action) error

func ChainHandle

func ChainHandle(handlers ...Handle) Handle

ChainHandle creates middleware for executes command.

type Option

type Option func(*Command)

func WithHandle

func WithHandle(handles ...Handle) Option

WithHandle append middleware for executed command.

func WithHidden

func WithHidden(hidden bool) Option

WithHidden sets hidden command.

func WithName

func WithName(name string) Option

WithName sets name command.

func WithPrepare

func WithPrepare(prepares ...Prepare) Option

WithPrepare append middleware for configuration command.

type Prepare

type Prepare func(ctx context.Context, cfg *input.Definition, n Configure) error

func ChainPrepare

func ChainPrepare(prepare ...Prepare) Prepare

ChainPrepare creates middleware for configures command.

Directories

Path Synopsis
cfg Module

Jump to

Keyboard shortcuts

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