A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/edi/st.rs')
| -rw-r--r-- | src/edi/st.rs | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/edi/st.rs b/src/edi/st.rs new file mode 100644 index 0000000..f487a0e --- /dev/null +++ b/src/edi/st.rs @@ -0,0 +1,118 @@ +use std::ops::Range; + +use Default::default; +use NamedKey::*; +use lsp_types::*; +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::text::TextArea; +use crate::{ + BoolRequest, CLICKING, InputRequest, act, ctrl, handle, shift, +}; + +impl Default for State { + fn default() -> Self { + Self::Default + } +} +rust_fsm::state_machine! { +#[derive(Debug)] +pub(crate) State => Action => Do + +Dead => K(Key => _) => Dead, +Default => { + K(Key::Character(x) if x == "s" && ctrl()) => Save [Save], + K(Key::Character(x) if x == "q" && ctrl()) => Dead [Quit], + K(Key::Character(x) if x == "v" && ctrl()) => _ [Paste], + K(Key::Character(x) if x == "z" && ctrl()) => _ [Undo], + K(Key::Character(x) if x == "y" && ctrl()) => _ [Redo], + K(Key::Character(x) if x == "f" && ctrl()) => Procure((default(), InputRequest::Search)), + K(Key::Character(x) if x == "o" && ctrl()) => Procure((default(), InputRequest::OpenFile)), + K(Key::Character(x) if x == "c" && ctrl()) => _, + K(Key::Character(x) if x == "l" && ctrl()) => _ [Symbols], + K(Key::Character(x) if x == "." && ctrl()) => _ [CodeAction], + K(Key::Character(x) if x == "0" && ctrl()) => _ [MatchingBrace], + K(Key::Character(x) if x == "`" && ctrl()) => _ [SpawnTerminal], + K(Key::Named(ArrowUp | ArrowLeft | ArrowDown | ArrowRight | Home | End) if shift()) => Selection(Range<usize> => 0..0) [StartSelection], + M(MouseButton::Left if shift()) => Selection(Range<usize> => 0..0) [StartSelection], + M(MouseButton::Left if ctrl()) => _ [GoToDefinition], + M(MouseButton::Left) => _ [MoveCursor], + M(MouseButton::Back) => _ [NavBack], + M(MouseButton::Forward) => _ [NavForward], + C(((usize, usize)) => .. if unsafe { CLICKING }) => Selection(0..0) [StartSelection], + Changed => RequestBoolean(BoolRequest => BoolRequest::ReloadFile), + C(_) => _ [Hover], + K(_) => _ [Edit], + M(_) => _, +}, +Symbols(Rq { result: Some(_x), request: None }) => { + K(Key::Named(Tab) if shift()) => _ [SymbolsSelectNext], + K(Key::Named(ArrowDown)) => _ [SymbolsSelectNext], + 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) => { + K(Key::Named(Escape)) => Default, + C(_) => _, + M(_) => _, + K(_) => _, +}, +CodeAction(Rq { result : Some(_x), request }) => { + K(Key::Named(Tab) if shift()) => _ [CASelectPrev], + K(Key::Named(ArrowDown | Tab)) => _ [CASelectNext], + K(Key::Named(ArrowUp)) => _ [CASelectPrev], + K(Key::Named(Enter | ArrowRight)) => _ [CASelectRight], + K(Key::Named(ArrowLeft)) => _ [CASelectLeft], +}, +CodeAction(RqS<act::CodeActions, lsp_request!("textDocument/codeAction")> => rq) => { + K(Key::Named(Escape)) => Default, + C(_) => _, + M(_) => _, + K(_) => _, +}, +Selection(x if shift()) => { + K(Key::Named(ArrowUp | ArrowLeft | ArrowDown | ArrowRight | Home | End)) => Selection(x) [UpdateSelection], + M(MouseButton => MouseButton::Left) => Selection(x) [ExtendSelectionToMouse], +}, // note: it does in fact fall through. this syntax is not an arm, merely shorthand. +Selection(x) => { + C(_ if unsafe { CLICKING }) => _ [ExtendSelectionToMouse], + C(_) => Selection(x), + M(MouseButton => MouseButton::Left) => Default [MoveCursor], + K(Key::Named(Backspace)) => Default [Delete(Range<usize> => x)], + K(Key::Character(y) if y == "x" && ctrl()) => Default [Cut(Range<usize> => x)], + K(Key::Character(y) if y == "c" && ctrl()) => Default [Copy(Range<usize> => x)], + K(Key::Character(y)) => Default [Insert((Range<usize>, SmolStr) => (x, y))], + K(_) => Default [Edit], +}, +Save => { + RequireFilename => Procure((TextArea, InputRequest) => (default(), InputRequest::SaveFile)), + Saved => Default, +}, +Procure((_, _)) => K(Key::Named(Escape)) => Default, +Procure((t, InputRequest::Search)) => K(Key::Named(Enter)) => Default [StartSearch(String => t.rope.to_string())], +Procure((t, InputRequest::SaveFile)) => K(Key::Named(Enter)) => Default [SaveTo(String => t.rope.to_string())], +Procure((t, InputRequest::OpenFile)) => K(Key::Named(Enter)) => Default [OpenFile(String => t.rope.to_string())], +Procure((t, a)) => K(k) => Procure((handle(k, t), a)), +RequestBoolean(t) => { + K(Key::Character(x) if x == "y") => Default [Boolean((BoolRequest, bool) => (t, true))], + K(Key::Character(x) if x == "n") => Default [Boolean((t, false))], + K(Key::Named(Escape)) => Default [Boolean((t, false))], + K(_) => RequestBoolean(t), + C(_) => _, + Changed => _, + M(_) => _, +}, +Search((x, y, m)) => { + M(MouseButton::Left) => Default [MoveCursor], + C(_) => Search((x, y, m)), + K(Key::Named(Enter) if shift()) => Search((x, y.checked_sub(1).unwrap_or(m-1), m)) [SearchChanged], + K(Key::Named(Enter)) => Search((Regex, usize, usize) => (x, (y+ 1) % m, m)) [SearchChanged], + K(_) => Default [Reinsert], +} +} |