-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add suggestions for context and resources on the command bar #2285
Conversation
e82c94e
to
4d93d53
Compare
4d93d53
to
4b0ad25
Compare
internal/view/app.go
Outdated
} | ||
} | ||
default: | ||
nss, err := a.factory.Client().ValidNamespaces() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't make sense to limit only at the search bar and within the given namespace?
from UX perspective I think we should allow only the resource type from current screen (only deployments, namespaces, stateful sets) and not mix all together
might be objective on this one, but I find it more organised this way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@placintaalexandru Thank you for weighting in! Could you clarify, don't think I understood your point??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hello @derailed
the original issue, according to my understanding, was to add search suggestions: for example if i am in the deployment view and type my-deployment
, the search bar would suggest everything starting with my-deployment
within the current namespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the clarification @placintaalexandru! I see what you are saying now. The original issue which Jayson implemented here is correct. I believe this issue relates to completing on the namespace when users enter a command ie dp xxx
where xxx denotes suggestions from matching namespaces.
Best I can tell when the user activates a filter aka /
we just want to filter the resources based on what the user types i.e no autocomplete. Does this make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wjiec Nice work!! Thank you so much Jayson for this PR!
This is great and something users have asked for.
I have some suggestions/improvements. I know I am asking a lot here ;(
We could push it as it is and I can help iterate on or if you want to drive this home I am game for that too...
internal/view/app.go
Outdated
@@ -173,6 +172,49 @@ func (a *App) suggestCommand() model.SuggestionFunc { | |||
} | |||
} | |||
|
|||
func (a *App) suggestSubCommand(command string) []string { | |||
cmds := strings.Split(command, " ") | |||
if len(cmds[0]) == 0 || len(cmds) != 2 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have several suggestions here:
- I think it might be a good idea to use strings.Fields instead to pick up potential typo ie
po fred
- Best to make this call a helper and take in dependencies aka context, ns maps. So we don't have to refetch as there could be lots there. I think we should provide apis ie ContextNames and NamespaceNames which could return a map of names??
- Would be great to put some tests on this call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have several suggestions here:
- I think it might be a good idea to use strings.Fields instead to pick up potential typo ie
po fred
- Best to make this call a helper and take in dependencies aka context, ns maps. So we don't have to refetch as there could be lots there. I think we should provide apis ie ContextNames and NamespaceNames which could return a map of names??
- Would be great to put some tests on this call.
- done
- I'm trying to understand this suggestion, do you mean implementing it as a method in a struct while caching the contexts and the namespaces in the struct?
- I'll provide test cases later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right! I was originally thinking something like
func suggestSubCommand(cmd string, namespaces, contexts map[string]struct{}) []string {
...
}
As this would make it cacheable and easier to test.
But... creating something like CmdParser/Interpreter struct would make better sense actually as we could use it for suggestions, hang convenience ie IsXrayCmd(), IsK9sCmd(), Suggest() etc...
This will allow us to have a single command interpreter for all command related things.
Would this make sense?
internal/view/app.go
Outdated
|
||
var suggests []string | ||
switch strings.ToLower(cmds[0]) { | ||
case "cow", "q", "q!", "qa", "Q", "quit", "?", "h", "help", "a", "alias", "x", "xray", "dir": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think this is necessary to check for those since we only care about context or something with this shape aka xxx ns
ie len = 2 or am I missing it?
I am also thinking we should intro a command type, so we can hang convenience like IsContext() or IsTuple()?? These could be reused in several places and also could open up listing multiple nss i.e dp ns1 ns2
at some point in the future...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think this is necessary to check for those since we only care about context or something with this shape aka xxx ns ie len = 2 or am I missing it?
There are two reasons for this, the first being that some of the commands in here have a second argument that is not ns, such as xray dp
. The second is that for e.g. q
these commands don't really need any more arguments, would it be weird if the user accidentally typed q x
to see suggestions?
I am also thinking we should intro a command type, so we can hang convenience like IsContext() or IsTuple()?? These could be reused in several places and also could open up listing multiple nss i.e dp ns1 ns2 at some point in the future...
Yes, it also helps to manage these commands better. It may be a bit tricky to manage with resource commands?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! And there might be others coming in the future that could break this code.
Thus I think the command struct parser/interpreter makes more and more sense to derive all these from a central place.
internal/view/app.go
Outdated
} | ||
} | ||
default: | ||
nss, err := a.factory.Client().ValidNamespaces() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@placintaalexandru Thank you for weighting in! Could you clarify, don't think I understood your point??
internal/view/app.go
Outdated
} | ||
|
||
for contextName := range ctxs { | ||
if suggest, ok := shouldAddSuggest(cmds[1], contextName); ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also it would be great to add fuzzy matching here (we do this with filter commands) so user could type po ed
and suggest fred, bleed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using fuzzy matching can result in very strange views. For example, there are these namespaces: kube-system, kube-storage
, if I type: po ks
it comes up with po ks[gray]kube-system[gray]
, or if I type po age
it comes up with po age[gray]kube-storage[gray]
. , I think this may be not understandable for users, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right! This could be a double edge sword indeed.
Perhaps using fuzzy logic and returning the top 3 scored suggestions could make sense?
I was looking at #2163 so perhaps checking for contains vs prefix would help in this case? but could also yield additional user headaches?
Perhaps outside the scope of this PR and we could experiment with this a bit and see how we could address this better in the future.
If you have other ideas, I am all ears!
4b0ad25
to
03f3011
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wjiec Thank you for these updates and questions!
I am on the fence here as we could just tune things a bit more and checkin as such as this will already help our users a all lot.
Perhaps in the background, we could experiment with other mechanics and see how we could help users further dealing with either bad typist or long entity names??
internal/view/app.go
Outdated
@@ -173,6 +172,49 @@ func (a *App) suggestCommand() model.SuggestionFunc { | |||
} | |||
} | |||
|
|||
func (a *App) suggestSubCommand(command string) []string { | |||
cmds := strings.Split(command, " ") | |||
if len(cmds[0]) == 0 || len(cmds) != 2 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right! I was originally thinking something like
func suggestSubCommand(cmd string, namespaces, contexts map[string]struct{}) []string {
...
}
As this would make it cacheable and easier to test.
But... creating something like CmdParser/Interpreter struct would make better sense actually as we could use it for suggestions, hang convenience ie IsXrayCmd(), IsK9sCmd(), Suggest() etc...
This will allow us to have a single command interpreter for all command related things.
Would this make sense?
internal/view/app.go
Outdated
|
||
var suggests []string | ||
switch strings.ToLower(cmds[0]) { | ||
case "cow", "q", "q!", "qa", "Q", "quit", "?", "h", "help", "a", "alias", "x", "xray", "dir": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! And there might be others coming in the future that could break this code.
Thus I think the command struct parser/interpreter makes more and more sense to derive all these from a central place.
internal/view/app.go
Outdated
} | ||
|
||
for contextName := range ctxs { | ||
if suggest, ok := shouldAddSuggest(cmds[1], contextName); ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right! This could be a double edge sword indeed.
Perhaps using fuzzy logic and returning the top 3 scored suggestions could make sense?
I was looking at #2163 so perhaps checking for contains vs prefix would help in this case? but could also yield additional user headaches?
Perhaps outside the scope of this PR and we could experiment with this a bit and see how we could address this better in the future.
If you have other ideas, I am all ears!
03f3011
to
4a4e0d2
Compare
Sorry for the late reply, I changed the signature of I think we should start by making this PR as concise as possible, it probably solves 90% of the problems already, although there are a few things that make people uncomfortable. I couldn't agree more with your parser/interpreter idea, which makes it possible to configure independent suggestions for each command, and also provides more freedom to the user (suggestions via plugins?). I'd be happy to implement this later. Fuzzy matching is also a very useful feature, and we might be able to provide suggestions by way of a dropdown? (with up down keypad). Sort of like how fig works in iterm2. And I found an example of using dropdown in tview: |
@@ -1,19 +1,46 @@ | |||
// SPDX-License-Identifier: Apache-2.0 | |||
// Copyright Authors of K9s | |||
|
|||
package view_test | |||
package view |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: In the project, we typically use xxx_test.go to test exported calls and xxx_int_test to test unexported calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wjiec Thank you for the updates Jayson! Just a small pick...
…d#2285) * add suggestions for context and resources on the command bar * instead strings.Fields * cacheable and provide test cases
…d#2285) * add suggestions for context and resources on the command bar * instead strings.Fields * cacheable and provide test cases
This PR adds autocompletion for context and resource types in the command bar, related Issue #2283.
It triggers the autocomplete after typing the Resource and then a space.
Looking forward to your guidance!