Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/edi/input_handlers/keyboard.rs')
| -rw-r--r-- | src/edi/input_handlers/keyboard.rs | 410 |
1 files changed, 240 insertions, 170 deletions
diff --git a/src/edi/input_handlers/keyboard.rs b/src/edi/input_handlers/keyboard.rs index f61a338..08376aa 100644 --- a/src/edi/input_handlers/keyboard.rs +++ b/src/edi/input_handlers/keyboard.rs @@ -5,11 +5,9 @@ use std::sync::Arc; use Default::default; use lsp_server::ResponseError; -use lsp_types::request::*; use lsp_types::*; use regex::Regex; use ropey::Rope; -use rust_analyzer::lsp::ext::OnTypeFormatting; use rust_fsm::StateMachine; use tokio_util::task::AbortOnDropHandle as DropH; use ttools::{IteratorOfTuples, IteratorOfTuplesWithF, hrf}; @@ -19,6 +17,7 @@ use winit::window::Window; use crate::Freq; use crate::edi::*; +use crate::lsp::{Require, acceptable_duration}; impl Editor { pub fn keyboard( @@ -26,27 +25,31 @@ impl Editor { event: KeyEvent, window: &mut Arc<dyn Window>, freq: &mut Freq, + kr: &mut KillRing, + lsp_mn: &mut LSPM, ) -> ControlFlow<()> { - let mut o: Option<Do> = self - .state - .consume(Action::K(event.logical_key.clone())) - .unwrap(); + let Some(mut o) = + self.transition(Action::K(event.logical_key.clone())) + else { + return ControlFlow::Continue(()); + }; + if let Do::Reinsert = o { + let Some(o2) = + self.transition(Action::K(event.logical_key.clone())) + else { + return ControlFlow::Continue(()); + }; + dbg!(&o2); + o = o2; + }; match o { - Some(Do::Reinsert) => - o = self - .state - .consume(Action::K(event.logical_key.clone())) - .unwrap(), - _ => {} - } - match o { - Some(Do::Escape) => { + Do::Escape => { take(&mut self.requests.complete); take(&mut self.requests.sig_help); self.text.cursor.alone(); } - Some(Do::Comment(p)) => { + Do::Comment(p) => { ceach!(self.text.cursor, |cursor| { Some( if let Some(x) = cursor.sel @@ -62,29 +65,46 @@ impl Editor { self.text.cursor.clear_selections(); change!(self, window.clone()); } - Some(Do::SpawnTerminal) => { - if let Err(e) = trm::toggle( - self.workspace + #[cfg(target_family = "unix")] + Do::SpawnTerminal => { + if let Err(e) = crate::trm::toggle( + &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}"); } } - Some(Do::MatchingBrace) => + #[cfg(not(target_family = "unix"))] + Do::SpawnTerminal => { + unimplemented!() + } + Do::MatchingBrace => if let Some((l, f)) = lsp!(self + p) { l.matching_brace(f, &mut self.text) }, - Some(Do::DeleteBracketPair) => self.delete_bracket_pair(), - Some(Do::Symbols) => + Do::DeleteBracketPair => self.delete_bracket_pair(), + Do::Symbols if let Some((lsp, o)) = lsp!(self + p) - && let Ok(syms) = lsp.workspace_symbols("".into()) - { - let mut q = Rq::new(lsp.runtime.spawn( - syms.map(Anonymize::anonymize).map(|x| { - x.map(|x| x.map(SymbolsList::Workspace)) - }), - )); + && let Ok(syms) = lsp.workspace_symbols("".into()) => + { + let mut q = Rq::new( + lsp.runtime.spawn(syms.map(Anonymize::anonymize).map( + |x| x.map(|x| x.map(SymbolsList::Workspace)), + )), + ); + q.result = Some(Symbols::new( + self.tree.as_deref().unwrap(), + self.text.bookmarks.clone(), + o.into(), + )); + self.state = State::Symbols(q); + } + Do::Symbols => + if let Some(o) = &self.origin { + let mut q = Rq::default(); q.result = Some(Symbols::new( self.tree.as_deref().unwrap(), self.text.bookmarks.clone(), @@ -92,7 +112,7 @@ impl Editor { )); self.state = State::Symbols(q); }, - Some(Do::SwitchType) => + Do::SwitchType => if let Some((lsp, p)) = lsp!(self + p) { let State::Symbols(Rq { result: Some(x), request }) = &mut self.state @@ -113,7 +133,7 @@ impl Editor { )); } }, - Some(Do::ProcessCommand(mut x, z)) => + Do::ProcessCommand(mut x, z) => match Cmds::complete_or_accept(&z) { crate::menu::generic::CorA::Complete => { x.tedit.rope = @@ -122,14 +142,17 @@ impl Editor { self.state = State::Command(x); } crate::menu::generic::CorA::Accept => { - if let Err(e) = - self.handle_command(z, window.clone()) - { + if let Err(e) = self.handle_command( + z, + window.clone(), + kr, + lsp_mn, + ) { self.bar.last_action = format!("{e}"); } } }, - Some(Do::CmdTyped) => { + Do::CmdTyped => { let State::Command(x) = &self.state else { unreachable!() }; @@ -139,13 +162,11 @@ impl Editor { self.text.scroll_to_ln_centering(x as _); } } - Some(Do::SymbolsHandleKey) => { - if let Some(lsp) = lsp!(self) { - let State::Symbols(Rq { result: Some(x), request }) = + Do::SymbolsHandleKey => { + if let Some(lsp) = lsp!(self) + && let State::Symbols(Rq { result: Some(x), request }) = &mut self.state - else { - unreachable!() - }; + { let ptedit = x.tedit.rope.clone(); if handle2( &event.logical_key, @@ -183,7 +204,7 @@ impl Editor { } } } - Some(Do::SymbolsSelectNext) => { + Do::SymbolsSelectNext => { let State::Symbols(Rq { result: Some(x), .. }) = &mut self.state else { @@ -203,7 +224,7 @@ impl Editor { } } } - Some(Do::SymbolsSelectPrev) => { + Do::SymbolsSelectPrev => { let State::Symbols(Rq { result: Some(x), .. }) = &mut self.state else { @@ -223,15 +244,15 @@ impl Editor { } } } - Some(Do::SymbolsSelect(x)) => + 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}") }, - Some(Do::RenameSymbol(to)) => self.rename_symbol(to), - Some(Do::CodeAction) => self.request_code_actions(), - Some(Do::CASelectLeft) => { + Do::RenameSymbol(to) => self.rename_symbol(to), + Do::CodeAction => self.request_code_actions(), + Do::CASelectLeft => { let State::CodeAction(Rq { result: Some(c), .. }) = &mut self.state else { @@ -239,7 +260,7 @@ impl Editor { }; c.left(); } - Some(Do::CASelectRight) => 'out: { + Do::CASelectRight => 'out: { let Some(lsp) = lsp!(self) else { unreachable!() }; let State::CodeAction(Rq { result: Some(c), .. }) = &mut self.state @@ -252,15 +273,15 @@ impl Editor { self.hist.lc = self.text.cursor.clone(); self.hist.test_push(&mut self.text); let act = lsp - .request_immediate::<CodeActionResolveRequest>(&act) + .request_immediate::<rust_analyzer::lsp::ext::CodeActionResolveRequest>(&act) .unwrap(); if let Some(x) = act.edit - && let Err(e) = self.apply_wsedit(x) + && let Err(e) = self.apply_swsedit(x) { log::error!("{e}"); } } - Some(Do::CASelectNext) => { + Do::CASelectNext => { let State::CodeAction(Rq { result: Some(c), .. }) = &mut self.state else { @@ -268,7 +289,7 @@ impl Editor { }; c.down(); } - Some(Do::CASelectPrev) => { + Do::CASelectPrev => { let State::CodeAction(Rq { result: Some(c), .. }) = &mut self.state else { @@ -276,7 +297,7 @@ impl Editor { }; c.up(); } - Some(Do::GoToMatch) + Do::GoToMatch if let Some(x) = &self.requests.document_highlights.result => 'out: { @@ -295,8 +316,10 @@ impl Editor { })) .max_by_key(|x| x.0.start) else { - self.bar.last_action = - "couldnt get symbol here".into(); + self.requests.document_highlights.result = None; + self.refresh_document_highlights(); + // self.bar.last_action = + // "couldnt get symbol here".into(); break 'out; }; if self.text.cursor.inner.len() == 1 @@ -314,37 +337,35 @@ impl Editor { } } } - Some(Do::GoToMatch) => + Do::GoToMatch => if self.requests.document_highlights.request.is_none() { self.refresh_document_highlights(); }, - Some(Do::NavBack) => self.nav_back(), - Some(Do::NavForward) => self.nav_forward(), - Some( - Do::Reinsert - | Do::GoToDefinition(_) - | Do::MoveCursor - | Do::ExtendSelectionToMouse - | Do::Hover - | Do::InsertCursorAtMouse - | Do::SetHovering - | Do::ClickedHover, - ) => panic!(), - Some(Do::Save) => match &self.origin { + Do::NavBack => self.nav_back(), + Do::NavForward => self.nav_forward(), + + Do::Reinsert + | Do::GoToDefinition(_) + | Do::MoveCursor + | Do::ExtendSelectionToMouse + | Do::Hover + | Do::InsertCursorAtMouse + | Do::SetHovering => panic!(), + Do::Save => match &self.origin { Some(_) => { - self.state.consume(Action::Saved).unwrap(); + self.transition(Action::Saved); self.save(); } None => { - self.state.consume(Action::RequireFilename).unwrap(); + self.transition(Action::RequireFilename); } }, - Some(Do::SaveTo(x)) => { + Do::SaveTo(x) => { self.origin = Some(PathBuf::try_from(x).unwrap()); self.save(); } - Some(Do::Edit) => self.handle_edit(event), - Some(Do::Undo) => { + Do::Edit => self.handle_edit(event), + Do::Undo => { self.hist.test_push(&mut self.text); if let Err(e) = self.hist.undo(&mut self.text) { eprintln!("undo failed: {e}"); @@ -353,14 +374,14 @@ impl Editor { change!(self, window.clone()); } - Some(Do::Redo) => { + Do::Redo => { self.hist.test_push(&mut self.text); self.hist.redo(&mut self.text).unwrap(); self.bar.last_action = "redid".to_string(); change!(self, window.clone()); } - Some(Do::Quit) => return ControlFlow::Break(()), - Some(Do::SetCursor(x)) => { + Do::Quit => return ControlFlow::Break(()), + Do::SetCursor(x) => { self.text.cursor.each(|c| { let Some(r) = c.sel else { return }; match x { @@ -370,7 +391,7 @@ impl Editor { }); self.text.cursor.clear_selections(); } - Some(Do::StartSelection) => { + Do::StartSelection => { let Key::Named(y) = event.logical_key else { panic!() }; // let mut z = vec![]; self.text.cursor.each(|x| { @@ -385,7 +406,7 @@ impl Editor { }); // *self.state.sel() = z; } - Some(Do::UpdateSelection) => { + Do::UpdateSelection => { let Key::Named(y) = event.logical_key else { panic!() }; self.text.cursor.each(|x| { x.extend_selection( @@ -400,9 +421,10 @@ impl Editor { self.text.scroll_to_cursor(); inlay!(self); } - Some(Do::Insert(c)) => { + Do::Insert(c) => { // self.text.cursor.inner.clear(); self.hist.push_if_changed(&mut self.text); + self.kill(kr); ceach!(self.text.cursor, |cursor| { let Some(r) = cursor.sel else { return }; _ = self.text.remove(r.into()); @@ -413,30 +435,29 @@ impl Editor { self.hist.push_if_changed(&mut self.text); change!(self, window.clone()); } - Some(Do::Delete) => { + Do::Delete => { self.hist.push_if_changed(&mut self.text); + self.kill(kr); ceach!(self.text.cursor, |cursor| { let Some(r) = cursor.sel else { return }; _ = self.text.remove(r.into()); }); self.text.cursor.clear_selections(); - self.hist.push_if_changed(&mut self.text); change!(self, window.clone()); } - Some(Do::Copy) => { + Do::Copy => { self.hist.push_if_changed(&mut self.text); unsafe { take(&mut META) }; let mut clip = String::new(); - self.text.cursor.each_ref(|x| { - if let Some(x) = x.sel { - unsafe { - META.count += 1; - META.splits.push(clip.len()); - } - clip.extend(self.text.rope.slice(x).chars()); + self.kill(kr); + for sel in self.text.cursor.sels(&self.text) { + unsafe { + META.count += 1; + META.splits.push(clip.len()); } - }); + clip.extend(sel.chars()); + } unsafe { META.splits.push(clip.len()); META.hash = hash(&clip) @@ -446,19 +467,18 @@ impl Editor { self.hist.push_if_changed(&mut self.text); change!(self, window.clone()); } - Some(Do::Cut) => { + Do::Cut => { self.hist.push_if_changed(&mut self.text); unsafe { take(&mut META) }; let mut clip = String::new(); - self.text.cursor.each_ref(|x| { - if let Some(x) = x.sel { - unsafe { - META.count += 1; - META.splits.push(clip.len()); - } - clip.extend(self.text.rope.slice(x).chars()); + self.kill(kr); + for sel in self.text.cursor.sels(&self.text) { + unsafe { + META.count += 1; + META.splits.push(clip.len()); } - }); + clip.extend(sel.chars()); + } unsafe { META.splits.push(clip.len()); META.hash = hash(&clip) @@ -473,8 +493,9 @@ impl Editor { self.hist.push_if_changed(&mut self.text); change!(self, window.clone()); } - Some(Do::PasteOver) => { + Do::PasteOver => { self.hist.push_if_changed(&mut self.text); + self.kill(kr); ceach!(self.text.cursor, |cursor| { let Some(r) = cursor.sel else { return }; _ = self.text.remove(r.into()); @@ -483,11 +504,11 @@ impl Editor { self.paste(); // self.hist.push_if_changed(&mut self.text); } - Some(Do::Paste) => self.paste(), - Some(Do::OpenFile(x)) => { - _ = self.open(Path::new(&x), window.clone()); + Do::Paste => self.paste(), + Do::OpenFile(x) => { + _ = self.open(Path::new(&x), window.clone(), lsp_mn); } - Some(Do::StartSearch(x)) => { + Do::StartSearch(x) => { let s = Regex::new(&x).unwrap(); let n = s .find_iter(&self.text.rope.to_string()) @@ -510,7 +531,7 @@ impl Editor { self.bar.last_action = "no matches".into() }); } - Some(Do::SearchChanged) => { + Do::SearchChanged => { let (re, index, _) = self.state.search(); let s = self.text.rope.to_string(); let m = re.find_iter(&s).nth(*index).unwrap(); @@ -521,48 +542,41 @@ impl Editor { self.text.scroll_to_cursor_centering(); inlay!(self); } - Some(Do::Boolean(BoolRequest::ReloadFile, true)) => { - self.hist.push_if_changed(&mut self.text); - self.text.rope = Rope::from_str( - &std::fs::read_to_string( - self.origin.as_ref().unwrap(), - ) - .unwrap(), - ); - - self.text.cursor.first_mut().position = self - .text + Do::Boolean(BoolRequest::ReloadFile, true) => self.reload(), + Do::Boolean(BoolRequest::ReloadFile, false) => {} + Do::InsertCursor(dir) => { + self.text .cursor - .first() - .position - .min(self.text.rope.len_chars()); - self.mtime = Self::modify(self.origin.as_deref()); - self.bar.last_action = "reloaded".into(); - self.hist.push(&mut self.text) - } - Some(Do::Boolean(BoolRequest::ReloadFile, false)) => {} - Some(Do::InsertCursor(dir)) => { - let (x, y) = match dir { - Direction::Above => self.text.cursor.min(), - Direction::Below => self.text.cursor.max(), - } - .cursor(&self.text.rope); - let y = match dir { - Direction::Above => y - 1, - Direction::Below => y + 1, - }; - let position = self.text.line_to_char(y); - self.text.cursor.add(position + x, &self.text.rope); + .inner + .iter() + .filter_map(|cursor| { + let (x, y) = cursor.cursor(&self.text.rope); + let y = match dir { + Direction::Above => y.checked_sub(1)?, + Direction::Below => y + 1, + }; + let position = self.text.line_to_char(y) + x; + Some(position) + }) + .filter(|&p| self.text.cursor.iter().all(|x| x != p)) + .collect::<Vec<_>>() + .into_iter() + .for_each(|x| { + self.text.cursor.add(x, &self.text.rope); + }); } - Some(Do::Run(x)) => + #[cfg(target_family = "unix")] + 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)) .unwrap(); }, - Some(Do::GoToImplementations) => { + #[cfg(not(target_family = "unix"))] + Do::Run(_) => {} + Do::GoToImplementations => { let State::GoToL(x) = &mut self.state else { unreachable!() }; @@ -574,13 +588,13 @@ impl Editor { ))); } } - Some(Do::GTLSelect(x)) => + 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}"); }, - Some(Do::GT) => { + Do::GT => { let State::GoToL(x) = &mut self.state else { unreachable!() }; @@ -593,7 +607,28 @@ impl Editor { // self.text.vo = self.text.char_to_line(x.start); } } - None => {} + // Do::KillRing => { + // self.state = State::KillRing(KillRM { + // data: kr.clone(), + // tedit: default(), + // selection: 0, + // vo: 0, + // }); + // } + Do::KillRMHandleKey => { + if let State::KillRing(x) = &mut self.state { + handle2( + &event.logical_key, + &mut x.tedit, + lsp!(self + p), + ); + } + } + Do::Revive(x) => + if let Some(Ok(x)) = x.sel(Some(freq)) { + self.paste_m(x.iter()) + }, + Do::R(_) => {} } ControlFlow::Continue(()) } @@ -628,25 +663,21 @@ impl Editor { || t.iter().any(|y| y == x)) && self.text.cursor.inner.len() == 1 && change!(just self).is_some() - && let Ok(Some(mut x)) = l - .request_immediate::<OnTypeFormatting>( + && let Ok(Ok(Some(mut x))) = l + .request_by::<rust_analyzer::lsp::ext::DocumentOnTypeFormattingRequest>( &DocumentOnTypeFormattingParams { - text_document_position: - TextDocumentPositionParams { - text_document: p.tid(), - position: self - .text - .to_l_position( - *self.text.cursor.first(), - ) - .unwrap(), - }, + text_document: p.tid(), + position: self + .text + .to_l_position(*self.text.cursor.first()) + .unwrap(), ch: x.into(), options: FormattingOptions { tab_size: 4, ..default() }, }, + acceptable_duration(), ) { x.sort_tedits(); @@ -699,7 +730,11 @@ impl Editor { .requests .complete .consume(CompletionAction::K(event.logical_key.as_ref())) - .unwrap() + .inspect_err(|e| { + log::error!("failure: {e}"); + }) + .ok() + .flatten() { Some(CDo::Request(ctx)) => { if let Ok(fut) = lsp.request_complete( @@ -776,15 +811,16 @@ impl Editor { let x = lsp .request_immediate::<lsp_request!("textDocument/rename")>( &RenameParams { - text_document_position: TextDocumentPositionParams { - text_document: f.tid(), - position: self - .text - .to_l_position( - self.text.cursor.first().position, - ) - .unwrap(), - }, + text_document_position_params: + TextDocumentPositionParams { + text_document: f.tid(), + position: self + .text + .to_l_position( + self.text.cursor.first().position, + ) + .unwrap(), + }, new_name, work_done_progress_params: default(), }, @@ -814,8 +850,11 @@ 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")>( + .request::<rust_analyzer::lsp::ext::CodeActionRequest>( &CodeActionParams { text_document: f.tid(), range: self @@ -826,7 +865,7 @@ impl Editor { ) .unwrap(), context: CodeActionContext { - trigger_kind: Some(CodeActionTriggerKind::INVOKED), + trigger_kind: Some(CodeActionTriggerKind::Invoked), // diagnostics: if let Some((lsp, p)) = lsp!() && let uri = Url::from_file_path(p).unwrap() && let Some(diag) = lsp.requests.diagnostics.get(&uri, &lsp.requests.diagnostics.guard()) { dbg!(diag.iter().filter(|x| { // self.text.l_range(x.range).unwrap().contains(&self.text.cursor) // }).cloned().collect()) } else { vec![] }, @@ -854,4 +893,35 @@ impl Editor { .request(lsp.runtime.spawn(fut)); } } + pub fn reload(&mut self) { + self.hist.push_if_changed(&mut self.text); + self.text.rope = Rope::from_str( + &std::fs::read_to_string(self.origin.as_ref().unwrap()) + .map(|x| x.replace("\r\n", "\n")) + .unwrap(), + ); + + self.text.cursor.first_mut().position = self + .text + .cursor + .first() + .position + .min(self.text.rope.len_chars()); + self.mtime = Self::modify(self.origin.as_deref()); + self.bar.last_action = "reloaded".into(); + self.hist.push(&mut self.text) + } + pub fn kill(&mut self, kr: &mut KillRing) { + if let x = self + .text + .cursor + .sels(&self.text) + .map(String::from) + .collect::<Box<[_]>>() + && !x.is_empty() + { + println!("kill {x:?}"); + kr.push(x); + } + } } |