Added the RC file which can be used to load commands on startup. Also added the "echo" command which can be used for debugging.
116 lines
2.6 KiB
Go
116 lines
2.6 KiB
Go
package commandctrl
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/pkg/errors"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/lmika/audax/internal/common/ui/events"
|
|
"github.com/lmika/shellwords"
|
|
)
|
|
|
|
type CommandController struct {
|
|
commandList *CommandList
|
|
}
|
|
|
|
func NewCommandController() *CommandController {
|
|
return &CommandController{
|
|
commandList: nil,
|
|
}
|
|
}
|
|
|
|
func (c *CommandController) AddCommands(ctx *CommandList) {
|
|
ctx.parent = c.commandList
|
|
c.commandList = ctx
|
|
}
|
|
|
|
func (c *CommandController) Prompt() tea.Msg {
|
|
return events.PromptForInputMsg{
|
|
Prompt: ":",
|
|
OnDone: func(value string) tea.Msg {
|
|
return c.Execute(value)
|
|
},
|
|
}
|
|
}
|
|
|
|
func (c *CommandController) Execute(commandInput string) tea.Msg {
|
|
return c.execute(ExecContext{FromFile: false}, commandInput)
|
|
}
|
|
|
|
func (c *CommandController) execute(ctx ExecContext, commandInput string) tea.Msg {
|
|
input := strings.TrimSpace(commandInput)
|
|
if input == "" {
|
|
return nil
|
|
}
|
|
|
|
tokens := shellwords.Split(input)
|
|
command := c.lookupCommand(tokens[0])
|
|
if command == nil {
|
|
return events.Error(errors.New("no such command: " + tokens[0]))
|
|
}
|
|
|
|
return command(ctx, tokens[1:])
|
|
}
|
|
|
|
func (c *CommandController) Alias(commandName string) Command {
|
|
return func(ctx ExecContext, args []string) tea.Msg {
|
|
command := c.lookupCommand(commandName)
|
|
if command == nil {
|
|
return events.Error(errors.New("no such command: " + commandName))
|
|
}
|
|
|
|
return command(ctx, args)
|
|
}
|
|
}
|
|
|
|
func (c *CommandController) lookupCommand(name string) Command {
|
|
for ctx := c.commandList; ctx != nil; ctx = ctx.parent {
|
|
if cmd, ok := ctx.Commands[name]; ok {
|
|
return cmd
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *CommandController) ExecuteFile(filename string) error {
|
|
baseFilename := filepath.Base(filename)
|
|
|
|
if rcFile, err := os.ReadFile(filename); err == nil {
|
|
if err := c.executeFile(rcFile, baseFilename); err != nil {
|
|
return errors.Wrapf(err, "error executing %v", filename)
|
|
}
|
|
} else {
|
|
return errors.Wrapf(err, "error loading %v", filename)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *CommandController) executeFile(file []byte, filename string) error {
|
|
scnr := bufio.NewScanner(bytes.NewReader(file))
|
|
|
|
lineNo := 0
|
|
for scnr.Scan() {
|
|
lineNo++
|
|
line := strings.TrimSpace(scnr.Text())
|
|
if line == "" {
|
|
continue
|
|
} else if line[0] == '#' {
|
|
continue
|
|
}
|
|
|
|
msg := c.execute(ExecContext{FromFile: true}, line)
|
|
switch m := msg.(type) {
|
|
case events.ErrorMsg:
|
|
log.Printf("%v:%v: error - %v", filename, lineNo, m.Error())
|
|
case events.StatusMsg:
|
|
log.Printf("%v:%v: %v", filename, lineNo, string(m))
|
|
}
|
|
}
|
|
return scnr.Err()
|
|
}
|