Abstract Transaction::change_by_selection, working del/backspace.

pull/1/head
Blaž Hrastnik 4 years ago
parent f098166571
commit d466882d04

@ -1,4 +1,4 @@
use crate::graphemes::next_grapheme_boundary; use crate::graphemes;
use crate::selection::Range; use crate::selection::Range;
use crate::state::{Direction, Granularity, Mode, State}; use crate::state::{Direction, Granularity, Mode, State};
use crate::transaction::{ChangeSet, Transaction}; use crate::transaction::{ChangeSet, Transaction};
@ -53,7 +53,10 @@ pub fn append_mode(state: &mut State, _count: usize) {
let text = &state.doc.slice(..); let text = &state.doc.slice(..);
state.selection = state.selection.transform(|range| { state.selection = state.selection.transform(|range| {
// TODO: to() + next char // TODO: to() + next char
Range::new(range.from(), next_grapheme_boundary(text, range.to())) Range::new(
range.from(),
graphemes::next_grapheme_boundary(text, range.to()),
)
}) })
} }
@ -75,3 +78,30 @@ pub fn insert_char(state: &mut State, c: char) {
transaction.apply(state); transaction.apply(state);
// TODO: need to store into history if successful // TODO: need to store into history if successful
} }
// TODO: handle indent-aware delete
pub fn delete_char_backward(state: &mut State, count: usize) {
let text = &state.doc.slice(..);
let transaction = Transaction::change_by_selection(state, |range| {
(
graphemes::nth_prev_grapheme_boundary(text, range.head, count),
range.head,
None,
)
});
transaction.apply(state);
// TODO: need to store into history if successful
}
pub fn delete_char_forward(state: &mut State, count: usize) {
let text = &state.doc.slice(..);
let transaction = Transaction::change_by_selection(state, |range| {
(
graphemes::nth_next_grapheme_boundary(text, range.head, count),
range.head,
None,
)
});
transaction.apply(state);
// TODO: need to store into history if successful
}

@ -342,31 +342,37 @@ impl Transaction {
true true
} }
pub fn insert(state: &State, text: Tendril) -> Self { pub fn change_by_selection<F>(state: &State, f: F) -> Self
where
F: Fn(&SelectionRange) -> (usize, usize, Option<Tendril>),
{
let len = state.doc.len_chars(); let len = state.doc.len_chars();
let ranges = state.selection.ranges(); let ranges = state.selection.ranges();
let mut changes = Vec::with_capacity(2 * ranges.len() + 1); let mut acc = Vec::with_capacity(2 * ranges.len() + 1);
let mut last = 0;
let changes = ranges.iter().map(f);
// TODO: verify ranges are ordered and not overlapping.
for range in state.selection.ranges() { let mut last = 0;
let cur = range.head; for (from, to, tendril) in changes {
changes.push(Change::Retain(cur)); // TODO: need to fill the in-between ranges too
changes.push(Change::Insert(text.clone())); // Retain from last "to" to current "from"
last = cur; acc.push(Change::Retain(from - last));
match tendril {
Some(text) => acc.push(Change::Insert(text)),
None => acc.push(Change::Delete(to - from)),
}
last = to;
} }
changes.push(Change::Retain(len - last)); acc.push(Change::Retain(len - last));
Self::from(ChangeSet { changes, len }) Self::from(ChangeSet { changes: acc, len })
} }
pub fn change_selection<F>(selection: Selection, f: F) -> Self /// Insert text at each selection head.
where pub fn insert(state: &State, text: Tendril) -> Self {
F: Fn(SelectionRange) -> ChangeSet, Self::change_by_selection(state, |range| (range.head, range.head, Some(text.clone())))
{
selection.ranges().iter().map(|range| true);
// TODO: most idiomatic would be to return a
// Change { from: x, to: y, insert: "str" }
unimplemented!()
} }
} }

@ -259,7 +259,7 @@ impl Editor {
} }
} }
pub async fn print_events(&mut self) { pub async fn event_loop(&mut self) {
let mut reader = EventStream::new(); let mut reader = EventStream::new();
let keymap = keymap::default(); let keymap = keymap::default();
@ -284,6 +284,14 @@ impl Editor {
KeyEvent { KeyEvent {
code: KeyCode::Esc, .. code: KeyCode::Esc, ..
} => helix_core::commands::normal_mode(state, 1), } => helix_core::commands::normal_mode(state, 1),
KeyEvent {
code: KeyCode::Backspace,
..
} => helix_core::commands::delete_char_backward(state, 1),
KeyEvent {
code: KeyCode::Delete,
..
} => helix_core::commands::delete_char_forward(state, 1),
KeyEvent { KeyEvent {
code: KeyCode::Char(c), code: KeyCode::Char(c),
.. ..
@ -320,7 +328,7 @@ impl Editor {
execute!(stdout, terminal::EnterAlternateScreen)?; execute!(stdout, terminal::EnterAlternateScreen)?;
self.print_events().await; self.event_loop().await;
// reset cursor shape // reset cursor shape
write!(stdout, "\x1B[2 q"); write!(stdout, "\x1B[2 q");

Loading…
Cancel
Save