aboutsummaryrefslogtreecommitdiff
path: root/helix-core/src/state.rs
diff options
context:
space:
mode:
authorBlaž Hrastnik2020-06-01 08:42:28 +0000
committerBlaž Hrastnik2020-06-01 08:42:28 +0000
commit613d06dfb0e5fe2fc05b94e5c651dfd10af23310 (patch)
tree74696d63909ffe05903870bfca19d9beabe0e621 /helix-core/src/state.rs
parent6905ff03c29c9fc020a6333adf9e9d5004c3f3c5 (diff)
wip: importing to github
Diffstat (limited to 'helix-core/src/state.rs')
-rw-r--r--helix-core/src/state.rs86
1 files changed, 81 insertions, 5 deletions
diff --git a/helix-core/src/state.rs b/helix-core/src/state.rs
index 22de6ca7..682d298a 100644
--- a/helix-core/src/state.rs
+++ b/helix-core/src/state.rs
@@ -1,17 +1,30 @@
-use crate::{Buffer, Selection};
+use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary};
+use crate::{Buffer, Selection, SelectionRange};
/// A state represents the current editor state of a single buffer.
pub struct State {
- // TODO: maybe doc: ?
- buffer: Buffer,
+ doc: Buffer,
selection: Selection,
}
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub enum Direction {
+ Forward,
+ Backward,
+}
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub enum Granularity {
+ Character,
+ Word,
+ Line,
+ // LineBoundary
+}
+
impl State {
#[must_use]
- pub fn new(buffer: Buffer) -> Self {
+ pub fn new(doc: Buffer) -> Self {
Self {
- buffer,
+ doc,
selection: Selection::single(0, 0),
}
}
@@ -40,4 +53,67 @@ impl State {
// syntax
// foldable
// changeFilter/transactionFilter
+
+ pub fn move_pos(
+ &self,
+ pos: usize,
+ dir: Direction,
+ granularity: Granularity,
+ n: usize,
+ ) -> usize {
+ let text = &self.doc.contents;
+ match (dir, granularity) {
+ (Direction::Backward, Granularity::Character) => {
+ nth_prev_grapheme_boundary(&text.slice(..), pos, n)
+ }
+ (Direction::Forward, Granularity::Character) => {
+ nth_next_grapheme_boundary(&text.slice(..), pos, n)
+ }
+ _ => pos,
+ }
+ }
+
+ pub fn move_selection(
+ &self,
+ sel: Selection,
+ dir: Direction,
+ granularity: Granularity,
+ // TODO: n
+ ) -> Selection {
+ // TODO: move all selections according to normal cursor move semantics by collapsing it
+ // into cursors and moving them vertically
+
+ let ranges = sel.ranges.into_iter().map(|range| {
+ // let pos = if !range.is_empty() {
+ // // if selection already exists, bump it to the start or end of current select first
+ // if dir == Direction::Backward {
+ // range.from()
+ // } else {
+ // range.to()
+ // }
+ // } else {
+ let pos = self.move_pos(range.head, dir, granularity, 1)
+ // };
+ SelectionRange::new(pos, pos)
+ });
+
+ Selection::new(ranges.collect(), sel.primary_index)
+ // TODO: update selection in state via transaction
+ }
+
+ pub fn extend_selection(
+ &self,
+ sel: Selection,
+ dir: Direction,
+ granularity: Granularity,
+ n: usize,
+ ) -> Selection {
+ let ranges = sel.ranges.into_iter().map(|range| {
+ let pos = self.move_pos(range.head, dir, granularity, n);
+ SelectionRange::new(range.anchor, pos)
+ });
+
+ Selection::new(ranges.collect(), sel.primary_index)
+ // TODO: update selection in state via transaction
+ }
}