A simple CPU rendered GUI IDE experience.
move a few things around
| -rw-r--r-- | src/edi.rs | 2 | ||||
| -rw-r--r-- | src/edi/input_handlers/cursor.rs | 3 | ||||
| -rw-r--r-- | src/hov.rs | 2 | ||||
| -rw-r--r-- | src/main.rs | 4 | ||||
| -rw-r--r-- | src/rnd.rs | 3 | ||||
| -rw-r--r-- | src/rnd/cell_buffer.rs | 35 | ||||
| -rw-r--r-- | src/sig.rs | 3 | ||||
| -rw-r--r-- | src/text.rs | 255 | ||||
| -rw-r--r-- | src/text/cursor.rs | 15 | ||||
| -rw-r--r-- | src/text/mapper.rs | 224 |
10 files changed, 285 insertions, 261 deletions
@@ -39,7 +39,7 @@ use crate::meta::META; use crate::sym::{Symbols, SymbolsList, SymbolsType}; use crate::text::cursor::{Ronge, ceach}; use crate::text::hist::{ClickHistory, Hist}; -use crate::text::{self, Mapping, RopeExt, SortTedits, TextArea}; +use crate::text::{Mapping, RopeExt, SortTedits, TextArea}; use crate::{ BoolRequest, CDo, CompletionAction, CompletionState, alt, ctrl, filter, hash, shift, sym, trm, diff --git a/src/edi/input_handlers/cursor.rs b/src/edi/input_handlers/cursor.rs index bb283af..4aeaf02 100644 --- a/src/edi/input_handlers/cursor.rs +++ b/src/edi/input_handlers/cursor.rs @@ -11,6 +11,7 @@ use tokio_util::task::AbortOnDropHandle as DropH; use winit::window::Window; use crate::edi::*; +use crate::rnd::CellBuffer; impl Editor { #[implicit_fn] pub fn cursor_moved( @@ -223,7 +224,7 @@ impl Editor { Ok(Some( hov::Hovr { span, - item: text::CellBuffer { + item: CellBuffer { c: w, vo: 0, cells: cells.into(), @@ -305,7 +305,7 @@ fn t() { #[derive(Debug, Serialize, Deserialize)] pub struct Hovr { pub(crate) span: Option<[(VisualX, usize); 2]>, - pub(crate) item: crate::text::CellBuffer, + pub(crate) item: crate::rnd::CellBuffer, #[serde(skip)] pub(crate) range: Option<lsp_types::Range>, } diff --git a/src/main.rs b/src/main.rs index 6c92fe4..92dc5ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -235,9 +235,7 @@ pub(crate) fn entry(event_loop: EventLoop) { // let ev = format!("{event:?}"); // use WindowEvent as Event; match event { - // Event::AboutToWait => {} - - + // Event::AboutToWait => {} WindowEvent::SurfaceResized(size) if window_id == window.id() => { let Some(surface) = surface else { eprintln!( @@ -26,6 +26,9 @@ use crate::{ BG, BORDER, CompletionAction, CompletionState, FG, FONT, complete, filter, lsp, sig, }; +pub use cell_buffer::CellBuffer; +mod cell_buffer; + #[implicit_fn::implicit_fn] pub fn render( diff --git a/src/rnd/cell_buffer.rs b/src/rnd/cell_buffer.rs new file mode 100644 index 0000000..2ac7e62 --- /dev/null +++ b/src/rnd/cell_buffer.rs @@ -0,0 +1,35 @@ +use std::ops::Deref; + +use dsb::Cell; + +#[derive(serde::Serialize, serde::Deserialize)] +pub struct CellBuffer { + pub c: usize, + pub vo: usize, + pub cells: Box<[Cell]>, +} +impl std::fmt::Debug for CellBuffer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CellBuffer") + .field("c", &self.c) + .field("vo", &self.vo) + .field("cells", &self.cells.len()) + .finish() + } +} +impl Deref for CellBuffer { + type Target = [Cell]; + + fn deref(&self) -> &Self::Target { + &self.cells + } +} + +impl CellBuffer { + pub fn displayable(&self, r: usize) -> &[Cell] { + &self[self.vo * self.c..((self.vo + r) * self.c).min(self.len())] + } + pub fn l(&self) -> usize { + self.len() / self.c + } +} @@ -8,7 +8,8 @@ use lsp_types::{ }; use crate::FG; -use crate::text::{CellBuffer, color_}; +use crate::rnd::CellBuffer; +use crate::text::color_; pub fn active( sig: &SignatureHelp, ) -> (&SignatureInformation, Option<&ParameterInformation>) { diff --git a/src/text.rs b/src/text.rs index e481d4f..8f644e0 100644 --- a/src/text.rs +++ b/src/text.rs @@ -38,6 +38,8 @@ use hist::Changes; mod bookmark; pub use bookmark::*; mod manipulations; +mod mapper; +pub use mapper::*; use crate::sni::{Snippet, StopP}; use crate::text::hist::Action; @@ -117,38 +119,6 @@ pub struct TextArea { pub changes: Changes, } -#[derive(Serialize, Deserialize)] -pub struct CellBuffer { - pub c: usize, - pub vo: usize, - pub cells: Box<[Cell]>, -} -impl Debug for CellBuffer { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("CellBuffer") - .field("c", &self.c) - .field("vo", &self.vo) - .field("cells", &self.cells.len()) - .finish() - } -} -impl Deref for CellBuffer { - type Target = [Cell]; - - fn deref(&self) -> &Self::Target { - &self.cells - } -} - -impl CellBuffer { - pub fn displayable(&self, r: usize) -> &[Cell] { - &self[self.vo * self.c..((self.vo + r) * self.c).min(self.len())] - } - pub fn l(&self) -> usize { - self.len() / self.c - } -} - impl Debug for TextArea { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("TextArea") @@ -1406,227 +1376,6 @@ pub fn hl( // }) } -#[derive(Copy, Clone)] -/// this struct is made to mimic a simple 2d vec -/// over the entire text area -/// without requiring that entire allocation, and the subsequent copy into the output area. -/// ```text -/// text above view offset (global text area)² -/// ╶╶╶╶╶├╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶ view offset -/// ┏━━━━┿━━━━━━━━━━━━┓← into_ and into_s³ -/// ┃ ╏← offset y ┃ -/// ┃ ┏╺╺┿╺╺╺╺╺╺╺╺╺╺╺╺┃ -/// ┃ ╏ v╎iewable area┃ -/// ┃ ╏ g╎oes here¹ ┃ -/// ┃ ╏ ╎ ┃ -/// ┃ ╏ ╎ ┃ -/// ┃ ╏ ╎ ┃ -/// ┗━━━━━━━━━━━━━━━━━┛ -/// ═ ══╎ -/// ↑ ↑ ╎ -/// │ ╰ horiz scroll -/// ╰ horizontal offset -/// ``` -#[allow(dead_code)] // ? -pub struct Mapper { - /// c, r - pub into_s: (usize, usize), - pub ox: usize, - pub oy: usize, - - pub from_c: usize, - pub from_r: usize, - pub vo: usize, - pub ho: usize, -} -pub struct Output<'a> { - pub into: &'a mut [Cell], - pub output: Mapper, -} -impl Deref for Output<'_> { - type Target = Mapper; - - fn deref(&self) -> &Self::Target { - &self.output - } -} - -impl Mapper { - /// translate an index into the global text buffer² into an (x, y), of the global text buffer - // fn to_point(&self, rope: &Rope, index: usize) -> (usize, usize) { - // ((index % self.from_c), (index / self.from_c)) - // } - - // fn from_point(&self, (x, y): (usize, usize)) -> usize { - // y * self.from_c + x - // } - - /// translate an (x, y) into the global text buffer² - /// to a point over the viewable area¹ (offset by the given offsets) of the global text buffer, - /// returning none if the given point is outside of the viewable area - fn translate(&self, (x, y): (usize, usize)) -> Option<(usize, usize)> { - let (x, y) = ( - x.checked_sub(self.ho)? + self.ox, - y.checked_sub(self.vo)? + self.oy, - ); - ((x < self.into_s.0) & (y < self.into_s.1) - & (x >= self.ox) // this is kind of forced already but its ok - & (y >= self.oy)) // " - .then_some((x, y)) - } - /// converts an (x, y) of the viewable area¹ to an index into [`Output::into`] - fn from_point_global(&self, (x, y): (usize, usize)) -> usize { - y * self.into_s.0 + x - } - // /// translate an index into a (x, y), of the output³ - // fn to_point_global(&self, index: usize) -> (usize, usize) { - // (index % self.into_s.0, index / self.into_s.0) - // } - // fn etalsnart_( - // &self, - // (x, y): (usize, usize), - // ) -> Option<(usize, usize)> { - // Some(( - // x.checked_sub(self.ox)? + self.ho, // - // y.checked_sub(self.oy)? + self.vo, - // )) - // } -} -impl<'a> Output<'a> { - // /// get an index thats relative over the viewable area¹ of the global text area - // fn get_at_compensated( - // &mut self, - // (x, y): (usize, usize), - // ) -> Option<&mut Cell> { - // Some(&mut self.into[(y + self.oy) * self.into_s.0 + (x + self.ox)]) - // } - pub fn get_range( - &mut self, - a: (usize, usize), - b: (usize, usize), - ) -> impl Iterator<Item = &mut Cell> { - self.get_range_enumerated(a, b).map(|x| x.0) - } - // needs rope to work properly (see [xy]) - // pub fn get_char_range( - // &mut self, - // a: usize, - // b: usize, - // ) -> impl Iterator<Item = &mut Cell> { - // self.get_range_enumerated(self.to_point(a), self.to_point(b)) - // .map(|x| x.0) - // } - //// coords reference global text buffer² - pub gen fn get_range_enumerated( - &mut self, - (x1, y1): (usize, usize), - (x2, y2): (usize, usize), - // impl Iterator<Item = (&mut Cell, (usize, usize))> { - ) -> (&mut Cell, (usize, usize)) { - let m = self.output; - let c = self.into.as_mut_ptr(); - // x1 = x1.checked_sub(m.ho).unwrap_or(m.ho); - // x2 = x2.checked_sub(m.ho).unwrap_or(m.ho); - // y1 = y1.checked_sub(m.vo).unwrap_or(m.vo); - // y2 = y2.checked_sub(m.vo).unwrap_or(m.vo); - // let a = m.from_point((x1, y1)); - // let b = m.from_point((x2, y2)); - // let a = m.from_point_global(m.translate(m.to_point(a)).unwrap()); - // let b = m.from_point_global(m.translate(m.to_point(b)).unwrap()); - // dbg!(a, b); - let mut p = (x1, y1); - while p != (x2, y2) { - if let Some(x) = m.translate(p) { - // SAFETY: trust me very disjoint - yield (unsafe { &mut *c.add(m.from_point_global(x)) }, p) - } - p.0 += 1; - if p.0.checked_sub(m.ho) == Some(m.from_c) { - p.0 = 0; - p.1 += 1; - if p.1 > y2 { - break; - } - } - if let Some(x) = p.0.checked_sub(m.ho) - && x > m.from_c - { - break; - } - } - - // (a..=b) - // .filter_map(move |x| { - // // println!("{:?} {x}", m.translate(m.to_point(x))); - // let (x, y) = m.to_point(x); - // m.translate((x, y)) - // // m.to_point_global(x) - // }) - // .inspect(move |x| { - // assert!(x.0 < self.into_s.0 && x.1 < self.into_s.1); - // assert!(m.from_point_global(*x) < self.into.len()); - // }) - // .map(move |x| { - // // SAFETY: :) - // (unsafe { &mut *p.add(m.from_point_global(x)) }, x) - // }) - // self.get_char_range_enumerated( - // self.output.from_point(a), - // self.output.from_point(b), - // ) - } - - // oughtnt really be multiline - pub fn get_simple( - &mut self, - s: (usize, usize), - e: (usize, usize), - ) -> Option<&mut [Cell]> { - let s = self.from_point_global(self.translate(s)?); - let e = self.from_point_global(self.translate(e)?); - self.into.get_mut(s..e) - } - // impl<'a> IndexMut<(usize, usize)> for Output<'a> { - // fn index_mut(&mut self, p: (usize, usize)) -> &mut Self::Output { - // let x = self.from_point_global(self.translate(p).unwrap()); - // &mut self.into[x] - // } - // } - pub fn get(&mut self, p: (usize, usize)) -> Option<&mut Cell> { - let n = self.from_point_global(self.translate(p)?); - self.into.get_mut(n) - } -} - -// impl<'a> Index<usize> for Output<'a> { -// type Output = Cell; - -// fn index(&self, index: usize) -> &Self::Output { -// &self[self.translate(index).unwrap()] -// } -// } - -// impl<'a> IndexMut<usize> for Output<'a> { -// fn index_mut(&mut self, index: usize) -> &mut Self::Output { -// let x = self.translate(index).unwrap(); -// &mut self[x] -// } -// } - -// impl<'a> Index<(usize, usize)> for Output<'a> { -// type Output = Cell; - -// fn index(&self, p: (usize, usize)) -> &Self::Output { -// &self.into[self.from_point_global(self.translate(p).unwrap())] -// } -// } -// impl<'a> IndexMut<(usize, usize)> for Output<'a> { -// fn index_mut(&mut self, p: (usize, usize)) -> &mut Self::Output { -// let x = self.from_point_global(self.translate(p).unwrap()); -// &mut self.into[x] -// } -// } - pub trait CoerceOption<T> { fn coerce(self) -> impl Iterator<Item = T>; } diff --git a/src/text/cursor.rs b/src/text/cursor.rs index f8e4cc9..ed86ec9 100644 --- a/src/text/cursor.rs +++ b/src/text/cursor.rs @@ -113,7 +113,19 @@ pub macro ceach($cursor: expr, $f:expr $( => $q:tt)?) { // use unhygienic2::unhygienic; impl Cursor { pub fn new(c: usize, r: &Rope) -> Self { - Self { column: r.x(c).unwrap(), position: c, sel: None } + Self { + column: r.x(c).unwrap_or_else(|| { + log::error!("couldnt position column"); + 0 + }), + position: if c > r.len_chars() { + log::error!("couldnt add cursor at {c}"); + r.len_chars() - 5 + } else { + c + }, + sel: None, + } } fn cl(self, r: &Rope) -> RopeSlice<'_> { r.line(r.char_to_line(*self)) @@ -245,6 +257,7 @@ impl Cursor { self.set_ho(); } + #[lower::apply(saturating)] fn left(&mut self, r: &Rope) { self.position -= 1; self.setc(r); diff --git a/src/text/mapper.rs b/src/text/mapper.rs new file mode 100644 index 0000000..2d29286 --- /dev/null +++ b/src/text/mapper.rs @@ -0,0 +1,224 @@ +use std::ops::Deref; + +use dsb::Cell; + +#[derive(Copy, Clone)] +/// this struct is made to mimic a simple 2d vec +/// over the entire text area +/// without requiring that entire allocation, and the subsequent copy into the output area. +/// ```text +/// text above view offset (global text area)² +/// ╶╶╶╶╶├╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶ view offset +/// ┏━━━━┿━━━━━━━━━━━━┓← into_ and into_s³ +/// ┃ ╏← offset y ┃ +/// ┃ ┏╺╺┿╺╺╺╺╺╺╺╺╺╺╺╺┃ +/// ┃ ╏ v╎iewable area┃ +/// ┃ ╏ g╎oes here¹ ┃ +/// ┃ ╏ ╎ ┃ +/// ┃ ╏ ╎ ┃ +/// ┃ ╏ ╎ ┃ +/// ┗━━━━━━━━━━━━━━━━━┛ +/// ═ ══╎ +/// ↑ ↑ ╎ +/// │ ╰ horiz scroll +/// ╰ horizontal offset +/// ``` +#[allow(dead_code)] // ? +pub struct Mapper { + /// c, r + pub into_s: (usize, usize), + pub ox: usize, + pub oy: usize, + + pub from_c: usize, + pub from_r: usize, + pub vo: usize, + pub ho: usize, +} +pub struct Output<'a> { + pub into: &'a mut [Cell], + pub output: Mapper, +} +impl Deref for Output<'_> { + type Target = Mapper; + + fn deref(&self) -> &Self::Target { + &self.output + } +} + +impl Mapper { + /// translate an index into the global text buffer² into an (x, y), of the global text buffer + // fn to_point(&self, rope: &Rope, index: usize) -> (usize, usize) { + // ((index % self.from_c), (index / self.from_c)) + // } + + // fn from_point(&self, (x, y): (usize, usize)) -> usize { + // y * self.from_c + x + // } + + /// translate an (x, y) into the global text buffer² + /// to a point over the viewable area¹ (offset by the given offsets) of the global text buffer, + /// returning none if the given point is outside of the viewable area + fn translate(&self, (x, y): (usize, usize)) -> Option<(usize, usize)> { + let (x, y) = ( + x.checked_sub(self.ho)? + self.ox, + y.checked_sub(self.vo)? + self.oy, + ); + ((x < self.into_s.0) & (y < self.into_s.1) + & (x >= self.ox) // this is kind of forced already but its ok + & (y >= self.oy)) // " + .then_some((x, y)) + } + /// converts an (x, y) of the viewable area¹ to an index into [`Output::into`] + fn from_point_global(&self, (x, y): (usize, usize)) -> usize { + y * self.into_s.0 + x + } + // /// translate an index into a (x, y), of the output³ + // fn to_point_global(&self, index: usize) -> (usize, usize) { + // (index % self.into_s.0, index / self.into_s.0) + // } + // fn etalsnart_( + // &self, + // (x, y): (usize, usize), + // ) -> Option<(usize, usize)> { + // Some(( + // x.checked_sub(self.ox)? + self.ho, // + // y.checked_sub(self.oy)? + self.vo, + // )) + // } +} +impl<'a> Output<'a> { + // /// get an index thats relative over the viewable area¹ of the global text area + // fn get_at_compensated( + // &mut self, + // (x, y): (usize, usize), + // ) -> Option<&mut Cell> { + // Some(&mut self.into[(y + self.oy) * self.into_s.0 + (x + self.ox)]) + // } + pub fn get_range( + &mut self, + a: (usize, usize), + b: (usize, usize), + ) -> impl Iterator<Item = &mut Cell> { + self.get_range_enumerated(a, b).map(|x| x.0) + } + // needs rope to work properly (see [xy]) + // pub fn get_char_range( + // &mut self, + // a: usize, + // b: usize, + // ) -> impl Iterator<Item = &mut Cell> { + // self.get_range_enumerated(self.to_point(a), self.to_point(b)) + // .map(|x| x.0) + // } + //// coords reference global text buffer² + pub gen fn get_range_enumerated( + &mut self, + (x1, y1): (usize, usize), + (x2, y2): (usize, usize), + // impl Iterator<Item = (&mut Cell, (usize, usize))> { + ) -> (&mut Cell, (usize, usize)) { + let m = self.output; + let c = self.into.as_mut_ptr(); + // x1 = x1.checked_sub(m.ho).unwrap_or(m.ho); + // x2 = x2.checked_sub(m.ho).unwrap_or(m.ho); + // y1 = y1.checked_sub(m.vo).unwrap_or(m.vo); + // y2 = y2.checked_sub(m.vo).unwrap_or(m.vo); + // let a = m.from_point((x1, y1)); + // let b = m.from_point((x2, y2)); + // let a = m.from_point_global(m.translate(m.to_point(a)).unwrap()); + // let b = m.from_point_global(m.translate(m.to_point(b)).unwrap()); + // dbg!(a, b); + let mut p = (x1, y1); + while p != (x2, y2) { + if let Some(x) = m.translate(p) { + // SAFETY: trust me very disjoint + yield (unsafe { &mut *c.add(m.from_point_global(x)) }, p) + } + p.0 += 1; + if p.0.checked_sub(m.ho) == Some(m.from_c) { + p.0 = 0; + p.1 += 1; + if p.1 > y2 { + break; + } + } + if let Some(x) = p.0.checked_sub(m.ho) + && x > m.from_c + { + break; + } + } + + // (a..=b) + // .filter_map(move |x| { + // // println!("{:?} {x}", m.translate(m.to_point(x))); + // let (x, y) = m.to_point(x); + // m.translate((x, y)) + // // m.to_point_global(x) + // }) + // .inspect(move |x| { + // assert!(x.0 < self.into_s.0 && x.1 < self.into_s.1); + // assert!(m.from_point_global(*x) < self.into.len()); + // }) + // .map(move |x| { + // // SAFETY: :) + // (unsafe { &mut *p.add(m.from_point_global(x)) }, x) + // }) + // self.get_char_range_enumerated( + // self.output.from_point(a), + // self.output.from_point(b), + // ) + } + + // oughtnt really be multiline + pub fn get_simple( + &mut self, + s: (usize, usize), + e: (usize, usize), + ) -> Option<&mut [Cell]> { + let s = self.from_point_global(self.translate(s)?); + let e = self.from_point_global(self.translate(e)?); + self.into.get_mut(s..e) + } + // impl<'a> IndexMut<(usize, usize)> for Output<'a> { + // fn index_mut(&mut self, p: (usize, usize)) -> &mut Self::Output { + // let x = self.from_point_global(self.translate(p).unwrap()); + // &mut self.into[x] + // } + // } + pub fn get(&mut self, p: (usize, usize)) -> Option<&mut Cell> { + let n = self.from_point_global(self.translate(p)?); + self.into.get_mut(n) + } +} + +// impl<'a> Index<usize> for Output<'a> { +// type Output = Cell; + +// fn index(&self, index: usize) -> &Self::Output { +// &self[self.translate(index).unwrap()] +// } +// } + +// impl<'a> IndexMut<usize> for Output<'a> { +// fn index_mut(&mut self, index: usize) -> &mut Self::Output { +// let x = self.translate(index).unwrap(); +// &mut self[x] +// } +// } + +// impl<'a> Index<(usize, usize)> for Output<'a> { +// type Output = Cell; + +// fn index(&self, p: (usize, usize)) -> &Self::Output { +// &self.into[self.from_point_global(self.translate(p).unwrap())] +// } +// } +// impl<'a> IndexMut<(usize, usize)> for Output<'a> { +// fn index_mut(&mut self, p: (usize, usize)) -> &mut Self::Output { +// let x = self.from_point_global(self.translate(p).unwrap()); +// &mut self.into[x] +// } +// } |