Detailed changes
@@ -746,7 +746,8 @@
"alt-tab": "editor::AcceptEditPrediction",
"alt-l": "editor::AcceptEditPrediction",
"tab": "editor::AcceptEditPrediction",
- "alt-right": "editor::AcceptPartialEditPrediction",
+ "alt-right": "editor::AcceptNextWordEditPrediction",
+ "alt-down": "editor::AcceptNextLineEditPrediction",
},
},
{
@@ -754,7 +755,8 @@
"bindings": {
"alt-tab": "editor::AcceptEditPrediction",
"alt-l": "editor::AcceptEditPrediction",
- "alt-right": "editor::AcceptPartialEditPrediction",
+ "alt-right": "editor::AcceptNextWordEditPrediction",
+ "alt-down": "editor::AcceptNextLineEditPrediction",
},
},
{
@@ -810,7 +810,8 @@
"bindings": {
"alt-tab": "editor::AcceptEditPrediction",
"tab": "editor::AcceptEditPrediction",
- "ctrl-cmd-right": "editor::AcceptPartialEditPrediction",
+ "ctrl-cmd-right": "editor::AcceptNextWordEditPrediction",
+ "ctrl-cmd-down": "editor::AcceptNextLineEditPrediction",
},
},
{
@@ -818,7 +819,8 @@
"use_key_equivalents": true,
"bindings": {
"alt-tab": "editor::AcceptEditPrediction",
- "ctrl-cmd-right": "editor::AcceptPartialEditPrediction",
+ "ctrl-cmd-right": "editor::AcceptNextWordEditPrediction",
+ "ctrl-cmd-down": "editor::AcceptNextLineEditPrediction",
},
},
{
@@ -747,7 +747,8 @@
"alt-tab": "editor::AcceptEditPrediction",
"alt-l": "editor::AcceptEditPrediction",
"tab": "editor::AcceptEditPrediction",
- "alt-right": "editor::AcceptPartialEditPrediction",
+ "alt-right": "editor::AcceptNextWordEditPrediction",
+ "alt-down": "editor::AcceptNextLineEditPrediction",
},
},
{
@@ -756,7 +757,8 @@
"bindings": {
"alt-tab": "editor::AcceptEditPrediction",
"alt-l": "editor::AcceptEditPrediction",
- "alt-right": "editor::AcceptPartialEditPrediction",
+ "alt-right": "editor::AcceptNextWordEditPrediction",
+ "alt-down": "editor::AcceptNextLineEditPrediction",
},
},
{
@@ -71,7 +71,8 @@
"context": "Editor && mode == full && edit_prediction",
"use_key_equivalents": true,
"bindings": {
- "cmd-right": "editor::AcceptPartialEditPrediction",
+ "cmd-right": "editor::AcceptNextWordEditPrediction",
+ "cmd-down": "editor::AcceptNextLineEditPrediction",
},
},
{
@@ -261,12 +261,14 @@ fn update_command_palette_filter(cx: &mut App) {
CommandPaletteFilter::update_global(cx, |filter, _| {
use editor::actions::{
- AcceptEditPrediction, AcceptPartialEditPrediction, NextEditPrediction,
- PreviousEditPrediction, ShowEditPrediction, ToggleEditPrediction,
+ AcceptEditPrediction, AcceptNextLineEditPrediction, AcceptNextWordEditPrediction,
+ NextEditPrediction, PreviousEditPrediction, ShowEditPrediction, ToggleEditPrediction,
};
let edit_prediction_actions = [
TypeId::of::<AcceptEditPrediction>(),
- TypeId::of::<AcceptPartialEditPrediction>(),
+ TypeId::of::<AcceptNextWordEditPrediction>(),
+ TypeId::of::<AcceptNextLineEditPrediction>(),
+ TypeId::of::<AcceptEditPrediction>(),
TypeId::of::<ShowEditPrediction>(),
TypeId::of::<NextEditPrediction>(),
TypeId::of::<PreviousEditPrediction>(),
@@ -269,6 +269,7 @@ fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b:
#[cfg(test)]
mod tests {
use super::*;
+ use edit_prediction_types::EditPredictionGranularity;
use editor::{
Editor, ExcerptRange, MultiBuffer, MultiBufferOffset, SelectionEffects,
test::editor_lsp_test_context::EditorLspTestContext,
@@ -581,13 +582,15 @@ mod tests {
assert!(editor.has_active_edit_prediction());
// Accepting the first word of the suggestion should only accept the first word and still show the rest.
- editor.accept_partial_edit_prediction(&Default::default(), window, cx);
+ editor.accept_partial_edit_prediction(EditPredictionGranularity::Word, window, cx);
+
assert!(editor.has_active_edit_prediction());
assert_eq!(editor.text(cx), "one.copilot\ntwo\nthree\n");
assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n");
// Accepting next word should accept the non-word and copilot suggestion should be gone
- editor.accept_partial_edit_prediction(&Default::default(), window, cx);
+ editor.accept_partial_edit_prediction(EditPredictionGranularity::Word, window, cx);
+
assert!(!editor.has_active_edit_prediction());
assert_eq!(editor.text(cx), "one.copilot1\ntwo\nthree\n");
assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n");
@@ -623,7 +626,7 @@ mod tests {
assert!(editor.has_active_edit_prediction());
// Accepting the first word (non-word) of the suggestion should only accept the first word and still show the rest.
- editor.accept_partial_edit_prediction(&Default::default(), window, cx);
+ editor.accept_partial_edit_prediction(EditPredictionGranularity::Word, window, cx);
assert!(editor.has_active_edit_prediction());
assert_eq!(editor.text(cx), "one.123. \ntwo\nthree\n");
assert_eq!(
@@ -632,7 +635,7 @@ mod tests {
);
// Accepting next word should accept the next word and copilot suggestion should still exist
- editor.accept_partial_edit_prediction(&Default::default(), window, cx);
+ editor.accept_partial_edit_prediction(EditPredictionGranularity::Word, window, cx);
assert!(editor.has_active_edit_prediction());
assert_eq!(editor.text(cx), "one.123. copilot\ntwo\nthree\n");
assert_eq!(
@@ -641,7 +644,7 @@ mod tests {
);
// Accepting the whitespace should accept the non-word/whitespaces with newline and copilot suggestion should be gone
- editor.accept_partial_edit_prediction(&Default::default(), window, cx);
+ editor.accept_partial_edit_prediction(EditPredictionGranularity::Word, window, cx);
assert!(!editor.has_active_edit_prediction());
assert_eq!(editor.text(cx), "one.123. copilot\n 456\ntwo\nthree\n");
assert_eq!(
@@ -249,6 +249,12 @@ where
}
}
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum EditPredictionGranularity {
+ Word,
+ Line,
+ Full,
+}
/// Returns edits updated based on user edits since the old snapshot. None is returned if any user
/// edit is not a prefix of a predicted insertion.
pub fn interpolate_edits(
@@ -370,7 +370,8 @@ actions!(
AcceptEditPrediction,
/// Accepts a partial edit prediction.
#[action(deprecated_aliases = ["editor::AcceptPartialCopilotSuggestion"])]
- AcceptPartialEditPrediction,
+ AcceptNextWordEditPrediction,
+ AcceptNextLineEditPrediction,
/// Applies all diff hunks in the editor.
ApplyAllDiffHunks,
/// Applies the diff hunk at the current position.
@@ -92,7 +92,9 @@ use collections::{BTreeMap, HashMap, HashSet, VecDeque};
use convert_case::{Case, Casing};
use dap::TelemetrySpawnLocation;
use display_map::*;
-use edit_prediction_types::{EditPredictionDelegate, EditPredictionDelegateHandle};
+use edit_prediction_types::{
+ EditPredictionDelegate, EditPredictionDelegateHandle, EditPredictionGranularity,
+};
use editor_settings::{GoToDefinitionFallback, Minimap as MinimapSettings};
use element::{AcceptEditPredictionBinding, LineWithInvisibles, PositionMap, layout_line};
use futures::{
@@ -2778,21 +2780,24 @@ impl Editor {
pub fn accept_edit_prediction_keybind(
&self,
- accept_partial: bool,
+ granularity: EditPredictionGranularity,
window: &mut Window,
cx: &mut App,
) -> AcceptEditPredictionBinding {
let key_context = self.key_context_internal(true, window, cx);
let in_conflict = self.edit_prediction_in_conflict();
- let bindings = if accept_partial {
- window.bindings_for_action_in_context(&AcceptPartialEditPrediction, key_context)
- } else {
- window.bindings_for_action_in_context(&AcceptEditPrediction, key_context)
- };
+ let bindings =
+ match granularity {
+ EditPredictionGranularity::Word => window
+ .bindings_for_action_in_context(&AcceptNextWordEditPrediction, key_context),
+ EditPredictionGranularity::Line => window
+ .bindings_for_action_in_context(&AcceptNextLineEditPrediction, key_context),
+ EditPredictionGranularity::Full => {
+ window.bindings_for_action_in_context(&AcceptEditPrediction, key_context)
+ }
+ };
- // TODO: if the binding contains multiple keystrokes, display all of them, not
- // just the first one.
AcceptEditPredictionBinding(bindings.into_iter().rev().find(|binding| {
!in_conflict
|| binding
@@ -7633,9 +7638,9 @@ impl Editor {
}
}
- pub fn accept_edit_prediction(
+ pub fn accept_partial_edit_prediction(
&mut self,
- _: &AcceptEditPrediction,
+ granularity: EditPredictionGranularity,
window: &mut Window,
cx: &mut Context<Self>,
) {
@@ -7647,47 +7652,59 @@ impl Editor {
return;
};
+ if !matches!(granularity, EditPredictionGranularity::Full) && self.selections.count() != 1 {
+ return;
+ }
+
match &active_edit_prediction.completion {
EditPrediction::MoveWithin { target, .. } => {
let target = *target;
- if let Some(position_map) = &self.last_position_map {
- if position_map
- .visible_row_range
- .contains(&target.to_display_point(&position_map.snapshot).row())
- || !self.edit_prediction_requires_modifier()
- {
- self.unfold_ranges(&[target..target], true, false, cx);
- // Note that this is also done in vim's handler of the Tab action.
- self.change_selections(
- SelectionEffects::scroll(Autoscroll::newest()),
- window,
- cx,
- |selections| {
- selections.select_anchor_ranges([target..target]);
- },
- );
- self.clear_row_highlights::<EditPredictionPreview>();
+ if matches!(granularity, EditPredictionGranularity::Full) {
+ if let Some(position_map) = &self.last_position_map {
+ let target_row = target.to_display_point(&position_map.snapshot).row();
+ let is_visible = position_map.visible_row_range.contains(&target_row);
- self.edit_prediction_preview
- .set_previous_scroll_position(None);
- } else {
- self.edit_prediction_preview
- .set_previous_scroll_position(Some(
- position_map.snapshot.scroll_anchor,
- ));
-
- self.highlight_rows::<EditPredictionPreview>(
- target..target,
- cx.theme().colors().editor_highlighted_line_background,
- RowHighlightOptions {
- autoscroll: true,
- ..Default::default()
- },
- cx,
- );
- self.request_autoscroll(Autoscroll::fit(), cx);
+ if is_visible || !self.edit_prediction_requires_modifier() {
+ self.unfold_ranges(&[target..target], true, false, cx);
+ self.change_selections(
+ SelectionEffects::scroll(Autoscroll::newest()),
+ window,
+ cx,
+ |selections| {
+ selections.select_anchor_ranges([target..target]);
+ },
+ );
+ self.clear_row_highlights::<EditPredictionPreview>();
+ self.edit_prediction_preview
+ .set_previous_scroll_position(None);
+ } else {
+ // Highlight and request scroll
+ self.edit_prediction_preview
+ .set_previous_scroll_position(Some(
+ position_map.snapshot.scroll_anchor,
+ ));
+ self.highlight_rows::<EditPredictionPreview>(
+ target..target,
+ cx.theme().colors().editor_highlighted_line_background,
+ RowHighlightOptions {
+ autoscroll: true,
+ ..Default::default()
+ },
+ cx,
+ );
+ self.request_autoscroll(Autoscroll::fit(), cx);
+ }
}
+ } else {
+ self.change_selections(
+ SelectionEffects::scroll(Autoscroll::newest()),
+ window,
+ cx,
+ |selections| {
+ selections.select_anchor_ranges([target..target]);
+ },
+ );
}
}
EditPrediction::MoveOutside { snapshot, target } => {
@@ -7703,126 +7720,131 @@ impl Editor {
cx,
);
- if let Some(provider) = self.edit_prediction_provider() {
- provider.accept(cx);
- }
+ match granularity {
+ EditPredictionGranularity::Full => {
+ if let Some(provider) = self.edit_prediction_provider() {
+ provider.accept(cx);
+ }
- // Store the transaction ID and selections before applying the edit
- let transaction_id_prev = self.buffer.read(cx).last_transaction_id(cx);
+ let transaction_id_prev = self.buffer.read(cx).last_transaction_id(cx);
+ let snapshot = self.buffer.read(cx).snapshot(cx);
+ let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
- let snapshot = self.buffer.read(cx).snapshot(cx);
- let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
+ self.buffer.update(cx, |buffer, cx| {
+ buffer.edit(edits.iter().cloned(), None, cx)
+ });
- self.buffer.update(cx, |buffer, cx| {
- buffer.edit(edits.iter().cloned(), None, cx)
- });
+ self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
+ s.select_anchor_ranges([last_edit_end..last_edit_end]);
+ });
- self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
- s.select_anchor_ranges([last_edit_end..last_edit_end]);
- });
+ let selections = self.selections.disjoint_anchors_arc();
+ if let Some(transaction_id_now) =
+ self.buffer.read(cx).last_transaction_id(cx)
+ {
+ if transaction_id_prev != Some(transaction_id_now) {
+ self.selection_history
+ .insert_transaction(transaction_id_now, selections);
+ }
+ }
- let selections = self.selections.disjoint_anchors_arc();
- if let Some(transaction_id_now) = self.buffer.read(cx).last_transaction_id(cx) {
- let has_new_transaction = transaction_id_prev != Some(transaction_id_now);
- if has_new_transaction {
- self.selection_history
- .insert_transaction(transaction_id_now, selections);
+ self.update_visible_edit_prediction(window, cx);
+ if self.active_edit_prediction.is_none() {
+ self.refresh_edit_prediction(true, true, window, cx);
+ }
+ cx.notify();
}
- }
+ _ => {
+ let snapshot = self.buffer.read(cx).snapshot(cx);
+ let cursor_offset = self
+ .selections
+ .newest::<MultiBufferOffset>(&self.display_snapshot(cx))
+ .head();
+
+ let insertion = edits.iter().find_map(|(range, text)| {
+ let range = range.to_offset(&snapshot);
+ if range.is_empty() && range.start == cursor_offset {
+ Some(text)
+ } else {
+ None
+ }
+ });
- self.update_visible_edit_prediction(window, cx);
- if self.active_edit_prediction.is_none() {
- self.refresh_edit_prediction(true, true, window, cx);
- }
+ if let Some(text) = insertion {
+ let text_to_insert = match granularity {
+ EditPredictionGranularity::Word => {
+ let mut partial = text
+ .chars()
+ .by_ref()
+ .take_while(|c| c.is_alphabetic())
+ .collect::<String>();
+ if partial.is_empty() {
+ partial = text
+ .chars()
+ .by_ref()
+ .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
+ .collect::<String>();
+ }
+ partial
+ }
+ EditPredictionGranularity::Line => {
+ if let Some(line) = text.split_inclusive('\n').next() {
+ line.to_string()
+ } else {
+ text.to_string()
+ }
+ }
+ EditPredictionGranularity::Full => unreachable!(),
+ };
- cx.notify();
+ cx.emit(EditorEvent::InputHandled {
+ utf16_range_to_replace: None,
+ text: text_to_insert.clone().into(),
+ });
+
+ self.insert_with_autoindent_mode(&text_to_insert, None, window, cx);
+ self.refresh_edit_prediction(true, true, window, cx);
+ cx.notify();
+ } else {
+ self.accept_partial_edit_prediction(
+ EditPredictionGranularity::Full,
+ window,
+ cx,
+ );
+ }
+ }
+ }
}
}
self.edit_prediction_requires_modifier_in_indent_conflict = false;
}
- pub fn accept_partial_edit_prediction(
+ pub fn accept_next_word_edit_prediction(
&mut self,
- _: &AcceptPartialEditPrediction,
+ _: &AcceptNextWordEditPrediction,
window: &mut Window,
cx: &mut Context<Self>,
) {
- let Some(active_edit_prediction) = self.active_edit_prediction.as_ref() else {
- return;
- };
- if self.selections.count() != 1 {
- return;
- }
-
- match &active_edit_prediction.completion {
- EditPrediction::MoveWithin { target, .. } => {
- let target = *target;
- self.change_selections(
- SelectionEffects::scroll(Autoscroll::newest()),
- window,
- cx,
- |selections| {
- selections.select_anchor_ranges([target..target]);
- },
- );
- }
- EditPrediction::MoveOutside { snapshot, target } => {
- if let Some(workspace) = self.workspace() {
- Self::open_editor_at_anchor(snapshot, *target, &workspace, window, cx)
- .detach_and_log_err(cx);
- }
- }
- EditPrediction::Edit { edits, .. } => {
- self.report_edit_prediction_event(
- active_edit_prediction.completion_id.clone(),
- true,
- cx,
- );
-
- // Find an insertion that starts at the cursor position.
- let snapshot = self.buffer.read(cx).snapshot(cx);
- let cursor_offset = self
- .selections
- .newest::<MultiBufferOffset>(&self.display_snapshot(cx))
- .head();
- let insertion = edits.iter().find_map(|(range, text)| {
- let range = range.to_offset(&snapshot);
- if range.is_empty() && range.start == cursor_offset {
- Some(text)
- } else {
- None
- }
- });
-
- if let Some(text) = insertion {
- let mut partial_completion = text
- .chars()
- .by_ref()
- .take_while(|c| c.is_alphabetic())
- .collect::<String>();
- if partial_completion.is_empty() {
- partial_completion = text
- .chars()
- .by_ref()
- .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
- .collect::<String>();
- }
-
- cx.emit(EditorEvent::InputHandled {
- utf16_range_to_replace: None,
- text: partial_completion.clone().into(),
- });
+ self.accept_partial_edit_prediction(EditPredictionGranularity::Word, window, cx);
+ }
- self.insert_with_autoindent_mode(&partial_completion, None, window, cx);
+ pub fn accept_next_line_edit_prediction(
+ &mut self,
+ _: &AcceptNextLineEditPrediction,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.accept_partial_edit_prediction(EditPredictionGranularity::Line, window, cx);
+ }
- self.refresh_edit_prediction(true, true, window, cx);
- cx.notify();
- } else {
- self.accept_edit_prediction(&Default::default(), window, cx);
- }
- }
- }
+ pub fn accept_edit_prediction(
+ &mut self,
+ _: &AcceptEditPrediction,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.accept_partial_edit_prediction(EditPredictionGranularity::Full, window, cx);
}
fn discard_edit_prediction(
@@ -8042,21 +8064,23 @@ impl Editor {
cx: &mut Context<Self>,
) {
let mut modifiers_held = false;
- if let Some(accept_keystroke) = self
- .accept_edit_prediction_keybind(false, window, cx)
- .keystroke()
- {
- modifiers_held = modifiers_held
- || (accept_keystroke.modifiers() == modifiers
- && accept_keystroke.modifiers().modified());
- };
- if let Some(accept_partial_keystroke) = self
- .accept_edit_prediction_keybind(true, window, cx)
- .keystroke()
- {
- modifiers_held = modifiers_held
- || (accept_partial_keystroke.modifiers() == modifiers
- && accept_partial_keystroke.modifiers().modified());
+
+ // Check bindings for all granularities.
+ // If the user holds the key for Word, Line, or Full, we want to show the preview.
+ let granularities = [
+ EditPredictionGranularity::Full,
+ EditPredictionGranularity::Line,
+ EditPredictionGranularity::Word,
+ ];
+
+ for granularity in granularities {
+ if let Some(keystroke) = self
+ .accept_edit_prediction_keybind(granularity, window, cx)
+ .keystroke()
+ {
+ modifiers_held = modifiers_held
+ || (keystroke.modifiers() == modifiers && keystroke.modifiers().modified());
+ }
}
if modifiers_held {
@@ -9476,7 +9500,8 @@ impl Editor {
window: &mut Window,
cx: &mut App,
) -> Option<AnyElement> {
- let accept_binding = self.accept_edit_prediction_keybind(false, window, cx);
+ let accept_binding =
+ self.accept_edit_prediction_keybind(EditPredictionGranularity::Full, window, cx);
let accept_keystroke = accept_binding.keystroke()?;
let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
@@ -62,6 +62,7 @@ use multi_buffer::{
MultiBufferRow, RowInfo,
};
+use edit_prediction_types::EditPredictionGranularity;
use project::{
Entry, ProjectPath,
debugger::breakpoint_store::{Breakpoint, BreakpointSessionState},
@@ -603,7 +604,8 @@ impl EditorElement {
register_action(editor, window, Editor::display_cursor_names);
register_action(editor, window, Editor::unique_lines_case_insensitive);
register_action(editor, window, Editor::unique_lines_case_sensitive);
- register_action(editor, window, Editor::accept_partial_edit_prediction);
+ register_action(editor, window, Editor::accept_next_word_edit_prediction);
+ register_action(editor, window, Editor::accept_next_line_edit_prediction);
register_action(editor, window, Editor::accept_edit_prediction);
register_action(editor, window, Editor::restore_file);
register_action(editor, window, Editor::git_restore);
@@ -4900,8 +4902,11 @@ impl EditorElement {
let edit_prediction = if edit_prediction_popover_visible {
self.editor.update(cx, move |editor, cx| {
- let accept_binding =
- editor.accept_edit_prediction_keybind(false, window, cx);
+ let accept_binding = editor.accept_edit_prediction_keybind(
+ EditPredictionGranularity::Full,
+ window,
+ cx,
+ );
let mut element = editor.render_edit_prediction_cursor_popover(
min_width,
max_width,
@@ -159,3 +159,9 @@ pub(crate) mod m_2025_12_01 {
pub(crate) use settings::SETTINGS_PATTERNS;
}
+
+pub(crate) mod m_2025_12_08 {
+ mod keymap;
+
+ pub(crate) use keymap::KEYMAP_PATTERNS;
+}
@@ -0,0 +1,33 @@
+use collections::HashMap;
+use std::{ops::Range, sync::LazyLock};
+use tree_sitter::{Query, QueryMatch};
+
+use crate::MigrationPatterns;
+use crate::patterns::KEYMAP_ACTION_STRING_PATTERN;
+
+pub const KEYMAP_PATTERNS: MigrationPatterns =
+ &[(KEYMAP_ACTION_STRING_PATTERN, replace_string_action)];
+
+fn replace_string_action(
+ contents: &str,
+ mat: &QueryMatch,
+ query: &Query,
+) -> Option<(Range<usize>, String)> {
+ let action_name_ix = query.capture_index_for_name("action_name")?;
+ let action_name_node = mat.nodes_for_capture_index(action_name_ix).next()?;
+ let action_name_range = action_name_node.byte_range();
+ let action_name = contents.get(action_name_range.clone())?;
+
+ if let Some(new_action_name) = STRING_REPLACE.get(&action_name) {
+ return Some((action_name_range, new_action_name.to_string()));
+ }
+
+ None
+}
+
+static STRING_REPLACE: LazyLock<HashMap<&str, &str>> = LazyLock::new(|| {
+ HashMap::from_iter([(
+ "editor::AcceptPartialEditPrediction",
+ "editor::AcceptNextWordEditPrediction",
+ )])
+});
@@ -139,6 +139,10 @@ pub fn migrate_keymap(text: &str) -> Result<Option<String>> {
migrations::m_2025_04_15::KEYMAP_PATTERNS,
&KEYMAP_QUERY_2025_04_15,
),
+ MigrationType::TreeSitter(
+ migrations::m_2025_12_08::KEYMAP_PATTERNS,
+ &KEYMAP_QUERY_2025_12_08,
+ ),
];
run_migrations(text, migrations)
}
@@ -358,6 +362,10 @@ define_query!(
SETTINGS_QUERY_2025_11_20,
migrations::m_2025_11_20::SETTINGS_PATTERNS
);
+define_query!(
+ KEYMAP_QUERY_2025_12_08,
+ migrations::m_2025_12_08::KEYMAP_PATTERNS
+);
// custom query
static EDIT_PREDICTION_SETTINGS_MIGRATION_QUERY: LazyLock<Query> = LazyLock::new(|| {
@@ -58,7 +58,8 @@ In these cases, `alt-tab` is used instead to accept the prediction. When the lan
On Linux, `alt-tab` is often used by the window manager for switching windows, so `alt-l` is provided as the default binding for accepting predictions. `tab` and `alt-tab` also work, but aren't displayed by default.
-{#action editor::AcceptPartialEditPrediction} ({#kb editor::AcceptPartialEditPrediction}) can be used to accept the current edit prediction up to the next word boundary.
+{#action editor::AcceptNextWordEditPrediction} ({#kb editor::AcceptNextWordEditPrediction}) can be used to accept the current edit prediction up to the next word boundary.
+{#action editor::AcceptNextLineEditPrediction} ({#kb editor::AcceptNextLineEditPrediction}) can be used to accept the current edit prediction up to the new line boundary.
## Configuring Edit Prediction Keybindings {#edit-predictions-keybinding}