A simple CPU rendered GUI IDE experience.
docu symbols
bendn 4 weeks ago
parent 5e9c211 · commit 6cc36b3
-rw-r--r--src/edi.rs150
-rw-r--r--src/edi/st.rs9
-rw-r--r--src/lsp.rs64
-rw-r--r--src/main.rs4
-rw-r--r--src/rnd.rs12
-rw-r--r--src/sym.rs19
6 files changed, 188 insertions, 70 deletions
diff --git a/src/edi.rs b/src/edi.rs
index 1b9baaa..da5328c 100644
--- a/src/edi.rs
+++ b/src/edi.rs
@@ -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(_) => _,
diff --git a/src/lsp.rs b/src/lsp.rs
index 06c3447..5f0218b 100644
--- a/src/lsp.rs
+++ b/src/lsp.rs
@@ -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,
diff --git a/src/rnd.rs b/src/rnd.rs
index 0f625d6..faaf599 100644
--- a/src/rnd.rs
+++ b/src/rnd.rs
@@ -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;
diff --git a/src/sym.rs b/src/sym.rs
index bbd0651..57436d4 100644
--- a/src/sym.rs
+++ b/src/sym.rs
@@ -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| {