on master help sign in
cleanup: Make Buffer just a part of State.
8b3e152Blaž Hrastnik
helix-core/src/buffer.rsdeleted−18
@@ -1,18 +0,0 @@
1−use anyhow::Error;
2−use ropey::Rope;
3−use std::{env, fs::File, io::BufReader, path::PathBuf};
4−
5−pub struct Buffer {
6− pub contents: Rope,
7−}
8−
9−impl Buffer {
10− pub fn load(path: PathBuf) -> Result<Self, Error> {
11− let _current_dir = env::current_dir()?;
12−
13− let contents = Rope::from_reader(BufReader::new(File::open(path)?))?;
14−
15− // TODO: create if not found
16− Ok(Buffer { contents })
17− }
18−}
helix-core/src/commands.rs+1−1
@@ -65,6 +65,6 @@ pub fn insert(state: &mut State, c: char) {
65 let pos = state.selection.primary().head;
65 let pos = state.selection.primary().head;
66 let changes = ChangeSet::insert(&state.doc, pos, c);
66 let changes = ChangeSet::insert(&state.doc, pos, c);
67 // TODO: need to store history
67 // TODO: need to store history
68− changes.apply(state.contents_mut());
68+ changes.apply(&mut state.doc);
69 state.selection = state.selection.clone().map(&changes);
69 state.selection = state.selection.clone().map(&changes);
70}
70}
helix-core/src/lib.rs−3
@@ -1,5 +1,4 @@
1#![allow(unused)]
1#![allow(unused)]
2−mod buffer;
3pub mod commands;
2pub mod commands;
4mod graphemes;
3mod graphemes;
5mod selection;
4mod selection;
@@ -9,8 +8,6 @@ mod transaction;
9pub use ropey::{Rope, RopeSlice};
8pub use ropey::{Rope, RopeSlice};
10pub use tendril::StrTendril as Tendril;
9pub use tendril::StrTendril as Tendril;
11
10
12−pub use buffer::Buffer;
13−
14pub use selection::Range as SelectionRange;
11pub use selection::Range as SelectionRange;
15pub use selection::Selection;
12pub use selection::Selection;
16
13
helix-core/src/state.rs+26−15
@@ -1,5 +1,8 @@
1use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes};
1use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes};
2−use crate::{Buffer, Rope, RopeSlice, Selection, SelectionRange};
2+use crate::{Rope, RopeSlice, Selection, SelectionRange};
3+use anyhow::Error;
4+
5+use std::path::PathBuf;
3
6
4pub enum Mode {
7pub enum Mode {
5 Normal,
8 Normal,
@@ -8,7 +11,9 @@ pub enum Mode {
8
11
9/// A state represents the current editor state of a single buffer.
12/// A state represents the current editor state of a single buffer.
10pub struct State {
13pub struct State {
14+ /// Path to file on disk.
15+ pub path: Option<PathBuf>,
11− pub doc: Buffer,
16+ pub doc: Rope,
12 pub selection: Selection,
17 pub selection: Selection,
13 pub mode: Mode,
18 pub mode: Mode,
14}
19}
@@ -28,15 +33,31 @@ pub enum Granularity {
28
33
29impl State {
34impl State {
30 #[must_use]
35 #[must_use]
31− pub fn new(doc: Buffer) -> Self {
36+ pub fn new(doc: Rope) -> Self {
32 Self {
37 Self {
38+ path: None,
33 doc,
39 doc,
34 selection: Selection::single(0, 0),
40 selection: Selection::single(0, 0),
35 mode: Mode::Normal,
41 mode: Mode::Normal,
36 }
42 }
37 }
43 }
38
44
45+ #[must_use]
46+ pub fn load(path: PathBuf) -> Result<Self, Error> {
47+ use std::{env, fs::File, io::BufReader, path::PathBuf};
48+ let _current_dir = env::current_dir()?;
49+
50+ let doc = Rope::from_reader(BufReader::new(File::open(path.clone())?))?;
51+
52+ // TODO: create if not found
53+
54+ let mut state = Self::new(doc);
55+ state.path = Some(path);
56+
57+ Ok(state)
58+ }
59+
39− // TODO: buf/selection accessors
60+ // TODO: doc/selection accessors
40
61
41 // update/transact:
62 // update/transact:
42 // update(desc) => transaction ? transaction.doc() for applied doc
63 // update(desc) => transaction ? transaction.doc() for applied doc
@@ -68,7 +89,7 @@ impl State {
68 granularity: Granularity,
89 granularity: Granularity,
69 count: usize,
90 count: usize,
70 ) -> usize {
91 ) -> usize {
71− let text = &self.doc.contents;
92+ let text = &self.doc;
72 match (dir, granularity) {
93 match (dir, granularity) {
73 // TODO: clamp movement to line, prevent moving onto \n at the end
94 // TODO: clamp movement to line, prevent moving onto \n at the end
74 (Direction::Backward, Granularity::Character) => {
95 (Direction::Backward, Granularity::Character) => {
@@ -125,16 +146,6 @@ impl State {
125 Selection::new(ranges.collect(), sel.primary_index)
146 Selection::new(ranges.collect(), sel.primary_index)
126 // TODO: update selection in state via transaction
147 // TODO: update selection in state via transaction
127 }
148 }
128−
129− pub fn contents(&self) -> &Rope {
130− // used to access file contents for rendering to screen
131− &self.doc.contents
132− }
133−
134− pub fn contents_mut(&mut self) -> &mut Rope {
135− // used to access file contents for rendering to screen
136− &mut self.doc.contents
137− }
138}
149}
139
150
140/// Coordinates are a 0-indexed line and column pair.
151/// Coordinates are a 0-indexed line and column pair.
helix-core/src/transaction.rs+5−5
@@ -1,4 +1,4 @@
1−use crate::{Buffer, Rope, Selection, Tendril};
1+use crate::{Rope, Selection, Tendril};
2
2
3// TODO: divided into three different operations, I sort of like having just
3// TODO: divided into three different operations, I sort of like having just
4// Splice { extent, Option<text>, distance } better.
4// Splice { extent, Option<text>, distance } better.
@@ -39,16 +39,16 @@ pub struct ChangeSet {
39
39
40impl ChangeSet {
40impl ChangeSet {
41 #[must_use]
41 #[must_use]
42− pub fn new(buf: &Buffer) -> Self {
42+ pub fn new(doc: &Rope) -> Self {
43− let len = buf.contents.len_chars();
43+ let len = doc.len_chars();
44 Self {
44 Self {
45 changes: vec![Change::Retain(len)],
45 changes: vec![Change::Retain(len)],
46 len,
46 len,
47 }
47 }
48 }
48 }
49
49
50− pub fn insert(buf: &Buffer, pos: usize, c: char) -> Self {
50+ pub fn insert(doc: &Rope, pos: usize, c: char) -> Self {
51− let len = buf.contents.len_chars();
51+ let len = doc.len_chars();
52 Self {
52 Self {
53 changes: vec![
53 changes: vec![
54 Change::Retain(pos),
54 Change::Retain(pos),
helix-term/src/editor.rs+4−6
@@ -9,7 +9,7 @@ use crossterm::{
9 terminal::{self, disable_raw_mode, enable_raw_mode},
9 terminal::{self, disable_raw_mode, enable_raw_mode},
10};
10};
11use futures::{future::FutureExt, select, StreamExt};
11use futures::{future::FutureExt, select, StreamExt};
12−use helix_core::{state::coords_at_pos, state::Mode, Buffer, State};
12+use helix_core::{state::coords_at_pos, state::Mode, State};
13use std::io::{self, stdout, Write};
13use std::io::{self, stdout, Write};
14use std::path::PathBuf;
14use std::path::PathBuf;
15use std::time::Duration;
15use std::time::Duration;
@@ -38,9 +38,7 @@ impl Editor {
38 }
38 }
39
39
40 pub fn open(&mut self, path: PathBuf) -> Result<(), Error> {
40 pub fn open(&mut self, path: PathBuf) -> Result<(), Error> {
41− let buffer = Buffer::load(path)?;
42− let state = State::new(buffer);
43− self.state = Some(state);
41+ self.state = Some(State::load(path)?);
44 Ok(())
42 Ok(())
45 }
43 }
46
44
@@ -48,7 +46,7 @@ impl Editor {
48 match &self.state {
46 match &self.state {
49 Some(state) => {
47 Some(state) => {
50 let lines = state
48 let lines = state
51− .contents()
49+ .doc
52 .lines_at(self.first_line as usize)
50 .lines_at(self.first_line as usize)
53 .take(self.size.1 as usize)
51 .take(self.size.1 as usize)
54 .map(|x| x.as_str().unwrap());
52 .map(|x| x.as_str().unwrap());
@@ -90,7 +88,7 @@ impl Editor {
90
88
91 // render the cursor
89 // render the cursor
92 let pos = state.selection.primary().head;
90 let pos = state.selection.primary().head;
93− let coords = coords_at_pos(&state.doc.contents.slice(..), pos);
91+ let coords = coords_at_pos(&state.doc.slice(..), pos);
94 execute!(
92 execute!(
95 stdout,
93 stdout,
96 cursor::MoveTo((coords.1 + 2) as u16, coords.0 as u16)
94 cursor::MoveTo((coords.1 + 2) as u16, coords.0 as u16)