diff --git a/commands/cargo.go b/commands/cargo.go new file mode 100644 index 0000000..f5638ff --- /dev/null +++ b/commands/cargo.go @@ -0,0 +1,29 @@ +package commands + +import ( + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "cargo", + Description: "rust toolchain", + Subcommands: []core.Subcommand{ + {Name: "build", Description: "compile project", + Options: []core.Option{ + {Name: "--release", Description: "optimized build"}, + }, + }, + {Name: "run", Description: "run project"}, + {Name: "test", Description: "run tests"}, + {Name: "new", Description: "create project"}, + {Name: "add", Description: "add dependency"}, + {Name: "fmt", Description: "format code"}, + {Name: "clippy", Description: "lint code"}, + {Name: "check", Description: "check without build"}, + {Name: "clean", Description: "remove build artifacts"}, + {Name: "publish", Description: "publish crate"}, + {Name: "doc", Description: "build documentation"}, + }, + }) +} diff --git a/commands/docker.go b/commands/docker.go new file mode 100644 index 0000000..c679f1d --- /dev/null +++ b/commands/docker.go @@ -0,0 +1,119 @@ +package commands + +import ( + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "docker", + Description: "container engine", + Subcommands: []core.Subcommand{ + { + Name: "ps", + Description: "list containers", + Options: []core.Option{ + {Name: "-a", Description: "show all"}, + {Name: "-q", Description: "only show IDs"}, + }, + }, + { + Name: "build", + Description: "build image", + Options: []core.Option{ + {Name: "-t", Description: "tag name"}, + {Name: "-f", Description: "dockerfile path"}, + {Name: "--no-cache", Description: "no build cache"}, + }, + }, + { + Name: "run", + Description: "run container", + Options: []core.Option{ + {Name: "-d", Description: "detached mode"}, + {Name: "-p", Description: "port mapping"}, + {Name: "-v", Description: "volume mount"}, + {Name: "--rm", Description: "auto remove"}, + {Name: "--name", Description: "container name"}, + {Name: "-it", Description: "interactive tty"}, + {Name: "-e", Description: "set env variable"}, + }, + }, + { + Name: "pull", + Description: "pull image", + }, + { + Name: "push", + Description: "push image", + }, + { + Name: "exec", + Description: "exec in container", + Options: []core.Option{ + {Name: "-it", Description: "interactive tty"}, + }, + }, + { + Name: "stop", + Description: "stop container", + }, + { + Name: "rm", + Description: "remove container", + Options: []core.Option{ + {Name: "-f", Description: "force remove"}, + }, + }, + { + Name: "rmi", + Description: "remove image", + }, + { + Name: "images", + Description: "list images", + }, + { + Name: "logs", + Description: "view logs", + Options: []core.Option{ + {Name: "-f", Description: "follow output"}, + {Name: "--tail", Description: "last n lines"}, + }, + }, + { + Name: "compose", + Description: "multi-container", + Subcommands: []core.Subcommand{ + {Name: "up", Description: "start services"}, + {Name: "down", Description: "stop services"}, + {Name: "build", Description: "build services"}, + {Name: "logs", Description: "view logs"}, + {Name: "ps", Description: "list services"}, + {Name: "exec", Description: "execute command"}, + {Name: "restart", Description: "restart services"}, + }, + }, + { + Name: "network", + Description: "manage networks", + Subcommands: []core.Subcommand{ + {Name: "ls", Description: "list networks"}, + {Name: "create", Description: "create network"}, + {Name: "rm", Description: "remove network"}, + {Name: "inspect", Description: "show details"}, + }, + }, + { + Name: "volume", + Description: "manage volumes", + Subcommands: []core.Subcommand{ + {Name: "ls", Description: "list volumes"}, + {Name: "create", Description: "create volume"}, + {Name: "rm", Description: "remove volume"}, + {Name: "prune", Description: "remove unused"}, + }, + }, + }, + }) +} diff --git a/commands/git.go b/commands/git.go new file mode 100644 index 0000000..c1fa682 --- /dev/null +++ b/commands/git.go @@ -0,0 +1,205 @@ +package commands + +import ( + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "git", + Description: "version control", + Options: []core.Option{ + {Name: "--version", Description: "print version"}, + {Name: "--help", Description: "show help"}, + }, + Subcommands: []core.Subcommand{ + { + Name: "init", + Description: "create empty repo", + Options: []core.Option{ + {Name: "--bare", Description: "create bare repo"}, + {Name: "-b", Description: "initial branch name"}, + }, + }, + { + Name: "clone", + Description: "clone a repository", + Options: []core.Option{ + {Name: "--depth", Description: "shallow clone depth"}, + {Name: "--branch", Description: "specific branch"}, + {Name: "--bare", Description: "clone as bare"}, + }, + }, + { + Name: "status", + Description: "show working tree", + Options: []core.Option{ + {Name: "-s", Description: "short format"}, + {Name: "--porcelain", Description: "machine format"}, + }, + }, + { + Name: "add", + Description: "stage changes", + Options: []core.Option{ + {Name: "-A", Description: "add all files"}, + {Name: "-p", Description: "interactive patch"}, + {Name: ".", Description: "add current dir"}, + }, + }, + { + Name: "commit", + Description: "record changes", + Options: []core.Option{ + {Name: "-m", Description: "commit message"}, + {Name: "-a", Description: "auto stage tracked"}, + {Name: "--amend", Description: "amend last commit"}, + {Name: "--no-edit", Description: "keep message"}, + }, + }, + { + Name: "push", + Description: "update remote refs", + Options: []core.Option{ + {Name: "-u", Description: "set upstream"}, + {Name: "--force", Description: "force push"}, + {Name: "--tags", Description: "push tags"}, + {Name: "origin", Description: "default remote"}, + }, + }, + { + Name: "pull", + Description: "fetch and merge", + Options: []core.Option{ + {Name: "--rebase", Description: "rebase on pull"}, + {Name: "origin", Description: "default remote"}, + }, + }, + { + Name: "fetch", + Description: "download objects", + Options: []core.Option{ + {Name: "--all", Description: "fetch all remotes"}, + {Name: "--prune", Description: "remove stale refs"}, + }, + }, + { + Name: "checkout", + Description: "switch branches", + Options: []core.Option{ + {Name: "-b", Description: "create new branch"}, + }, + }, + { + Name: "switch", + Description: "switch branches", + Options: []core.Option{ + {Name: "-c", Description: "create and switch"}, + }, + }, + { + Name: "branch", + Description: "manage branches", + Options: []core.Option{ + {Name: "-d", Description: "delete branch"}, + {Name: "-D", Description: "force delete"}, + {Name: "-a", Description: "list all"}, + {Name: "-m", Description: "rename branch"}, + }, + }, + { + Name: "merge", + Description: "join branches", + Options: []core.Option{ + {Name: "--no-ff", Description: "no fast forward"}, + {Name: "--squash", Description: "squash commits"}, + {Name: "--abort", Description: "abort merge"}, + }, + }, + { + Name: "rebase", + Description: "reapply commits", + Options: []core.Option{ + {Name: "-i", Description: "interactive"}, + {Name: "--onto", Description: "rebase onto"}, + {Name: "--abort", Description: "abort rebase"}, + {Name: "--continue", Description: "continue rebase"}, + }, + }, + { + Name: "log", + Description: "show commit log", + Options: []core.Option{ + {Name: "--oneline", Description: "compact format"}, + {Name: "--graph", Description: "show graph"}, + {Name: "-n", Description: "limit count"}, + }, + }, + { + Name: "diff", + Description: "show changes", + Options: []core.Option{ + {Name: "--staged", Description: "staged changes"}, + {Name: "--stat", Description: "diffstat only"}, + }, + }, + { + Name: "stash", + Description: "stash changes", + Subcommands: []core.Subcommand{ + {Name: "pop", Description: "apply and drop"}, + {Name: "apply", Description: "apply stash"}, + {Name: "drop", Description: "remove stash"}, + {Name: "list", Description: "list stashes"}, + {Name: "show", Description: "show stash diff"}, + }, + }, + { + Name: "reset", + Description: "reset HEAD", + Options: []core.Option{ + {Name: "--hard", Description: "discard changes"}, + {Name: "--soft", Description: "keep staged"}, + {Name: "--mixed", Description: "unstage changes"}, + }, + }, + { + Name: "tag", + Description: "manage tags", + Options: []core.Option{ + {Name: "-a", Description: "annotated tag"}, + {Name: "-d", Description: "delete tag"}, + {Name: "-l", Description: "list tags"}, + }, + }, + { + Name: "remote", + Description: "manage remotes", + Subcommands: []core.Subcommand{ + {Name: "add", Description: "add remote"}, + {Name: "remove", Description: "remove remote"}, + {Name: "rename", Description: "rename remote"}, + {Name: "-v", Description: "verbose list"}, + }, + }, + { + Name: "cherry-pick", + Description: "apply commit", + Options: []core.Option{ + {Name: "--no-commit", Description: "no auto commit"}, + {Name: "--abort", Description: "abort pick"}, + }, + }, + { + Name: "bisect", + Description: "binary search bug", + Subcommands: []core.Subcommand{ + {Name: "start", Description: "start bisect"}, + {Name: "good", Description: "mark good"}, + {Name: "bad", Description: "mark bad"}, + {Name: "reset", Description: "end bisect"}, + }, + }, + }, + }) +} diff --git a/commands/go.go b/commands/go.go new file mode 100644 index 0000000..0075eda --- /dev/null +++ b/commands/go.go @@ -0,0 +1,99 @@ +package commands + +import ( + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "go", + Description: "go toolchain", + Subcommands: []core.Subcommand{ + { + Name: "build", + Description: "compile packages", + Options: []core.Option{ + {Name: "-o", Description: "output file"}, + {Name: "-v", Description: "verbose"}, + {Name: "-race", Description: "enable race detector"}, + {Name: "-ldflags", Description: "linker flags"}, + }, + }, + { + Name: "run", + Description: "compile and run", + Options: []core.Option{ + {Name: "-race", Description: "enable race detector"}, + }, + }, + { + Name: "test", + Description: "run tests", + Options: []core.Option{ + {Name: "-v", Description: "verbose output"}, + {Name: "-run", Description: "run specific test"}, + {Name: "-bench", Description: "run benchmarks"}, + {Name: "-cover", Description: "coverage report"}, + {Name: "-count", Description: "run count times"}, + {Name: "-race", Description: "enable race detector"}, + }, + }, + { + Name: "mod", + Description: "module maintenance", + Subcommands: []core.Subcommand{ + {Name: "init", Description: "initialize module"}, + {Name: "tidy", Description: "clean up modules"}, + {Name: "download", Description: "download modules"}, + {Name: "vendor", Description: "make vendor copy"}, + {Name: "edit", Description: "edit go.mod"}, + {Name: "graph", Description: "print module graph"}, + {Name: "verify", Description: "verify dependencies"}, + }, + }, + { + Name: "get", + Description: "add dependency", + Options: []core.Option{ + {Name: "-u", Description: "update module"}, + }, + }, + { + Name: "fmt", + Description: "format source", + }, + { + Name: "vet", + Description: "examine code", + }, + { + Name: "install", + Description: "compile and install", + }, + { + Name: "generate", + Description: "run go generate", + }, + { + Name: "clean", + Description: "remove object files", + Options: []core.Option{ + {Name: "-cache", Description: "clean build cache"}, + {Name: "-testcache", Description: "clean test cache"}, + }, + }, + { + Name: "env", + Description: "print go environment", + }, + { + Name: "doc", + Description: "show documentation", + }, + { + Name: "tool", + Description: "run go tool", + }, + }, + }) +} diff --git a/commands/justfile.go b/commands/justfile.go new file mode 100644 index 0000000..87c111c --- /dev/null +++ b/commands/justfile.go @@ -0,0 +1,82 @@ +package commands + +import ( + "bufio" + "os" + "regexp" + "strings" + + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "just", + Description: "command runner", + Generator: func(tokens []string, prefix string) []core.Suggestion { + file, err := os.Open("justfile") + if err != nil { + // try uppercase + file, err = os.Open("Justfile") + if err != nil { + return nil + } + } + defer file.Close() + + var suggestions []core.Suggestion + seen := make(map[string]bool) + scanner := bufio.NewScanner(file) + // matching recipes like `build:` + recipeRegex := regexp.MustCompile(`^([a-zA-Z0-9_-]+):`) + + lastComment := "" + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + + // Handle comments + if strings.HasPrefix(line, "#") { + lastComment = strings.TrimSpace(strings.TrimPrefix(line, "#")) + continue + } + + // Skip blank lines or group attributes + if line == "" || strings.HasPrefix(line, "[") { + continue + } + + if matches := recipeRegex.FindStringSubmatch(line); len(matches) > 1 { + recipe := matches[1] + if seen[recipe] { + lastComment = "" + continue + } + seen[recipe] = true + + cmd := recipe + if prefix != "" { + cmd = prefix + " " + recipe + } + + desc := "just recipe" + if lastComment != "" { + desc = lastComment + } + + suggestions = append(suggestions, core.Suggestion{ + Cmd: cmd, + Desc: desc, + }) + lastComment = "" + } else { + // If it's something else (like a command line), reset comment + // unless it's just indented (which we already skip or handle) + if !strings.HasPrefix(scanner.Text(), " ") && !strings.HasPrefix(scanner.Text(), "\t") { + lastComment = "" + } + } + } + return suggestions + }, + }) +} diff --git a/commands/kubectl.go b/commands/kubectl.go new file mode 100644 index 0000000..5b9364f --- /dev/null +++ b/commands/kubectl.go @@ -0,0 +1,38 @@ +package commands + +import ( + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "kubectl", + Description: "kubernetes cli", + Subcommands: []core.Subcommand{ + {Name: "get", Description: "display resources", + Subcommands: []core.Subcommand{ + {Name: "pods", Description: "list pods"}, + {Name: "services", Description: "list services"}, + {Name: "deployments", Description: "list deployments"}, + {Name: "nodes", Description: "list nodes"}, + {Name: "namespaces", Description: "list namespaces"}, + }, + }, + {Name: "apply", Description: "apply config", + Options: []core.Option{ + {Name: "-f", Description: "filename"}, + }, + }, + {Name: "describe", Description: "show details"}, + {Name: "logs", Description: "view pod logs", + Options: []core.Option{ + {Name: "-f", Description: "follow logs"}, + }, + }, + {Name: "delete", Description: "delete resource"}, + {Name: "exec", Description: "execute in pod"}, + {Name: "port-forward", Description: "forward ports"}, + {Name: "scale", Description: "scale resource"}, + }, + }) +} diff --git a/commands/makefile.go b/commands/makefile.go new file mode 100644 index 0000000..b4f32f0 --- /dev/null +++ b/commands/makefile.go @@ -0,0 +1,54 @@ +package commands + +import ( + "bufio" + "os" + "regexp" + + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "make", + Description: "build automation", + Generator: func(tokens []string, prefix string) []core.Suggestion { + // Read the Makefile + file, err := os.Open("Makefile") + if err != nil { + // No Makefile, don't pretend we have one + return nil + } + defer file.Close() + + var suggestions []core.Suggestion + seen := make(map[string]bool) + scanner := bufio.NewScanner(file) + // Matches targets like `build:`, ` run :`, etc. + // Ignores lines starting with whitespace followed by command (tab) + targetRegex := regexp.MustCompile(`^[ \t]*([a-zA-Z0-9_-]+)[ \t]*:`) + + for scanner.Scan() { + line := scanner.Text() + if matches := targetRegex.FindStringSubmatch(line); len(matches) > 1 { + target := matches[1] + // Ignore standard non-target keywords + if target == "PHONY" || seen[target] { + continue + } + seen[target] = true + + cmd := target + if prefix != "" { + cmd = prefix + " " + target + } + suggestions = append(suggestions, core.Suggestion{ + Cmd: cmd, + Desc: "make target", + }) + } + } + return suggestions + }, + }) +} diff --git a/commands/npm.go b/commands/npm.go new file mode 100644 index 0000000..a93fa8d --- /dev/null +++ b/commands/npm.go @@ -0,0 +1,37 @@ +package commands + +import ( + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "npm", + Description: "node packages", + Subcommands: []core.Subcommand{ + {Name: "install", Description: "install packages"}, + {Name: "run", Description: "run script", + Subcommands: []core.Subcommand{ + {Name: "dev", Description: "development server"}, + {Name: "build", Description: "build for production"}, + {Name: "start", Description: "start application"}, + {Name: "test", Description: "run test suite"}, + {Name: "lint", Description: "run linter"}, + }, + }, + {Name: "test", Description: "run tests"}, + {Name: "init", Description: "create package.json"}, + {Name: "publish", Description: "publish package"}, + {Name: "update", Description: "update packages"}, + {Name: "uninstall", Description: "remove package"}, + {Name: "ls", Description: "list installed"}, + {Name: "audit", Description: "security audit"}, + {Name: "cache", Description: "manage cache", + Subcommands: []core.Subcommand{ + {Name: "clean", Description: "clear cache"}, + {Name: "verify", Description: "verify cache"}, + }, + }, + }, + }) +} diff --git a/commands/pip.go b/commands/pip.go new file mode 100644 index 0000000..d005e92 --- /dev/null +++ b/commands/pip.go @@ -0,0 +1,19 @@ +package commands + +import ( + "github.com/versenilvis/iris/commands/core" +) + +func init() { + core.Register(&core.Spec{ + Name: "pip", + Description: "python packages", + Subcommands: []core.Subcommand{ + {Name: "install", Description: "install package"}, + {Name: "uninstall", Description: "remove package"}, + {Name: "freeze", Description: "list packages"}, + {Name: "list", Description: "list installed"}, + {Name: "show", Description: "show package info"}, + }, + }) +}