Migrate keymap and settings + edit predictions rename (#23834)

- [x] snake case keymap properties
- [x] flatten actions
- [x] keymap migration + notfication
- [x] settings migration + notification
- [x] inline completions -> edit predictions 

### future: 
- keymap notification doesn't show up on start up, only on keymap save.
this is existing bug in zed, will be addressed in seperate PR.

Release Notes:

- Added a notification for deprecated settings and keymaps, allowing you
to migrate them with a single click. A backup of your existing keymap
and settings will be created in your home directory.
- Modified some keymap actions and settings for consistency.

---------

Co-authored-by: Piotr Osiewicz <piotr@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
smit 2025-02-07 21:17:07 +05:30 committed by GitHub
parent a1544f47ad
commit 00c2a30059
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 2106 additions and 617 deletions

View file

@ -35,6 +35,7 @@ use language::{CursorShape, Point, Selection, SelectionGoal, TransactionId};
pub use mode_indicator::ModeIndicator;
use motion::Motion;
use normal::search::SearchSubmit;
use object::Object;
use schemars::JsonSchema;
use serde::Deserialize;
use serde_derive::Serialize;
@ -45,24 +46,10 @@ use surrounds::SurroundsType;
use theme::ThemeSettings;
use ui::{px, IntoElement, SharedString};
use vim_mode_setting::VimModeSetting;
use workspace::{self, Pane, ResizeIntent, Workspace};
use workspace::{self, Pane, Workspace};
use crate::state::ReplayableAction;
/// Used to resize the current pane
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
pub struct ResizePane(pub ResizeIntent);
/// An Action to Switch between modes
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
pub struct SwitchMode(pub Mode);
/// PushOperator is used to put vim into a "minor" mode,
/// where it's waiting for a specific next set of keystrokes.
/// For example 'd' needs a motion to complete.
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
pub struct PushOperator(pub Operator);
/// Number is used to manage vim's count. Pushing a digit
/// multiplies the current value by 10 and adds the digit.
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
@ -71,29 +58,126 @@ struct Number(usize);
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
struct SelectRegister(String);
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushObject {
around: bool,
}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushFindForward {
before: bool,
}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushFindBackward {
after: bool,
}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushSneak {
first_char: Option<char>,
}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushSneakBackward {
first_char: Option<char>,
}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushAddSurrounds {}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushChangeSurrounds {
target: Option<Object>,
}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushJump {
line: bool,
}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushDigraph {
first_char: Option<char>,
}
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
#[serde(deny_unknown_fields)]
struct PushLiteral {
prefix: Option<String>,
}
actions!(
vim,
[
SwitchToNormalMode,
SwitchToInsertMode,
SwitchToReplaceMode,
SwitchToVisualMode,
SwitchToVisualLineMode,
SwitchToVisualBlockMode,
SwitchToHelixNormalMode,
ClearOperators,
Tab,
Enter,
InnerObject,
FindForward,
FindBackward,
MaximizePane,
OpenDefaultKeymap,
ResetPaneSizes,
Sneak,
SneakBackward,
ResizePaneRight,
ResizePaneLeft,
ResizePaneUp,
ResizePaneDown,
PushChange,
PushDelete,
PushYank,
PushReplace,
PushDeleteSurrounds,
PushMark,
PushIndent,
PushOutdent,
PushAutoIndent,
PushRewrap,
PushShellCommand,
PushLowercase,
PushUppercase,
PushOppositeCase,
PushRegister,
PushRecordRegister,
PushReplayRegister,
PushReplaceWithRegister,
PushToggleComments,
]
);
// in the workspace namespace so it's not filtered out when vim is disabled.
actions!(workspace, [ToggleVimMode]);
actions!(workspace, [ToggleVimMode,]);
impl_actions!(
vim,
[ResizePane, SwitchMode, PushOperator, Number, SelectRegister]
[
Number,
SelectRegister,
PushObject,
PushFindForward,
PushFindBackward,
PushSneak,
PushSneakBackward,
PushAddSurrounds,
PushChangeSurrounds,
PushJump,
PushDigraph,
PushLiteral
]
);
/// Initializes the `vim` crate.
@ -142,7 +226,7 @@ pub fn init(cx: &mut App) {
workspace.resize_pane(Axis::Vertical, desired_size - size.size.height, window, cx)
});
workspace.register_action(|workspace, action: &ResizePane, window, cx| {
workspace.register_action(|workspace, _: &ResizePaneRight, window, cx| {
let count = Vim::take_count(cx).unwrap_or(1) as f32;
let theme = ThemeSettings::get_global(cx);
let Ok(font_id) = window.text_system().font_id(&theme.buffer_font) else {
@ -154,16 +238,36 @@ pub fn init(cx: &mut App) {
else {
return;
};
let height = theme.buffer_font_size() * theme.buffer_line_height.value();
workspace.resize_pane(Axis::Horizontal, width.width * count, window, cx);
});
let (axis, amount) = match action.0 {
ResizeIntent::Lengthen => (Axis::Vertical, height),
ResizeIntent::Shorten => (Axis::Vertical, height * -1.),
ResizeIntent::Widen => (Axis::Horizontal, width.width),
ResizeIntent::Narrow => (Axis::Horizontal, width.width * -1.),
workspace.register_action(|workspace, _: &ResizePaneLeft, window, cx| {
let count = Vim::take_count(cx).unwrap_or(1) as f32;
let theme = ThemeSettings::get_global(cx);
let Ok(font_id) = window.text_system().font_id(&theme.buffer_font) else {
return;
};
let Ok(width) = window
.text_system()
.advance(font_id, theme.buffer_font_size(), 'm')
else {
return;
};
workspace.resize_pane(Axis::Horizontal, -width.width * count, window, cx);
});
workspace.resize_pane(axis, amount * count, window, cx);
workspace.register_action(|workspace, _: &ResizePaneUp, window, cx| {
let count = Vim::take_count(cx).unwrap_or(1) as f32;
let theme = ThemeSettings::get_global(cx);
let height = theme.buffer_font_size() * theme.buffer_line_height.value();
workspace.resize_pane(Axis::Vertical, height * count, window, cx);
});
workspace.register_action(|workspace, _: &ResizePaneDown, window, cx| {
let count = Vim::take_count(cx).unwrap_or(1) as f32;
let theme = ThemeSettings::get_global(cx);
let height = theme.buffer_font_size() * theme.buffer_line_height.value();
workspace.resize_pane(Axis::Vertical, -height * count, window, cx);
});
workspace.register_action(|workspace, _: &SearchSubmit, window, cx| {
@ -330,12 +434,212 @@ impl Vim {
});
vim.update(cx, |_, cx| {
Vim::action(editor, cx, |vim, action: &SwitchMode, window, cx| {
vim.switch_mode(action.0, false, window, cx)
Vim::action(editor, cx, |vim, _: &SwitchToNormalMode, window, cx| {
vim.switch_mode(Mode::Normal, false, window, cx)
});
Vim::action(editor, cx, |vim, action: &PushOperator, window, cx| {
vim.push_operator(action.0.clone(), window, cx)
Vim::action(editor, cx, |vim, _: &SwitchToInsertMode, window, cx| {
vim.switch_mode(Mode::Insert, false, window, cx)
});
Vim::action(editor, cx, |vim, _: &SwitchToReplaceMode, window, cx| {
vim.switch_mode(Mode::Replace, false, window, cx)
});
Vim::action(editor, cx, |vim, _: &SwitchToVisualMode, window, cx| {
vim.switch_mode(Mode::Visual, false, window, cx)
});
Vim::action(editor, cx, |vim, _: &SwitchToVisualLineMode, window, cx| {
vim.switch_mode(Mode::VisualLine, false, window, cx)
});
Vim::action(
editor,
cx,
|vim, _: &SwitchToVisualBlockMode, window, cx| {
vim.switch_mode(Mode::VisualBlock, false, window, cx)
},
);
Vim::action(
editor,
cx,
|vim, _: &SwitchToHelixNormalMode, window, cx| {
vim.switch_mode(Mode::HelixNormal, false, window, cx)
},
);
Vim::action(editor, cx, |vim, action: &PushObject, window, cx| {
vim.push_operator(
Operator::Object {
around: action.around,
},
window,
cx,
)
});
Vim::action(editor, cx, |vim, action: &PushFindForward, window, cx| {
vim.push_operator(
Operator::FindForward {
before: action.before,
},
window,
cx,
)
});
Vim::action(editor, cx, |vim, action: &PushFindBackward, window, cx| {
vim.push_operator(
Operator::FindBackward {
after: action.after,
},
window,
cx,
)
});
Vim::action(editor, cx, |vim, action: &PushSneak, window, cx| {
vim.push_operator(
Operator::Sneak {
first_char: action.first_char,
},
window,
cx,
)
});
Vim::action(editor, cx, |vim, action: &PushSneakBackward, window, cx| {
vim.push_operator(
Operator::SneakBackward {
first_char: action.first_char,
},
window,
cx,
)
});
Vim::action(editor, cx, |vim, _: &PushAddSurrounds, window, cx| {
vim.push_operator(Operator::AddSurrounds { target: None }, window, cx)
});
Vim::action(
editor,
cx,
|vim, action: &PushChangeSurrounds, window, cx| {
vim.push_operator(
Operator::ChangeSurrounds {
target: action.target,
},
window,
cx,
)
},
);
Vim::action(editor, cx, |vim, action: &PushJump, window, cx| {
vim.push_operator(Operator::Jump { line: action.line }, window, cx)
});
Vim::action(editor, cx, |vim, action: &PushDigraph, window, cx| {
vim.push_operator(
Operator::Digraph {
first_char: action.first_char,
},
window,
cx,
)
});
Vim::action(editor, cx, |vim, action: &PushLiteral, window, cx| {
vim.push_operator(
Operator::Literal {
prefix: action.prefix.clone(),
},
window,
cx,
)
});
Vim::action(editor, cx, |vim, _: &PushChange, window, cx| {
vim.push_operator(Operator::Change, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushDelete, window, cx| {
vim.push_operator(Operator::Delete, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushYank, window, cx| {
vim.push_operator(Operator::Yank, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushReplace, window, cx| {
vim.push_operator(Operator::Replace, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushDeleteSurrounds, window, cx| {
vim.push_operator(Operator::DeleteSurrounds, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushMark, window, cx| {
vim.push_operator(Operator::Mark, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushIndent, window, cx| {
vim.push_operator(Operator::Indent, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushOutdent, window, cx| {
vim.push_operator(Operator::Outdent, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushAutoIndent, window, cx| {
vim.push_operator(Operator::AutoIndent, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushRewrap, window, cx| {
vim.push_operator(Operator::Rewrap, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushShellCommand, window, cx| {
vim.push_operator(Operator::ShellCommand, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushLowercase, window, cx| {
vim.push_operator(Operator::Lowercase, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushUppercase, window, cx| {
vim.push_operator(Operator::Uppercase, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushOppositeCase, window, cx| {
vim.push_operator(Operator::OppositeCase, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushRegister, window, cx| {
vim.push_operator(Operator::Register, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushRecordRegister, window, cx| {
vim.push_operator(Operator::RecordRegister, window, cx)
});
Vim::action(editor, cx, |vim, _: &PushReplayRegister, window, cx| {
vim.push_operator(Operator::ReplayRegister, window, cx)
});
Vim::action(
editor,
cx,
|vim, _: &PushReplaceWithRegister, window, cx| {
vim.push_operator(Operator::ReplaceWithRegister, window, cx)
},
);
Vim::action(editor, cx, |vim, _: &PushToggleComments, window, cx| {
vim.push_operator(Operator::ToggleComments, window, cx)
});
Vim::action(editor, cx, |vim, _: &ClearOperators, window, cx| {
@ -1275,8 +1579,8 @@ impl Vim {
if self.mode == Mode::Normal {
self.update_editor(window, cx, |_, editor, window, cx| {
editor.accept_inline_completion(
&editor::actions::AcceptInlineCompletion {},
editor.accept_edit_prediction(
&editor::actions::AcceptEditPrediction {},
window,
cx,
);