A simple CPU rendered GUI IDE experience.
| -rw-r--r-- | src/commands.rs | 10 | ||||
| -rw-r--r-- | src/edi.rs | 201 | ||||
| -rw-r--r-- | src/edi/input_handlers/click.rs | 3 | ||||
| -rw-r--r-- | src/edi/input_handlers/keyboard.rs | 29 | ||||
| -rw-r--r-- | src/edi/lsp.rs | 0 | ||||
| -rw-r--r-- | src/edi/lsp_mn.rs | 52 | ||||
| -rw-r--r-- | src/lsp.rs | 1 | ||||
| -rw-r--r-- | src/lsp/client.rs | 19 | ||||
| -rw-r--r-- | src/lsp/communication.rs | 22 | ||||
| -rw-r--r-- | src/lsp/rq.rs | 29 | ||||
| -rw-r--r-- | src/main.rs | 13 | ||||
| -rw-r--r-- | src/rnd.rs | 12 |
12 files changed, 252 insertions, 139 deletions
diff --git a/src/commands.rs b/src/commands.rs index f91ee2d..014a3f8 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -11,6 +11,7 @@ use lsp_types::*; use rootcause::{bail, report}; use rust_analyzer::lsp::ext::*; +use crate::edi::lsp_mn::LSPM; use crate::edi::{Editor, lsp}; use crate::gotolist::{At, GoToList}; use crate::lsp::{PathURI, Rq, tdpp}; @@ -228,6 +229,7 @@ impl Editor { z: Cmd, w: Arc<dyn winit::window::Window>, kr: &mut KillRing, + lsp_mn: &mut LSPM, ) -> rootcause::Result<()> { match z { Cmd::GoTo(Some(x)) => @@ -288,7 +290,8 @@ impl Editor { ); } Cmd::Reload => self.reload(), - z if z.needs_lsp() => return self.handle_lsp_command(z, w), + z if z.needs_lsp() => + return self.handle_lsp_command(z, w, lsp_mn), x => unimplemented!("{x:?}"), } @@ -298,6 +301,7 @@ impl Editor { &mut self, z: Cmd, w: Arc<dyn winit::window::Window>, + lsp_mn: &mut LSPM, ) -> rootcause::Result<()> { let Some((l, o)) = lsp!(self + p) else { bail!("no lsp"); @@ -337,7 +341,7 @@ impl Editor { self.bar.last_action = "no such parent".into(); return Ok(()); }; - self.go(x, w)?; + self.go(x, w, lsp_mn)?; } Cmd::RAJoinLines => { let teds = @@ -412,7 +416,7 @@ impl Editor { else { bail!("wtf?"); }; - self.go(x, w)?; + self.go(x, w, lsp_mn)?; } Cmd::RARunnables => { let p = self.text.to_l_position(*self.text.cursor.first()); @@ -16,6 +16,7 @@ use rootcause::report; use ropey::Rope; use rust_fsm::StateMachine; use tokio::sync::oneshot::Sender; +use tree_house::Language; use winit::keyboard::NamedKey; use winit::window::Window; @@ -23,7 +24,7 @@ mod input_handlers; pub use input_handlers::handle2; mod lsp_impl; -mod lsp_mn; +pub mod lsp_mn; mod ra; pub mod st; mod wsedit; @@ -33,6 +34,7 @@ use st::*; use crate::bar::Bar; use crate::commands::Cmds; +use crate::edi::lsp_mn::{LSPM, LoadedLSP}; use crate::error::WDebug; use crate::gotolist::{At, GoTo}; use crate::hov::{self, HOV_HEIGHT, Hovr, Hovring, Rendered}; @@ -59,7 +61,6 @@ impl Debug for Editor { .field("origin", &self.origin) .field("state", &self.state.name()) .field("bar", &self.bar) - .field("workspace", &self.workspace) .field("hist", &self.hist) .field("mtime", &self.mtime) .finish() @@ -81,14 +82,11 @@ pub struct Editor { pub state: State, #[serde(skip)] pub bar: Bar, - pub workspace: Option<PathBuf>, + // pub workspace: Option<PathBuf>, + #[serde(skip)] pub git_dir: Option<PathBuf>, #[serde(skip)] - pub lsp: Option<( - Arc<Client>, - std::thread::JoinHandle<()>, - Option<Sender<Arc<dyn Window>>>, - )>, + pub lsp: Option<(Arc<Client>, Option<Sender<Arc<dyn Window>>>)>, // #[serde(skip)] pub requests: Requests, #[serde(skip)] @@ -203,9 +201,9 @@ fn rooter( } impl Editor { - pub fn new() -> rootcause::Result<(Self, Freq, KillRing)> { - let mut me = Self::default(); - + pub fn new( + lsp_mn: &mut LSPM, + ) -> rootcause::Result<(Self, Freq, KillRing)> { let mut o = std::env::args() .nth(1) .and_then(|x| PathBuf::try_from(x).ok()) @@ -224,7 +222,6 @@ impl Editor { .set_title("pick dir to open") .pick_folder() }); - if let Some(x) = &o { match std::fs::read_to_string(x) { Ok(_) => {} @@ -258,6 +255,56 @@ impl Editor { } } }; + Editor::new_for(o, lsp_mn) + } + + pub fn upto(&self) -> impl std::ops::Fn(&&Path) -> bool + Clone { + let upto = self + .git_dir + .clone() + .or(std::env::current_dir().ok()) + .unwrap_or(PathBuf::from("/home/")); + move |x: &&Path| x.starts_with(&upto) + } + + pub fn root_for(&self, o: &Path, l: Language) -> Option<PathBuf> { + let l = LOADER.language(l).config(); + + o.parent() + .and_then(|x| rooter(&x, |f| l.roots.is_match(f), self.upto())) + .or(std::env::current_dir().ok()) + .and_then(|x| x.canonicalize().ok()) + } + pub fn vsc(&self) -> Option<serde_json::Value> { + self.origin + .as_ref() + .and_then(|x| x.parent()) + .and_then(|x| rooter(&x, |x| x == ".vscode", self.upto())) + .map(|x| (x.clone(), x.join(".vscode").join("settings.json"))) + .filter(|x| x.1.exists()) + .and_then(|(ws, x)| vsc_settings::load(&x, &ws).ok()) + } + pub fn load_lsp(&mut self, lsp_mn: &mut LSPM) { + self.language = self + .origin + .as_deref() + .and_then(|o| LOADER.language_for_filename(o)); + let ws = self + .origin + .as_deref() + .zip(self.language) + .and_then(|(p, l)| self.root_for(p, l)); + let l = ws + .as_ref() + .zip(self.language) + .and_then(|(w, ln)| lsp_mn.load(w, ln, self.vsc())); + self.lsp = l; + } + pub fn new_for( + o: Option<PathBuf>, + lsp_mn: &mut LSPM, + ) -> rootcause::Result<(Self, Freq, KillRing)> { + let mut me = Self::default(); if let Some(o) = o.as_deref() && let o = std::fs::read_to_string(o).unwrap() { @@ -267,8 +314,7 @@ impl Editor { let n = o.as_deref().and_then(|o| LOADER.language_for_filename(o)); me.language = n; - let l = - n.map(|n| LOADER.languages().nth(n.idx()).unwrap().1.config()); + let l = n.map(|n| LOADER.language(n).config()); me.git_dir = o .as_deref() .and_then(|x| { @@ -277,43 +323,26 @@ impl Editor { .map(PathBuf::from) }) .and_then(|x| x.canonicalize().ok()); - let upto = me - .git_dir - .clone() - .or(std::env::current_dir().ok()) - .unwrap_or(PathBuf::from("/home/")); - let upto = |x: &&Path| x.starts_with(&upto); - me.workspace = o - .as_ref() - .and_then(|x| x.parent()) - .and_then(|x| { - l.and_then(|l| rooter(&x, |f| l.roots.is_match(f), upto)) - }) - .or(std::env::current_dir().ok()) - .and_then(|x| x.canonicalize().ok()); - let vsc = o - .as_ref() - .and_then(|x| x.parent()) - .and_then(|x| rooter(&x, |x| x == ".vscode", upto)) - .map(|x| (x.clone(), x.join(".vscode").join("settings.json"))) - .filter(|x| x.1.exists()) - .and_then(|(ws, x)| vsc_settings::load(&x, &ws).ok()); + let ws = o.as_deref().zip(n).and_then(|(p, l)| me.root_for(p, l)); let mut loaded_state = false; let mut freq = default(); let mut kr = default(); - if let Some(ws) = me.workspace.as_deref() + if let Some(ws) = ws.as_deref() && let h = hash(&ws) && let cf = cfgdir().join(format!("{h:x}")) && let at = cf.join(SSTORE) && at.exists() { + println!("loaded "); let x = std::fs::read(at)?; let x = bendncode::from_bytes::<Editor>(&x)?; + let gd = me.git_dir.take(); me = x; + me.git_dir = gd; loaded_state = true; - assert!(me.workspace.is_some()); + // assert!(me.workspace.is_some()); if let at = cf.join(FSTORE) && at.exists() { @@ -327,9 +356,10 @@ impl Editor { kr = bendncode::from_bytes::<KillRing>(&x)?; } } + println!("set git dir {:?}", &me.git_dir); me.language = n; me.origin = o; - me.tree = me.workspace.as_ref().map(|x| { + me.tree = ws.as_ref().map(|x| { walkdir::WalkDir::new(x) .into_iter() .flatten() @@ -348,30 +378,20 @@ impl Editor { .collect::<Vec<_>>() }); - let l = me - .workspace - .as_ref() - .zip(n) - .and_then(|(w, ln)| lsp_mn::load(w, ln, vsc)); let g = me.git_dir.clone(); if let Some(o) = me.origin.clone() && loaded_state { - let w = me.workspace.clone(); - let la = me.language; - let t = me.tree.clone(); if me.files.len() != 0 { log::error!( "too many files? {:?}", me.files.keys().collect::<Vec<_>>() ); } - me.open_or_restore(&o, l, la, None, w)?; - me.git_dir = g; - me.tree = t; + me.open_or_restore(&o, g, None, lsp_mn)?; me.language = n; } else { - me.lsp = l; + me.load_lsp(lsp_mn); me.hist.lc = me.text.cursor.clone(); me.hist.last = me.text.changes.clone(); if let Some((c, origin)) = lsp!(me + p) { @@ -428,7 +448,8 @@ impl Editor { self.bar.last_action = "saved".into(); lsp!(self + p).map(|(l, o)| { if let Ok(fut) = l.format(o) - && let Ok(Some(v)) = l.runtime.block_on(fut) + && let Ok(Ok(Some(v))) = + l.by(fut, tokio::time::Duration::from_millis(500)) && let Err(x) = self.text.apply_tedits_adjusting(&mut { v }) { @@ -559,6 +580,7 @@ impl Editor { &mut self, x: &Path, w: Arc<dyn Window>, + lsp_mn: &mut LSPM, ) -> rootcause::Result<()> { let x = x.canonicalize()?.to_path_buf(); if Some(&*x) == self.origin.as_deref() { @@ -566,38 +588,33 @@ impl Editor { return Ok(()); } let r = self.text.r; - let ws = self.workspace.clone(); - let git_dir = self.workspace.clone(); + // let ws = self.workspace.clone(); + let git_dir = self.git_dir.clone(); let tree = self.tree.clone(); - let lsp = self.lsp.take(); - let l = self.language; + // let lsp = self.lsp.take(); let mut me = take(self); let f = take(&mut me.files); if let Some(x) = me.origin.clone() { - lsp.as_ref().map(|l| l.0.close(&x)); + lsp!(me).as_ref().map(|l| l.close(&x)); self.files.insert(x, me); self.files.extend(f); // assert!(f.len() == 0); } - self.open_or_restore(&x, lsp, l, Some(w), ws)?; + self.open_or_restore(&x, git_dir, Some(w), lsp_mn)?; self.text.r = r; self.tree = tree; - self.git_dir = git_dir; // maybe it should change? you know. sometimes? Ok(()) } fn restore( &mut self, - - lsp: Option<( - Arc<Client>, - std::thread::JoinHandle<()>, - Option<Sender<Arc<dyn Window>>>, - )>, - l: Option<helix_core::Language>, + git_dir: Option<PathBuf>, + // lsp: Option<(Arc<Client>, Option<Sender<Arc<dyn Window>>>)>, + // l: Option<helix_core::Language>, with: Editor, + lsp_mn: &mut LSPM, ) -> rootcause::Result<()> { let f = take(&mut self.files); @@ -627,8 +644,9 @@ impl Editor { take(&mut self.requests); self.hist.push(&mut self.text) } - self.lsp = lsp; - self.language = l; + self.git_dir = git_dir; + self.load_lsp(lsp_mn); + if let Some((x, origin)) = lsp!(self + p) { x.open( &origin, @@ -641,19 +659,17 @@ impl Editor { fn open_or_restore( &mut self, x: &Path, - lsp: Option<( - Arc<Client>, - std::thread::JoinHandle<()>, - Option<Sender<Arc<dyn Window>>>, - )>, - l: Option<helix_core::Language>, + git_dir: Option<PathBuf>, + // lsp: Option<(Arc<Client>, Option<Sender<Arc<dyn Window>>>)>, + // l: Option<helix_core::Language>, w: Option<Arc<dyn Window>>, - ws: Option<PathBuf>, + lsp_mn: &mut LSPM, + // ws: Option<PathBuf>, ) -> rootcause::Result<()> { if let Some(x) = self.files.remove(x) { - self.restore(lsp, l, x)? + self.restore(git_dir, x, lsp_mn)? } else { - self.workspace = ws; + // self.workspace = ws; self.origin = Some(x.to_path_buf()); let new = std::fs::read_to_string(&x)?; @@ -663,8 +679,8 @@ impl Editor { self.text.cursor.just(0, &self.text.rope); self.bar.last_action = "open".into(); self.mtime = Self::modify(self.origin.as_deref()); - self.lsp = lsp; - self.language = l; + self.git_dir = git_dir; + self.load_lsp(lsp_mn); if let Some((ls, origin)) = lsp!(self + p) { take(&mut self.requests); @@ -676,6 +692,24 @@ impl Editor { .peel()?; } } + + fn is_hidden(entry: &walkdir::DirEntry) -> bool { + entry + .file_name() + .to_str() + .map(|s| s.starts_with(".")) + .unwrap_or(false) + } + + self.tree = self.git_dir.as_ref().map(|x| { + walkdir::WalkDir::new(x) + .into_iter() + .filter_entry(|e| !is_hidden(e)) + .flatten() + .filter(|x| !x.path().starts_with(".")) + .map(|x| x.path().to_owned()) + .collect::<Vec<_>>() + }); self.set_title(w); Ok(()) } @@ -687,7 +721,7 @@ impl Editor { } } pub fn title(&self) -> Option<String> { - [self.workspace.as_deref(), self.origin.as_deref()] + [self.git_dir.as_deref(), self.origin.as_deref()] .try_map(|x| { x.and_then(Path::file_name).and_then(|x| x.to_str()) }) @@ -699,14 +733,14 @@ impl Editor { fq: &Freq, kr: &KillRing, ) -> rootcause::Result<()> { - let ws = self.workspace.clone(); + // let ws = self.workspace.clone(); let tree = self.tree.clone(); let mtime = self.mtime.clone(); let origin = self.origin.clone(); - if let Some(w) = self.workspace.clone() { + if let Some(w) = self.git_dir.clone() { let mut me = take(self); - self.workspace = ws; + // self.workspace = ws; self.tree = tree; self.mtime = mtime; self.origin = origin; @@ -735,10 +769,11 @@ impl Editor { &mut self, g: impl Into<GoTo<'_>>, w: Arc<dyn Window>, + lsp_mn: &mut LSPM, ) -> rootcause::Result<()> { let g = g.into(); let f = g.path.canonicalize()?; - self.open(&f, w.clone())?; + self.open(&f, w.clone(), lsp_mn)?; match g.at { At::R(r) => { diff --git a/src/edi/input_handlers/click.rs b/src/edi/input_handlers/click.rs index d89552f..2fc4db3 100644 --- a/src/edi/input_handlers/click.rs +++ b/src/edi/input_handlers/click.rs @@ -11,6 +11,7 @@ impl Editor { bt: MouseButton, cursor_position: (usize, usize), w: Arc<dyn Window>, + lsp_mn: &mut LSPM, ) { _ = self .requests @@ -73,7 +74,7 @@ impl Editor { _ => None, }) }) - && let Err(e) = self.go(&x, w.clone()) + && let Err(e) = self.go(&x, w.clone(),lsp_mn) { log::error!("gtd: {e}"); } diff --git a/src/edi/input_handlers/keyboard.rs b/src/edi/input_handlers/keyboard.rs index ca74611..b1e780d 100644 --- a/src/edi/input_handlers/keyboard.rs +++ b/src/edi/input_handlers/keyboard.rs @@ -19,7 +19,7 @@ use winit::window::Window; use crate::Freq; use crate::edi::*; -use crate::lsp::acceptable_duration; +use crate::lsp::{Require, acceptable_duration}; impl Editor { pub fn keyboard( @@ -28,6 +28,7 @@ impl Editor { window: &mut Arc<dyn Window>, freq: &mut Freq, kr: &mut KillRing, + lsp_mn: &mut LSPM, ) -> ControlFlow<()> { let Some(mut o) = self.transition(Action::K(event.logical_key.clone())) @@ -68,9 +69,11 @@ impl Editor { } Do::SpawnTerminal => { if let Err(e) = trm::toggle( - self.workspace + &lsp!(self) .as_deref() - .unwrap_or(Path::new("/home/os/")), + .map_or(Path::new("/home/os/").into(), |x| { + x.workspace.uri.to_file_path().unwrap() + }), ) { log::error!("opening terminal failed {e}"); } @@ -126,9 +129,12 @@ impl Editor { self.state = State::Command(x); } crate::menu::generic::CorA::Accept => { - if let Err(e) = - self.handle_command(z, window.clone(), kr) - { + if let Err(e) = self.handle_command( + z, + window.clone(), + kr, + lsp_mn, + ) { self.bar.last_action = format!("{e}"); } } @@ -227,7 +233,7 @@ impl Editor { } Do::SymbolsSelect(x) => if let Some(Ok(x)) = x.sel(Some(freq)) - && let Err(e) = self.go(x.at, window.clone()) + && let Err(e) = self.go(x.at, window.clone(), lsp_mn) { log::error!("alas! {e}") }, @@ -487,7 +493,7 @@ impl Editor { } Do::Paste => self.paste(), Do::OpenFile(x) => { - _ = self.open(Path::new(&x), window.clone()); + _ = self.open(Path::new(&x), window.clone(), lsp_mn); } Do::StartSearch(x) => { let s = Regex::new(&x).unwrap(); @@ -548,7 +554,7 @@ impl Editor { } Do::Run(x) => if let Some((l, ws)) = - lsp!(self).zip(self.workspace.as_deref()) + lsp!(self).zip(self.git_dir.as_deref()) { l.runtime .block_on(crate::runnables::run(x, ws)) @@ -568,7 +574,7 @@ impl Editor { } Do::GTLSelect(x) => if let Some(Ok((g, _))) = x.sel(None) - && let Err(e) = self.go(g, window.clone()) + && let Err(e) = self.go(g, window.clone(), lsp_mn) { eprintln!("go-to-list select fail: {e}"); }, @@ -828,6 +834,9 @@ impl Editor { pub fn request_code_actions(&mut self) { lsp!(let lsp, f = self); + if lsp.caps().code_action_provider.is_none() { + return; + } let r = lsp .request::<lsp_request!("textDocument/codeAction")>( &CodeActionParams { diff --git a/src/edi/lsp.rs b/src/edi/lsp.rs deleted file mode 100644 index e69de29..0000000 --- a/src/edi/lsp.rs +++ /dev/null diff --git a/src/edi/lsp_mn.rs b/src/edi/lsp_mn.rs index 6c76bdc..0bc7dce 100644 --- a/src/edi/lsp_mn.rs +++ b/src/edi/lsp_mn.rs @@ -11,26 +11,44 @@ use tokio::sync::oneshot::Sender; use tree_house::Language; use winit::window::Window; -struct LSP4 { - four: HashMap<(Language, PathBuf), &'static Client>, +pub struct LSPM { + pub four: HashMap<(Language, PathBuf), LoadedLSP>, } -struct Loaded { - iot: Option<IoThreads>, - +pub struct LoadedLSP { + pub c: Arc<Client>, + pub iot: Option<IoThreads>, + pub comms: std::thread::JoinHandle<()>, +} + +impl LSPM { + pub fn load( + &mut self, + workspace: &PathBuf, + l: Language, + vsc: Option<serde_json::Value>, + ) -> Option<(Arc<Client>, Option<Sender<Arc<dyn Window + 'static>>>)> + { + let e = match self.four.entry((l, workspace.to_owned())) { + std::collections::hash_map::Entry::Occupied(x) => { + let x = x.get(); + return Some((x.c.clone(), None)); + } + std::collections::hash_map::Entry::Vacant(e) => e, + }; + let (l, w) = load(workspace, l, vsc)?; + let v = e.insert(l); + Some((v.c.clone(), Some(w))) + } } use crate::lsp::Client; pub fn load( workspace: &PathBuf, l: Language, vsc: Option<serde_json::Value>, -) -> Option<( - Arc<Client>, - std::thread::JoinHandle<()>, - Option<Sender<Arc<dyn Window + 'static>>>, -)> { +) -> Option<(LoadedLSP, Sender<Arc<dyn Window>>)> { let l = super::LOADER.language(l).config(); - let (Connection { sender, receiver }, conf,iot) = if l.language_id + let (Connection { sender, receiver }, conf, iot) = if l.language_id == "rust" { let (_jh, a) = super::ra::ra(workspace.clone()); @@ -40,7 +58,7 @@ pub fn load( &super::LOADER.language_server_configs()["rust-analyzer"], &l.language_servers[0], ), - None + None, ) } else { let (mut c, conf) = l @@ -88,13 +106,5 @@ pub fn load( conf, ) .unwrap(); - Some((Arc::new(c), (t2), Some(changed))) + Some((LoadedLSP { iot, c: Arc::new(c), comms: t2 }, changed)) } - -fn rah() { -let stdout = 4; -super let x =( - &stdout, - - ); -}
\ No newline at end of file @@ -60,6 +60,7 @@ pub fn run( req_rx: _req_rx, not_rx, lsp_data: data, + workspace: workspace.clone(), }; let mut opts = init_opts::get( workspace, diff --git a/src/lsp/client.rs b/src/lsp/client.rs index 059e523..a0db994 100644 --- a/src/lsp/client.rs +++ b/src/lsp/client.rs @@ -23,7 +23,7 @@ use tokio::sync::oneshot; use ttools::*; use crate::lsp::BehaviourAfter::{self, *}; -use crate::lsp::{RequestError, Require, Requiring, Rq}; +use crate::lsp::{RequestError, Require, Requiring, Rq, RqSendError}; use crate::text::cursor::ceach; use crate::text::{LOADER, RopeExt, SortTedits, TextArea}; #[derive(Debug, Clone)] @@ -65,11 +65,16 @@ pub struct Client { &'static LanguageServerConfiguration, &'static LanguageServerFeatures, ), + pub workspace: WorkspaceFolder, } impl Drop for Client { fn drop(&mut self) { - println!("dropped lsp"); + _ = self.notify::<Exit>(&()); + println!( + "dropped lsp({}) @ {}", + self.lsp_data.1.name, self.workspace.uri + ); // panic!("please dont"); } } @@ -577,7 +582,7 @@ impl Client { ) -> Result< impl Future<Output = Result<Vec<Runnable>, RequestError<Runnables>>> + use<>, - SendError<Message>, + RqSendError<Runnables>, > { self.request::<Runnables>(&RunnablesParams { text_document: t.tid(), @@ -597,7 +602,7 @@ impl Client { RequestError<ChildModules>, >, >, - SendError<Message>, + RqSendError<ChildModules>, > { self.request::<ChildModules>(&TextDocumentPositionParams { position: p, @@ -615,7 +620,7 @@ impl Client { RequestError<GotoImplementation>, >, > + use<>, - SendError<Message>, + RqSendError<GotoImplementation>, > { self.request::<GotoImplementation>(&GotoImplementationParams { text_document_position_params: tdpp, @@ -635,7 +640,7 @@ impl Client { RequestError<References>, >, > + use<>, - SendError<Message>, + RqSendError<References>, > { self.request::<References>(&ReferenceParams { text_document_position: tdpp, @@ -664,7 +669,7 @@ impl Client { RequestError<CallHierarchyPrepare>, >, > + use<>, - SendError<Message>, + RqSendError<CallHierarchyPrepare>, > { self.request::<CallHierarchyPrepare>(&CallHierarchyPrepareParams { text_document_position_params: at, diff --git a/src/lsp/communication.rs b/src/lsp/communication.rs index 3e5bc3d..2ef150c 100644 --- a/src/lsp/communication.rs +++ b/src/lsp/communication.rs @@ -18,7 +18,7 @@ use tokio::time::error::Elapsed; use winit::window::Window; use crate::lsp::BehaviourAfter::{self, *}; -use crate::lsp::RequestError; +use crate::lsp::{RequestError, RqSendError}; pub fn handler( window_rx: oneshot::Receiver<Arc<dyn Window + 'static>>, progress: &papaya::HashMap< @@ -33,6 +33,7 @@ pub fn handler( ) { let mut map = HashMap::new(); let w = window_rx.blocking_recv().unwrap(); + println!("got w"); loop { crossbeam::select! { recv(req_rx) -> x => match x { @@ -149,7 +150,12 @@ impl super::Client { &'me self, y: &X::Params, ) -> Result<X::Result, RequestError<X>> { - self.runtime.block_on(self.request_::<X, { Nil }>(y)?.0) + self.runtime + .block_on(tokio::time::timeout( + tokio::time::Duration::from_secs(20), + self.request_::<X, { Nil }>(y)?.0, + )) + .unwrap() } pub fn request_by<'me, X: Request>( &'me self, @@ -166,6 +172,14 @@ impl super::Client { )) } + pub fn by<T>( + &self, + x: impl Future<Output = T>, + d: tokio::time::Duration, + ) -> Result<T, Elapsed> { + let _guard = self.runtime.enter(); + self.runtime.block_on(tokio::time::timeout(d, x)) + } pub fn request<'me, X: Request>( &'me self, y: &X::Params, @@ -174,7 +188,7 @@ impl super::Client { impl Future<Output = Result<X::Result, RequestError<X>>> + use<X>, i32, ), - SendError<Message>, + RqSendError<X>, > { self.request_::<X, { Redraw }>(y) } @@ -188,7 +202,7 @@ impl super::Client { + use<X, THEN>, i32, ), - SendError<Message>, + RqSendError<X>, > { let id = self.id.fetch_add(1, std::sync::atomic::Ordering::AcqRel); self.tx.send(Message::Request(LRq { diff --git a/src/lsp/rq.rs b/src/lsp/rq.rs index ef1316f..b7e42e0 100644 --- a/src/lsp/rq.rs +++ b/src/lsp/rq.rs @@ -12,7 +12,8 @@ use tokio::task; use tokio_util::task::AbortOnDropHandle; use crate::lsp::Void; - +#[derive(Serialize, Deserialize)] +pub struct RqSendError<X>(Message, PhantomData<X>); #[derive(Serialize, Deserialize)] pub enum RequestError<X> { Rx(PhantomData<X>), @@ -50,16 +51,42 @@ impl<X> From<oneshot::error::RecvError> for RequestError<X> { Self::Rx(PhantomData) } } +impl<X: Request> std::error::Error for RqSendError<X> { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } +} impl<X: Request> std::error::Error for RequestError<X> { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } } +impl<X> From<SendError<Message>> for RqSendError<X> { + fn from(x: SendError<Message>) -> Self { + Self(x.into_inner(), PhantomData) + } +} impl<X> From<SendError<Message>> for RequestError<X> { fn from(x: SendError<Message>) -> Self { Self::Send(x.into_inner()) } } +impl<X> From<RqSendError<X>> for RequestError<X> { + fn from(x: RqSendError<X>) -> Self { + Self::Send(x.0) + } +} + +impl<X: Request> std::fmt::Display for RqSendError<X> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} failed; couldnt send {:?}", X::METHOD, self.0) + } +} +impl<X: Request> std::fmt::Debug for RqSendError<X> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} impl<X: Request> std::fmt::Display for RequestError<X> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/src/main.rs b/src/main.rs index 6cd7223..6dfe02b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -83,6 +83,7 @@ use winit::window::{ }; use crate::edi::Editor; +use crate::edi::lsp_mn::LSPM; use crate::edi::st::*; use crate::lsp::RqS; use crate::text::{TextArea, col, is_word}; @@ -140,8 +141,10 @@ extern "C" fn sigint(_: i32) { type FID = u8; type Freq = FxHashMap<FID, FxHashMap<u64, u16>>; pub(crate) fn entry(event_loop: EventLoop) { + let mut lsp_mn = LSPM { four: default() }; + unsafe { - let (ed, freq, kr) = match Editor::new() { + let (ed, freq, kr) = match Editor::new(&mut lsp_mn) { Err(e) => { eprintln!("failure to launch: {e}"); return; @@ -225,6 +228,10 @@ pub(crate) fn entry(event_loop: EventLoop) { .with_event_handler( move |(window, _context), surface, window_id, event, elwt| { elwt.set_control_flow(ControlFlow::Wait); + if let Some((.., c)) = &mut ed.lsp && let Some(c) = c.take() { + c.send(window.clone()).unwrap(); + } + let lsp_mn = &mut lsp_mn; let (fw, fh) = dsb::dims(&FONT, ppem); let (c, r) = dsb::fit( &FONT, @@ -325,7 +332,7 @@ pub(crate) fn entry(event_loop: EventLoop) { if button == MouseButton::Left { unsafe { CLICKING = true }; } - ed.click(button, cursor_position, window.clone()); + ed.click(button, cursor_position, window.clone(), lsp_mn); window.request_redraw(); } WindowEvent::PointerButton { @@ -368,7 +375,7 @@ pub(crate) fn entry(event_loop: EventLoop) { ) { return; } - if ed.keyboard(event, window, freq, kr).is_break() { + if ed.keyboard(event, window, freq, kr, lsp_mn).is_break() { elwt.exit(); } window.request_redraw(); @@ -385,7 +385,7 @@ pub fn render( ed.origin .as_ref() .map(|x| { - ed.workspace + ed.git_dir .as_ref() .and_then(|w| x.strip_prefix(w).ok()) .unwrap_or(&x) @@ -847,27 +847,27 @@ pub fn render( ); } State::Command(x) if x.should_render() => { - let ws = ed.workspace.as_deref().unwrap(); + let ws = ed.git_dir.as_deref().unwrap(); let c = x.cells(50, ws, None); drawb(&c, 50); } State::Symbols(Rq { result: Some(x), .. }) => { - let ws = ed.workspace.as_deref().unwrap(); + let ws = ed.git_dir.as_deref().unwrap(); let c = x.cells(50, ws, Some(freq)); drawb(&c, 50); } State::Runnables(Rq { result: Some(x), .. }) => { - let ws = ed.workspace.as_deref().unwrap(); + let ws = ed.git_dir.as_deref().unwrap(); let c = x.cells(50, ws, None); drawb(&c, 50); } State::GoToL(y) => { - let ws = ed.workspace.as_deref().unwrap(); + let ws = ed.git_dir.as_deref().unwrap(); let c = y.cells(50, ws, None); drawb(&c, 50); } State::KillRing(y) => { - let ws = ed.workspace.as_deref().unwrap(); + let ws = ed.git_dir.as_deref().unwrap(); let c = y.cells(50, ws, None); drawb(&c, 50); } |