Reset mode when changing buffers (#5072)
* Reset mode when changing buffers
This is similar to the change in
e4c9d4082a
: reset the editor to normal
mode when changing buffers. Usually the editor is already in normal
mode but it's possible to setup insert-mode keybindings that change
buffers.
* Move normal mode entering code to Editor
This should be called internally in the Editor when changing documents
(Editor::switch) or changing focuses (Editor::focus).
This commit is contained in:
parent
70d78123b9
commit
cdc54f50a2
@ -2672,62 +2672,7 @@ fn open_above(cx: &mut Context) {
|
||||
}
|
||||
|
||||
fn normal_mode(cx: &mut Context) {
|
||||
if cx.editor.mode == Mode::Normal {
|
||||
return;
|
||||
}
|
||||
|
||||
cx.editor.mode = Mode::Normal;
|
||||
let (view, doc) = current!(cx.editor);
|
||||
|
||||
try_restore_indent(doc, view);
|
||||
|
||||
// if leaving append mode, move cursor back by 1
|
||||
if doc.restore_cursor {
|
||||
let text = doc.text().slice(..);
|
||||
let selection = doc.selection(view.id).clone().transform(|range| {
|
||||
Range::new(
|
||||
range.from(),
|
||||
graphemes::prev_grapheme_boundary(text, range.to()),
|
||||
)
|
||||
});
|
||||
|
||||
doc.set_selection(view.id, selection);
|
||||
doc.restore_cursor = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn try_restore_indent(doc: &mut Document, view: &mut View) {
|
||||
use helix_core::chars::char_is_whitespace;
|
||||
use helix_core::Operation;
|
||||
|
||||
fn inserted_a_new_blank_line(changes: &[Operation], pos: usize, line_end_pos: usize) -> bool {
|
||||
if let [Operation::Retain(move_pos), Operation::Insert(ref inserted_str), Operation::Retain(_)] =
|
||||
changes
|
||||
{
|
||||
move_pos + inserted_str.len() == pos
|
||||
&& inserted_str.starts_with('\n')
|
||||
&& inserted_str.chars().skip(1).all(char_is_whitespace)
|
||||
&& pos == line_end_pos // ensure no characters exists after current position
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
let doc_changes = doc.changes().changes();
|
||||
let text = doc.text().slice(..);
|
||||
let range = doc.selection(view.id).primary();
|
||||
let pos = range.cursor(text);
|
||||
let line_end_pos = line_end_char_index(&text, range.cursor_line(text));
|
||||
|
||||
if inserted_a_new_blank_line(doc_changes, pos, line_end_pos) {
|
||||
// Removes tailing whitespaces.
|
||||
let transaction =
|
||||
Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
|
||||
let line_start_pos = text.line_to_char(range.cursor_line(text));
|
||||
(line_start_pos, pos, None)
|
||||
});
|
||||
apply_transaction(&transaction, doc, view);
|
||||
}
|
||||
cx.editor.enter_normal_mode();
|
||||
}
|
||||
|
||||
// Store a jump on the jumplist.
|
||||
|
@ -1005,6 +1005,8 @@ pub fn switch(&mut self, id: DocumentId, action: Action) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.enter_normal_mode();
|
||||
|
||||
match action {
|
||||
Action::Replace => {
|
||||
let (view, doc) = current_ref!(self);
|
||||
@ -1025,6 +1027,9 @@ pub fn switch(&mut self, id: DocumentId, action: Action) {
|
||||
let (view, doc) = current!(self);
|
||||
let view_id = view.id;
|
||||
|
||||
// Append any outstanding changes to history in the old document.
|
||||
doc.append_changes_to_history(view);
|
||||
|
||||
if remove_empty_scratch {
|
||||
// Copy `doc.id` into a variable before calling `self.documents.remove`, which requires a mutable
|
||||
// borrow, invalidating direct access to `doc.id`.
|
||||
@ -1262,7 +1267,7 @@ pub fn focus(&mut self, view_id: ViewId) {
|
||||
// if leaving the view: mode should reset and the cursor should be
|
||||
// within view
|
||||
if prev_id != view_id {
|
||||
self.mode = Mode::Normal;
|
||||
self.enter_normal_mode();
|
||||
self.ensure_cursor_in_view(view_id);
|
||||
|
||||
// Update jumplist selections with new document changes.
|
||||
@ -1427,4 +1432,67 @@ pub async fn flush_writes(&mut self) -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Switches the editor into normal mode.
|
||||
pub fn enter_normal_mode(&mut self) {
|
||||
use helix_core::{graphemes, Range};
|
||||
|
||||
if self.mode == Mode::Normal {
|
||||
return;
|
||||
}
|
||||
|
||||
self.mode = Mode::Normal;
|
||||
let (view, doc) = current!(self);
|
||||
|
||||
try_restore_indent(doc, view);
|
||||
|
||||
// if leaving append mode, move cursor back by 1
|
||||
if doc.restore_cursor {
|
||||
let text = doc.text().slice(..);
|
||||
let selection = doc.selection(view.id).clone().transform(|range| {
|
||||
Range::new(
|
||||
range.from(),
|
||||
graphemes::prev_grapheme_boundary(text, range.to()),
|
||||
)
|
||||
});
|
||||
|
||||
doc.set_selection(view.id, selection);
|
||||
doc.restore_cursor = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_restore_indent(doc: &mut Document, view: &mut View) {
|
||||
use helix_core::{
|
||||
chars::char_is_whitespace, line_ending::line_end_char_index, Operation, Transaction,
|
||||
};
|
||||
|
||||
fn inserted_a_new_blank_line(changes: &[Operation], pos: usize, line_end_pos: usize) -> bool {
|
||||
if let [Operation::Retain(move_pos), Operation::Insert(ref inserted_str), Operation::Retain(_)] =
|
||||
changes
|
||||
{
|
||||
move_pos + inserted_str.len() == pos
|
||||
&& inserted_str.starts_with('\n')
|
||||
&& inserted_str.chars().skip(1).all(char_is_whitespace)
|
||||
&& pos == line_end_pos // ensure no characters exists after current position
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
let doc_changes = doc.changes().changes();
|
||||
let text = doc.text().slice(..);
|
||||
let range = doc.selection(view.id).primary();
|
||||
let pos = range.cursor(text);
|
||||
let line_end_pos = line_end_char_index(&text, range.cursor_line(text));
|
||||
|
||||
if inserted_a_new_blank_line(doc_changes, pos, line_end_pos) {
|
||||
// Removes tailing whitespaces.
|
||||
let transaction =
|
||||
Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
|
||||
let line_start_pos = text.line_to_char(range.cursor_line(text));
|
||||
(line_start_pos, pos, None)
|
||||
});
|
||||
crate::apply_transaction(&transaction, doc, view);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user