Salamander

package module
v0.0.0-...-d2962a3 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2019 License: MIT Imports: 6 Imported by: 1

README

🦎 Salamander

Salamander is a Go commander library designed to be integrated with the discordgo library. For an active project using Salamander check out mamba.

Salamander is an active work in progress, but is currently fully usable, bar the use of flags, in its current state!

Install

Salamander requires a Go version with Module support. To install simply run the following command:

go get github.com/madxmike/Salamander

Use

New Command

Salamander provides a simple builder to create commands easily. See the example below or find additional examples in the examples folder. Please note that this is an evolving api, and some information may need to be periodicly updated.

var EchoCmd = Salamander.NewCommand("echo"). // Create a new command named Echo. This is the name that a user will call the command by.
	WithShortName("e"). // Short name acts as a alias such that a user could call "echo <args>" or "e <args>" 
	WithValidator(Salamander.RequiresMinArgs(1)). // Ensure arguments are correct. See validators.go for built-in validators.
	WithHandler(func(cmd *Salamander.Command, ctx context.Context, p *Salamander.Provider) error {
    // The Handler is the block of code executed when the command is ran. See Pre- and Post- handlers also for respective uses.
		args := cmd.GetArgs()
		echo := strings.Join(args, " ")
		_, err := p.Session.ChannelMessageSend(p.Channel.ID, echo)
		return err
}).Build() // Finally build the command
Running a command

While you can run any command by calling .Run(...) on the command instance, it is generally recommended that you keep a command tree that stores all of your commands. The following is an example of building a simple command tree:

func tree() (root *Command, err error) {
  root = Salamander.NewCommand("root").Build() // Create a root node for the tree. Will only be run if no other command is found.
  err = root.AddChild(&PingCmd) // Add a subcommand to the root.
  err = PingCmd.AddChild(&SubPingCmd) // You can add subcommands to a command at any time and it will be added to the tree correctly
  err = root.AddChild(&EchoCmd)
  return
}

Please note that storing commands in package-level variables means once you add a subcommand it will attached forever, across all trees, until you explicity remove it

Once you have a tree built simply call .Run(...) on the root node to run the command!

...
root, err := tree()
if err != nil {
  return
}
childRan, err := root.Run(provider, context, input)

The input is a slice of strings that includes both the command path and the arguments for the command. For example to call a command bar that is a child of foo and takes the arguments baz and bav simply pass the following slice:

input := {"foo", "bar", "baz", "bav"}

The .Run(...) command will search this list and find the lowest depth command, starting from the root, that matches the names given. Once the command to run has been found, a slice containing the remaining inputs will be passes as the arguments to the command. In this example the bar command will be executed and a slice of {"baz", "bav"} will be passed as the arguments.

Note that the command executed will always be the lowest depth command that matches the inputs. As such, if bar is not found then foo will be executed and be passed the arguments {"bar", "baz", "bav"}

Additional note: while .Run(...) can be called on any command node in the tree, it will always find and run on the root node instead.

Roadmap

  • Flags
  • Better native concurrency support
  • Additional validators
  • Command database connection

Additional Information

If you see any improvements that you would like to make please feel free to fork the project and submit a pull request! Again, this is a work in progress API so expect frequent updates and changes.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotImplemented          = errors.New("not implemented")
	ErrChildIsNil              = errors.New("child is nil")
	ErrChildAlreadyAdded       = errors.New("child already added")
	ErrChildNotFound           = errors.New("child not found")
	ErrLoopedChildren          = errors.New("child-parent loop exists")
	ErrNoMessageAvailable      = errors.New("no message available")
	ErrTooFewArguments         = errors.New("too few arguments")
	ErrCouldNotRunCommand      = errors.New("could not run command")
	ErrPositionalArgsMisplaced = errors.New("args in incorrect place")
)

Functions

func NewCommand

func NewCommand(name string) *builder

func RequiresMinArgs

func RequiresMinArgs(n uint) func(args []string) error

func RequiresMulti

func RequiresMulti(f ...func(args []string) error) func(args []string) error

func RequiresPositionalArgs

func RequiresPositionalArgs(p map[string]uint) func(args []string) error

Types

type Command

type Command struct {
	Name  string
	Short string

	Parent *Command

	PreExecute  func(cmd *Command, ctx context.Context, p *Provider) error
	Execute     func(cmd *Command, ctx context.Context, p *Provider) error
	PostExecute func(cmd *Command, ctx context.Context, p *Provider) error
	Validate    func(args []string) error

	CaptureInput bool
	// contains filtered or unexported fields
}

func (*Command) AddChild

func (cmd *Command) AddChild(child *Command) error

Adds a child to the command node, and sets the child's parent to be the command node.

Will return ErrChildAlreadyAdded if the child already has been added to the node.

func (*Command) FindChild

func (cmd *Command) FindChild(name ...string) (*Command, error)

func (*Command) GetArgs

func (cmd *Command) GetArgs() []string

func (*Command) GetInbound

func (cmd *Command) GetInbound() chan<- *discordgo.Message

func (*Command) GetReader

func (cmd *Command) GetReader() io.Reader

func (*Command) GetWriter

func (cmd *Command) GetWriter() io.Writer

func (*Command) ParseArgs

func (cmd *Command) ParseArgs(args []string) []string

func (*Command) RemoveAllChildren

func (cmd *Command) RemoveAllChildren()

func (*Command) RemoveChild

func (cmd *Command) RemoveChild(name string) (*Command, error)

func (Command) Root

func (cmd Command) Root() (root *Command, err error)

func (*Command) Run

func (cmd *Command) Run(p *Provider, ctx context.Context, input []string) (*Command, error)

func (*Command) RunConcurrently

func (cmd *Command) RunConcurrently(p *Provider, ctx context.Context, input []string) (c *Command, errReturn chan error)

func (*Command) SetArgs

func (cmd *Command) SetArgs(args ...string)

func (*Command) SetReader

func (cmd *Command) SetReader(r io.Reader)

func (*Command) SetWriter

func (cmd *Command) SetWriter(w io.Writer)

func (*Command) ThreadSafe

func (cmd *Command) ThreadSafe() (Command, error)

Creates a threadsafe version of the command. This command is effectively a deep copy of the original command, But still retains a pointer to its original parent and children Such that only one command is initialized instead of the entire tree

func (*Command) WriteString

func (cmd *Command) WriteString(s string)

type Provider

type Provider struct {
	Session *discordgo.Session
	User    *discordgo.User
	Channel *discordgo.Channel
	GuildID string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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