diff options
Diffstat (limited to 'helix-core')
-rw-r--r-- | helix-core/src/commands.rs | 22 | ||||
-rw-r--r-- | helix-core/src/selection.rs | 4 | ||||
-rw-r--r-- | helix-core/src/state.rs | 14 | ||||
-rw-r--r-- | helix-core/src/transaction.rs | 12 |
4 files changed, 48 insertions, 4 deletions
diff --git a/helix-core/src/commands.rs b/helix-core/src/commands.rs index 62e97686..a6b74449 100644 --- a/helix-core/src/commands.rs +++ b/helix-core/src/commands.rs @@ -1,4 +1,4 @@ -use crate::state::{Direction, Granularity, State}; +use crate::state::{Direction, Granularity, Mode, State}; /// A command is a function that takes the current state and a count, and does a side-effect on the /// state (usually by creating and applying a transaction). @@ -48,3 +48,23 @@ pub fn move_line_down(state: &mut State, count: usize) { count, ); } + +pub fn insert_mode(state: &mut State, _count: usize) { + state.mode = Mode::Insert; +} + +pub fn normal_mode(state: &mut State, _count: usize) { + state.mode = Mode::Normal; +} + +// TODO: insert means add text just before cursor, on exit we should be on the last letter. +pub fn insert(state: &mut State, c: char) { + // TODO: needs to work with multiple cursors + use crate::transaction::ChangeSet; + + let pos = state.selection.primary().head; + let changes = ChangeSet::insert(&state.doc, pos, c); + // TODO: need to store history + changes.apply(state.contents_mut()); + state.selection = state.selection.clone().map(&changes); +} diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs index 3e28c9ce..1c0b6b74 100644 --- a/helix-core/src/selection.rs +++ b/helix-core/src/selection.rs @@ -63,8 +63,8 @@ impl Range { /// Map a range through a set of changes. Returns a new range representing the same position /// after the changes are applied. pub fn map(self, changes: &ChangeSet) -> Self { - let anchor = changes.map_pos(self.anchor, Assoc::Before); - let head = changes.map_pos(self.head, Assoc::Before); + let anchor = changes.map_pos(self.anchor, Assoc::After); + let head = changes.map_pos(self.head, Assoc::After); // TODO: possibly unnecessary if self.anchor == anchor && self.head == head { diff --git a/helix-core/src/state.rs b/helix-core/src/state.rs index 9c227a92..8568c3c3 100644 --- a/helix-core/src/state.rs +++ b/helix-core/src/state.rs @@ -1,10 +1,16 @@ use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes}; use crate::{Buffer, Rope, RopeSlice, Selection, SelectionRange}; +pub enum Mode { + Normal, + Insert, +} + /// A state represents the current editor state of a single buffer. pub struct State { pub doc: Buffer, pub selection: Selection, + pub mode: Mode, } #[derive(Copy, Clone, PartialEq, Eq)] @@ -26,6 +32,7 @@ impl State { Self { doc, selection: Selection::single(0, 0), + mode: Mode::Normal, } } @@ -119,10 +126,15 @@ impl State { // TODO: update selection in state via transaction } - pub fn file(&self) -> &Rope { + pub fn contents(&self) -> &Rope { // used to access file contents for rendering to screen &self.doc.contents } + + pub fn contents_mut(&mut self) -> &mut Rope { + // used to access file contents for rendering to screen + &mut self.doc.contents + } } /// Coordinates are a 0-indexed line and column pair. diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs index 1619a4db..2d8afc9b 100644 --- a/helix-core/src/transaction.rs +++ b/helix-core/src/transaction.rs @@ -47,6 +47,18 @@ impl ChangeSet { } } + pub fn insert(buf: &Buffer, pos: usize, c: char) -> Self { + let len = buf.contents.len_chars(); + Self { + changes: vec![ + Change::Retain(pos), + Change::Insert(Tendril::from_char(c)), + Change::Retain(len - pos), + ], + len, + } + } + // TODO: from iter /// Combine two changesets together. |