A simple CPU rendered GUI IDE experience.
scrollin
| -rw-r--r-- | src/edi.rs | 45 | ||||
| -rw-r--r-- | src/edi/input_handlers/cursor.rs | 36 | ||||
| -rw-r--r-- | src/edi/lsp_impl.rs | 4 | ||||
| -rw-r--r-- | src/hov.rs | 1 | ||||
| -rw-r--r-- | src/lsp.rs | 1 | ||||
| -rw-r--r-- | src/lsp/communication.rs | 11 | ||||
| -rw-r--r-- | src/lsp/rq.rs | 6 | ||||
| -rw-r--r-- | src/main.rs | 48 | ||||
| -rw-r--r-- | src/rnd.rs | 83 |
9 files changed, 134 insertions, 101 deletions
@@ -31,7 +31,7 @@ use crate::bar::Bar; use crate::commands::Cmds; use crate::error::WDebug; use crate::gotolist::{At, GoTo}; -use crate::hov::{self, Hovr, Hovring, Rendered}; +use crate::hov::{self, HOV_HEIGHT, Hovr, Hovring, Rendered}; use crate::lsp::{ Anonymize, Client, Map_, PathURI, RequestError, Rq, tdpp, vsc_settings, }; @@ -390,17 +390,38 @@ impl Editor { } pub fn scroll(&mut self, rows: f32) { let rows = if alt() { rows * 8. } else { rows * 3. }; - let (vo, max) = lower::saturating::math! { if let State::Hovering(Rq {result: Some(Hovring { - rndr: Some(Rendered {scroll, .. }),.. - }), ..}) = &mut self.state && shift() { - // let n = x.item.l(); - // (&mut x.item.vo, n - 15) - todo!() - } else if let Some((_, ref mut vo, Some(max))) = self.requests.sig_help.result && shift(){ - (vo, max - 15) - } else { - let n =self. text.l() - 1; (&mut self.text.vo, n) - }}; + if let State::Hovering(Rq { + result: + Some(Hovring { + rndr: Some(Rendered { scroll: vo, image, .. }), + .. + }), + .. + }) = &mut self.state + && shift() + { + let max = image.height().saturating_sub(HOV_HEIGHT as _); + let rows = rows * 21.; + if rows < 0.0 { + let rows = rows.ceil().abs() as u32; + *vo = (*vo + rows).min(max); + } else { + let rows = rows.floor() as u32; + *vo = vo.saturating_sub(rows); + } + return; + }; + let (vo, max) = lower::saturating::math! { + if let Some((_, ref mut vo, Some(max))) = + self.requests.sig_help.result + && shift() + { + (vo, max - 15) + } else { + let n = self.text.l() - 1; + (&mut self.text.vo, n) + } + }; if rows < 0.0 { let rows = rows.ceil().abs() as usize; *vo = (*vo + rows).min(max); diff --git a/src/edi/input_handlers/cursor.rs b/src/edi/input_handlers/cursor.rs index 05b6f95..f61fdfc 100644 --- a/src/edi/input_handlers/cursor.rs +++ b/src/edi/input_handlers/cursor.rs @@ -16,6 +16,7 @@ enum Set<T> { } use crate::edi::*; use crate::hov::{DiagnosticHovr, Hoverable, Hovring}; +use crate::lsp::BehaviourAfter; use crate::rnd::CellBuffer; impl Editor { #[implicit_fn] @@ -118,7 +119,7 @@ impl Editor { pub fn find_diags( &mut self, cursor_position: (usize, usize), - w: Arc<dyn Window>, + w: &Arc<dyn Window>, ) -> Option<Vec<Hoverable>> { lsp!(let lsp, p = self else None); @@ -160,7 +161,7 @@ impl Editor { ] }; // println!("{x:?}"); - DiagnosticHovr::new(span, x, &w, r) + DiagnosticHovr::new(span, x, w, r) }) .map(Hoverable::Diagnostic) .collect::<Vec<_>>() @@ -261,20 +262,25 @@ impl Editor { // return; // } // if !running.insert(hover) {return} - let (rx, _) = lsp - .request::<HoverRequest>(&HoverParams { - text_document_position_params: tdpp.clone(), - work_done_progress_params: default(), - }) - .unwrap(); + // let (rx, _) =; // println!("rq hov of {hover:?} (cur {})", requests.hovering.request.is_some()); let tdp = tdpp.clone(); + let window = w.clone(); let handle: tokio::task::JoinHandle<Result<Option<Hovr>, _>> = lsp.runtime.spawn(async move { - let Some(x) = rx.await? else { + let Some(x) = lsp + .request_::<HoverRequest, { BehaviourAfter::Nil }>( + &HoverParams { + text_document_position_params: tdp.clone(), + work_done_progress_params: default(), + }, + )? + .0 + .await? + else { return Ok(None::<Hovr>); }; - let (w, cells) = spawn_blocking(move || { + let (width, cells) = spawn_blocking(move || { let x = match &x.contents { lsp_types::HoverContents::Scalar( marked_string, @@ -327,22 +333,20 @@ impl Editor { ] }) }); + let cells = cells.into(); + window.request_redraw(); Ok(Some( hov::Hovr { span, tdpp: tdp, - item: CellBuffer { - c: w, - vo: 0, - cells: cells.into(), - }, + item: CellBuffer { c: width, vo: 0, cells: cells }, range: x.range, // range: x.range.and_then(|x| text.l_range(x)), } .into(), )) }); - let diags = self.find_diags(cursor_position, w); + let diags = self.find_diags(cursor_position, &w); self.state .consume(Action::SetHovering( diags.map(|of| Hovring { of, ..default() }), diff --git a/src/edi/lsp_impl.rs b/src/edi/lsp_impl.rs index 068667d..d0e506e 100644 --- a/src/edi/lsp_impl.rs +++ b/src/edi/lsp_impl.rs @@ -164,7 +164,9 @@ impl crate::edi::Editor { ..default() }, }) - }) && x.result.is_none() + }) && super::lsp!(self).unwrap().redraw_now().unwrap() // im not a fan of this, but its kinda. necessary. annoyingly. + == () + && x.result.is_none() { self.state = State::Default; } @@ -479,3 +479,4 @@ pub struct Rendered { impl Hovring { pub fn rndr() {} } +pub const HOV_HEIGHT: usize = 500; @@ -84,6 +84,7 @@ pub fn run( } #[derive(Copy, Clone, PartialEq, Eq, std::marker::ConstParamTy, Debug)] pub enum BehaviourAfter { + RedrawNow, Redraw, // Poll, ? how impl. Nil, diff --git a/src/lsp/communication.rs b/src/lsp/communication.rs index 8899f0f..0013ad1 100644 --- a/src/lsp/communication.rs +++ b/src/lsp/communication.rs @@ -35,6 +35,7 @@ pub fn handler( loop { crossbeam::select! { recv(req_rx) -> x => match x { + Ok((.., BehaviourAfter::RedrawNow)) => w.request_redraw(), Ok((x, y, and)) => { debug!("received request {x}"); assert!(map.insert(x, (y, Instant::now(), and)).is_none()); @@ -162,7 +163,7 @@ impl super::Client { self.request_::<X, { Redraw }>(y) } #[must_use] - pub(super) fn request_<'me, X: Request, const THEN: BehaviourAfter>( + pub fn request_<'me, X: Request, const THEN: BehaviourAfter>( &'me self, y: &X::Params, ) -> Result< @@ -224,4 +225,12 @@ impl super::Client { id, )) } + + pub fn redraw_now<'me>( + &'me self, + ) -> Result<(), SendError<(i32, oneshot::Sender<Re>, BehaviourAfter)>> + { + let (tx, _) = oneshot::channel(); + self.send_to.send((0, tx, BehaviourAfter::RedrawNow)) + } } diff --git a/src/lsp/rq.rs b/src/lsp/rq.rs index b9b2c7b..0a145d6 100644 --- a/src/lsp/rq.rs +++ b/src/lsp/rq.rs @@ -125,7 +125,7 @@ impl<T, R, D, E> Rq<T, R, D, E> { self.request = Some((AbortOnDropHandle::new(f), d)); } } -impl<T, R, D, E> Rq<T, R, D, E> { +impl<T, R, D, E: std::fmt::Debug> Rq<T, R, D, E> { pub fn running(&self) -> bool { matches!( self, @@ -143,7 +143,9 @@ impl<T, R, D, E> Rq<T, R, D, E> { let (_, d) = self.request.take().unwrap(); self.result = f( match x { - Ok(x) => x, + Ok(x) => x.inspect_err(|x| { + dbg!(&x); + }), Err(e) => { log::error!( "unexpected join error from request poll: {e}" diff --git a/src/main.rs b/src/main.rs index b80cea4..e199e2e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ #![feature( + exact_div, yeet_expr, const_array, const_closures, @@ -16,7 +17,7 @@ try_blocks_heterogeneous, current_thread_id, vec_try_remove, - lazy_type_alias, + // lazy_type_alias, thread_local, iter_intersperse, stmt_expr_attributes, @@ -112,7 +113,6 @@ extern "C" fn sigint(_: i32) { std::process::exit(12); } -#[implicit_fn::implicit_fn] pub(crate) fn entry(event_loop: EventLoop) { unsafe { __ED.write(match Editor::new() { @@ -139,7 +139,7 @@ pub(crate) fn entry(event_loop: EventLoop) { let mut cursor_position = (0, 0); let mut i = Image::build(1, 1).fill(BG); - let mut cells = vec![]; + let mut cells = vec![]; let mut w = match &mut ed.lsp { Some((.., c)) => c.take(), None => None, @@ -255,6 +255,7 @@ pub(crate) fn entry(event_loop: EventLoop) { window.request_redraw(); } WindowEvent::RedrawRequested if window_id == window.id() => { + println!("running redraw"); rnd::render( ed, &mut cells, @@ -285,13 +286,10 @@ pub(crate) fn entry(event_loop: EventLoop) { ); ed.cursor_moved(cursor_position, window.clone(), c); } - - WindowEvent::PointerButton { - state: bt, - button: ButtonSource::Mouse(button), - .. - - + WindowEvent::PointerButton { + state: bt, + button: ButtonSource::Mouse(button), + .. } if bt.is_pressed() => { if button == MouseButton::Left { unsafe { CLICKING = true }; @@ -299,19 +297,15 @@ pub(crate) fn entry(event_loop: EventLoop) { ed.click(button, cursor_position, window.clone()); window.request_redraw(); } - - WindowEvent::PointerButton { - button: ButtonSource::Mouse(MouseButton::Left), - .. - } - - => unsafe { CLICKING = false }, - - WindowEvent::MouseWheel { - device_id: _, - delta: MouseScrollDelta::LineDelta(_, rows), - phase: _, - } => { + WindowEvent::PointerButton { + button: ButtonSource::Mouse(MouseButton::Left), + .. + } => unsafe { CLICKING = false }, + WindowEvent::MouseWheel { + device_id: _, + delta: MouseScrollDelta::LineDelta(_, rows), + phase: _, + } => { ed.scroll(rows); window.request_redraw(); } @@ -320,10 +314,10 @@ pub(crate) fn entry(event_loop: EventLoop) { window.request_redraw(); } WindowEvent::KeyboardInput { - event, - is_synthetic: false, - .. - } if event.state == ElementState::Pressed => { + event, + is_synthetic: false, + .. + } if event.state == ElementState::Pressed => { // if event.logical_key == Key::Named(NamedKey::F12) { // lsp.unwrap().runtime.spawn(async move { // lsp.unwrap().symbols().await; @@ -19,7 +19,9 @@ use winit::window::{ImeRequestData, Window}; use crate::edi::st::State; use crate::edi::{Editor, lsp}; use crate::gotolist::{At, GoTo}; -use crate::hov::{DiagnosticHovr, Hoverable, Hovr, Hovring, Rendered}; +use crate::hov::{ + DiagnosticHovr, HOV_HEIGHT, Hoverable, Hovr, Hovring, Rendered, +}; use crate::lsp::Rq; use crate::sym::UsedSI; use crate::text::{CoerceOption, RopeExt, TextArea, col, color_}; @@ -452,51 +454,48 @@ pub fn render( // i: Image<&mut [u8], 3>, // c: &[Cell], // columns: usize, - ls_: f32, ox: f32, oy: f32, toy: f32, add1_below: bool| { let met = super::FONT.metrics(&[]); let fac = ppem / met.units_per_em as f32; - let position = ( + let (px, py) = ( (((_x) as f32 * fw).round() + ox) as usize, (((_y) as f32 * (fh + ls * fac)).round() + oy) as usize, ); - let ls = ls_; // let mut r = c.len() / columns; // assert_eq!(c.len() % columns, 0); // std::fs::write("cells", Cell::store(c)); if w >= size.width as usize - || (position - .1 - .checked_add(h) - .is_none_or(|x| x >= size.height as usize) - && !position.1.checked_sub(h).is_some()) - || position.1 >= size.height as usize - || position.0 >= size.width as usize + // if y + height > height, cant fit it anywhere + || ((py.checked_add(h) + .is_none_or(|x| x >= size.height as usize)) + && !py.checked_sub(h).is_some()) + || py >= size.height as usize + || px >= size.width as usize { - return Err(()); + return Err(((px, py), size, (w, h))); } assert!( w < window.surface_size().width as _ && h < window.surface_size().height as _ ); - let is_above = position.1.checked_sub(h).is_some(); - let top = position.1.checked_sub(h).unwrap_or( + let is_above = py.checked_sub(h).is_some(); + let top = py.checked_sub(h).unwrap_or( ((((_y + add1_below as usize) as f32) * (fh + ls * fac)) .round() + toy) as usize, ); - let left = if position.0 + w as usize + let left = if px + w as usize > window.surface_size().width as usize { window.surface_size().width as usize - w as usize } else { - position.0 + px }; // let (w, h) = @@ -525,19 +524,12 @@ pub fn render( let ppem = ppem_; let ls = ls_; - assert_eq!(c.len() % columns, 0); + let r = c.len().div_exact(columns).unwrap(); let (w, h) = dsb::size(&fonts.regular, ppem, ls, (columns, r)); - let (is_above, left, top) = position( - (_x, _y), - (w, h), - ls_, - ox, - oy, - toy, - add1_below, - )?; + let (is_above, left, top) = + position((_x, _y), (w, h), ox, oy, toy, add1_below)?; // std::fs::write("cells", Cell::store(c)); // if w >= size.width as usize @@ -607,7 +599,9 @@ pub fn render( (left as _, top as _), ) }; - Ok::<_, ()>((is_above, left, top, w, h)) + Ok::<_, ((usize, usize), PhysicalSize<u32>, (usize, usize))>( + (is_above, left, top, w, h), + ) }; // dbg!(&ed.requests.document_symbols); @@ -732,9 +726,10 @@ pub fn render( // && pass { let hof = hash(&of); - let buffer = match rndr { - Some(Rendered { hash, image, .. }) if *hash == hof => - image, + let rh = th.min(HOV_HEIGHT); + let (buffer, scr) = match rndr { + Some(Rendered { hash, image, scroll }) if *hash == hof => + (image, *scroll), _ => { let mut buffer = Image::<_, 3>::build(tw as _, th as _).alloc(); @@ -786,7 +781,8 @@ pub fn render( hash: hof, scroll: 0, }); - &mut rndr.as_mut().unwrap().image + let r = rndr.as_mut().unwrap(); + (&mut r.image, r.scroll) } }; @@ -806,21 +802,23 @@ pub fn render( && let Some(_x) = _x.checked_sub(text.ho) && (cursor_position.1 == _y && (_x..=_x2).contains(&cursor_position.0)) - && let Ok((_, x, y)) = position( - (_x, _y), - (tw, th), - -200.0, - 0.0, - 0.0, - 0.0, - true, - ) + && let Ok((_, x, y)) = + position((_x, _y), (tw, rh), 0.0, 0.0, 0.0, true) { - unsafe { i.overlay_at(&buffer.as_ref(), x as _, y as _) }; + let top = scr * tw as u32 * 3; + let o = &buffer.bytes()[top as usize + ..(top + (rh as u32 * tw as u32 * 3)) as usize]; + unsafe { + i.overlay_at( + &Image::<_, 3>::build(tw as _, rh as _).buf(o), + x as _, + y as _, + ) + }; i.r#box( (x.saturating_sub(1) as _, y.saturating_sub(1) as _), tw as _, - th as _, + rh as _, BORDER, ); } @@ -1055,6 +1053,7 @@ pub fn render( true, fonts, ) else { + println!("RAHHH"); break 'out; }; i.r#box( |