Files
spellbook/cmd/root.go
T
2026-08-21 16:30:49 +05:00

109 lines
2.7 KiB
Go

package cmd
import (
"context"
"github.com/abelith/spellbook/internal/models"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"io"
"os"
"strings"
)
type Application interface {
AddSpell(ctx context.Context, spell models.Spell) error
GetSpell(ctx context.Context, spellName string) (models.Spell, error)
GetSpells(ctx context.Context, query models.SearchQuery) ([]models.Spell, error)
DeleteSpell(ctx context.Context, spellName string) error
CastSpell(ctx context.Context, spellCast models.SpellCast) (models.CastResult, error)
ExportSpells(ctx context.Context, exp string, w io.Writer) error
ImportSpells(ctx context.Context, exp string, r io.Reader) error
}
func rootCmd(app Application) func(*cobra.Command, []string) error {
return func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
if len(args) < 1 {
return listCommands(ctx, cmd, app)
}
return runCommand(ctx, app, args)
}
}
func runCommand(ctx context.Context, app Application, args []string) error {
spell, err := app.GetSpell(ctx, args[0])
if err != nil {
return err
}
m := make(map[string]string, len(args[1:]))
for _, pair := range args[1:] {
keyVal := strings.Split(pair, "=")
m[keyVal[0]] = keyVal[1]
}
_, err = app.CastSpell(ctx, models.SpellCast{
Spell: spell,
Args: m,
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
})
if err != nil {
return err
}
return nil
}
func listCommands(ctx context.Context, cmd *cobra.Command, app Application) error {
spells, err := app.GetSpells(ctx, models.SearchQuery{})
if err != nil {
return err
}
if len(spells) == 0 {
cmd.Println("Spell book is empty. Try `spellbook add` to add your first spell")
return nil
}
return printTable(cmd, spells)
}
func printTable(cmd *cobra.Command, spells []models.Spell) error {
table := tablewriter.NewTable(cmd.OutOrStdout())
rows := make([][]string, 0, len(spells))
for _, spell := range spells {
row := []string{
spell.Name, spell.Spell, spell.ShortDesc, strings.Join(spell.Tags, ", "),
}
rows = append(rows, row)
}
table.Header("Name", "Spell", "Short description", "Tags")
_ = table.Bulk(rows)
if err := table.Render(); err != nil {
return err
}
return nil
}
func NewRootCmd(ver string, app Application) *cobra.Command {
cmd := &cobra.Command{
Use: "spellbook",
Short: "CLI tool to store, manage and execute command templates",
Long: `Spellbook is a lightweight binary command manager written in Go.
It allows you to save complex shell commands as parametrized templates (spells)
and execute them instantly with custom arguments from anywhere in your terminal`,
RunE: rootCmd(app),
Args: cobra.ArbitraryArgs,
Version: ver,
}
return cmd
}