A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/commands.rs')
| -rw-r--r-- | src/commands.rs | 395 |
1 files changed, 139 insertions, 256 deletions
diff --git a/src/commands.rs b/src/commands.rs index 9e01796..05135cb 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,281 +1,164 @@ use std::iter::repeat; use std::path::Path; -use std::process::Stdio; -use std::sync::Arc; use Default::default; -use Into::into; -use anyhow::{anyhow, bail}; use dsb::Cell; use dsb::cell::Style; -use lsp_types::*; -use rust_analyzer::lsp::ext::*; use crate::FG; -use crate::edi::{Editor, lsp_m}; -use crate::lsp::{Anonymize, PathURI}; -use crate::menu::charc; -use crate::menu::generic::{GenericMenu, MenuData}; -use crate::text::{RopeExt, SortTedits, col, color_}; +use crate::menu::{back, filter, next, score}; +use crate::text::{TextArea, col, color_}; -macro_rules! commands { - ($(#[doc = $d: literal] $t:tt $identifier: ident: $c:literal),+ $(,)?) => { - #[derive(Copy, Clone, PartialEq, Eq)] - pub enum Cmd { - $(#[doc = $d] $identifier),+ - } - impl Cmd { - pub const ALL: [Cmd; { [$($c),+].len() }] = [$(Self::$identifier,)+]; - pub fn name(self) -> &'static str { - match self { - $(Self::$identifier => $c,)+ - } - } - pub fn desc(self) -> &'static str { - match self { - $(Self::$identifier => $d,)+ - } - } - pub fn needs_lsp(self) -> bool { - match self { - $(Self::$identifier => stringify!($t) == "@",)+ - } - } - } - }; +const COMMANDS: [(&str, &str); 3] = [ + ("w", "Write / Save"), + ("q", "Quit"), + ("exit-vim-mode", "Go back to default editting mode"), +]; + +#[derive(Debug, Default)] +pub struct Commands { + pub tedit: TextArea, + pub selection: usize, + pub vo: usize, } -commands!( - /// move item at cursor down - @ RAMoveID: "move-item-down", - /// move item at cursor up - @ RAMoveIU: "move-item-up", - /// restart rust analyzer - @ RARestart: "ra-restart", - /// go to parent module - @ RAParent: "parent", - /// join lines under cursors. - @ RAJoinLines: "join-lines", - /// gets list of runnables - @ RARunnables: "runnables", - /// Open docs for type at cursor - @ RADocs: "open-docs", - /// Rebuilds rust-analyzer proc macros - @ RARebuildProcMacros: "rebuild-proc-macros", - /// Cancels current running rust-analyzer check process - @ RACancelFlycheck: "cancel-flycheck", - /// Opens Cargo.toml file for this workspace - @ RAOpenCargoToml: "open-cargo-toml", - /// Runs the test at the cursor - @ RARunTest: "run-test", -); -pub enum Cmds {} -impl MenuData for Cmds { - const HEIGHT: usize = 30; - type Data = (); - type Element<'a> = Cmd; - fn gn((): &()) -> impl Iterator<Item = Cmd> { - Cmd::ALL.into_iter() +const N: usize = 30; +impl Commands { + fn f(&self) -> String { + self.tedit.rope.to_string() + } + pub fn next(&mut self) { + let n = filter_c(self, &self.f()).count(); + // coz its bottom up + back::<N>(n, &mut self.selection, &mut self.vo); + } + + pub fn sel(&self) -> &str { + let f = self.f(); + score_c(filter_c(self, &f), &f)[self.selection].1 + } + + pub fn back(&mut self) { + let n = filter_c(self, &self.f()).count(); + next::<N>(n, &mut self.selection, &mut self.vo); } + pub fn cells(&self, c: usize, ws: &Path) -> Vec<Cell> { + let f = self.f(); + let mut out = vec![]; + let v = score_c(filter_c(self, &f), &f); + let vlen = v.len(); + let i = v.into_iter().zip(0..vlen).skip(self.vo).take(N).rev(); - fn r( - _: &Self::Data, - x: Cmd, - _: &Path, - c: usize, - selected: bool, - indices: &[u32], - to: &mut Vec<Cell>, - ) { - let bg = if selected { col!("#262d3b") } else { col!("#1c212b") }; + // let Some((s, x)) = i.next() else { + // return vec![]; + // }; - let ds: Style = Style::new(FG, bg); - let d: Cell = Cell { letter: None, style: ds }; - let mut b = vec![d; c]; - let (bgt, col, ty) = (col!("#FFFFFF"), col!("#ACACAC"), ""); - b.iter_mut().zip(ty.chars()).for_each(|(x, c)| { - *x = (Style::new(col, bgt) | Style::BOLD).basic(c) + // let mut q = Dq::<_, 13>::new((s, x)); + // for (s, x) in i { + // if q.first().0 <= s { + // q.push_front((s, x)); + // } + // } + + // fuzzy_aho_corasick::FuzzyAhoCorasickBuilder::new() + // .fuzzy( + // FuzzyLimits::new() + // .insertions(20) + // .deletions(2) + // .edits(4) + // .substitutions(5) + // .swaps(3), + // .penalties(FuzzyPenalties { + // ) + // insertion: 0.0, + // deletion: 1.0, + // substitution: 0.5, + // swap: 0.5, + // }) + // .build( + // y.iter().map(|x| x.filter_text.as_deref().unwrap_or(&x.label)), + // ) + // .search(filter, 0.25) + // .into_iter() + // .map(|x| &y[x.pattern_index]) + // // .take(13); + // // for x in y + // // .iter() + // // .filter(|x| { + // // x.filter_text + // // .as_deref() + // // .unwrap_or(&x.label) + // // .starts_with(filter) + // // }) + // .take(13) + i.for_each(|((_, x, indices), i)| { + r(x, ws, c, i == self.selection, &indices, &mut out) }); - let i = &mut b[..]; - let qualifier = x.desc().chars(); - let _left = i.len() as i32 - - (charc(&x.name()) as i32 + qualifier.clone().count() as i32) - - 3; - i.iter_mut() - .zip( - x.name() - .chars() - .chain([' ']) - .map(|x| ds.basic(x)) - .zip(0..) - .chain( - qualifier - .map(|x| { - Style { - bg, - fg: color_("#858685"), - ..default() - } - .basic(x) - }) - .zip(repeat(u32::MAX)), - ), - ) - .for_each(|(a, (b, i))| { - *a = b; - if indices.contains(&i) { - a.style |= (Style::BOLD, color_("#ffcc66")); - } - }); - to.extend(b); + out } } -pub type Commands = GenericMenu<Cmds>; -impl<'a> crate::menu::Key<'a> for Cmd { +fn score_c<'a>( + x: impl Iterator<Item = &'a str>, + filter: &'_ str, +) -> Vec<(u32, &'a str, Vec<u32>)> { + score(x, filter) +} + +fn filter_c<'a>( + _me: &'a Commands, + f: &'_ str, +) -> impl Iterator<Item = &'a str> { + filter(COMMANDS.into_iter().map(|(x, _)| x), f) +} +impl<'a> crate::menu::Key<'a> for &'a str { fn key(&self) -> impl Into<std::borrow::Cow<'a, str>> { - self.name() + *self } } +fn charc(c: &str) -> usize { + c.chars().count() +} +#[implicit_fn::implicit_fn] +fn r( + x: &str, + _workspace: &Path, + c: usize, + selected: bool, + indices: &[u32], + to: &mut Vec<Cell>, +) { + let bg = if selected { col!("#262d3b") } else { col!("#1c212b") }; -impl Editor { - pub fn handle_command( - &mut self, - z: Cmd, - w: Arc<winit::window::Window>, - ) -> anyhow::Result<()> { - if !z.needs_lsp() { - return Ok(()); - } - let Some((l, o)) = lsp_m!(self + p) else { - bail!("no lsp"); - }; - - match z { - Cmd::RAMoveIU | Cmd::RAMoveID => { - let r = self - .text - .to_l_position(*self.text.cursor.first()) - .unwrap(); - let mut x = l.request_immediate::<rust_analyzer::lsp::ext::MoveItem>(&MoveItemParams { - direction: if let Cmd::RAMoveIU = z { MoveItemDirection::Up } else { MoveItemDirection::Down }, - text_document: o.tid(), - range: Range { start : r, end : r}, - })?; + let ds: Style = Style::new(FG, bg); + let d: Cell = Cell { letter: None, style: ds }; + let mut b = vec![d; c]; + let (bgt, col, ty) = (col!("#FFFFFF"), col!("#ACACAC"), ""); + b.iter_mut().zip(ty.chars()).for_each(|(x, c)| { + *x = (Style::new(col, bgt) | Style::BOLD).basic(c) + }); + let i = &mut b[2..]; + let qualifier = COMMANDS.iter().find(|y| y.0 == x).unwrap().1.chars(); + let _left = i.len() as i32 + - (charc(&x) as i32 + qualifier.clone().count() as i32) + - 3; - x.sort_tedits(); - for t in x { - self.text.apply_snippet_tedit(&t)?; - } - } - Cmd::RARestart => { - _ = l.request::<ReloadWorkspace>(&())?.0; - } - Cmd::RAParent => { - let Some(GotoDefinitionResponse::Link([ref x])) = - l.request_immediate::<ParentModule>( - &TextDocumentPositionParams { - text_document: o.tid(), - position: self - .text - .to_l_position(*self.text.cursor.first()) - .unwrap(), - }, - )? - else { - self.bar.last_action = "no such parent".into(); - return Ok(()); - }; - self.open_loclink(x, w); - } - Cmd::RAJoinLines => { - let teds = - l.request_immediate::<JoinLines>(&JoinLinesParams { - ranges: self - .text - .cursor - .iter() - .filter_map(|x| { - self.text.to_l_range( - x.sel.map(into).unwrap_or(*x..*x), - ) - }) - .collect(), - text_document: o.tid(), - })?; - self.text - .apply_tedits(&mut { teds }) - .map_err(|_| anyhow!("couldnt apply edits"))?; - } - Cmd::RADocs => { - let u = l.request_immediate::<ExternalDocs>( - &TextDocumentPositionParams { - position: self - .text - .to_l_position(*self.text.cursor.first()) - .unwrap(), - text_document: o.tid(), - }, - )?; - use rust_analyzer::lsp::ext::ExternalDocsResponse::*; - std::process::Command::new("firefox-nightly") - .arg( - match &u { - WithLocal(ExternalDocsPair { - web: Some(x), - .. - }) if let Some("doc.rust-lang.org") = - x.domain() - && let Some(x) = - x.path().strip_prefix("/nightly/") - && option_env!("USER") == Some("os") => - format!("http://127.0.0.1:3242/{x}"), // i have a lighttpd server running - WithLocal(ExternalDocsPair { - local: Some(url), - .. - }) if let Ok(p) = url.to_file_path() - && p.exists() => - url.to_string(), - WithLocal(ExternalDocsPair { - web: Some(url), - .. - }) - | Simple(Some(url)) => url.to_string(), - _ => return Ok(()), - } - .to_string(), - ) - .stdout(Stdio::null()) - .spawn() - .unwrap(); + i.iter_mut() + .zip( + x.chars().chain([' ']).map(|x| ds.basic(x)).zip(0..).chain( + qualifier + .map(|x| { + Style { bg, fg: color_("#858685"), ..default() } + .basic(x) + }) + .zip(repeat(u32::MAX)), + ), + ) + .for_each(|(a, (b, i))| { + *a = b; + if indices.contains(&i) { + a.style |= (Style::BOLD, color_("#ffcc66")); } - Cmd::RARebuildProcMacros => { - _ = l.request::<RebuildProcMacros>(&())?; - } - Cmd::RACancelFlycheck => l.notify::<CancelFlycheck>(&())?, - Cmd::RAOpenCargoToml => { - let Some(GotoDefinitionResponse::Scalar(x)) = - &l.request_immediate::<OpenCargoToml>( - &OpenCargoTomlParams { text_document: o.tid() }, - )? - else { - bail!("wtf?"); - }; - self.open_loc(x, w); - } - Cmd::RARunnables => { - let x = l - .runtime - .block_on(l.runnables( - o, - self.text.to_l_position(*self.text.cursor.first()), - )?) - .anonymize()?; - // self.state = State::Runnables; - } - _ => unimplemented!(), - } - - Ok(()) - } + }); + to.extend(b); } |