-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
implement keyboard layout remapping #5046
Conversation
Adds a config option to remap keys in a different keyboard layout into English so that keybindings work even when switched into a non-English keyboard layout. The corresponding config option is `editor.layout-remap` which is a list of dictionaries with two mandatory keys, `from` and `into`, which specify the translation mapping, e.g.: ```toml [[editor.layout-remap]] from = 'йцукенгшщзхъЙЦУКЕНГШЩЗХЪ' into = 'qwertyuiop[]QWERTYUIOP{}' ``` These can be repeated multiple times to facilitate specifying mappings containing different types of quotes and other special characters which may require escaping in TOML config. This circumvents helix-editor#133 in a way that Helix still does not recognise keypresses by their scan-codes but still allows for the non-English layout users to operate Helix without switching the layout which can be especially useful for writing documentation in their native language with Helix.
My 2 cents: Something like this: [[editor.layout-remap-r1]]
from = '<!"№%:,.;()_+'
into = '±!@#$%^&*()_+'
[[editor.layout-remap-r2]]
from = 'йцукенгшщзхъЙЦУКЕНГШЩЗХЪ'
into = 'qwertyuiop[]QWERTYUIOP{}' etc. |
I'm using the bépo layout (some kind of french dvorak), and where you find the y on a qwerty layout there is a dead key (which doesn't generate a character by itself) on the bépo. Am I mistaken in thinking that this PR would not solve this scenario? Also, I don't understand what the caveat is. |
Will this be merged any time soon? I'm waiting to switch to Helix and Workman support is the dealbreaker |
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've tested, it works great.
So will this be merged?
to be honest i would prefer for the command mode to use the scancode or keyid instead of remappings. swiss german or swiss french keyboards have a dead key on the english ] position, also described a little in #133. something in the lines of this tiny library. |
@SoraTenshi I'm afraid I don't get your point on explicit row mapping. Why would you want that? I just allowed the user to split the mapping into sections for easier reading and writing; these sections do not have to be rows. I'm coming from vim here where you can't do this and you end up with a really long @idoric I guess you're right, dead key won't generate a keystroke therefore I don't think you'd be able to remap it this way. This whole remapping thing, it's still a hack, a good one (in my opinion at least), but a hack nevertheless! @BreakingLead glad it worked for you too! I'm using it for several moths straight and have zero problems. It's quite a simple piece of code actually. @soloturn yeah you're right, I'd very much prefer that too. I just didn't see that coming in any near future so I felt this workaround was essential for me (and perhaps many others who write in a language other than English). I'm not sure at the moment how hard it would be to implement these scancodes. I certainly would like to try it so thanks for pointing to the library. But I guess someone may have already tried this? |
My idea here was to map it based around the actual, physical keyboard 'rows', so that there is not a real ambiguity. |
@sinefabula often only one dead key looks a challenge, though i think the PR should be merged. for dead keys, i found another file with keylayouts and wonder if this would help specify a dead key in the from mapping? lets pick out one example, the diaresis dead key, on swiss german keyboard at the location of english right brace, ].
links: |
@pascalkuthe anything missing to merge this? |
I don't have merge permissions so mostly a review from @archseer. From my side tKS We have a lot on our plate right now as we are heading towards the next release but I am sure he will get to your PR eventually. |
* changelog: Checkpoint 2023-01-10 commit: 927fa11 * changelog: Checkpoint 2023-02-05 commit: 9c98043 * changelog: Checkpoint 2023-03-17 commit: bd47392 * changelog: Checkpoint 2023-03-27 commit: 5323020 * Set a tentative release date for 2023-03-31 * Update CHANGELOG.md * Mention virtual text PR in inlayed type hints feature links * Fix description for 5097 * Rebalance features, usability improvements and fixes * Reorganize some out-of-place changes to the proper sections * Eliminate the LSP configurations section This has a lot of overlap with the 'new languages' section with newly supported LSP configurations. Smaller changes to LSP configurations are not so common so I folded those into the 'updated languages and queries' section.
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 left some notes on the changes themselves but IMO this shouldn't be merged. It's something I imagine would be really trivial to do once we can script config: I'm imagining mapping over the keymap data structure and switching the characters using a hashmap - that's similar to how you'd do this in an editor like Kakoune. That would also be more flexible so that you could choose to apply these in any mode, for example only in insert mode. Also see #5520 (comment).
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.
It looks like there is a problem with the merge commit - all of these changes are from the master branch and shouldn't be duplicated
/// `KeyCode::Char(c)` are translated. This method should be used | ||
/// whenever a translation for the characters is desired, e.g. when | ||
/// remapping a keyboard layout from non-Latin to Latin. | ||
pub fn translate<F>(&self, f: F) -> KeyEvent |
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.
This is unused and can be removed
@@ -300,6 +300,32 @@ impl Keymap { | |||
res | |||
} | |||
|
|||
pub fn traverse_map<F>(&self, f: F) |
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.
This is also unused, can be removed
pairs | ||
.iter() | ||
.filter_map(|(_, to)| pairs.contains_key(to).then(|| *to)) | ||
.collect::<Vec<_>>() | ||
.into_iter() | ||
.for_each(|c| { | ||
warn!( | ||
"Key '{}' removed from layout-remap as it would overwrite Latin layout binding", | ||
c | ||
); | ||
pairs.remove(&c); | ||
}); |
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.
Is this part actually necessary? If you wanted to remap between keyboard layouts for example:
[[editor.layout-remap]]
# qwerty
from = "qwertyuiop[]asdfghjkl;'zxcvbnm,./"
# dvorak
into = "',.pyfgcrl/=aoeuidhtns-;qjkxbmwvz"
you would only rebind [
and ]
since those are the only characters not duplicated between from
and into
. You only translate the incoming key event once so having duplication between from
and into
shouldn't matter - it won't cause some recursive loop of remapping.
struct LayoutMap { | ||
from: String, | ||
into: String, | ||
} |
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'm very opposed to this representation. It's a lot of indirection to have a Vec<LayoutMap>
turn into a HashMap<char, char>
when we could just use a TOML table. This is less verbose than a TOML table but we don't really need to optimize for concise config - I would rather have it be explicit.
closing this as this pr has gone stale. As Mike already said I don't see us going forward with something like this in core. This should instead be covered by #10389 in the future. Thank you for contributing! |
This patch adds a config option to remap keys from a different keyboard layout into English so that keybindings work even with the keyboard switched into a non-English layout.
The corresponding config option is
editor.layout-remap
which is a list of dictionaries with two mandatory keys,from
andinto
, which specify the translation mapping, e.g.:These can be repeated multiple times to facilitate specifying mappings containing different types of quotes and other special characters which may require escaping in TOML config. Naming (
from
andinto
) is chosen to be of the same length so that the letters are aligned when using a monospace font, and the config is easier to write.These translation mappings are applied in every mode except for (obviously) the Insert mode.
This circumvents #133 in a way that while Helix still does not recognise keypresses by their scan-codes but yet it allows for the non-English layout users to operate the editor without switching the layout which can be especially useful for writing documentation in their native language with Helix.
One caveat with this patch is that you can't remap keys already present in the English layout because Helix is not aware of the current keyboard layout and will apply translation every time, thus messing with the original mapping. This patch prevents such behaviour by disabling corresponding bindings and reporting these cases to the Helix log file. The other option would be to fail but I thought it would be safe to just filter them and log it.
A complete configuration example for macOS ISO keyboard layout looks like this. I've been using this for over a month now and it works great. Of course it is not the best solution of #133 but it does like 80% of the job, covering most used cases.