From 0a11fb1045017da449988f770672880aa28caaca Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 19 Dec 2023 11:47:25 -0700 Subject: [PATCH] Make Editor::buffer_ref accessible, rename lifetimes --- examples/editor-libcosmic/src/main.rs | 4 +- src/edit/editor.rs | 60 +++++-------------------- src/edit/mod.rs | 64 +++++++++++++++++++++++---- src/edit/syntect.rs | 36 ++++++++------- src/edit/vi.rs | 35 ++++++++------- 5 files changed, 108 insertions(+), 91 deletions(-) diff --git a/examples/editor-libcosmic/src/main.rs b/examples/editor-libcosmic/src/main.rs index 1fa01e4..9b66e6d 100644 --- a/examples/editor-libcosmic/src/main.rs +++ b/examples/editor-libcosmic/src/main.rs @@ -372,7 +372,7 @@ impl Application for Window { } } -fn update_attrs(editor: &mut T, attrs: Attrs) { +fn update_attrs<'buffer, E: Edit<'buffer>>(editor: &mut E, attrs: Attrs) { editor.with_buffer_mut(|buffer| { buffer.lines.iter_mut().for_each(|line| { line.set_attrs_list(AttrsList::new(attrs)); @@ -380,7 +380,7 @@ fn update_attrs(editor: &mut T, attrs: Attrs) { }); } -fn update_alignment(editor: &mut T, align: Align) { +fn update_alignment<'buffer, E: Edit<'buffer>>(editor: &mut E, align: Align) { let current_line = editor.cursor().line; let selection_bounds_opt = editor.selection_bounds(); editor.with_buffer_mut(|buffer| { diff --git a/src/edit/editor.rs b/src/edit/editor.rs index 1de6ef5..be475f6 100644 --- a/src/edit/editor.rs +++ b/src/edit/editor.rs @@ -2,46 +2,20 @@ #[cfg(not(feature = "std"))] use alloc::string::{String, ToString}; -use alloc::sync::Arc; use core::{cmp, iter::once}; use unicode_segmentation::UnicodeSegmentation; #[cfg(feature = "swash")] use crate::Color; use crate::{ - Action, AttrsList, BorrowedWithFontSystem, Buffer, BufferLine, Change, ChangeItem, Cursor, + Action, AttrsList, BorrowedWithFontSystem, BufferLine, BufferRef, Change, ChangeItem, Cursor, Edit, FontSystem, Selection, Shaping, }; -#[derive(Debug)] -pub enum BufferRef<'a> { - Owned(Buffer), - Borrowed(&'a mut Buffer), - Arc(Arc), -} - -impl<'a> From for BufferRef<'a> { - fn from(buffer: Buffer) -> Self { - Self::Owned(buffer) - } -} - -impl<'a> From<&'a mut Buffer> for BufferRef<'a> { - fn from(buffer: &'a mut Buffer) -> Self { - Self::Borrowed(buffer) - } -} - -impl<'a> From> for BufferRef<'a> { - fn from(arc: Arc) -> Self { - Self::Arc(arc) - } -} - /// A wrapper of [`Buffer`] for easy editing #[derive(Debug)] -pub struct Editor<'a> { - buffer_ref: BufferRef<'a>, +pub struct Editor<'buffer> { + buffer_ref: BufferRef<'buffer>, cursor: Cursor, cursor_x_opt: Option, selection: Selection, @@ -51,9 +25,9 @@ pub struct Editor<'a> { change: Option, } -impl<'a> Editor<'a> { +impl<'buffer> Editor<'buffer> { /// Create a new [`Editor`] with the provided [`Buffer`] - pub fn new(buffer: impl Into>) -> Self { + pub fn new(buffer: impl Into>) -> Self { Self { buffer_ref: buffer.into(), cursor: Cursor::default(), @@ -241,25 +215,13 @@ impl<'a> Editor<'a> { } } -impl<'a> Edit for Editor<'a> { - fn with_buffer T, T>(&self, f: F) -> T { - match &self.buffer_ref { - BufferRef::Owned(buffer) => f(buffer), - BufferRef::Borrowed(buffer) => f(buffer), - BufferRef::Arc(buffer) => f(buffer), - } +impl<'buffer> Edit<'buffer> for Editor<'buffer> { + fn buffer_ref(&self) -> &BufferRef<'buffer> { + &self.buffer_ref } - fn with_buffer_mut T, T>(&mut self, f: F) -> T { - match &mut self.buffer_ref { - BufferRef::Owned(buffer) => f(buffer), - BufferRef::Borrowed(buffer) => f(buffer), - BufferRef::Arc(arc) => match Arc::get_mut(arc) { - Some(buffer) => f(buffer), - //TODO: use make_mut? - None => panic!("BufferRef::Arc cannot be accessed mutibly"), - }, - } + fn buffer_ref_mut(&mut self) -> &mut BufferRef<'buffer> { + &mut self.buffer_ref } fn cursor(&self) -> Cursor { @@ -886,7 +848,7 @@ impl<'a> Edit for Editor<'a> { } } -impl<'a, 'b> BorrowedWithFontSystem<'a, Editor<'b>> { +impl<'font_system, 'buffer> BorrowedWithFontSystem<'font_system, Editor<'buffer>> { #[cfg(feature = "swash")] pub fn draw( &mut self, diff --git a/src/edit/mod.rs b/src/edit/mod.rs index f7600fa..01c89cf 100644 --- a/src/edit/mod.rs +++ b/src/edit/mod.rs @@ -1,3 +1,4 @@ +use alloc::sync::Arc; #[cfg(not(feature = "std"))] use alloc::{string::String, vec::Vec}; use core::cmp; @@ -63,6 +64,31 @@ pub enum Action { }, } +#[derive(Debug)] +pub enum BufferRef<'buffer> { + Owned(Buffer), + Borrowed(&'buffer mut Buffer), + Arc(Arc), +} + +impl<'buffer> From for BufferRef<'buffer> { + fn from(buffer: Buffer) -> Self { + Self::Owned(buffer) + } +} + +impl<'buffer> From<&'buffer mut Buffer> for BufferRef<'buffer> { + fn from(buffer: &'buffer mut Buffer) -> Self { + Self::Borrowed(buffer) + } +} + +impl<'buffer> From> for BufferRef<'buffer> { + fn from(arc: Arc) -> Self { + Self::Arc(arc) + } +} + /// A unique change to an editor #[derive(Clone, Debug)] pub struct ChangeItem { @@ -115,12 +141,12 @@ pub enum Selection { } /// A trait to allow easy replacements of [`Editor`], like `SyntaxEditor` -pub trait Edit { +pub trait Edit<'buffer> { /// Mutably borrows `self` together with an [`FontSystem`] for more convenient methods - fn borrow_with<'a>( - &'a mut self, - font_system: &'a mut FontSystem, - ) -> BorrowedWithFontSystem<'a, Self> + fn borrow_with<'font_system>( + &'font_system mut self, + font_system: &'font_system mut FontSystem, + ) -> BorrowedWithFontSystem<'font_system, Self> where Self: Sized, { @@ -130,11 +156,33 @@ pub trait Edit { } } + /// Get the internal [`BufferRef`] + fn buffer_ref(&self) -> &BufferRef<'buffer>; + + /// Get the internal [`BufferRef`] + fn buffer_ref_mut(&mut self) -> &mut BufferRef<'buffer>; + /// Get the internal [`Buffer`] - fn with_buffer T, T>(&self, f: F) -> T; + fn with_buffer T, T>(&self, f: F) -> T { + match self.buffer_ref() { + BufferRef::Owned(buffer) => f(buffer), + BufferRef::Borrowed(buffer) => f(buffer), + BufferRef::Arc(buffer) => f(buffer), + } + } /// Get the internal [`Buffer`], mutably - fn with_buffer_mut T, T>(&mut self, f: F) -> T; + fn with_buffer_mut T, T>(&mut self, f: F) -> T { + match self.buffer_ref_mut() { + BufferRef::Owned(buffer) => f(buffer), + BufferRef::Borrowed(buffer) => f(buffer), + BufferRef::Arc(arc) => match Arc::get_mut(arc) { + Some(buffer) => f(buffer), + //TODO: use make_mut? + None => panic!("BufferRef::Arc cannot be accessed mutibly"), + }, + } + } /// Get the [`Buffer`] redraw flag fn redraw(&self) -> bool { @@ -277,7 +325,7 @@ pub trait Edit { fn action(&mut self, font_system: &mut FontSystem, action: Action); } -impl<'a, E: Edit> BorrowedWithFontSystem<'a, E> { +impl<'font_system, 'buffer, E: Edit<'buffer>> BorrowedWithFontSystem<'font_system, E> { /// Get the internal [`Buffer`], mutably pub fn with_buffer_mut) -> T, T>( &mut self, diff --git a/src/edit/syntect.rs b/src/edit/syntect.rs index 5d932c2..b8a605f 100644 --- a/src/edit/syntect.rs +++ b/src/edit/syntect.rs @@ -8,8 +8,8 @@ use syntect::highlighting::{ use syntect::parsing::{ParseState, ScopeStack, SyntaxReference, SyntaxSet}; use crate::{ - Action, AttrsList, BorrowedWithFontSystem, Buffer, BufferRef, Change, Color, Cursor, Edit, - Editor, FontSystem, Selection, Shaping, Style, Weight, + Action, AttrsList, BorrowedWithFontSystem, BufferRef, Change, Color, Cursor, Edit, Editor, + FontSystem, Selection, Shaping, Style, Weight, }; pub use syntect::highlighting::Theme as SyntaxTheme; @@ -33,24 +33,24 @@ impl SyntaxSystem { /// A wrapper of [`Editor`] with syntax highlighting provided by [`SyntaxSystem`] #[derive(Debug)] -pub struct SyntaxEditor<'a, 'b> { - editor: Editor<'b>, - syntax_system: &'a SyntaxSystem, - syntax: &'a SyntaxReference, - theme: &'a SyntaxTheme, - highlighter: Highlighter<'a>, +pub struct SyntaxEditor<'syntax_system, 'buffer> { + editor: Editor<'buffer>, + syntax_system: &'syntax_system SyntaxSystem, + syntax: &'syntax_system SyntaxReference, + theme: &'syntax_system SyntaxTheme, + highlighter: Highlighter<'syntax_system>, syntax_cache: Vec<(ParseState, ScopeStack)>, } -impl<'a, 'b> SyntaxEditor<'a, 'b> { +impl<'syntax_system, 'buffer> SyntaxEditor<'syntax_system, 'buffer> { /// Create a new [`SyntaxEditor`] with the provided [`Buffer`], [`SyntaxSystem`], and theme name. /// /// A good default theme name is "base16-eighties.dark". /// /// Returns None if theme not found pub fn new( - buffer: impl Into>, - syntax_system: &'a SyntaxSystem, + buffer: impl Into>, + syntax_system: &'syntax_system SyntaxSystem, theme_name: &str, ) -> Option { let editor = Editor::new(buffer); @@ -213,13 +213,13 @@ impl<'a, 'b> SyntaxEditor<'a, 'b> { } } -impl<'a, 'b> Edit for SyntaxEditor<'a, 'b> { - fn with_buffer T, T>(&self, f: F) -> T { - self.editor.with_buffer(f) +impl<'syntax_system, 'buffer> Edit<'buffer> for SyntaxEditor<'syntax_system, 'buffer> { + fn buffer_ref(&self) -> &BufferRef<'buffer> { + self.editor.buffer_ref() } - fn with_buffer_mut T, T>(&mut self, f: F) -> T { - self.editor.with_buffer_mut(f) + fn buffer_ref_mut(&mut self) -> &mut BufferRef<'buffer> { + self.editor.buffer_ref_mut() } fn cursor(&self) -> Cursor { @@ -408,7 +408,9 @@ impl<'a, 'b> Edit for SyntaxEditor<'a, 'b> { } } -impl<'a, 'b, 'c> BorrowedWithFontSystem<'c, SyntaxEditor<'a, 'b>> { +impl<'font_system, 'syntax_system, 'buffer> + BorrowedWithFontSystem<'font_system, SyntaxEditor<'syntax_system, 'buffer>> +{ /// Load text from a file, and also set syntax to the best option /// /// ## Errors diff --git a/src/edit/vi.rs b/src/edit/vi.rs index bfdc58f..8d6382b 100644 --- a/src/edit/vi.rs +++ b/src/edit/vi.rs @@ -4,13 +4,16 @@ use modit::{Event, Key, Parser, TextObject, WordIter}; use unicode_segmentation::UnicodeSegmentation; use crate::{ - Action, AttrsList, BorrowedWithFontSystem, Buffer, Change, Color, Cursor, Edit, FontSystem, + Action, AttrsList, BorrowedWithFontSystem, BufferRef, Change, Color, Cursor, Edit, FontSystem, Motion, Selection, SyntaxEditor, SyntaxTheme, }; pub use modit::{ViMode, ViParser}; -fn undo_2_action(editor: &mut E, action: cosmic_undo_2::Action<&Change>) { +fn undo_2_action<'buffer, E: Edit<'buffer>>( + editor: &mut E, + action: cosmic_undo_2::Action<&Change>, +) { match action { cosmic_undo_2::Action::Do(change) => { editor.apply_change(change); @@ -24,7 +27,7 @@ fn undo_2_action(editor: &mut E, action: cosmic_undo_2::Action<&Change> } } -fn finish_change( +fn finish_change<'buffer, E: Edit<'buffer>>( editor: &mut E, commands: &mut cosmic_undo_2::Commands, changed: &mut bool, @@ -42,7 +45,7 @@ fn finish_change( } } -fn search(editor: &mut E, value: &str, forwards: bool) -> bool { +fn search<'buffer, E: Edit<'buffer>>(editor: &mut E, value: &str, forwards: bool) -> bool { let mut cursor = editor.cursor(); let start_line = cursor.line; if forwards { @@ -94,7 +97,7 @@ fn search(editor: &mut E, value: &str, forwards: bool) -> bool { false } -fn select_in(editor: &mut E, start_c: char, end_c: char, include: bool) { +fn select_in<'buffer, E: Edit<'buffer>>(editor: &mut E, start_c: char, end_c: char, include: bool) { // Find the largest encompasing object, or if there is none, find the next one. let cursor = editor.cursor(); let (start, end) = editor.with_buffer(|buffer| { @@ -156,8 +159,8 @@ fn select_in(editor: &mut E, start_c: char, end_c: char, include: bool) } #[derive(Debug)] -pub struct ViEditor<'a, 'b> { - editor: SyntaxEditor<'a, 'b>, +pub struct ViEditor<'syntax_system, 'buffer> { + editor: SyntaxEditor<'syntax_system, 'buffer>, parser: ViParser, passthrough: bool, registers: BTreeMap, @@ -166,8 +169,8 @@ pub struct ViEditor<'a, 'b> { changed: bool, } -impl<'a, 'b> ViEditor<'a, 'b> { - pub fn new(editor: SyntaxEditor<'a, 'b>) -> Self { +impl<'syntax_system, 'buffer> ViEditor<'syntax_system, 'buffer> { + pub fn new(editor: SyntaxEditor<'syntax_system, 'buffer>) -> Self { Self { editor, parser: ViParser::new(), @@ -477,13 +480,13 @@ impl<'a, 'b> ViEditor<'a, 'b> { } } -impl<'a, 'b> Edit for ViEditor<'a, 'b> { - fn with_buffer T, T>(&self, f: F) -> T { - self.editor.with_buffer(f) +impl<'syntax_system, 'buffer> Edit<'buffer> for ViEditor<'syntax_system, 'buffer> { + fn buffer_ref(&self) -> &BufferRef<'buffer> { + self.editor.buffer_ref() } - fn with_buffer_mut T, T>(&mut self, f: F) -> T { - self.editor.with_buffer_mut(f) + fn buffer_ref_mut(&mut self) -> &mut BufferRef<'buffer> { + self.editor.buffer_ref_mut() } fn cursor(&self) -> Cursor { @@ -1098,7 +1101,9 @@ impl<'a, 'b> Edit for ViEditor<'a, 'b> { } } -impl<'a, 'b, 'c> BorrowedWithFontSystem<'c, ViEditor<'a, 'b>> { +impl<'font_system, 'syntax_system, 'buffer> + BorrowedWithFontSystem<'font_system, ViEditor<'syntax_system, 'buffer>> +{ /// Load text from a file, and also set syntax to the best option #[cfg(feature = "std")] pub fn load_text>(