cleanup: Make Buffer just a part of State.

This commit is contained in:
Blaž Hrastnik 2020-09-07 11:28:52 +09:00
parent 579b6899f1
commit 8b3e152126
6 changed files with 36 additions and 48 deletions

View file

@ -1,18 +0,0 @@
use anyhow::Error;
use ropey::Rope;
use std::{env, fs::File, io::BufReader, path::PathBuf};
pub struct Buffer {
pub contents: Rope,
}
impl Buffer {
pub fn load(path: PathBuf) -> Result<Self, Error> {
let _current_dir = env::current_dir()?;
let contents = Rope::from_reader(BufReader::new(File::open(path)?))?;
// TODO: create if not found
Ok(Buffer { contents })
}
}

View file

@ -65,6 +65,6 @@ pub fn insert(state: &mut State, c: char) {
let pos = state.selection.primary().head; let pos = state.selection.primary().head;
let changes = ChangeSet::insert(&state.doc, pos, c); let changes = ChangeSet::insert(&state.doc, pos, c);
// TODO: need to store history // TODO: need to store history
changes.apply(state.contents_mut()); changes.apply(&mut state.doc);
state.selection = state.selection.clone().map(&changes); state.selection = state.selection.clone().map(&changes);
} }

View file

@ -1,5 +1,4 @@
#![allow(unused)] #![allow(unused)]
mod buffer;
pub mod commands; pub mod commands;
mod graphemes; mod graphemes;
mod selection; mod selection;
@ -9,8 +8,6 @@ mod transaction;
pub use ropey::{Rope, RopeSlice}; pub use ropey::{Rope, RopeSlice};
pub use tendril::StrTendril as Tendril; pub use tendril::StrTendril as Tendril;
pub use buffer::Buffer;
pub use selection::Range as SelectionRange; pub use selection::Range as SelectionRange;
pub use selection::Selection; pub use selection::Selection;

View file

@ -1,5 +1,8 @@
use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes}; use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes};
use crate::{Buffer, Rope, RopeSlice, Selection, SelectionRange}; use crate::{Rope, RopeSlice, Selection, SelectionRange};
use anyhow::Error;
use std::path::PathBuf;
pub enum Mode { pub enum Mode {
Normal, Normal,
@ -8,7 +11,9 @@ pub enum Mode {
/// A state represents the current editor state of a single buffer. /// A state represents the current editor state of a single buffer.
pub struct State { pub struct State {
pub doc: Buffer, /// Path to file on disk.
pub path: Option<PathBuf>,
pub doc: Rope,
pub selection: Selection, pub selection: Selection,
pub mode: Mode, pub mode: Mode,
} }
@ -28,15 +33,31 @@ pub enum Granularity {
impl State { impl State {
#[must_use] #[must_use]
pub fn new(doc: Buffer) -> Self { pub fn new(doc: Rope) -> Self {
Self { Self {
path: None,
doc, doc,
selection: Selection::single(0, 0), selection: Selection::single(0, 0),
mode: Mode::Normal, mode: Mode::Normal,
} }
} }
// TODO: buf/selection accessors #[must_use]
pub fn load(path: PathBuf) -> Result<Self, Error> {
use std::{env, fs::File, io::BufReader, path::PathBuf};
let _current_dir = env::current_dir()?;
let doc = Rope::from_reader(BufReader::new(File::open(path.clone())?))?;
// TODO: create if not found
let mut state = Self::new(doc);
state.path = Some(path);
Ok(state)
}
// TODO: doc/selection accessors
// update/transact: // update/transact:
// update(desc) => transaction ? transaction.doc() for applied doc // update(desc) => transaction ? transaction.doc() for applied doc
@ -68,7 +89,7 @@ impl State {
granularity: Granularity, granularity: Granularity,
count: usize, count: usize,
) -> usize { ) -> usize {
let text = &self.doc.contents; let text = &self.doc;
match (dir, granularity) { match (dir, granularity) {
// TODO: clamp movement to line, prevent moving onto \n at the end // TODO: clamp movement to line, prevent moving onto \n at the end
(Direction::Backward, Granularity::Character) => { (Direction::Backward, Granularity::Character) => {
@ -125,16 +146,6 @@ impl State {
Selection::new(ranges.collect(), sel.primary_index) Selection::new(ranges.collect(), sel.primary_index)
// TODO: update selection in state via transaction // TODO: update selection in state via transaction
} }
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. /// Coordinates are a 0-indexed line and column pair.

View file

@ -1,4 +1,4 @@
use crate::{Buffer, Rope, Selection, Tendril}; use crate::{Rope, Selection, Tendril};
// TODO: divided into three different operations, I sort of like having just // TODO: divided into three different operations, I sort of like having just
// Splice { extent, Option<text>, distance } better. // Splice { extent, Option<text>, distance } better.
@ -39,16 +39,16 @@ pub struct ChangeSet {
impl ChangeSet { impl ChangeSet {
#[must_use] #[must_use]
pub fn new(buf: &Buffer) -> Self { pub fn new(doc: &Rope) -> Self {
let len = buf.contents.len_chars(); let len = doc.len_chars();
Self { Self {
changes: vec![Change::Retain(len)], changes: vec![Change::Retain(len)],
len, len,
} }
} }
pub fn insert(buf: &Buffer, pos: usize, c: char) -> Self { pub fn insert(doc: &Rope, pos: usize, c: char) -> Self {
let len = buf.contents.len_chars(); let len = doc.len_chars();
Self { Self {
changes: vec![ changes: vec![
Change::Retain(pos), Change::Retain(pos),

View file

@ -9,7 +9,7 @@ use crossterm::{
terminal::{self, disable_raw_mode, enable_raw_mode}, terminal::{self, disable_raw_mode, enable_raw_mode},
}; };
use futures::{future::FutureExt, select, StreamExt}; use futures::{future::FutureExt, select, StreamExt};
use helix_core::{state::coords_at_pos, state::Mode, Buffer, State}; use helix_core::{state::coords_at_pos, state::Mode, State};
use std::io::{self, stdout, Write}; use std::io::{self, stdout, Write};
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
@ -38,9 +38,7 @@ impl Editor {
} }
pub fn open(&mut self, path: PathBuf) -> Result<(), Error> { pub fn open(&mut self, path: PathBuf) -> Result<(), Error> {
let buffer = Buffer::load(path)?; self.state = Some(State::load(path)?);
let state = State::new(buffer);
self.state = Some(state);
Ok(()) Ok(())
} }
@ -48,7 +46,7 @@ impl Editor {
match &self.state { match &self.state {
Some(state) => { Some(state) => {
let lines = state let lines = state
.contents() .doc
.lines_at(self.first_line as usize) .lines_at(self.first_line as usize)
.take(self.size.1 as usize) .take(self.size.1 as usize)
.map(|x| x.as_str().unwrap()); .map(|x| x.as_str().unwrap());
@ -90,7 +88,7 @@ impl Editor {
// render the cursor // render the cursor
let pos = state.selection.primary().head; let pos = state.selection.primary().head;
let coords = coords_at_pos(&state.doc.contents.slice(..), pos); let coords = coords_at_pos(&state.doc.slice(..), pos);
execute!( execute!(
stdout, stdout,
cursor::MoveTo((coords.1 + 2) as u16, coords.0 as u16) cursor::MoveTo((coords.1 + 2) as u16, coords.0 as u16)