Skip to content
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

Validate user config keybindings #4275

Merged
merged 5 commits into from
Feb 21, 2025
Merged

Conversation

stefanhaller
Copy link
Collaborator

  • PR Description

This improves the user experience when users try to use an invalid key name in their config, either for one of our standard keybindings or for the key of a custom command.

Fixes half of #4256 (only the keybindings aspect of it, not the context names).

  • Please check if the PR fulfills these requirements
  • Cheatsheets are up-to-date (run go generate ./...)
  • Code has been formatted (see here)
  • Tests have been added/updated (see here for the integration test guide)
  • Text is internationalised (see here)
  • If a new UserConfig entry was added, make sure it can be hot-reloaded (see here)
  • Docs have been updated if necessary
  • You've read through your own file changes for silly mistakes etc

Copy link

codacy-production bot commented Feb 16, 2025

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
Report missing for 52b1c421 95.65%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (52b1c42) Report Missing Report Missing Report Missing
Head commit (5979b40) 53089 45986 86.62%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#4275) 69 66 95.65%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Codacy stopped sending the deprecated coverage status on June 5th, 2024. Learn more

Footnotes

  1. Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

@stefanhaller stefanhaller force-pushed the validate-user-config-keybindings branch from 2be8c3c to e0e726d Compare February 16, 2025 17:21
key := node.(string)
if !isValidKeybindingKey(key) {
return fmt.Errorf("Unrecognized key '%s' for keybinding '%s'. For permitted values see %s",
strings.ToLower(key), path, constants.Links.Docs.CustomKeybindings)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we can't i18n-ize these, because the config is read very early, before the translation system is initialized. And it is important that we validate the config right after loading, so that all clients of it can just use it without having to worry about valid data.

@stefanhaller stefanhaller mentioned this pull request Feb 16, 2025
7 tasks
Comment on lines +71 to +74
gocui.KeyCtrl4: "<c-4>", // <c-\>
gocui.KeyCtrl5: "<c-5>", // <c-]>
gocui.KeyCtrl6: "<c-6>",
gocui.KeyCtrl8: "<c-8>",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to the body of this work, but why are <c-1> and others not considered valid keys? I see them in the comments up above, but don't know what that means.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comes from commit 2e66d87. The goal of that commit was to ensure that the keys you see in the global ? menu are exactly what you put in your config file. And the approach it took to ensure this was to have two inverse maps for labelByKey and keyByLabel. The problem with this approach is that there are several labels that map to the same key (e.g. backspace and ctrl-h both map to ascii 8), so you can't put them both in the labelByKey map. We also have #2953 about this.

It would be nice to fix this, and I suppose the way to do that is to manually maintain two separate maps for labelToKey and keyToLabel, where labelToKey can have more entries. And then we need to add a field to the types.Binding struct that stores the original string so that we can show it in the menu. This would still not allow to bind one action to backspace and another to ctrl-h, but it would at least allow binding things to ctrl-h at all (or ctrl-3). This should really work since those are the actual keys that a user presses to invoke the action. (Although I'm not sure about ctrl-3; that's the same as Esc, and this could be confusing.)

strings.ToLower(key), path, constants.Links.Docs.CustomKeybindings)
}
} else {
panic("Unexpected type")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would adding the failed node, or value to this panic message be helpful? I'm not sure how possible it is for somebody to sneak other value types inside of here via wacky config.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A wacky config can never cause this panic. We're iterating over the compile-time types of the KeybindingConfig fields here, so the panic can only be seen by a developer who adds something to the KeybindingConfig struct that we don't know how to iterate over (e.g. a map).

But adding the path to the error message could still be helpful for that developer, and it's easy, so why not: 8575494


func validateCustomCommandKey(key string) error {
if !isValidKeybindingKey(key) {
return fmt.Errorf("Unrecognized key '%s' for custom command. For permitted values see %s",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe that we have an equivalent to the path variable that we can use to point them to where in their config they messed up, but maybe using the CustomCommand.Command, or the index in the slice could be helpful to somebody.

Particularly because we do string.ToLower what they send to use, so if someone creates a custom command with key <CC-4>, and then we give them an error message about <cc-4>, and they do a case sensitive search for where that is in their config. Might be confusing.

That example is starting to seem a bit contrived though....

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I briefly thought about adding the command to the error message, but commands can sometimes be very long, so this could be unwieldy. Also, I don't follow your concern about the case sensitive search; the tolower happens inside of isValidKeybindingKey, so the error message contains the actual key in its original case. A case sensitive search will find it in the config file, and I think this is good enough.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The highlighting of the line of code leads to some confusion on that 2nd part.

We do strings.ToLower(key) before populating the %s.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if a valid concern, also applies higher up in the file on the other error message.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, I totally missed that. It doesn't make sense to lower-case there, removing in 9fd487b and 0126e72.

(I had copied this from here without thinking; it doesn't make sense there either, but I'm not bothering to change it there, as the fatal should never trigger any more now.)

@stefanhaller stefanhaller force-pushed the validate-user-config-keybindings branch 2 times, most recently from 8575494 to 0126e72 Compare February 17, 2025 19:53
Copy link
Owner

@jesseduffield jesseduffield left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM but I'll let @ChrisMcD1 finish his review

BTW @ChrisMcD1 it's great to have you onboard.

Copy link
Contributor

@ChrisMcD1 ChrisMcD1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works well when I tested locally!

@stefanhaller stefanhaller force-pushed the validate-user-config-keybindings branch from 0126e72 to 5979b40 Compare February 21, 2025 12:22
@stefanhaller stefanhaller merged commit 16f5348 into master Feb 21, 2025
15 checks passed
@stefanhaller stefanhaller deleted the validate-user-config-keybindings branch February 21, 2025 12:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants