on master help sign in
Abstract Transaction::change_by_selection, working del/backspace.
commitd466882d0432b7e9cf905041aa7a4f8d56047de0 authorBlaž Hrastnik <blaz@mxxn.io> dateSun 13 Sep 2020, 11:32 (6 years ago) parentf098166
3 files changed+66−22
helix-core/src/commands.rs+32−2 helix-core/src/transaction.rs+24−18 helix-term/src/editor.rs+10−2
helix-core/src/commands.rs+32−2
@@ -1,4 +1,4 @@
1−use crate::graphemes::next_grapheme_boundary;
1+use crate::graphemes;
22use crate::selection::Range;
33use crate::state::{Direction, Granularity, Mode, State};
44use crate::transaction::{ChangeSet, Transaction};
@@ -53,7 +53,10 @@ pub fn append_mode(state: &mut State, _count: usize) {
5353 let text = &state.doc.slice(..);
5454 state.selection = state.selection.transform(|range| {
5555 // TODO: to() + next char
56− Range::new(range.from(), next_grapheme_boundary(text, range.to()))
56+ Range::new(
57+ range.from(),
58+ graphemes::next_grapheme_boundary(text, range.to()),
59+ )
5760 })
5861}
5962
@@ -75,3 +78,30 @@ pub fn insert_char(state: &mut State, c: char) {
7578 transaction.apply(state);
7679 // TODO: need to store into history if successful
7780}
81+
82+// TODO: handle indent-aware delete
83+pub fn delete_char_backward(state: &mut State, count: usize) {
84+ let text = &state.doc.slice(..);
85+ let transaction = Transaction::change_by_selection(state, |range| {
86+ (
87+ graphemes::nth_prev_grapheme_boundary(text, range.head, count),
88+ range.head,
89+ None,
90+ )
91+ });
92+ transaction.apply(state);
93+ // TODO: need to store into history if successful
94+}
95+
96+pub fn delete_char_forward(state: &mut State, count: usize) {
97+ let text = &state.doc.slice(..);
98+ let transaction = Transaction::change_by_selection(state, |range| {
99+ (
100+ graphemes::nth_next_grapheme_boundary(text, range.head, count),
101+ range.head,
102+ None,
103+ )
104+ });
105+ transaction.apply(state);
106+ // TODO: need to store into history if successful
107+}
helix-core/src/transaction.rs+24−18
@@ -342,31 +342,37 @@ impl Transaction {
342342 true
343343 }
344344
345− pub fn insert(state: &State, text: Tendril) -> Self {
345+ pub fn change_by_selection<F>(state: &State, f: F) -> Self
346+ where
347+ F: Fn(&SelectionRange) -> (usize, usize, Option<Tendril>),
348+ {
346349 let len = state.doc.len_chars();
347350 let ranges = state.selection.ranges();
348− let mut changes = Vec::with_capacity(2 * ranges.len() + 1);
349− let mut last = 0;
351+ let mut acc = Vec::with_capacity(2 * ranges.len() + 1);
352+
353+ let changes = ranges.iter().map(f);
354+
355+ // TODO: verify ranges are ordered and not overlapping.
350356
351− for range in state.selection.ranges() {
352− let cur = range.head;
353− changes.push(Change::Retain(cur));
354− changes.push(Change::Insert(text.clone()));
355− last = cur;
357+ let mut last = 0;
358+ for (from, to, tendril) in changes {
359+ // TODO: need to fill the in-between ranges too
360+ // Retain from last "to" to current "from"
361+ acc.push(Change::Retain(from - last));
362+ match tendril {
363+ Some(text) => acc.push(Change::Insert(text)),
364+ None => acc.push(Change::Delete(to - from)),
365+ }
366+ last = to;
356367 }
357− changes.push(Change::Retain(len - last));
368+ acc.push(Change::Retain(len - last));
358369
359− Self::from(ChangeSet { changes, len })
370+ Self::from(ChangeSet { changes: acc, len })
360371 }
361372
362− pub fn change_selection<F>(selection: Selection, f: F) -> Self
363− where
364− F: Fn(SelectionRange) -> ChangeSet,
365− {
366− selection.ranges().iter().map(|range| true);
367− // TODO: most idiomatic would be to return a
368− // Change { from: x, to: y, insert: "str" }
369− unimplemented!()
373+ /// Insert text at each selection head.
374+ pub fn insert(state: &State, text: Tendril) -> Self {
375+ Self::change_by_selection(state, |range| (range.head, range.head, Some(text.clone())))
370376 }
371377}
372378
helix-term/src/editor.rs+10−2
@@ -259,7 +259,7 @@ impl Editor {
259259 }
260260 }
261261
262− pub async fn print_events(&mut self) {
262+ pub async fn event_loop(&mut self) {
263263 let mut reader = EventStream::new();
264264 let keymap = keymap::default();
265265
@@ -284,6 +284,14 @@ impl Editor {
284284 KeyEvent {
285285 code: KeyCode::Esc, ..
286286 } => helix_core::commands::normal_mode(state, 1),
287+ KeyEvent {
288+ code: KeyCode::Backspace,
289+ ..
290+ } => helix_core::commands::delete_char_backward(state, 1),
291+ KeyEvent {
292+ code: KeyCode::Delete,
293+ ..
294+ } => helix_core::commands::delete_char_forward(state, 1),
287295 KeyEvent {
288296 code: KeyCode::Char(c),
289297 ..
@@ -320,7 +328,7 @@ impl Editor {
320328
321329 execute!(stdout, terminal::EnterAlternateScreen)?;
322330
323− self.print_events().await;
331+ self.event_loop().await;
324332
325333 // reset cursor shape
326334 write!(stdout, "\x1B[2 q");