A simple CPU rendered GUI IDE experience.
docu symbols
| -rw-r--r-- | src/edi.rs | 150 | ||||
| -rw-r--r-- | src/edi/st.rs | 9 | ||||
| -rw-r--r-- | src/lsp.rs | 64 | ||||
| -rw-r--r-- | src/main.rs | 4 | ||||
| -rw-r--r-- | src/rnd.rs | 12 | ||||
| -rw-r--r-- | src/sym.rs | 19 |
6 files changed, 188 insertions, 70 deletions
@@ -28,7 +28,10 @@ use st::*; use crate::bar::Bar; use crate::com::Complete; use crate::hov::{self, Hovr}; -use crate::lsp::{self, Client, PathURI, RedrawAfter, RequestError, Rq}; +use crate::lsp::{ + self, Anonymize, Client, Map_, PathURI, RedrawAfter, RequestError, Rq, +}; +use crate::sym::SymbolsType; use crate::text::{self, CoerceOption, Mapping, SortTedits, TextArea}; use crate::{ BoolRequest, CDo, ClickHistory, CompletionAction, CompletionState, @@ -394,33 +397,48 @@ impl Editor { x.poll( |x, (_, p)| { x.ok().map(|r| { - let tree = - self.tree.as_deref().unwrap().iter().map( - |x| SymbolInformation { - name: x - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_string(), - kind: SymbolKind::FILE, - location: Location { - range: lsp_types::Range { - end: default(), - start: default(), + if p.as_ref() + .is_none_or(|x| x.ty == SymbolsType::Workspace) + { + let tree = + self.tree.as_deref().unwrap().iter().map( + |x| SymbolInformation { + name: x + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(), + kind: SymbolKind::FILE, + location: Location { + range: lsp_types::Range { + end: default(), + start: default(), + }, + uri: Url::from_file_path(&x) + .unwrap(), }, - uri: Url::from_file_path(&x) - .unwrap(), + container_name: None, + deprecated: None, + tags: None, }, - container_name: None, - deprecated: None, - tags: None, - }, - ); - sym::Symbols { - tedit: p.map(|x| x.tedit).unwrap_or_default(), - r: tree.chain(r).collect(), - ..default() // dont care about previous selection + ); + sym::Symbols { + tedit: p + .map(|x| x.tedit) + .unwrap_or_default(), + r: tree.chain(r).collect(), + ..default() // dont care about previous selection + } + } else { + sym::Symbols { + tedit: p + .map(|x| x.tedit) + .unwrap_or_default(), + r, + ty: SymbolsType::Document, + ..default() + } } }) }, @@ -504,26 +522,23 @@ impl Editor { 'out: { let l = &mut self.requests.hovering.result; if let Some(Hovr { - span: Some([(_x, _y), (_x2, _)]), - .. + span: Some([(_x, _y), (_x2, _)]), .. }) = &*l + && let Some(_y) = _y.checked_sub(self.text.vo) + && let Some(_x) = _x.checked_sub(self.text.ho) + && let Some(_x2) = _x2.checked_sub(self.text.ho) + && cursor_position.1 == _y + && (_x..=_x2).contains( + &&(cursor_position.0 + - self.text.line_number_offset() + - 1), + ) { - let Some(_y) = _y.checked_sub(self.text.vo) else { - break 'out; - }; - if cursor_position.1 == _y - && (_x..=_x2).contains( - &&(cursor_position.0 - - self.text.line_number_offset() - - 1), - ) - { - break 'out; - } else { - // println!("span no longer below cursor; cancel hover {_x}..{_x2} {}", cursor_position.0 - text.line_number_offset() - 1); - *l = None; - w.request_redraw(); - } + break 'out; + } else { + // println!("span no longer below cursor; cancel hover {_x}..{_x2} {}", cursor_position.0 - text.line_number_offset() - 1); + *l = None; + w.request_redraw(); } let text = self.text.clone(); let mut rang = None; @@ -840,10 +855,31 @@ impl Editor { } Some(Do::Symbols) => if let Some(lsp) = lsp!(self) { - self.state = - State::Symbols(Rq::new(lsp.runtime.spawn( - window.redraw_after(lsp.symbols("".into())), - ))); + self.state = State::Symbols(Rq::new( + lsp.runtime.spawn(window.redraw_after( + lsp.symbols("".into()).map(|x| x.anonymize()), + )), + )); + }, + Some(Do::SwitchType) => + if let Some((lsp, p)) = lsp!(self + p) { + dbg!("switch type"); + let State::Symbols(Rq { result: Some(x), request }) = + &mut self.state + else { + unreachable!() + }; + x.ty = sym::SymbolsType::Document; + let p = p.to_owned(); + take(&mut x.r); + *request = Some(( + DropH::new(lsp.runtime.spawn( + window.redraw_after(async move { + lsp.document_symbols(&p).await.anonymize() + }), + )), + (), + )); }, Some(Do::SymbolsHandleKey) => { if let Some(lsp) = lsp!(self) { @@ -853,20 +889,26 @@ impl Editor { unreachable!() }; let ptedit = x.tedit.rope.clone(); - if handle2( + if (handle2( &event.logical_key, &mut x.tedit, lsp!(self + p), ) .is_some() - || ptedit != x.tedit.rope + || ptedit != x.tedit.rope) + && x.ty == SymbolsType::Workspace { *request = Some(( - DropH::new(lsp.runtime.spawn( - window.redraw_after( - lsp.symbols(x.tedit.rope.to_string()), + DropH::new( + lsp.runtime.spawn( + window.redraw_after( + lsp.symbols( + x.tedit.rope.to_string(), + ) + .map(|x| x.anonymize()), + ), ), - )), + ), (), )); // state = State::Symbols(Rq::new(lsp.runtime.spawn(lsp.symbols("".into())))); diff --git a/src/edi/st.rs b/src/edi/st.rs index d00d539..3d38806 100644 --- a/src/edi/st.rs +++ b/src/edi/st.rs @@ -7,8 +7,8 @@ use regex::Regex; use winit::event::MouseButton; use winit::keyboard::{Key, NamedKey, SmolStr}; -use crate::lsp::{RequestError, Rq, RqS}; -use crate::sym::Symbols; +use crate::lsp::{AQErr, RequestError, Rq, RqS}; +use crate::sym::{Symbols, SymbolsType}; use crate::text::TextArea; use crate::{ BoolRequest, CLICKING, InputRequest, act, ctrl, handle, shift, @@ -57,9 +57,10 @@ Symbols(Rq { result: Some(_x), request: None }) => { K(Key::Named(ArrowUp | Tab)) => _ [SymbolsSelectPrev], K(Key::Named(Enter)) => _ [SymbolsSelect], K(Key::Named(Escape)) => Default, - K(_) => _ [SymbolsHandleKey], }, -Symbols(Rq::<Symbols, Vec<SymbolInformation>, (), RequestError<lsp_request!("workspace/symbol")>> => _rq) => { +Symbols(Rq::<Symbols, Vec<SymbolInformation>, (), AQErr> => _rq) => { + K(Key::Character(x) if x == "d" && ctrl()) => _ [SwitchType], // crahs cond methinks + K(_) => _ [SymbolsHandleKey], K(Key::Named(Escape)) => Default, C(_) => _, M(_) => _, @@ -58,6 +58,27 @@ pub enum RequestError<X> { Failure(Re, #[serde(skip)] Option<Backtrace>), Cancelled(Re, DiagnosticServerCancellationData), } +pub type AQErr = RequestError<LSPError>; +impl Request for LSPError { + type Params = (); + type Result = (); + const METHOD: &'static str = "<unknown method>"; +} +#[derive(Debug)] +pub struct LSPError {} +pub trait Anonymize<T> { + fn anonymize(self) -> Result<T, RequestError<LSPError>>; +} +impl<T, E> Anonymize<T> for Result<T, RequestError<E>> { + fn anonymize(self) -> Result<T, RequestError<LSPError>> { + self.map_err(|e| match e { + RequestError::Rx(_) => RequestError::Rx(PhantomData), + RequestError::Failure(r, b) => RequestError::Failure(r, b), + RequestError::Cancelled(r, d) => RequestError::Cancelled(r, d), + }) + } +} + // impl<X> Debug for RequestError<X> {} impl<X> From<oneshot::error::RecvError> for RequestError<X> { fn from(_: oneshot::error::RecvError) -> Self { @@ -137,7 +158,10 @@ impl Client { ); Err(RequestError::Cancelled(x, e.expect("lsp??"))) } else { - Err(RequestError::Failure(x, Some(Backtrace::capture()))) + Err(RequestError::Failure( + x, + Some(Backtrace::capture()), + )) } } else { Ok(serde_json::from_value::<X::Result>( @@ -169,7 +193,7 @@ impl Client { }, }) } - pub fn close(&self, f:&Path) ->Result<(), SendError<Message>>{ + pub fn close(&self, f: &Path) -> Result<(), SendError<Message>> { self.notify::<DidCloseTextDocument>(&DidCloseTextDocumentParams { text_document: f.tid(), }) @@ -390,6 +414,38 @@ impl Client { .0 .map(|x| x.map(|x| x.unwrap_or_default())) } + pub fn document_symbols( + &'static self, + p: &Path, + ) -> impl Future< + Output = Result< + Vec<SymbolInformation>, + RequestError<lsp_request!("textDocument/documentSymbol")>, + >, + > { + self.request::<lsp_request!("textDocument/documentSymbol")>( + &DocumentSymbolParams { + text_document: p.tid(), + work_done_progress_params: default(), + partial_result_params: default(), + }, + ) + .unwrap() + .0 + .map(|x| { + x.map(|x| { + x.map(|x| { + // std::fs::write("syms", serde_json::to_string_pretty(&x).unwrap()); + match x { + DocumentSymbolResponse::Flat(x) => x, + DocumentSymbolResponse::Nested(_) => + unreachable!(), + } + }) + .unwrap_or_default() + }) + }) + } pub fn symbols( &'static self, f: String, @@ -1087,10 +1143,10 @@ impl<R: Request> std::fmt::Debug for RequestError<R> { } } -fn none<T>() ->Option<T> { +fn none<T>() -> Option<T> { None } -impl<T: Clone,R,D,E> Clone for Rq<T, R, D, E> { +impl<T: Clone, R, D, E> Clone for Rq<T, R, D, E> { fn clone(&self) -> Self { Self { result: self.result.clone(), request: None } } diff --git a/src/main.rs b/src/main.rs index 366fc43..3961eb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -567,8 +567,8 @@ rust_fsm::state_machine! { // when Complete(Rq{ result: Some(_x),request: _y }) => K(Key::Named(NamedKey::Tab) if shift()) => _ [SelectPrevious], Complete(Rq { result: Some(_x),request: _y }) => K(Key::Named(NamedKey::Tab)) => _ [SelectNext], - Complete(Rq { result: Some(_x),request: _y }) => K(Key::Named(NamedKey::ArrowDown)) => _ [SelectNext], - Complete(Rq { result: Some(_x),request: _y }) => K(Key::Named(NamedKey::ArrowUp)) => _ [SelectPrevious], + // Complete(Rq { result: Some(_x),request: _y }) => K(Key::Named(NamedKey::ArrowDown)) => _ [SelectNext], + // Complete(Rq { result: Some(_x),request: _y }) => K(Key::Named(NamedKey::ArrowUp)) => _ [SelectPrevious], // exit cases Complete(_) => Click => None, @@ -4,6 +4,7 @@ use std::sync::{Arc, LazyLock}; use std::time::Instant; use atools::prelude::*; +use crossbeam::channel::select_biased; use dsb::cell::Style; use dsb::{Cell, Fonts}; use fimg::pixels::Blend; @@ -100,8 +101,7 @@ pub fn render( // } // } - text.write_to( - (cells, (c, r)), + text.write_to((cells, (c, r)), (t_ox, 0), x, |(_c, _r), text, mut x| { @@ -285,7 +285,10 @@ pub fn render( // std::fs::write("cells", Cell::store(c)); if w >= size.width as usize - || (position.1 + h >= size.height 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 @@ -463,6 +466,9 @@ pub fn render( let Some(_y) = _y.checked_sub(text.vo) else { return; }; + let Some(_x) = _x.checked_sub(text.ho) else { + return; + }; // if !(cursor_position.1 == _y && (_x..=_x2).contains(&cursor_position.0)) { // return; @@ -16,6 +16,14 @@ pub struct Symbols { pub tedit: TextArea, pub selection: usize, pub vo: usize, + pub ty: SymbolsType, +} + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +pub enum SymbolsType { + Document, + #[default] + Workspace, } const N: usize = 30; impl Symbols { @@ -87,7 +95,7 @@ impl Symbols { // // }) // .take(13) i.for_each(|((_, x, indices), i)| { - r(x, ws, c, i == self.selection, &indices, &mut out) + r(x, ws, c, i == self.selection, &indices, &mut out, self.ty) }); out @@ -121,6 +129,7 @@ fn r( selected: bool, indices: &[u32], to: &mut Vec<Cell>, + sty: SymbolsType, ) { let bg = if selected { col!("#262d3b") } else { col!("#1c212b") }; @@ -171,8 +180,11 @@ fn r( - (charc(&x.name) as i32 + qualifier.clone().count() as i32) - 3; let loc = x.location.uri.to_file_path().unwrap(); - let locs = - loc.strip_prefix(workspace).unwrap_or(&loc).to_str().unwrap_or(""); + let locs = if sty == SymbolsType::Workspace { + loc.strip_prefix(workspace).unwrap_or(&loc).to_str().unwrap_or("") + } else { + "" + }; let loc = locs.chars().rev().collect::<Vec<_>>().into_iter(); let q = if left < charc(&locs) as i32 { locs.chars() @@ -186,6 +198,7 @@ fn r( } else { loc }; + i.iter_mut() .rev() .zip(q.map(|x| { |