commander

package module
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Sep 19, 2024 License: MIT Imports: 11 Imported by: 0

README

commander

commander is an interactive command processor, similar to python's CMD2, but written for golang. it is not a golang REPL, but rather an interactive shell environment which allows the user to define and implement rich commands, which can then be executed with amenities such as:

  • full tab completion
  • contextual help
  • stdout piping and redirection

demo

a brief screen recording showcasing some of commander's capabilities demo

example

please explore the working example in the /example directory

go run ./example/*.go

Documentation

Index

Constants

View Source
const (
	PatternArg     string = "pattern"
	InsensitiveArg string = "insensitive"
)
View Source
const (
	COMMAND_PADDING = 30
)

Variables

View Source
var (
	C_RESET = "\x1b[0m"
	C_RED   = FgColor(255, 0, 0)
	C_GREEN = FgColor(0, 255, 0)
	C_BOLD  = "\x1b[1m"
)
View Source
var (
	FLOW_CONTROL_UNSPECIFIED byte = ' '
	FLOW_CONTROL_PIPE        byte = '|'
	FLOW_CONTROL_REDIRECT    byte = '>'
)
View Source
var ClearCommand = &Command{
	Name:        "clear",
	Description: "clear the terminal",
	OnExecute: func(c *Command, args map[string]any, capturedInput []byte) error {
		c.Commander.shell.Clear()

		return nil
	},
}
View Source
var ControlCharacters = map[byte]struct{}{
	FLOW_CONTROL_PIPE:     {},
	FLOW_CONTROL_REDIRECT: {},
}
View Source
var ExitCommand = &Command{
	Name:        "exit",
	Description: "exit the shell",
	OnExecute: func(c *Command, args map[string]any, capturedInput []byte) error {
		c.Commander.shell.Shutdown()
		os.Exit(0)

		return nil
	},
}
View Source
var GrepCommand = &Command{
	Name:        "grep",
	Description: "filter and pattern match input",
	Arguments: []*Argument{
		{
			Name:        PatternArg,
			Description: "search pattern",
			ArgType:     ArgTypeString,
		},
	},
	Flags: []*Flag{
		{
			Name:         InsensitiveArg,
			ShortName:    "i",
			Description:  "case insensitive matching",
			ArgType:      ArgTypeBool,
			DefaultValue: false,
		},
	},
	OnExecute: func(c *Command, args map[string]any, capturedInput []byte) error {
		pattern := args[PatternArg].(string)
		insensitive := args[InsensitiveArg].(bool)
		lowerPattern := strings.ToLower(pattern)

		if len(capturedInput) > 0 {
			ci := string(capturedInput)
			lines := strings.Split(ci, "\n")
			for _, line := range lines {
				if insensitive {
					if !strings.Contains(strings.ToLower(line), lowerPattern) {
						continue
					}
				} else if !strings.Contains(line, pattern) {
					continue
				}

				fmt.Println(line)
			}
		}

		return nil
	},
}
View Source
var HelpCommand = &Command{
	Name:        "help",
	Description: "display contextual command help",
	OnExecute: func(c *Command, args map[string]any, capturedInput []byte) error {
		fmt.Println("Command list:")

		commandList := []string{}
		for _, cmd := range c.Commander.commandMap {
			commandList = append(commandList, cmd.Name)
		}
		sort.Slice(commandList, func(i, j int) bool {
			return commandList[i] < commandList[j]
		})

		for _, cmdName := range commandList {
			cmd := c.Commander.commandMap[cmdName]
			fmt.Printf("  %s%s\n", PadRight(cmd.Name, COMMAND_PADDING), cmd.Description)
		}

		return nil
	},
}

Functions

func Errorln

func Errorln(text ...string)

func FgColor

func FgColor(red int, green int, blue int) string

func GetValueFromString

func GetValueFromString(argType ArgType, value string) (any, error)

func MatchesOneOf

func MatchesOneOf(oneOf []any, sample any) bool

func PadRight

func PadRight(text string, width int) string

func Println

func Println(text ...string)

func Sprintf

func Sprintf(text ...string) string

Types

type ArgType

type ArgType string
const (
	ArgTypeUnspecified ArgType = ""
	ArgTypeInt         ArgType = "INT"
	ArgTypeFloat       ArgType = "FLOAT"
	ArgTypeString      ArgType = "STRING"
	ArgTypeBool        ArgType = "BOOL"
)

func InferArgType

func InferArgType(value any) ArgType

InferArgType infers the ArgType based on the variable type, or returns ArgTypeUnspecified if the variable type does not match one of the known values.

type Argument

type Argument struct {
	Name          string
	Description   string
	ArgType       ArgType
	AllowMultiple bool  // if enabled, will be returned as an array of ArgType
	OneOf         []any // if specified, value must belong to collection
	Completer     Completer
}

an argument represents a positional argument. it is non-defaultable

func (*Argument) GetValueFromString

func (a *Argument) GetValueFromString(value string) (any, error)

GetValueFromString parses the provided value according to the argument's underlying data type and returns that parsed value, or an error

func (*Argument) PopulateMap

func (a *Argument) PopulateMap(value string, target map[string]any) error

func (*Argument) SuggestValues

func (a *Argument) SuggestValues(prefix string) []*ns.AutoComplete

func (*Argument) Validate

func (a *Argument) Validate() error

Validate returns an error if any part of the argument is invalid

type BoundExec

type BoundExec struct {
	IsCapturingOutput bool
	Command           *Command
	ArgMap            map[string]any
}

type Capture

type Capture struct {
	Buffer bytes.Buffer
	Error  error
}

type Command

type Command struct {
	Name        string
	Description string
	Flags       []*Flag
	Arguments   []*Argument
	SubCommands []*Command
	OnExecute   func(c *Command, args map[string]any, capturedInput []byte) error

	Commander *Commander
	// contains filtered or unexported fields
}

func (*Command) ClassifyTokens

func (c *Command) ClassifyTokens(tokens []string, parentFlags []*Flag) (map[string]any, error)

ClassifyTokens attempts to classify the token array using the defined flags and arguments, in order to populate a name to value mapping

func (*Command) GetHelpString

func (c *Command) GetHelpString(parentFlags []*Flag) string

func (*Command) Suggest

func (c *Command) Suggest(tokens []string, parentFlags []*Flag) []*ns.AutoComplete

func (*Command) Validate

func (c *Command) Validate(parentFlags map[string]struct{}) error

Validate ensures that the command is valid, returning a descriptive error if it is not. Also, performs any run-time optimization. This should only be called by the Commander.

type Commander

type Commander struct {
	Config Config
	// contains filtered or unexported fields
}

func NewCommander

func NewCommander(config Config) (*Commander, error)

NewCommander returns a new Commander instance

func (*Commander) LocateCommand

func (c *Commander) LocateCommand(tokens []string) (*Command, []*Flag, []string)

LocateCommand will attempt to locate a command from a series of tokens presented as arguments to the Commander. The method will match up to either the final subcommand, returning the remaining arguments, or to the final matching subcommand, returning whatever unmatched is left.

func (*Commander) Run

func (c *Commander) Run() error

type Completer

type Completer func(search string) []*ns.AutoComplete

Completer is a type of function which returns a list of strings based on a search string

type Config

type Config struct {
	Prompt   string
	Commands []*Command
	DumpFile string // For debugging purposes, all input will be sent to this file, if set

	AutoCompleteSuggestStyle string
}

func (*Config) ApplyDefaults

func (c *Config) ApplyDefaults()

type Flag

type Flag struct {
	Name          string
	ShortName     string
	Description   string
	ArgType       ArgType
	AllowMultiple bool // if enabled, will be returned as an array of ArgType
	DefaultValue  any
	OneOf         []any // if specified, value must belong to collection
	Completer     Completer
	IsRequired    bool
}

func (*Flag) GetInvocation

func (f *Flag) GetInvocation() string

func (*Flag) GetPaddedInvocation

func (f *Flag) GetPaddedInvocation() string

func (*Flag) GetValueFromString

func (f *Flag) GetValueFromString(value string) (any, error)

GetValueFromString parses the provided value according to the flag's underlying data type and returns that parsed value, or an error

func (*Flag) PopulateDefault

func (f *Flag) PopulateDefault(target map[string]any) error

func (*Flag) PopulateMap

func (f *Flag) PopulateMap(value string, target map[string]any) error

func (*Flag) SuggestValues

func (f *Flag) SuggestValues(prefix string) []*ns.AutoComplete

func (*Flag) Validate

func (f *Flag) Validate() error

Validate returns an error if any part of the flag is invalid

type TokenGroup

type TokenGroup struct {
	Tokens      []string
	FlowControl byte
}

func Tokenize

func Tokenize(line string) []*TokenGroup

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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