A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/text.rs')
| -rw-r--r-- | src/text.rs | 117 |
1 files changed, 3 insertions, 114 deletions
diff --git a/src/text.rs b/src/text.rs index b5175fc..c469042 100644 --- a/src/text.rs +++ b/src/text.rs @@ -16,7 +16,7 @@ use helix_core::Syntax; use helix_core::syntax::{HighlightEvent, Loader}; use implicit_fn::implicit_fn; use lsp_types::{ - DocumentSymbol, Location, Position, SemanticTokensLegend, + DocumentSymbol, Location, SemanticTokensLegend, SnippetTextEdit, TextEdit, }; pub use manipulations::Manip; @@ -40,6 +40,8 @@ pub use bookmark::*; mod manipulations; mod mapper; pub use mapper::*; +mod rope_ext; +pub use rope_ext::RopeExt; use crate::sni::{Snippet, StopP}; use crate::text::hist::Action; @@ -140,119 +142,6 @@ impl Deref for TextArea { } } -pub trait RopeExt { - fn position(&self, r: Range<usize>) -> Option<[(usize, usize); 2]>; - /// number of lines - fn l(&self) -> usize; - - // input: char, output: utf8 - fn x_bytes(&self, c: usize) -> Option<usize>; - fn y(&self, c: usize) -> Option<usize>; - fn x(&self, c: usize) -> Option<usize>; - fn xy(&self, c: usize) -> Option<(usize, usize)>; - - fn beginning_of_line(&self, c: usize) -> Option<usize>; - - fn indentation_of(&self, n: usize) -> usize; - - /// or eof - fn eol(&self, li: usize) -> usize; - - fn l_pos_to_char(&self, p: Position) -> Option<(usize, usize)>; - fn l_position(&self, p: Position) -> Option<usize>; - fn to_l_position(&self, l: usize) -> Option<lsp_types::Position>; - fn l_range(&self, r: lsp_types::Range) -> Option<Range<usize>>; - fn to_l_range(&self, r: Range<usize>) -> Option<lsp_types::Range>; -} -impl RopeExt for Rope { - fn position( - &self, - Range { start, end }: Range<usize>, - ) -> Option<[(usize, usize); 2]> { - let y1 = self.try_char_to_line(start).ok()?; - let y2 = self.try_char_to_line(end).ok()?; - let x1 = start - self.try_line_to_char(y1).ok()?; - let x2 = end - self.try_line_to_char(y2).ok()?; - [(x1, y1), (x2, y2)].into() - } - /// number of lines - fn l(&self) -> usize { - self.len_lines() - } - - // input: char, output: utf8 - fn x_bytes(&self, c: usize) -> Option<usize> { - let y = self.try_char_to_line(c).ok()?; - let x = self - .try_char_to_byte(c) - .ok()? - .checked_sub(self.try_line_to_byte(y).ok()?)?; - Some(x) - } - fn y(&self, c: usize) -> Option<usize> { - self.try_char_to_line(c).ok() - } - - fn xy(&self, c: usize) -> Option<(usize, usize)> { - let y = self.try_char_to_line(c).ok()?; - let x = c.checked_sub(self.try_line_to_char(y).ok()?)?; - Some((x, y)) - } - - fn x(&self, c: usize) -> Option<usize> { - self.xy(c).map(|x| x.0) - } - fn beginning_of_line(&self, c: usize) -> Option<usize> { - self.y(c).and_then(|x| self.try_line_to_char(x).ok()) - } - #[implicit_fn] - fn indentation_of(&self, n: usize) -> usize { - let Some(l) = self.get_line(n) else { return 0 }; - l.chars().filter(*_ != '\n').take_while(_.is_whitespace()).count() - } - - /// or eof - #[lower::apply(saturating)] - fn eol(&self, li: usize) -> usize { - self.try_line_to_char(li) - .map(|l| { - l + self - .get_line(li) - .map(|x| x.len_chars() - 1) - .unwrap_or_default() - }) - .unwrap_or(usize::MAX) - .min(self.len_chars()) - } - fn l_pos_to_char(&self, p: Position) -> Option<(usize, usize)> { - self.l_position(p).and_then(|x| self.xy(x)) - } - - fn l_position(&self, p: Position) -> Option<usize> { - self.try_byte_to_char( - self.try_line_to_byte(p.line as _).ok()? - + (p.character as usize) - .min(self.get_line(p.line as _)?.len_bytes()), - ) - .ok() - } - fn to_l_position(&self, l: usize) -> Option<lsp_types::Position> { - Some(Position { - line: self.y(l)? as _, - character: self.x_bytes(l)? as _, - }) - } - fn l_range(&self, r: lsp_types::Range) -> Option<Range<usize>> { - Some(self.l_position(r.start)?..self.l_position(r.end)?) - } - fn to_l_range(&self, r: Range<usize>) -> Option<lsp_types::Range> { - Some(lsp_types::Range { - start: self.to_l_position(r.start)?, - end: self.to_l_position(r.end)?, - }) - } -} - impl TextArea { pub fn visual_position( &self, |