Add Vim digraphs (#14887)

Vim digraphs are a way to insert special characters using sequences of
two ASCII characters. I've implemented the feature using a new `Digraph`
operator, following the example of `AddSurrounds`. There are still a few
issues that I'm not sure what the best way to resolve them is.

- To insert `ş`, the user must pause between pressing `ctrl-k` and `s
,`, otherwise it triggers the binding for `ctrl-k s`. Is there a way to
disable `ctrl-k *` bindings while in insert, replace or waiting mode?
- Is there a better way to insert a string at all of the cursors? At the
moment I'm constructing the edits manually.
- The table of default digraphs is a 1.4k line rust expression. Is this
okay as long as it's in its own module?
- I'd like a second opinion on how best to structure the settings.json
entry.
- I have omitted the "meta character" feature as I don't think it makes
sense when editing UTF-8 text.

Release Notes:

- Added support for Vim digraphs.

Resolves #11871
This commit is contained in:
Benjamin Davies 2024-07-29 16:44:32 +12:00 committed by GitHub
parent b87028956f
commit 26d0a33e79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 1613 additions and 2 deletions

View file

@ -5,6 +5,7 @@ mod test;
mod change_list;
mod command;
mod digraph;
mod editor_events;
mod insert;
mod mode_indicator;
@ -193,6 +194,7 @@ fn observe_keystrokes(keystroke_event: &KeystrokeEvent, cx: &mut WindowContext)
Operator::FindForward { .. }
| Operator::FindBackward { .. }
| Operator::Replace
| Operator::Digraph { .. }
| Operator::AddSurrounds { .. }
| Operator::ChangeSurrounds { .. }
| Operator::DeleteSurrounds
@ -876,6 +878,19 @@ impl Vim {
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => visual_replace(text, cx),
_ => Vim::update(cx, |vim, cx| vim.clear_operator(cx)),
},
Some(Operator::Digraph { first_char }) => {
if let Some(first_char) = first_char {
if let Some(second_char) = text.chars().next() {
digraph::insert_digraph(first_char, second_char, cx);
}
} else {
let first_char = text.chars().next();
Vim::update(cx, |vim, cx| {
vim.pop_operator(cx);
vim.push_operator(Operator::Digraph { first_char }, cx);
});
}
}
Some(Operator::AddSurrounds { target }) => match Vim::read(cx).state().mode {
Mode::Normal => {
if let Some(target) = target {
@ -1060,6 +1075,7 @@ struct VimSettings {
pub use_system_clipboard: UseSystemClipboard,
pub use_multiline_find: bool,
pub use_smartcase_find: bool,
pub custom_digraphs: HashMap<String, Arc<str>>,
}
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
@ -1067,6 +1083,7 @@ struct VimSettingsContent {
pub use_system_clipboard: Option<UseSystemClipboard>,
pub use_multiline_find: Option<bool>,
pub use_smartcase_find: Option<bool>,
pub custom_digraphs: Option<HashMap<String, Arc<str>>>,
}
impl Settings for VimSettings {