feat(app): add history navigation with `[` and `]`, most recent command with `-` (#2799)
* feat(app): add Go Back and Last View Go Back walks back through the history until at the oldest saved view Last View switches between the current and previous views like how "cd -" works * feat(history): add keyboard shortcuts to navigate history * fix(tests): fix history/app tests * docs(README): update history and last command navigation info * fix(internal): add missing parameter * feat(help): add history keybinds * fix(help): adjust capitalization for history commands * docs(readme): fix typo Co-authored-by: merusso <merusso@gmail.com> --------- Co-authored-by: merusso <merusso@gmail.com>mine
parent
4acf9384d9
commit
cc1c86ccb4
|
|
@ -362,6 +362,8 @@ K9s uses aliases to navigate most K8s resources.
|
|||
| To view and switch to another Kubernetes context (Pod view) | `:`ctx⏎ | |
|
||||
| To view and switch directly to another Kubernetes context (Last used view) | `:`ctx context-name⏎ | |
|
||||
| To view and switch to another Kubernetes namespace | `:`ns⏎ | |
|
||||
| To switch back to the last active command (like how "cd -" works) | `-` | Navigation that adds breadcrumbs to the bottom are not commands |
|
||||
| To go back and forward through the command history | back: `[`, forward: `]` | Same as above |
|
||||
| To view all saved resources | `:`screendump or sd⏎ | |
|
||||
| To delete a resource (TAB and ENTER to confirm) | `ctrl-d` | |
|
||||
| To kill a resource (no confirmation dialog, equivalent to kubectl delete --now) | `ctrl-k` | |
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@ const MaxHistory = 20
|
|||
|
||||
// History represents a command history.
|
||||
type History struct {
|
||||
commands []string
|
||||
limit int
|
||||
commands []string
|
||||
limit int
|
||||
activeCommandIndex int
|
||||
previousCommandIndex int
|
||||
}
|
||||
|
||||
// NewHistory returns a new instance.
|
||||
|
|
@ -23,12 +25,77 @@ func NewHistory(limit int) *History {
|
|||
}
|
||||
}
|
||||
|
||||
func (h *History) Pop() string {
|
||||
// Last switches the current and previous history index positions so the
|
||||
// new command referenced by the index is the previous command
|
||||
func (h *History) Last() bool {
|
||||
if h.Empty() {
|
||||
return ""
|
||||
return false
|
||||
}
|
||||
|
||||
return h.commands[0]
|
||||
h.activeCommandIndex, h.previousCommandIndex = h.previousCommandIndex, h.activeCommandIndex
|
||||
return true
|
||||
}
|
||||
|
||||
// Back moves the history position index back by one
|
||||
func (h *History) Back() bool {
|
||||
if h.Empty() {
|
||||
return false
|
||||
}
|
||||
|
||||
// Return if there are no more commands left in the backward history
|
||||
if h.activeCommandIndex == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
h.previousCommandIndex = h.activeCommandIndex
|
||||
h.activeCommandIndex = h.activeCommandIndex - 1
|
||||
return true
|
||||
}
|
||||
|
||||
// Forward moves the history position index forward by one
|
||||
func (h *History) Forward() bool {
|
||||
if h.Empty() {
|
||||
return false
|
||||
}
|
||||
|
||||
// Return if there are no more commands left in the forward history
|
||||
if h.activeCommandIndex >= len(h.commands)-1 {
|
||||
return false
|
||||
}
|
||||
|
||||
h.previousCommandIndex = h.activeCommandIndex
|
||||
h.activeCommandIndex = h.activeCommandIndex + 1
|
||||
return true
|
||||
}
|
||||
|
||||
// CurrentIndex returns the current index of the active command in the history
|
||||
func (h *History) CurrentIndex() int {
|
||||
return h.activeCommandIndex
|
||||
}
|
||||
|
||||
// PreviousIndex returns the index of the command that was the most recent
|
||||
// active command in the history
|
||||
func (h *History) PreviousIndex() int {
|
||||
return h.previousCommandIndex
|
||||
}
|
||||
|
||||
// Pop removes the single most recent history item
|
||||
// and returns a bool if the list changed.
|
||||
func (h *History) Pop() bool {
|
||||
return h.PopN(1)
|
||||
}
|
||||
|
||||
// PopN removes the N most recent history item
|
||||
// and returns a bool if the list changed.
|
||||
// Argument specifies how many to remove from the history
|
||||
func (h *History) PopN(n int) bool {
|
||||
cmdLength := len(h.commands)
|
||||
if cmdLength == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
h.commands = h.commands[:cmdLength-n]
|
||||
return true
|
||||
}
|
||||
|
||||
// List returns the current command history.
|
||||
|
|
@ -43,31 +110,22 @@ func (h *History) Push(c string) {
|
|||
}
|
||||
|
||||
c = strings.ToLower(c)
|
||||
if i := h.indexOf(c); i != -1 {
|
||||
return
|
||||
}
|
||||
if len(h.commands) < h.limit {
|
||||
h.commands = append([]string{c}, h.commands...)
|
||||
h.commands = append(h.commands, c)
|
||||
h.previousCommandIndex = h.activeCommandIndex
|
||||
h.activeCommandIndex = len(h.commands) - 1
|
||||
return
|
||||
}
|
||||
h.commands = append([]string{c}, h.commands[:len(h.commands)-1]...)
|
||||
}
|
||||
|
||||
// Clear clears out the stack.
|
||||
func (h *History) Clear() {
|
||||
h.commands = nil
|
||||
h.activeCommandIndex = 0
|
||||
h.previousCommandIndex = 0
|
||||
}
|
||||
|
||||
// Empty returns true if no history.
|
||||
func (h *History) Empty() bool {
|
||||
return len(h.commands) == 0
|
||||
}
|
||||
|
||||
func (h *History) indexOf(s string) int {
|
||||
for i, c := range h.commands {
|
||||
if c == s {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func TestHistory(t *testing.T) {
|
|||
h.Push(fmt.Sprintf("cmd%d", i))
|
||||
}
|
||||
|
||||
assert.Equal(t, []string{"cmd4", "cmd3", "cmd2"}, h.List())
|
||||
assert.Equal(t, []string{"cmd1", "cmd2", "cmd3"}, h.List())
|
||||
h.Clear()
|
||||
assert.True(t, h.Empty())
|
||||
}
|
||||
|
|
@ -30,5 +30,5 @@ func TestHistoryDups(t *testing.T) {
|
|||
h.Push("cmd1")
|
||||
h.Push("")
|
||||
|
||||
assert.Equal(t, []string{"cmd3", "cmd2", "cmd1"}, h.List())
|
||||
assert.Equal(t, []string{"cmd1", "cmd2", "cmd3"}, h.List())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,10 +76,13 @@ const (
|
|||
KeyX
|
||||
KeyY
|
||||
KeyZ
|
||||
KeyHelp = 63
|
||||
KeySlash = 47
|
||||
KeyColon = 58
|
||||
KeySpace = 32
|
||||
KeyHelp = 63
|
||||
KeySlash = 47
|
||||
KeyColon = 58
|
||||
KeySpace = 32
|
||||
KeyDash = 45 //or minus for those searching in the code
|
||||
KeyLeftBracket = 91
|
||||
KeyRightBracket = 93
|
||||
)
|
||||
|
||||
// Define Shift Keys.
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ func hotKeyActions(r Runner, aa *ui.KeyActions) error {
|
|||
|
||||
func gotoCmd(r Runner, cmd, path string, clearStack bool) ui.ActionHandler {
|
||||
return func(evt *tcell.EventKey) *tcell.EventKey {
|
||||
r.App().gotoResource(cmd, path, clearStack)
|
||||
r.App().gotoResource(cmd, path, clearStack, true)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func (a *Alias) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if r != 0 {
|
||||
s := ui.TrimCell(a.GetTable().SelectTable, r, 1)
|
||||
tokens := strings.Split(s, ",")
|
||||
a.App().gotoResource(tokens[0], "", true)
|
||||
a.App().gotoResource(tokens[0], "", true, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -240,13 +240,16 @@ func (a *App) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
|||
|
||||
func (a *App) bindKeys() {
|
||||
a.AddActions(ui.NewKeyActionsFromMap(ui.KeyMap{
|
||||
ui.KeyShift9: ui.NewSharedKeyAction("DumpGOR", a.dumpGOR, false),
|
||||
tcell.KeyCtrlE: ui.NewSharedKeyAction("ToggleHeader", a.toggleHeaderCmd, false),
|
||||
tcell.KeyCtrlG: ui.NewSharedKeyAction("toggleCrumbs", a.toggleCrumbsCmd, false),
|
||||
ui.KeyHelp: ui.NewSharedKeyAction("Help", a.helpCmd, false),
|
||||
tcell.KeyCtrlA: ui.NewSharedKeyAction("Aliases", a.aliasCmd, false),
|
||||
tcell.KeyEnter: ui.NewKeyAction("Goto", a.gotoCmd, false),
|
||||
tcell.KeyCtrlC: ui.NewKeyAction("Quit", a.quitCmd, false),
|
||||
ui.KeyShift9: ui.NewSharedKeyAction("DumpGOR", a.dumpGOR, false),
|
||||
tcell.KeyCtrlE: ui.NewSharedKeyAction("ToggleHeader", a.toggleHeaderCmd, false),
|
||||
tcell.KeyCtrlG: ui.NewSharedKeyAction("toggleCrumbs", a.toggleCrumbsCmd, false),
|
||||
ui.KeyHelp: ui.NewSharedKeyAction("Help", a.helpCmd, false),
|
||||
ui.KeyLeftBracket: ui.NewSharedKeyAction("Go Back", a.previousCommand, false),
|
||||
ui.KeyRightBracket: ui.NewSharedKeyAction("Go Forward", a.nextCommand, false),
|
||||
ui.KeyDash: ui.NewSharedKeyAction("Last View", a.lastCommand, false),
|
||||
tcell.KeyCtrlA: ui.NewSharedKeyAction("Aliases", a.aliasCmd, false),
|
||||
tcell.KeyEnter: ui.NewKeyAction("Goto", a.gotoCmd, false),
|
||||
tcell.KeyCtrlC: ui.NewKeyAction("Quit", a.quitCmd, false),
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -482,7 +485,7 @@ func (a *App) switchContext(ci *cmd.Interpreter, force bool) error {
|
|||
log.Debug().Msgf("--> Switching Context %q -- %q -- %q", name, ns, a.Config.ActiveView())
|
||||
a.Flash().Infof("Switching context to %q::%q", name, ns)
|
||||
a.ReloadStyles()
|
||||
a.gotoResource(a.Config.ActiveView(), "", true)
|
||||
a.gotoResource(a.Config.ActiveView(), "", true, true)
|
||||
a.clusterModel.Reset(a.factory)
|
||||
}
|
||||
|
||||
|
|
@ -630,7 +633,7 @@ func (a *App) toggleCrumbsCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
|
||||
func (a *App) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if a.CmdBuff().IsActive() && !a.CmdBuff().Empty() {
|
||||
a.gotoResource(a.GetCmd(), "", true)
|
||||
a.gotoResource(a.GetCmd(), "", true, true)
|
||||
a.ResetCmd()
|
||||
return nil
|
||||
}
|
||||
|
|
@ -691,6 +694,52 @@ func (a *App) helpCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
// previousCommand returns to the command prior to the current one in the history
|
||||
func (a *App) previousCommand(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if evt != nil && evt.Rune() == rune(ui.KeyLeftBracket) && a.Prompt().InCmdMode() {
|
||||
return evt
|
||||
}
|
||||
cmds := a.cmdHistory.List()
|
||||
if !a.cmdHistory.Back() {
|
||||
a.App.Flash().Warn("Can't go back any further")
|
||||
return evt
|
||||
}
|
||||
a.gotoResource(cmds[a.cmdHistory.CurrentIndex()], "", true, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// nextCommand returns to the command subsequent to the current one in the history
|
||||
func (a *App) nextCommand(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if evt != nil && evt.Rune() == rune(ui.KeyRightBracket) && a.Prompt().InCmdMode() {
|
||||
return evt
|
||||
}
|
||||
cmds := a.cmdHistory.List()
|
||||
if !a.cmdHistory.Forward() {
|
||||
a.App.Flash().Warn("Can't go forward any further")
|
||||
return evt
|
||||
}
|
||||
// We go to the resource before updating the history so that
|
||||
// gotoResource doesn't add this command to the history
|
||||
a.gotoResource(cmds[a.cmdHistory.CurrentIndex()], "", true, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// lastCommand switches between the last command and the current one a la `cd -`
|
||||
func (a *App) lastCommand(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if evt != nil && evt.Rune() == ui.KeyDash && a.Prompt().InCmdMode() {
|
||||
return evt
|
||||
}
|
||||
cmds := a.cmdHistory.List()
|
||||
if len(cmds) < 1 {
|
||||
a.App.Flash().Warn("No previous view to switch to")
|
||||
return evt
|
||||
} else {
|
||||
a.cmdHistory.Last()
|
||||
a.gotoResource(cmds[a.cmdHistory.CurrentIndex()], "", true, false)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) aliasCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if a.Content.Top() != nil && a.Content.Top().Name() == aliasTitle {
|
||||
a.Content.Pop()
|
||||
|
|
@ -704,8 +753,8 @@ func (a *App) aliasCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *App) gotoResource(c, path string, clearStack bool) {
|
||||
err := a.command.run(cmd.NewInterpreter(c), path, clearStack)
|
||||
func (a *App) gotoResource(c, path string, clearStack bool, pushCmd bool) {
|
||||
err := a.command.run(cmd.NewInterpreter(c), path, clearStack, pushCmd)
|
||||
if err != nil {
|
||||
dialog.ShowError(a.Styles.Dialog(), a.Content.Pages, err.Error())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@ func TestAppNew(t *testing.T) {
|
|||
a := view.NewApp(mock.NewMockConfig())
|
||||
_ = a.Init("blee", 10)
|
||||
|
||||
assert.Equal(t, 12, a.GetActions().Len())
|
||||
assert.Equal(t, 15, a.GetActions().Len())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func (c *Command) contextCmd(p *cmd.Interpreter) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return c.exec(p, gvr, c.componentFor(gvr, ct, v), true)
|
||||
return c.exec(p, gvr, c.componentFor(gvr, ct, v), true, true)
|
||||
}
|
||||
|
||||
func (c *Command) namespaceCmd(p *cmd.Interpreter) bool {
|
||||
|
|
@ -121,7 +121,7 @@ func (c *Command) aliasCmd(p *cmd.Interpreter) error {
|
|||
v := NewAlias(gvr)
|
||||
v.SetFilter(filter)
|
||||
|
||||
return c.exec(p, gvr, v, false)
|
||||
return c.exec(p, gvr, v, false, true)
|
||||
}
|
||||
|
||||
func (c *Command) xrayCmd(p *cmd.Interpreter) error {
|
||||
|
|
@ -147,11 +147,11 @@ func (c *Command) xrayCmd(p *cmd.Interpreter) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return c.exec(p, client.NewGVR("xrays"), NewXray(gvr), true)
|
||||
return c.exec(p, client.NewGVR("xrays"), NewXray(gvr), true, true)
|
||||
}
|
||||
|
||||
// Run execs the command by showing associated display.
|
||||
func (c *Command) run(p *cmd.Interpreter, fqn string, clearStack bool) error {
|
||||
func (c *Command) run(p *cmd.Interpreter, fqn string, clearStack bool, pushCmd bool) error {
|
||||
if c.specialCmd(p) {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -206,12 +206,12 @@ func (c *Command) run(p *cmd.Interpreter, fqn string, clearStack bool) error {
|
|||
co.SetLabelFilter(ll)
|
||||
}
|
||||
|
||||
return c.exec(p, gvr, co, clearStack)
|
||||
return c.exec(p, gvr, co, clearStack, pushCmd)
|
||||
}
|
||||
|
||||
func (c *Command) defaultCmd(isRoot bool) error {
|
||||
if c.app.Conn() == nil || !c.app.Conn().ConnectionOK() {
|
||||
return c.run(cmd.NewInterpreter("context"), "", true)
|
||||
return c.run(cmd.NewInterpreter("context"), "", true, true)
|
||||
}
|
||||
|
||||
defCmd := "pod"
|
||||
|
|
@ -220,13 +220,13 @@ func (c *Command) defaultCmd(isRoot bool) error {
|
|||
}
|
||||
p := cmd.NewInterpreter(c.app.Config.ActiveView())
|
||||
if p.IsBlank() {
|
||||
return c.run(p.Reset(defCmd), "", true)
|
||||
return c.run(p.Reset(defCmd), "", true, true)
|
||||
}
|
||||
|
||||
if err := c.run(p, "", true); err != nil {
|
||||
if err := c.run(p, "", true, true); err != nil {
|
||||
p = p.Reset(defCmd)
|
||||
log.Error().Err(fmt.Errorf("Command failed. Using default command: %s", p.GetLine()))
|
||||
return c.run(p, "", true)
|
||||
return c.run(p, "", true, true)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -319,7 +319,7 @@ func (c *Command) componentFor(gvr client.GVR, fqn string, v *MetaViewer) Resour
|
|||
return view
|
||||
}
|
||||
|
||||
func (c *Command) exec(p *cmd.Interpreter, gvr client.GVR, comp model.Component, clearStack bool) (err error) {
|
||||
func (c *Command) exec(p *cmd.Interpreter, gvr client.GVR, comp model.Component, clearStack bool, pushCmd bool) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Error().Msgf("Something bad happened! %#v", e)
|
||||
|
|
@ -328,10 +328,12 @@ func (c *Command) exec(p *cmd.Interpreter, gvr client.GVR, comp model.Component,
|
|||
log.Error().Msg(string(debug.Stack()))
|
||||
|
||||
p := cmd.NewInterpreter("pod")
|
||||
if cmd := c.app.cmdHistory.Pop(); cmd != "" {
|
||||
p = p.Reset(cmd)
|
||||
cmds := c.app.cmdHistory.List()
|
||||
currentCommand := cmds[c.app.cmdHistory.CurrentIndex()]
|
||||
if currentCommand != "pod" {
|
||||
p = p.Reset(currentCommand)
|
||||
}
|
||||
err = c.run(p, "", true)
|
||||
err = c.run(p, "", true, true)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
@ -347,7 +349,9 @@ func (c *Command) exec(p *cmd.Interpreter, gvr client.GVR, comp model.Component,
|
|||
return err
|
||||
}
|
||||
|
||||
c.app.cmdHistory.Push(p.GetLine())
|
||||
if pushCmd {
|
||||
c.app.cmdHistory.Push(p.GetLine())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ func (s *CRD) bindKeys(aa *ui.KeyActions) {
|
|||
|
||||
func (s *CRD) showCRD(app *App, _ ui.Tabular, _ client.GVR, path string) {
|
||||
_, crd := client.Namespaced(path)
|
||||
app.gotoResource(crd, "", false)
|
||||
app.gotoResource(crd, "", false, true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,6 +186,18 @@ func (h *Help) showNav() model.MenuHints {
|
|||
Mnemonic: "j",
|
||||
Description: "Down",
|
||||
},
|
||||
{
|
||||
Mnemonic: "[",
|
||||
Description: "History Back",
|
||||
},
|
||||
{
|
||||
Mnemonic: "]",
|
||||
Description: "History Forward",
|
||||
},
|
||||
{
|
||||
Mnemonic: "-",
|
||||
Description: "Last Used Command",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func (n *Namespace) bindKeys(aa *ui.KeyActions) {
|
|||
|
||||
func (n *Namespace) switchNs(app *App, _ ui.Tabular, _ client.GVR, path string) {
|
||||
n.useNamespace(path)
|
||||
app.gotoResource("pods", "", false)
|
||||
app.gotoResource("pods", "", false, true)
|
||||
}
|
||||
|
||||
func (n *Namespace) useNsCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ func (v *OwnerExtender) jumpOwner(ns string, owner metav1.OwnerReference) error
|
|||
ownerFQN = owner.Name
|
||||
}
|
||||
|
||||
v.App().gotoResource(gvr.String(), ownerFQN, false)
|
||||
v.App().gotoResource(gvr.String(), ownerFQN, false, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ func (p *Pulse) enterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if res == "cpu" || res == "mem" {
|
||||
res = "pod"
|
||||
}
|
||||
p.App().gotoResource(res+" all", "", false)
|
||||
p.App().gotoResource(res+" all", "", false, true)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func (r *Reference) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
path := r.GetTable().GetSelectedItem()
|
||||
ns, _ := client.Namespaced(path)
|
||||
gvr := ui.TrimCell(r.GetTable().SelectTable, row, 2)
|
||||
r.App().gotoResource(client.NewGVR(gvr).R()+" "+ns, path, false)
|
||||
r.App().gotoResource(client.NewGVR(gvr).R()+" "+ns, path, false, true)
|
||||
|
||||
return evt
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ func (s *Sanitizer) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if len(strings.Split(path, "/")) == 1 && spec.GVR() != "node" {
|
||||
path = "-/" + path
|
||||
}
|
||||
s.app.gotoResource(client.NewGVR(spec.GVR()).R(), path, false)
|
||||
s.app.gotoResource(client.NewGVR(spec.GVR()).R(), path, false, true)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ func (w *Workload) showRes(app *App, _ ui.Tabular, _ client.GVR, path string) {
|
|||
app.Flash().Err(fmt.Errorf("unable to parse path: %q", path))
|
||||
return
|
||||
}
|
||||
app.gotoResource(gvr.R(), fqn, false)
|
||||
app.gotoResource(gvr.R(), fqn, false, true)
|
||||
}
|
||||
|
||||
func (w *Workload) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
|
|
|
|||
|
|
@ -476,7 +476,7 @@ func (x *Xray) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
if len(strings.Split(spec.Path(), "/")) == 1 {
|
||||
return nil
|
||||
}
|
||||
x.app.gotoResource(client.NewGVR(spec.GVR()).R(), spec.Path(), false)
|
||||
x.app.gotoResource(client.NewGVR(spec.GVR()).R(), spec.Path(), false, true)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue