k9s/internal/views/command.go

128 lines
2.6 KiB
Go

package views
import (
"regexp"
"github.com/derailed/k9s/internal/resource"
"github.com/rs/zerolog/log"
)
type subjectViewer interface {
resourceViewer
setSubject(s string)
}
type command struct {
app *appView
history *cmdStack
}
func newCommand(app *appView) *command {
return &command{app: app, history: newCmdStack()}
}
func (c *command) lastCmd() bool {
return c.history.last()
}
func (c *command) pushCmd(cmd string) {
c.history.push(cmd)
c.app.crumbsView.update(c.history.stack)
}
func (c *command) previousCmd() (string, bool) {
if c.lastCmd() {
return c.history.top()
}
c.history.pop()
c.app.crumbsView.update(c.history.stack)
return c.history.top()
}
// DefaultCmd reset default command ie show pods.
func (c *command) defaultCmd() {
c.pushCmd(c.app.config.ActiveView())
c.run(c.app.config.ActiveView())
}
// Helpers...
var policyMatcher = regexp.MustCompile(`\Apol\s([u|g|s]):([\w-:]+)\b`)
// Exec the command by showing associated display.
func (c *command) run(cmd string) bool {
var v resourceViewer
switch {
case cmd == "q", cmd == "quit":
c.app.BailOut()
return true
case cmd == "?", cmd == "help":
c.app.inject(newHelpView(c.app))
return true
case cmd == "alias":
c.app.inject(newAliasView(c.app))
return true
case policyMatcher.MatchString(cmd):
tokens := policyMatcher.FindAllStringSubmatch(cmd, -1)
if len(tokens) == 1 && len(tokens[0]) == 3 {
c.app.inject(newPolicyView(c.app, tokens[0][1], tokens[0][2]))
return true
}
default:
if res, ok := resourceViews(c.app.conn())[cmd]; ok {
var r resource.List
if res.listFn != nil {
r = res.listFn(c.app.conn(), resource.DefaultNamespace)
}
v = res.viewFn(res.title, c.app, r)
if res.colorerFn != nil {
v.setColorerFn(res.colorerFn)
}
if res.enterFn != nil {
v.setEnterFn(res.enterFn)
}
if res.decorateFn != nil {
v.setDecorateFn(res.decorateFn)
}
const fmat = "Viewing resource %s..."
c.app.flash().infof(fmat, res.title)
log.Debug().Msgf("Running command %s", cmd)
c.exec(cmd, v)
return true
}
}
res, ok := allCRDs(c.app.conn())[cmd]
if !ok {
c.app.flash().warnf("Huh? `%s` command not found", cmd)
return false
}
name := res.Plural
if len(name) == 0 {
name = res.Singular
}
v = newResourceView(
res.Kind,
c.app,
resource.NewCustomList(c.app.conn(), "", res.Group, res.Version, name),
)
v.setColorerFn(defaultColorer)
c.exec(cmd, v)
return true
}
func (c *command) exec(cmd string, v igniter) {
if v == nil {
return
}
c.app.config.SetActiveView(cmd)
c.app.config.Save()
c.app.inject(v)
}