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.rs410
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);
+ }
+ }
}