add suggestions for context and resources on the command bar (#2285)
* add suggestions for context and resources on the command bar * instead strings.Fields * cacheable and provide test casesmine
parent
38275b25ea
commit
fcfff5701e
|
|
@ -151,6 +151,16 @@ func (a *App) initSignals() {
|
|||
}
|
||||
|
||||
func (a *App) suggestCommand() model.SuggestionFunc {
|
||||
namespaceNames, err := a.namespaceNames()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to list namespaces")
|
||||
}
|
||||
|
||||
contextNames, err := a.contextNames()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to list contexts")
|
||||
}
|
||||
|
||||
return func(s string) (entries sort.StringSlice) {
|
||||
if s == "" {
|
||||
if a.cmdHistory.Empty() {
|
||||
|
|
@ -161,13 +171,12 @@ func (a *App) suggestCommand() model.SuggestionFunc {
|
|||
|
||||
s = strings.ToLower(s)
|
||||
for _, k := range a.command.alias.Aliases.Keys() {
|
||||
if k == s {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(k, s) {
|
||||
entries = append(entries, strings.Replace(k, s, "", 1))
|
||||
if suggest, ok := shouldAddSuggest(s, k); ok {
|
||||
entries = append(entries, suggest)
|
||||
}
|
||||
}
|
||||
|
||||
entries = append(entries, suggestSubCommand(s, namespaceNames, contextNames)...)
|
||||
if len(entries) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -176,6 +185,32 @@ func (a *App) suggestCommand() model.SuggestionFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *App) namespaceNames() ([]string, error) {
|
||||
namespaces, err := a.factory.Client().ValidNamespaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
namespaceNames := make([]string, 0, len(namespaces))
|
||||
for _, namespace := range namespaces {
|
||||
namespaceNames = append(namespaceNames, namespace.Name)
|
||||
}
|
||||
return namespaceNames, nil
|
||||
}
|
||||
|
||||
func (a *App) contextNames() ([]string, error) {
|
||||
contexts, err := a.factory.Client().Config().Contexts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contextNames := make([]string, 0, len(contexts))
|
||||
for ctxName := range contexts {
|
||||
contextNames = append(contextNames, ctxName)
|
||||
}
|
||||
return contextNames, nil
|
||||
}
|
||||
|
||||
func (a *App) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if k, ok := a.HasAction(ui.AsKey(evt)); ok && !a.Content.IsTopDialog() {
|
||||
return k.Action(evt)
|
||||
|
|
@ -671,3 +706,45 @@ func (a *App) clusterInfo() *ClusterInfo {
|
|||
func (a *App) statusIndicator() *ui.StatusIndicator {
|
||||
return a.Views()["statusIndicator"].(*ui.StatusIndicator)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
|
||||
func suggestSubCommand(command string, namespaces, contexts []string) []string {
|
||||
cmds := strings.Fields(command)
|
||||
if len(cmds[0]) == 0 || len(cmds) != 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var suggests []string
|
||||
switch strings.ToLower(cmds[0]) {
|
||||
case "cow", "q", "q!", "qa", "Q", "quit", "?", "h", "help", "a", "alias", "x", "xray", "dir":
|
||||
return nil // ignore special commands
|
||||
case "ctx", "context", "contexts":
|
||||
for _, ctxName := range contexts {
|
||||
if suggest, ok := shouldAddSuggest(cmds[1], ctxName); ok {
|
||||
suggests = append(suggests, suggest)
|
||||
}
|
||||
}
|
||||
default:
|
||||
if suggest, ok := shouldAddSuggest(cmds[1], client.NamespaceAll); ok {
|
||||
suggests = append(suggests, suggest)
|
||||
}
|
||||
|
||||
for _, ns := range namespaces {
|
||||
if suggest, ok := shouldAddSuggest(cmds[1], ns); ok {
|
||||
suggests = append(suggests, suggest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return suggests
|
||||
}
|
||||
|
||||
func shouldAddSuggest(command, suggest string) (string, bool) {
|
||||
if command != suggest && strings.HasPrefix(suggest, command) {
|
||||
return strings.TrimPrefix(suggest, command), true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,46 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright Authors of K9s
|
||||
|
||||
package view_test
|
||||
package view
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
"github.com/derailed/k9s/internal/view"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAppNew(t *testing.T) {
|
||||
a := view.NewApp(config.NewConfig(ks{}))
|
||||
a := NewApp(config.NewConfig(ks{}))
|
||||
_ = a.Init("blee", 10)
|
||||
|
||||
assert.Equal(t, 11, len(a.GetActions()))
|
||||
}
|
||||
|
||||
func Test_suggestSubCommand(t *testing.T) {
|
||||
namespaceNames := []string{"kube-system", "kube-public", "default", "nginx-ingress"}
|
||||
contextNames := []string{"develop", "test", "pre", "prod"}
|
||||
|
||||
tests := []struct {
|
||||
Command string
|
||||
Suggestions []string
|
||||
}{
|
||||
{Command: "q", Suggestions: nil},
|
||||
{Command: "xray dp", Suggestions: nil},
|
||||
{Command: "help k", Suggestions: nil},
|
||||
{Command: "ctx p", Suggestions: []string{"re", "rod"}},
|
||||
{Command: "ctx p", Suggestions: []string{"re", "rod"}},
|
||||
{Command: "ctx pr", Suggestions: []string{"e", "od"}},
|
||||
{Command: "context d", Suggestions: []string{"evelop"}},
|
||||
{Command: "contexts t", Suggestions: []string{"est"}},
|
||||
{Command: "po ", Suggestions: nil},
|
||||
{Command: "po x", Suggestions: nil},
|
||||
{Command: "po k", Suggestions: []string{"ube-system", "ube-public"}},
|
||||
{Command: "po kube-", Suggestions: []string{"system", "public"}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := suggestSubCommand(tt.Command, namespaceNames, contextNames)
|
||||
assert.Equal(t, tt.Suggestions, got)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue