A simple CPU rendered GUI IDE experience.
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | LigaComicMono.ttf | bin | 0 -> 64044 bytes | |||
| -rw-r--r-- | fail.png | bin | 0 -> 15945 bytes | |||
| -rw-r--r-- | flake.lock | 82 | ||||
| -rw-r--r-- | flake.nix | 83 | ||||
| -rw-r--r-- | src/act.rs | 10 | ||||
| -rw-r--r-- | src/bar.rs | 12 | ||||
| -rw-r--r-- | src/com.rs (renamed from src/complete.rs) | 47 | ||||
| -rw-r--r-- | src/commands.rs | 395 | ||||
| -rw-r--r-- | src/edi.rs | 229 | ||||
| -rw-r--r-- | src/edi/st.rs | 47 | ||||
| -rw-r--r-- | src/hov.rs | 2 | ||||
| -rw-r--r-- | src/lsp.rs | 92 | ||||
| -rw-r--r-- | src/main.rs | 15 | ||||
| -rw-r--r-- | src/menu.rs | 10 | ||||
| -rw-r--r-- | src/menu/generic.rs | 129 | ||||
| -rw-r--r-- | src/rnd.rs | 49 | ||||
| -rw-r--r-- | src/sym.rs | 166 | ||||
| -rw-r--r-- | src/text.rs | 65 | ||||
| -rw-r--r-- | test | 525 |
20 files changed, 1177 insertions, 782 deletions
@@ -67,6 +67,7 @@ imara-diff = "0.2.0" vecto = "0.1.1" rangemap = { version = "1.7.1", features = ["const_fn", "nightly", "serde1"] } itern = "0.1.1" +png = "0.18.0" [profile.dev.package] rust-analyzer.opt-level = 3 diff --git a/LigaComicMono.ttf b/LigaComicMono.ttf Binary files differnew file mode 100644 index 0000000..a28bc72 --- /dev/null +++ b/LigaComicMono.ttf diff --git a/fail.png b/fail.png Binary files differnew file mode 100644 index 0000000..37d2dca --- /dev/null +++ b/fail.png diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..4c0ec34 --- /dev/null +++ b/flake.lock @@ -0,0 +1,82 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1769740369, + "narHash": "sha256-xKPyJoMoXfXpDM5DFDZDsi9PHArf2k5BJjvReYXoFpM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "6308c3b21396534d8aaeac46179c14c439a89b8a", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769915446, + "narHash": "sha256-f1F/umtX3ZD7fF9DHSloVHc0mnAT0ry0YK2jI/6E0aI=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "bc00300f010275e46feb3c3974df6587ff7b7808", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..dc427ab --- /dev/null +++ b/flake.nix @@ -0,0 +1,83 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = inputs @ { self, nixpkgs, flake-utils, rust-overlay, ... }: + flake-utils.lib.eachDefaultSystem ( + system: let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { inherit system overlays; }; + in { + devShells.default = with pkgs; mkShell rec { + buildInputs = [ + (rust-bin.nightly.latest.minimal.override { + extensions = [ "clippy" "rust-analyzer" "rust-docs" "rust-src" "miri" ]; + }) + # We use nightly rustfmt features. + (rust-bin.selectLatestNightlyWith (toolchain: toolchain.rustfmt)) + + # Vulkan dependencies + shaderc + spirv-tools + vulkan-loader + vulkan-tools + vulkan-tools-lunarg + vulkan-validation-layers + vulkan-extension-layer + + # winit dependencies + libxkbcommon + wayland + xorg.libX11 + xorg.libXcursor + xorg.libXi + xorg.libXrandr + SDL2 + + clang + libclang + glibc.dev + + valgrind + gdb + ]; + + LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs; + SHADERC_LIB_DIR = lib.makeLibraryPath [ shaderc ]; + VK_LAYER_PATH = "${vulkan-validation-layers}/share/vulkan/explicit_layer.d"; + }; + devShells.CI = with pkgs; mkShell rec { + buildInputs = [ + (rust-bin.stable.latest.minimal.override { + extensions = [ "clippy" ]; + # Windows CI unfortunately needs to cross-compile from within WSL because Nix doesn't + # work on Windows. + targets = [ "x86_64-pc-windows-msvc" ]; + }) + # We use nightly rustfmt features. + (rust-bin.selectLatestNightlyWith (toolchain: toolchain.rustfmt)) + + # Vulkan dependencies + shaderc + + # winit dependencies + libxkbcommon + wayland + xorg.libX11 + xorg.libXcursor + xorg.libXi + xorg.libXrandr + ]; + + LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs; + SHADERC_LIB_DIR = lib.makeLibraryPath [ shaderc ]; + }; + } + ); +} @@ -48,6 +48,16 @@ impl CodeActions { } pub fn down(&mut self) { + // let mut adj = |y: &mut usize, max| { + // *y += 1; + // if *y == max { + // self.vo = 0; + // *y = 0; + // } + // if *y >= self.vo + 13 { + // self.vo += 1; + // } + // }; match &mut self.inner { N::Many(x, Entry::Outside(y), _) => { let n = x.len(); @@ -98,14 +98,16 @@ impl Bar { }); } State::Command(x) => { - chain(['>'], x.tedit.rope.chars()).zip(row).for_each( - |(x, y)| { + ":".chars() + .zip(repeat(Style::BOLD | Style::ITALIC)) + .chain(s(&x.tedit.rope.to_string())) + .zip(row) + .for_each(|((x, z), y)| { *y = Cell { letter: Some(x), - style: Style { flags: 0, ..y.style }, + style: Style { flags: z, ..y.style }, } - }, - ); + }); } State::Symbols(Rq { result: Some(Symbols { tedit, .. }), diff --git a/src/complete.rs b/src/com.rs index fb326b0..e157787 100644 --- a/src/complete.rs +++ b/src/com.rs @@ -8,7 +8,7 @@ use lsp_types::*; use serde::{Deserialize, Serialize}; use crate::FG; -use crate::menu::{Key, back, charc, filter, next, score}; +use crate::menu::{Key, back, filter, next, score}; use crate::text::{col, color_, set_a}; #[derive(Serialize, Deserialize)] @@ -75,12 +75,57 @@ pub fn s(completion: &Complete, c: usize, f: &str) -> Vec<Cell> { .skip(completion.vo) .take(N); + // let Some((s, x)) = i.next() else { + // return vec![]; + // }; + + // 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, c, i == completion.selection, &indices, &mut out) }); out } +fn charc(c: &str) -> usize { + c.chars().count() +} #[implicit_fn::implicit_fn] fn r( x: &CompletionItem, 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); } @@ -1,6 +1,5 @@ use std::borrow::Cow; use std::collections::HashMap; -use std::fs::OpenOptions; use std::mem::take; use std::ops::ControlFlow; use std::path::{Path, PathBuf}; @@ -8,14 +7,12 @@ use std::sync::Arc; use std::time::SystemTime; use Default::default; -use anyhow::anyhow; use implicit_fn::implicit_fn; use lsp_server::{Connection, Request as LRq, 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 serde_derive::{Deserialize, Serialize}; use tokio::sync::oneshot::Sender; @@ -29,7 +26,7 @@ pub mod st; use st::*; use crate::bar::Bar; -use crate::complete::Complete; +use crate::com::Complete; use crate::hov::{self, Hovr}; use crate::lsp::{ self, Anonymize, Client, Map_, PathURI, RedrawAfter, RequestError, Rq, @@ -38,7 +35,9 @@ use crate::meta::META; use crate::sym::{Symbols, SymbolsList, SymbolsType}; use crate::text::cursor::{Ronge, ceach}; use crate::text::hist::{ClickHistory, Hist}; -use crate::text::{self, Mapping, RopeExt, SortTedits, TextArea}; +use crate::text::{ + self, CoerceOption, Mapping, RopeExt, SortTedits, TextArea, +}; use crate::{ BoolRequest, CDo, CompletionAction, CompletionState, act, alt, ctrl, filter, hash, shift, sig, sym, trm, @@ -178,11 +177,6 @@ macro_rules! change { ($self:ident, $w:expr) => { change!(@$self, Some($w)) }; - (just $self:ident) => { - lsp!($self + p).map(|(x, origin)| { - x.edit(&origin, $self.text.rope.to_string()).unwrap(); - }) - }; (@$self:ident, $w:expr) => { lsp!($self + p).map(|(x, origin)| { x.edit(&origin, $self.text.rope.to_string()).unwrap(); @@ -217,7 +211,6 @@ macro_rules! change { }); }; } - fn rooter(x: &Path) -> Option<PathBuf> { for f in std::fs::read_dir(&x).unwrap().filter_map(Result::ok) { if f.file_name() == "Cargo.toml" { @@ -267,6 +260,7 @@ impl Editor { .map(|x| x.path().to_owned()) .collect::<Vec<_>>() }); + assert!(me.tree.is_some()); let l = me.workspace.as_ref().map(|workspace| { let dh = std::panic::take_hook(); let main = std::thread::current_id(); @@ -388,10 +382,8 @@ impl Editor { self.bar.last_action = "saved".into(); lsp!(self + p).map(|(l, o)| { let v = l.runtime.block_on(l.format(o)).unwrap(); - if let Some(v) = v { - if let Err(()) = - self.text.apply_tedits_adjusting(&mut { v }) - { + for v in v.coerce() { + if let Err(()) = self.text.apply_adjusting(&v) { eprintln!("unhappy fmt") } } @@ -453,7 +445,7 @@ impl Editor { |x, (_, p)| { let Some(p) = p else { unreachable!() }; x.ok().flatten().map(|r| sym::Symbols { - data: (r, p.data.1, p.data.2), + r, selection: 0, vo: 0, ..p @@ -728,8 +720,6 @@ impl Editor { vo: 0, cells: cells.into(), }, - range: x.range, - // range: x.range.and_then(|x| text.l_range(x)), } .into(), )) @@ -809,8 +799,23 @@ impl Editor { self.hist.lc = text.cursor.clone(); } Some(Do::GoToDefinition) => { - if let Some(x) = self.requests.def.result.clone() { - self.open_loclink(&x, w.clone()); + if let Some(LocationLink { + ref target_uri, + target_range, + .. + }) = self.requests.def.result + { + self.open( + &target_uri.to_file_path().unwrap(), + w.clone(), + ) + .unwrap(); + + self.text.cursor.just( + self.text.l_position(target_range.start).unwrap(), + &self.text.rope, + ); + self.text.scroll_to_cursor(); } } Some(Do::InsertCursorAtMouse) => { @@ -826,7 +831,6 @@ impl Editor { _ => unreachable!(), } } - pub fn nav_back(&mut self) { self.chist.back().map(|x| { self.text.cursor.just( @@ -941,9 +945,9 @@ impl Editor { else { unreachable!() }; - x.data.2 = sym::SymbolsType::Document; + x.ty = sym::SymbolsType::Document; let p = p.to_owned(); - take(&mut x.data.0); + take(&mut x.r); *request = Some(( DropH::new(lsp.runtime.spawn( window.redraw_after(async move { @@ -956,12 +960,6 @@ impl Editor { (), )); }, - Some(Do::ProcessCommand(x)) => { - let z = x.sel(); - if let Err(e) = self.handle_command(z, window.clone()) { - self.bar.last_action = format!("{e}"); - } - } Some(Do::SymbolsHandleKey) => { if let Some(lsp) = lsp!(self) { let State::Symbols(Rq { result: Some(x), request }) = @@ -978,7 +976,7 @@ impl Editor { .is_some() || ptedit != x.tedit.rope { - if x.data.2 == SymbolsType::Workspace { + if x.ty == SymbolsType::Workspace { *request = Some(( DropH::new( lsp.runtime.spawn( @@ -1007,13 +1005,6 @@ impl Editor { unreachable!() }; x.next(); - match x.sel().at { - sym::GoTo::R(x) => { - let x = self.text.l_range(x).unwrap(); - self.text.vo = self.text.char_to_line(x.start); - } - _ => {} - } } Some(Do::SymbolsSelectPrev) => { let State::Symbols(Rq { result: Some(x), .. }) = @@ -1022,13 +1013,18 @@ impl Editor { unreachable!() }; x.back(); - match x.sel().at { - sym::GoTo::R(x) => { - let x = self.text.l_range(x).unwrap(); - self.text.vo = self.text.char_to_line(x.start); - } - _ => {} - } + } + Some(Do::CommandNext) => { + let State::Command(x) = &mut self.state else { + unreachable!() + }; + x.next(); + } + Some(Do::CommandPrev) => { + let State::Command(x) = &mut self.state else { + unreachable!() + }; + x.back(); } Some(Do::SymbolsSelect) => { let State::Symbols(Rq { result: Some(x), .. }) = @@ -1044,7 +1040,7 @@ impl Editor { let f = x .uri .to_file_path() - .map_err(|()| anyhow!("dammit"))? + .map_err(|()| anyhow::anyhow!("dammit"))? .canonicalize()?; self.state = State::Default; self.requests.complete = CompletionState::None; @@ -1058,7 +1054,7 @@ impl Editor { let p = self .text .l_position(r.start) - .ok_or(anyhow!("rah"))?; + .ok_or(anyhow::anyhow!("rah"))?; if p != 0 { self.text.cursor.just(p, &self.text.rope); } @@ -1236,58 +1232,14 @@ impl Editor { self.requests.complete { } else { - if let Some(x) = handle2( - &event.logical_key, - &mut self.text, - lsp!(self + p), - ) && let Some((l, p)) = lsp!(self + p) - && let Some( - InitializeResult { - capabilities: - ServerCapabilities { - document_on_type_formatting_provider: - Some(DocumentOnTypeFormattingOptions { - first_trigger_character, - more_trigger_character: Some(t), - }), - .. - }, - .. - }, - .., - ) = &l.initialized - && (first_trigger_character == first_trigger_character - || 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>( - &DocumentOnTypeFormattingParams { - text_document_position: - TextDocumentPositionParams { - text_document: p.tid(), - position: self - .text - .to_l_position( - *self.text.cursor.first(), - ) - .unwrap(), - }, - ch: x.into(), - options: FormattingOptions { - tab_size: 4, - ..default() - }, - }, - ) - { - x.sort_tedits(); - for x in x { - self.text.apply_snippet_tedit(&x).unwrap(); - } + handle2( + &event.logical_key, + &mut self.text, + lsp!(self + p), + ); } - }; self.text.scroll_to_cursor(); + inlay!(self); if cb4 != self.text.cursor.first() && let CompletionState::Complete(Rq { result: Some(c), @@ -1703,38 +1655,33 @@ impl Editor { let position = self.text.line_to_char(y); self.text.cursor.add(position + x, &self.text.rope); } + Some(Do::ProcessCommand(text)) => match text.sel() { + "w" => self.save(), + "q" => return ControlFlow::Break(()), + "exit-vim-mode" => { + self.state = State::Default; + } + _ => {} + }, None => {} } ControlFlow::Continue(()) } pub fn apply_wsedit(&mut self, x: WorkspaceEdit, f: &Path) { + let mut f_ = |edits: &mut [SnippetTextEdit]| { + edits.sort_tedits(); + // let mut first = false; + for edit in edits { + self.text.apply_snippet_tedit(edit).unwrap(); + } + }; let mut f2 = - |TextDocumentEdit { mut edits, text_document, .. }| { - edits.sort_tedits(); + |TextDocumentEdit { edits, text_document, .. }| { if text_document.uri != f.tid().uri { - let f = OpenOptions::new() - .read(true) - .create(true) - .write(true) - .open(text_document.uri.path()) - .unwrap(); - let mut r = Rope::from_reader(f).unwrap(); - for edit in &edits { - TextArea::apply_snippet_tedit_raw(edit, &mut r); - } - r.write_to( - OpenOptions::new() - .write(true) - .truncate(true) - .open(text_document.uri.path()) - .unwrap(), - ) - .unwrap(); - } else { - for edit in &edits { - self.text.apply_snippet_tedit(edit).unwrap(); - } + log::error!("didnt apply to {}", text_document.uri); + return; } + f_(&mut { edits }); }; match x { WorkspaceEdit { @@ -1859,23 +1806,8 @@ impl Editor { .unwrap(); }); } - self.set_title(w); Ok(()) } - pub fn set_title(&self, w: Option<Arc<Window>>) { - if let Some(x) = w - && let Some(t) = self.title() - { - x.set_title(&t); - } - } - pub fn title(&self) -> Option<String> { - [self.workspace.as_deref(), self.origin.as_deref()] - .try_map(|x| { - x.and_then(Path::file_name).and_then(|x| x.to_str()) - }) - .map(|[wo, or]| format!("gracilaria - {wo} - {or}")) - } pub fn store(&mut self) -> anyhow::Result<()> { let ws = self.workspace.clone(); @@ -1905,33 +1837,6 @@ impl Editor { } Ok(()) } - /// this is so dumb - pub fn open_loc( - &mut self, - Location { uri, range }: &Location, - w: Arc<Window>, - ) { - self.open(&uri.to_file_path().unwrap(), w.clone()).unwrap(); - - self.text.cursor.just( - self.text.l_position(range.start).unwrap(), - &self.text.rope, - ); - self.text.scroll_to_cursor(); - } - pub fn open_loclink( - &mut self, - LocationLink { target_uri, target_range, .. }: &LocationLink, - w: Arc<Window>, - ) { - self.open(&target_uri.to_file_path().unwrap(), w.clone()).unwrap(); - - self.text.cursor.just( - self.text.l_position(target_range.start).unwrap(), - &self.text.rope, - ); - self.text.scroll_to_cursor(); - } } use NamedKey::*; diff --git a/src/edi/st.rs b/src/edi/st.rs index de25b1b..3186b05 100644 --- a/src/edi/st.rs +++ b/src/edi/st.rs @@ -36,7 +36,44 @@ rust_fsm::state_machine! { pub(crate) State => #[derive(Debug)] pub(crate) Action => #[derive(Debug)] pub(crate) Do Dead => K(Key => _) => Dead, +Normal => { + K(Key::Character(x) if x == "i") => Insert, + K(Key::Character(x) if x == ":") => Command (Commands => default()), + K(Key::Character(x) if x == "/") => Procure((default(), InputRequest::Search)), + K(Key::Character(x) if x == "p") => _ [Paste], + K(Key::Character(x) if x == "u") => _ [Undo], + K(Key::Character(x) if x == "y") => _ [Redo], + K(Key::Named(Space)) => SpaceMode, + K(_) => _, + M(_) => _, + C(_) => _, +}, +Insert => { + K(Key::Named(Escape)) => Normal, + K(k) => _ [Edit], + K(_) => _, + M(_) => _, + C(_) => _, +}, +Command(_) => K(Key::Named(Escape)) => Normal, +Command(t) => K(Key::Named(Enter)) => Normal [ProcessCommand(Commands => t)], +Command(t) => K(Key::Named(Tab) if shift()) => _ [CommandPrev], +Command(t) => K(Key::Named(Tab)) => _ [CommandNext], +Command(mut t) => K(k) => Command({ handle2(&k, &mut t.tedit, None); t }), +Command(t) => C(_) => _, +Command(t) => M(_) => _, +Command(t) => K(_) => _, + +SpaceMode => K(Key::Named(Escape)) => Normal, +SpaceMode => K(Key::Character(x) if x == "f") => _ [Symbols], +SpaceMode => K(Key::Character(x) if x == "a") => _ [CodeAction], +SpaceMode => K(Key::Character(x) if x == "c") => _ [Comment(Self::SpaceMode)], +SpaceMode => C(_) => _, +SpaceMode => M(_) => _, +SpaceMode => K(_) => _, + Default => { + K(Key::Character(x) if x == "n" && ctrl()) => Normal, 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], @@ -50,7 +87,6 @@ Default => { K(Key::Character(x) if x == "0" && ctrl()) => _ [MatchingBrace], K(Key::Character(x) if x == "`" && ctrl()) => _ [SpawnTerminal], K(Key::Character(y) if y == "/" && ctrl()) => Default [Comment(State => State::Default)], - K(Key::Character(x) if x == "p" && ctrl()) => Command(Commands => Commands::default()), K(Key::Named(F1)) => Procure((default(), InputRequest::RenameSymbol)), K(Key::Named(k @ (ArrowUp | ArrowDown)) if alt()) => _ [InsertCursor(Direction => { if k == ArrowUp {Direction::Above} else { Direction::Below } @@ -71,19 +107,12 @@ Default => { K(_) => _ [Edit], M(_) => _, }, -Command(_) => K(Key::Named(Escape)) => Default, -Command(t) => K(Key::Named(Enter)) => Default [ProcessCommand(Commands => t)], -Command(mut t) => K(Key::Named(Tab) if shift()) => Command({ t.back();t }), -Command(mut t) => K(Key::Named(Tab)) => Command({ t.next(); t }), -Command(mut t) => K(k) => Command({ handle2(&k, &mut t.tedit, None); t }), -Command(t) => C(_) => _, -Command(t) => K(_) => _, Symbols(Rq { result: Some(_x), request: _rq }) => { 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(Key::Named(Escape)) => Normal, }, Symbols(Rq::<Symbols, Option<SymbolsList>, (), AQErr> => _rq) => { K(Key::Character(x) if x == "d" && ctrl()) => _ [SwitchType], // crahs cond methinks @@ -306,8 +306,6 @@ fn t() { pub struct Hovr { pub(crate) span: Option<[(VisualX, usize); 2]>, pub(crate) item: crate::text::CellBuffer, - #[serde(skip)] - pub(crate) range: Option<lsp_types::Range>, } pub type VisualX = usize; @@ -24,7 +24,6 @@ use lsp_server::{ use lsp_types::notification::*; use lsp_types::request::*; use lsp_types::*; -use rust_analyzer::lsp::ext::*; use serde::{Deserialize, Serialize}; use serde_json::json; use tokio::sync::oneshot; @@ -64,7 +63,6 @@ pub enum RequestError<X> { Rx(PhantomData<X>), Failure(Re, #[serde(skip)] Option<Backtrace>), Cancelled(Re, DiagnosticServerCancellationData), - Send(Message), } pub type AQErr = RequestError<LSPError>; impl Request for LSPError { @@ -80,7 +78,6 @@ pub trait Anonymize<T> { impl<T, E> Anonymize<T> for Result<T, RequestError<E>> { fn anonymize(self) -> Result<T, RequestError<LSPError>> { self.map_err(|e| match e { - RequestError::Send(x) => RequestError::Send(x), RequestError::Rx(_) => RequestError::Rx(PhantomData), RequestError::Failure(r, b) => RequestError::Failure(r, b), RequestError::Cancelled(r, d) => RequestError::Cancelled(r, d), @@ -99,16 +96,9 @@ impl<X: Request + std::fmt::Debug> std::error::Error for RequestError<X> { None } } -impl<X> From<SendError<Message>> for RequestError<X> { - fn from(x: SendError<Message>) -> Self { - Self::Send(x.into_inner()) - } -} impl<X: Request> Display for RequestError<X> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Send(x) => - write!(f, "{} failed; couldnt send {x:?}", X::METHOD), Self::Rx(_) => write!(f, "{} failed; couldnt get from thingy", X::METHOD), Self::Failure(x, bt) => write!( @@ -134,12 +124,6 @@ impl Client { pub fn cancel(&self, rid: i32) { _ = self.notify::<Cancel>(&CancelParams { id: rid.into() }); } - pub fn request_immediate<'me, X: Request>( - &'me self, - y: &X::Params, - ) -> Result<X::Result, RequestError<X>> { - self.runtime.block_on(self.request::<X>(y)?.0) - } #[must_use] pub fn request<'me, X: Request>( &'me self, @@ -465,14 +449,10 @@ impl Client { >, > { self.request::<lsp_request!("workspace/symbol")>( - &lsp_types::WorkspaceSymbolParams { + &WorkspaceSymbolParams { query: f, - search_scope: Some( - lsp_types::WorkspaceSymbolSearchScope::Workspace, - ), - search_kind: Some( - lsp_types::WorkspaceSymbolSearchKind::AllSymbols, - ), + search_scope: Some(WorkspaceSymbolSearchScope::Workspace), + search_kind: Some(WorkspaceSymbolSearchKind::AllSymbols), ..Default::default() }, ) @@ -484,13 +464,15 @@ impl Client { f: &Path, t: &'a mut TextArea, ) { - if let Ok([x]) = self.runtime.block_on( - self.request::<MatchingBrace>(&MatchingBraceParams { - text_document: f.tid(), - positions: vec![ - t.to_l_position(*t.cursor.first()).unwrap(), - ], - }) + if let Ok(Some([x])) = self.runtime.block_on( + self.request::<lsp_request!("experimental/matchingBrace")>( + &MatchingBraceParams { + text_document: f.tid(), + positions: vec![ + t.to_l_position(*t.cursor.first()).unwrap(), + ], + }, + ) .unwrap() .0, ) { @@ -555,6 +537,14 @@ impl Client { ) .unwrap() .0 + .map(|x| { + x.map(|x| { + x.map(|mut x| { + x.sort_tedits(); + x + }) + }) + }) } pub fn rq_semantic_tokens( &'static self, @@ -603,10 +593,12 @@ impl Client { let r = self .runtime .block_on( - self.request::<OnEnter>(&TextDocumentPositionParams { - text_document: f.tid(), - position: t.to_l_position(*c).unwrap(), - }) + self.request::<lsp_request!("experimental/onEnter")>( + &TextDocumentPositionParams { + text_document: f.tid(), + position: t.to_l_position(*c).unwrap(), + }, + ) .unwrap() .0, ) @@ -622,25 +614,6 @@ impl Client { } }); } - pub fn runnables( - &self, - t: &Path, - c: Option<Position>, - ) -> Result< - impl Future< - Output = Result< - Vec<Runnable>, - RequestError<Runnables>, - >, - >, - SendError<Message>, - > { - self.request::<Runnables>(&RunnablesParams { - text_document: t.tid(), - position: c, - }) - .map(|(x, _)| x) - } } pub fn run( (tx, rx): (Sender<Message>, Receiver<Message>), @@ -695,9 +668,6 @@ pub fn run( ..default() }), text_document: Some(TextDocumentClientCapabilities { - on_type_formatting: Some(DocumentOnTypeFormattingClientCapabilities { - dynamic_registration: Some(false), - }), document_highlight: Some(default()), formatting: Some(DynamicRegistrationClientCapabilities { dynamic_registration: Some(false) }), inlay_hint: Some(InlayHintClientCapabilities { dynamic_registration: None, resolve_support: Some(InlayHintResolveClientCapabilities { @@ -863,7 +833,6 @@ pub fn run( "hoverActions": true, "workspaceSymbolScopeKindFiltering": true, "onEnter": true, - "localDocs": true, }}), ..default() }, @@ -879,11 +848,6 @@ pub fn run( "enable": true, "attributes": { "enable": true } }, - "hover": { - "documentation": { - "keywords": { "enable": false }, - }, - }, "inlayHints": { "closureReturnTypeHints": { "enable": "with_block" }, "closingBraceHints": { "minLines": 5 }, @@ -892,7 +856,6 @@ pub fn run( "rangeExclusiveHints": { "enable": true }, "closureCaptureHints": { "enable": true }, }, - "typing": { "triggerChars": ".=<>{(+" }, "assist": { "preferSelf": true }, "checkOnSave": true, "diagnostics": { "enable": true }, @@ -919,9 +882,6 @@ pub fn run( "autoself": { "enable": true, }, "privateEditable": { "enable": true }, }, - "imports": { - "granularity": "group", - }, }}), trace: None, workspace_folders: Some(vec![workspace]), diff --git a/src/main.rs b/src/main.rs index cdde4c4..1311b32 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,5 @@ #![feature( btree_set_entry, - associated_type_defaults, - array_try_map, tuple_trait, unboxed_closures, fn_traits, @@ -45,6 +43,9 @@ mod act; mod edi; mod git; mod meta; +// mod new; +// mod new; +mod commands; mod rnd; mod sym; mod trm; @@ -80,8 +81,7 @@ use crate::edi::st::*; use crate::lsp::RqS; use crate::text::{TextArea, col, is_word}; mod bar; -mod commands; -mod complete; +mod com; pub mod hov; mod lsp; pub mod menu; @@ -139,7 +139,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { None => None, }; let (fw, fh) = dsb::dims(&fonts.bold, ls); - let title = ed.title(); + let app = winit_app::WinitAppBuilder::with_init( move |elwt| { let window = winit_app::make_window(elwt, |x| { @@ -159,8 +159,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { if let Some(x) = w.take() { x.send(window.clone()).unwrap(); } - let w_ = window.clone(); - title.as_deref().map(move |x| w_.set_title(x)); + window.set_ime_allowed(true); window.set_ime_purpose(winit::window::ImePurpose::Terminal); let context = @@ -480,7 +479,7 @@ rust_fsm::state_machine! { Complete(_x) => K(_) => _ [Request(CompletionContext { trigger_kind: CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS, trigger_character:None })], } -use complete::Complete; +use com::Complete; impl Default for CompletionState { fn default() -> Self { Self::None diff --git a/src/menu.rs b/src/menu.rs index 3c5f7a1..5c2d092 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -1,4 +1,3 @@ -pub mod generic; use std::borrow::Cow; use std::cmp::Reverse; use std::sync::LazyLock; @@ -89,12 +88,3 @@ pub trait Key<'a> { self.key().into() } } -pub fn charc(c: &str) -> usize { - c.chars().count() -} - -impl<'a> crate::menu::Key<'a> for &'a str { - fn key(&self) -> impl Into<std::borrow::Cow<'a, str>> { - *self - } -} diff --git a/src/menu/generic.rs b/src/menu/generic.rs deleted file mode 100644 index ba48d76..0000000 --- a/src/menu/generic.rs +++ /dev/null @@ -1,129 +0,0 @@ -use std::fmt::Debug; -use std::path::Path; - -use Default::default; -use dsb::Cell; - -use crate::menu::{Key, back, filter, next, score}; -use crate::text::TextArea; - -pub struct GenericMenu<T: MenuData> { - pub data: T::Data, - pub tedit: TextArea, - pub selection: usize, - pub vo: usize, -} -impl<T: MenuData<Data: Clone>> Clone for GenericMenu<T> { - fn clone(&self) -> Self { - Self { - data: self.data.clone(), - tedit: self.tedit.clone(), - selection: self.selection.clone(), - vo: self.vo.clone(), - } - } -} -impl<T: MenuData<Data: Default>> Default for GenericMenu<T> { - fn default() -> Self { - Self { - data: default(), - tedit: default(), - selection: default(), - vo: default(), - } - } -} -impl<T: MenuData<Data: Debug>> Debug for GenericMenu<T> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct(&format!( - "GenericMenu<{}>", - std::any::type_name::<T>() - )) - .field("data", &self.data) - .field("tedit", &self.tedit) - .field("selection", &self.selection) - .field("vo", &self.vo) - .finish() - } -} -pub trait MenuData { - const HEIGHT: usize = 30; - type Data; - type Element<'a>: Key<'a>; - - fn gn<'a>( - x: &'a Self::Data, - ) -> impl Iterator<Item = Self::Element<'a>>; - fn r( - data: &'_ Self::Data, - elem: Self::Element<'_>, - workspace: &Path, - columns: usize, - selected: bool, - indices: &[u32], - to: &mut Vec<Cell>, - ); - fn filter_c<'a>( - x: &'a Self::Data, - f: &str, - ) -> impl Iterator<Item = Self::Element<'a>> { - filter(Self::gn(x), f) - } - fn score_c<'a>( - x: impl Iterator<Item = Self::Element<'a>>, - f: &str, - ) -> Vec<(u32, Self::Element<'a>, Vec<u32>)> { - score(x, f) - } -} - -impl<T: MenuData> GenericMenu<T> { - fn f(&self) -> String { - self.tedit.rope.to_string() - } - pub fn next(&mut self) - where - [(); T::HEIGHT]:, - { - let n = T::filter_c(&self.data, &self.f()).count(); - // coz its bottom up - back::<{ T::HEIGHT }>(n, &mut self.selection, &mut self.vo); - } - - pub fn sel(&self) -> T::Element<'_> { - let f = self.f(); - T::score_c(T::filter_c(&self.data, &f), &f) - .swap_remove(self.selection) - .1 - } - - pub fn back(&mut self) - where - [(); T::HEIGHT]:, - { - let n = T::filter_c(&self.data, &self.f()).count(); - next::<{ T::HEIGHT }>(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 = T::score_c(T::filter_c(&self.data, &f), &f); - let vlen = v.len(); - let i = - v.into_iter().zip(0..vlen).skip(self.vo).take(T::HEIGHT).rev(); - - i.for_each(|((_, x, indices), i)| { - T::r( - &self.data, - x, - ws, - c, - i == self.selection, - &indices, - &mut out, - ) - }); - - out - } -} @@ -21,8 +21,8 @@ use crate::edi::{Editor, lsp_m}; use crate::lsp::Rq; use crate::text::{CoerceOption, RopeExt, col, color_}; use crate::{ - BG, BORDER, CompletionAction, CompletionState, FG, FONT, complete, - filter, lsp, sig, + BG, BORDER, CompletionAction, CompletionState, FG, FONT, com, filter, + lsp, sig, }; #[implicit_fn::implicit_fn] @@ -134,15 +134,6 @@ pub fn render( x.style.fg = col!("#FFD173"); }); } } - if let Some(crate::hov::Hovr{ range:Some(r),..} ) = &ed.requests.hovering.result { - x.get_range(text.map_to_visual((r.start.character as _, r.start.line as _)), - text.map_to_visual((r.end.character as usize, r.end.line as _))) - .for_each(|x| { - x.style.secondary_color = col!("#73d0ff"); - x.style.flags |= Style::UNDERCURL; - }); - // x.range; - } if let Some((lsp, p)) = lsp_m!(ed + p) && let uri = Url::from_file_path(p).unwrap() && let Some(diag) = lsp.diagnostics.get(&uri, &lsp.diagnostics.guard()) { #[derive(Copy, Clone, Debug)] enum EType { @@ -678,13 +669,13 @@ pub fn render( BORDER, ); } - State::Command(x) => 'out: { + State::Symbols(Rq { result: Some(x), .. }) => 'out: { let ws = ed.workspace.as_deref().unwrap(); let c = x.cells(50, ws); // let (_x, _y) = text.cursor_visual(); let _x = 0; let _y = r - 1; - let Ok((_, left, top, w, h)) = place_around( + let Ok((_is_above, left, top, w, h)) = place_around( (_x, _y), i.copy(), &c, @@ -707,14 +698,14 @@ pub fn render( h as _, BORDER, ); - } - State::Symbols(Rq { result: Some(x), .. }) => 'out: { + }, + State::Command(x) => 'out: { let ws = ed.workspace.as_deref().unwrap(); let c = x.cells(50, ws); // let (_x, _y) = text.cursor_visual(); let _x = 0; let _y = r - 1; - let Ok((_is_above, left, top, w, h)) = place_around( + let Ok((is_above, left, top, w, mut h)) = place_around( (_x, _y), i.copy(), &c, @@ -744,7 +735,7 @@ pub fn render( CompletionState::Complete(Rq { result: Some(ref x), .. }) => { - let c = complete::s(x, 40, &filter(&text)); + let c = com::s(x, 40, &filter(&text)); if c.len() == 0 { ed.requests .complete @@ -942,17 +933,15 @@ pub fn render( } pub fn simplify_path(x: &str) -> String { - static DEP: LazyLock<Regex> = LazyLock::new(|| { - Regex::new(r"\.cargo\/git\/checkouts\/(?<name>[^/]+)\-[a-f0-9]+\/[a-f0-9]+").unwrap() - }); - static DEP2: LazyLock<Regex> = LazyLock::new(|| { - Regex::new(r"\.cargo\/registry\/src/index.crates.io-[0-9a-f]+/(?<name>[^/]+)\-(?<version>[0-9]+\.[0-9]+\.[0-9]+)").unwrap() - }); - static RUST_SRC: LazyLock<Regex> = LazyLock::new(|| { - Regex::new(r".rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library").unwrap() - }); - let x = x.replace(env!("HOME"), " "); - [(&*RUST_SRC, " "), (&*DEP, " /$name"), (&*DEP2, " /$name")] - .into_iter() - .fold(x, |acc, (r, repl)| r.replace(&acc, repl).into_owned()) + static DEP: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\.cargo\/git\/checkouts\/(?<name>[^/]+)\-[a-f0-9]+\/[a-f0-9]+").unwrap()); + static DEP2: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\.cargo\/registry\/src/index.crates.io-[0-9a-f]+/(?<name>[^/]+)\-(?<version>[0-9]+\.[0-9]+\.[0-9]+)").unwrap()); + static RUST_SRC: LazyLock<Regex> = LazyLock::new(|| Regex::new(r".rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library").unwrap()); + let x = x.replace(env!("HOME"), " "); + [ + (&*RUST_SRC, " "), + (&*DEP, " /$name"), + (&*DEP2, " /$name"), + ].into_iter().fold(x, |acc, (r, repl)| { + r.replace(&acc, repl).into_owned() + }) } @@ -9,50 +9,18 @@ use itern::Iter3; use lsp_types::*; use crate::FG; -use crate::menu::generic::{GenericMenu, MenuData}; -use crate::menu::{Key, charc}; -use crate::text::{col, color_, set_a}; -pub enum Symb {} -impl MenuData for Symb { - type Data = (SymbolsList, Vec<SymbolInformation>, SymbolsType); +use crate::menu::{Key, back, filter, next, score}; +use crate::text::{TextArea, col, color_, set_a}; - type Element<'a> = UsedSI<'a>; - - fn gn( - (r, tree, _): &Self::Data, - ) -> impl Iterator<Item = Self::Element<'_>> { - match r { - SymbolsList::Document(DocumentSymbolResponse::Flat(x)) => - Iter3::A(x.iter().map(UsedSI::from)), - SymbolsList::Document(DocumentSymbolResponse::Nested(x)) => - Iter3::B(x.iter().flat_map(|x| gen move { - let mut q = VecDeque::with_capacity(12); - q.push_back(x); - while let Some(x) = q.pop_front() { - q.extend(x.children.iter().flatten()); - yield x.into(); - } - })), - SymbolsList::Workspace(WorkspaceSymbolResponse::Flat(x)) => - Iter3::C(chain(tree, x.iter()).map(UsedSI::from)), - _ => unreachable!("please no"), - } - } - - fn r( - &(.., sty): &Self::Data, - x: Self::Element<'_>, - workspace: &Path, - c: usize, - selected: bool, - indices: &[u32], - to: &mut Vec<Cell>, - ) { - r(x, workspace, c, selected, indices, to, sty) - } +#[derive(Debug, Default)] +pub struct Symbols { + pub r: SymbolsList, + pub tree: Vec<SymbolInformation>, + pub tedit: TextArea, + pub selection: usize, + pub vo: usize, + pub ty: SymbolsType, } -pub type Symbols = GenericMenu<Symb>; - #[derive(Debug, Eq, PartialEq, Clone, Copy)] pub enum GoTo<'a> { Loc(&'a Location), @@ -124,8 +92,8 @@ impl Default for SymbolsList { Self::Workspace(WorkspaceSymbolResponse::Flat(vec![])) } } - -impl GenericMenu<Symb> { +const N: usize = 30; +impl Symbols { pub fn new(tree: &[PathBuf]) -> Self { let tree = tree .iter() @@ -145,7 +113,80 @@ impl GenericMenu<Symb> { tags: None, }) .collect(); - Self { data: (default(), tree, default()), ..default() } + Self { tree, ..Default::default() } + } + 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) -> UsedSI<'_> { + 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(); + + // let Some((s, x)) = i.next() else { + // return vec![]; + // }; + + // 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, self.ty) + }); + + out } } @@ -154,6 +195,41 @@ impl<'a> Key<'a> for UsedSI<'a> { self.name } } +fn score_c<'a>( + x: impl Iterator<Item = UsedSI<'a>>, + filter: &'_ str, +) -> Vec<(u32, UsedSI<'a>, Vec<u32>)> { + score(x, filter) +} + +fn filter_c<'a>( + syms: &'a Symbols, + f: &'_ str, +) -> impl Iterator<Item = UsedSI<'a>> { + let x = &syms.r; + filter( + match x { + SymbolsList::Document(DocumentSymbolResponse::Flat(x)) => + Iter3::A(x.iter().map(UsedSI::from)), + SymbolsList::Document(DocumentSymbolResponse::Nested(x)) => + Iter3::B(x.iter().flat_map(|x| gen move { + let mut q = VecDeque::with_capacity(12); + q.push_back(x); + while let Some(x) = q.pop_front() { + q.extend(x.children.iter().flatten()); + yield x.into(); + } + })), + SymbolsList::Workspace(WorkspaceSymbolResponse::Flat(x)) => + Iter3::C(chain(&syms.tree, x.iter()).map(UsedSI::from)), + _ => unreachable!("please no"), + }, + f, + ) +} +fn charc(c: &str) -> usize { + c.chars().count() +} #[implicit_fn::implicit_fn] fn r<'a>( x: UsedSI<'a>, diff --git a/src/text.rs b/src/text.rs index 2f4d30a..00a2e65 100644 --- a/src/text.rs +++ b/src/text.rs @@ -478,50 +478,19 @@ impl TextArea { } Ok(()) } - pub fn apply_snippet_tedit_raw( - SnippetTextEdit { range,new_text, insert_text_format, .. }: &SnippetTextEdit, - text: &'_ mut Rope, - ) -> Option<()> { - match insert_text_format { - Some(lsp_types::InsertTextFormat::SNIPPET) => { - let begin = text.l_position(range.start)?; - let end = text.l_position(range.end)?; - text.try_remove(begin..end).ok()?; - let (_, tex) = - crate::sni::Snippet::parse(&new_text, begin)?; - text.try_insert(begin, &tex).ok()?; - } - _ => { - let begin = text.l_position(range.start)?; - let end = text.l_position(range.end)?; - text.try_remove(begin..end).ok()?; - text.try_insert(begin, &new_text).ok()?; - } - } - Some(()) - } pub fn apply_snippet_tedit( &mut self, - SnippetTextEdit { range,new_text, insert_text_format, .. }: &SnippetTextEdit, + SnippetTextEdit { text_edit, insert_text_format, .. }: &SnippetTextEdit, ) -> anyhow::Result<()> { match insert_text_format { - Some(lsp_types::InsertTextFormat::SNIPPET) => self - .apply_snippet(&TextEdit { - range: range.clone(), - new_text: new_text.clone(), - }) - .unwrap(), + Some(lsp_types::InsertTextFormat::SNIPPET) => + self.apply_snippet(&text_edit).unwrap(), _ => { - self.apply_adjusting(&TextEdit { - range: range.clone(), - new_text: new_text.clone(), - }) - .unwrap(); + self.apply_adjusting(text_edit).unwrap(); } } Ok(()) } - pub fn apply_snippet(&mut self, x: &TextEdit) -> anyhow::Result<()> { let begin = self .l_position(x.range.start) @@ -948,7 +917,7 @@ impl TextArea { // arc_swap::Guard<Arc<Box<[SemanticToken]>>>, // &SemanticTokensLegend, // )>; - if leg.is_none() || self.tokens.is_empty() { + if leg.is_none() { self.tree_sit(path, &mut cells); } if let Some(tabstops) = &self.tabstops { @@ -1110,28 +1079,6 @@ impl TextArea { } best } - - pub(crate) fn apply_tedits_adjusting( - &mut self, - teds: &mut [TextEdit], - ) -> Result<(), ()> { - teds.sort_tedits(); - for ted in teds { - self.apply_adjusting(ted)?; - } - Ok(()) - } - - pub(crate) fn apply_tedits( - &mut self, - teds: &mut [TextEdit], - ) -> Result<(), ()> { - teds.sort_tedits(); - for ted in teds { - self.apply(ted)?; - } - Ok(()) - } } pub fn is_word(r: char) -> bool { @@ -1730,7 +1677,7 @@ impl SortTedits for [TextEdit] { } impl SortTedits for [SnippetTextEdit] { fn sort_tedits(&mut self) { - self.as_mut().sort_by_key(|t| Reverse(t.range.start)); + self.as_mut().sort_by_key(|t| Reverse(t.text_edit.range.start)); } } @@ -0,0 +1,525 @@ +gracilaria v0.1.0 (/run/media/Programming/CodingShit/Rust/Act5Scratch/gracilaria) +├── amap v0.1.4 (proc-macro) +│ ├── itertools v0.14.0 +│ │ └── either v1.15.0 +│ ├── proc-macro2 v1.0.106 +│ │ └── unicode-ident v1.0.22 +│ ├── quote v1.0.44 +│ │ └── proc-macro2 v1.0.106 (*) +│ └── syn v2.0.114 +│ ├── proc-macro2 v1.0.106 (*) +│ ├── quote v1.0.44 (*) +│ └── unicode-ident v1.0.22 +├── anyhow v1.0.100 +├── arc-swap v1.8.0 +│ └── rustversion v1.0.22 (proc-macro) +├── array_chunks v1.0.0 +├── atools v0.1.12 +├── bendy v0.6.1 +│ ├── rustversion v1.0.22 (proc-macro) +│ ├── serde v1.0.228 +│ │ ├── serde_core v1.0.228 +│ │ └── serde_derive v1.0.228 (proc-macro) +│ ├── serde_bytes v0.11.19 +│ │ └── serde_core v1.0.228 +│ └── thiserror v2.0.18 +│ └── thiserror-impl v2.0.18 (proc-macro) +├── car v0.1.3 (proc-macro) +│ ├── proc-macro2 v1.0.106 (*) +│ ├── quote v1.0.44 (*) +│ └── syn v2.0.114 (*) +├── clipp v0.1.1 +├── crossbeam v0.8.4 +│ ├── crossbeam-channel v0.5.15 +│ │ └── crossbeam-utils v0.8.21 +│ ├── crossbeam-deque v0.8.6 +│ │ ├── crossbeam-epoch v0.9.18 +│ │ └── crossbeam-utils v0.8.21 +│ ├── crossbeam-epoch v0.9.18 (*) +│ ├── crossbeam-queue v0.3.12 +│ │ └── crossbeam-utils v0.8.21 +│ └── crossbeam-utils v0.8.21 +├── diff-match-patch-rs v0.5.1 (https://git.bendn.org/dmp#8d727531) +│ ├── percent-encoding v2.3.2 +│ ├── serde v1.0.228 (*) +│ └── serde_derive v1.0.228 (proc-macro) (*) +├── dsb v0.1.0 (https://git.bendn.org/dsb#02744132) +│ ├── array_chunks v1.0.0 +│ ├── atools v0.1.12 (https://git.bendn.org/atools#fd0a7b17) +│ ├── car v0.1.3 (proc-macro) (*) +│ ├── fimg v0.4.51 (https://git.bendn.org/fimg#cf01f538) +│ │ ├── array_chunks v1.0.0 +│ │ ├── atools v0.1.12 +│ │ ├── car v0.1.3 (proc-macro) (*) +│ │ ├── clipline v0.4.0 +│ │ ├── fer v0.1.1 +│ │ ├── hinted v1.0.0 +│ │ ├── libc v0.2.180 +│ │ ├── lower v0.2.1 +│ │ ├── mattr v0.0.2 +│ │ ├── png v0.17.16 +│ │ ├── qwant v1.0.3 +│ │ ├── umath v0.0.7 +│ │ └── vecto v0.1.1 +│ ├── implicit-fn v0.1.0 (proc-macro) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.114 (*) +│ ├── itertools v0.14.0 (*) +│ ├── lower v0.2.1 (*) +│ ├── lru-cache v0.1.2 +│ │ └── linked-hash-map v0.5.6 +│ ├── serde v1.0.228 (*) +│ ├── swash v0.2.6 +│ │ ├── skrifa v0.37.0 +│ │ ├── yazi v0.2.1 +│ │ └── zeno v0.3.3 +│ ├── swizzle v0.1.0 +│ └── umath v0.0.7 +├── env_logger v0.11.8 +│ ├── anstream v0.6.21 +│ │ ├── anstyle v1.0.13 +│ │ ├── anstyle-parse v0.2.7 +│ │ ├── anstyle-query v1.1.5 +│ │ ├── colorchoice v1.0.4 +│ │ ├── is_terminal_polyfill v1.70.2 +│ │ └── utf8parse v0.2.2 +│ ├── anstyle v1.0.13 +│ ├── env_filter v0.1.4 +│ │ ├── log v0.4.29 +│ │ └── regex v1.12.2 +│ ├── jiff v0.2.18 +│ └── log v0.4.29 +├── fimg v0.4.51 (https://git.bendn.org/fimg#cf01f538) (*) +├── helix-core v25.7.1 (https://git.bendn.org/helix#bcfbb875) +│ ├── anyhow v1.0.100 +│ ├── arc-swap v1.8.0 (*) +│ ├── bitflags v2.10.0 +│ ├── chrono v0.4.43 +│ │ └── num-traits v0.2.19 +│ │ [build-dependencies] +│ ├── encoding_rs v0.8.35 +│ │ └── cfg-if v1.0.4 +│ ├── foldhash v0.2.0 +│ ├── globset v0.4.16 +│ │ ├── aho-corasick v1.1.4 +│ │ ├── bstr v1.12.1 +│ │ ├── log v0.4.29 +│ │ ├── regex-automata v0.4.13 +│ │ └── regex-syntax v0.8.8 +│ ├── helix-loader v25.7.1 (https://git.bendn.org/helix#bcfbb875) +│ │ ├── anyhow v1.0.100 +│ │ ├── cc v1.2.55 +│ │ ├── etcetera v0.10.0 +│ │ ├── helix-stdx v25.7.1 (https://git.bendn.org/helix#bcfbb875) +│ │ ├── log v0.4.29 +│ │ ├── once_cell v1.21.3 +│ │ ├── serde v1.0.228 (*) +│ │ ├── tempfile v3.24.0 +│ │ ├── threadpool v1.8.1 +│ │ ├── toml v0.9.11+spec-1.1.0 +│ │ └── tree-house v0.3.0 +│ ├── helix-parsec v25.7.1 (https://git.bendn.org/helix#bcfbb875) +│ ├── helix-stdx v25.7.1 (https://git.bendn.org/helix#bcfbb875) (*) +│ ├── imara-diff v0.2.0 +│ │ ├── hashbrown v0.15.5 +│ │ └── memchr v2.7.6 +│ ├── log v0.4.29 +│ ├── nucleo v0.5.0 +│ │ ├── nucleo-matcher v0.3.1 +│ │ ├── parking_lot v0.12.5 +│ │ └── rayon v1.11.0 +│ ├── once_cell v1.21.3 +│ ├── parking_lot v0.12.5 (*) +│ ├── regex v1.12.2 (*) +│ ├── regex-cursor v0.1.5 +│ │ ├── log v0.4.29 +│ │ ├── memchr v2.7.6 +│ │ ├── regex-automata v0.4.13 (*) +│ │ ├── regex-syntax v0.8.8 +│ │ └── ropey v1.6.1 +│ ├── ropey v1.6.1 (*) +│ ├── serde v1.0.228 (*) +│ ├── serde_json v1.0.149 +│ │ ├── indexmap v2.13.0 +│ │ ├── itoa v1.0.17 +│ │ ├── memchr v2.7.6 +│ │ ├── serde_core v1.0.228 +│ │ └── zmij v1.0.19 +│ ├── slotmap v1.1.1 +│ │ [build-dependencies] +│ │ └── version_check v0.9.5 +│ ├── smallvec v1.15.1 +│ ├── smartstring v1.0.1 +│ │ └── static_assertions v1.1.0 +│ │ [build-dependencies] +│ │ ├── autocfg v1.5.0 +│ │ └── version_check v0.9.5 +│ ├── textwrap v0.16.2 +│ │ ├── smawk v0.3.2 +│ │ ├── unicode-linebreak v0.1.5 +│ │ └── unicode-width v0.2.2 +│ ├── toml v0.9.11+spec-1.1.0 (*) +│ ├── tree-house v0.3.0 (*) +│ ├── unicode-general-category v1.1.0 +│ ├── unicode-segmentation v1.12.0 +│ ├── unicode-width v0.1.12 +│ └── url v2.5.8 +│ ├── form_urlencoded v1.2.2 +│ ├── idna v1.1.0 +│ ├── percent-encoding v2.3.2 +│ ├── serde v1.0.228 (*) +│ └── serde_derive v1.0.228 (proc-macro) (*) +├── helix-loader v25.7.1 (https://git.bendn.org/helix#bcfbb875) (*) +├── helix-lsp-types v0.95.1 (https://git.bendn.org/helix#bcfbb875) +│ ├── bitflags v2.10.0 +│ ├── serde v1.0.228 (*) +│ ├── serde_json v1.0.149 (*) +│ └── url v2.5.8 (*) +├── implicit-fn v0.1.0 (proc-macro) (*) +├── itertools v0.14.0 (*) +├── libc v0.2.180 +├── log v0.4.29 +├── lower v0.2.1 (*) +├── lsp-server v0.7.9 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ ├── crossbeam-channel v0.5.15 (*) +│ ├── helix-lsp-types v0.95.1 (https://git.bendn.org/helix#bcfbb875) (*) +│ ├── log v0.4.29 +│ ├── serde v1.0.228 (*) +│ ├── serde_derive v1.0.228 (proc-macro) (*) +│ └── serde_json v1.0.149 (*) +├── markdown v1.0.0 +│ └── unicode-id v0.3.6 +├── memchr v2.7.6 +├── niri-ipc v25.11.0 +│ ├── serde v1.0.228 (*) +│ └── serde_json v1.0.149 (*) +├── nucleo v0.5.0 (*) +├── papaya v0.2.3 +│ ├── equivalent v1.0.2 +│ └── seize v0.5.1 +│ └── libc v0.2.180 +├── pattypan v0.1.0 (https://git.bendn.org/pattypan#51c4d77c) +│ ├── anstream v0.6.21 (*) +│ ├── anyhow v1.0.100 +│ ├── array_chunks v1.0.0 +│ ├── atools v0.1.12 +│ ├── chumsky v0.13.0 (https://github.com/zesterer/chumsky#b81c34c3) +│ │ ├── hashbrown v0.15.5 (*) +│ │ ├── stacker v0.1.22 +│ │ │ [build-dependencies] +│ │ ├── unicode-ident v1.0.22 +│ │ └── unicode-segmentation v1.12.0 +│ ├── color-hex v0.2.0 (proc-macro) +│ ├── ctlfun v0.1.0 (https://git.bendn.org/ctlfun#f00e5752) +│ ├── dsb v0.1.0 (https://git.bendn.org/dsb#02744132) (*) +│ ├── fimg v0.4.51 (https://git.bendn.org/fimg#cf01f538) (*) +│ ├── implicit-fn v0.1.0 (proc-macro) (*) +│ ├── libc v0.2.180 +│ ├── minifb v0.28.0 +│ │ ├── dlib v0.5.2 +│ │ ├── lazy_static v1.5.0 +│ │ ├── libc v0.2.180 +│ │ ├── raw-window-handle v0.6.2 +│ │ ├── tempfile v3.24.0 (*) +│ │ ├── wayland-client v0.29.5 +│ │ │ [build-dependencies] +│ │ ├── wayland-cursor v0.29.5 +│ │ ├── wayland-protocols v0.29.5 +│ │ │ [build-dependencies] +│ │ └── x11-dl v2.21.0 +│ │ [build-dependencies] +│ │ [build-dependencies] +│ │ └── cc v1.2.55 (*) +│ ├── nix v0.30.1 +│ │ ├── bitflags v2.10.0 +│ │ ├── cfg-if v1.0.4 +│ │ └── libc v0.2.180 +│ │ [build-dependencies] +│ │ └── cfg_aliases v0.2.1 +│ ├── parking_lot v0.12.5 (*) +│ ├── swash v0.2.6 (*) +│ └── winit v0.30.12 +│ ├── ahash v0.8.12 +│ │ [build-dependencies] +│ ├── bitflags v2.10.0 +│ ├── bytemuck v1.25.0 +│ ├── calloop v0.13.0 +│ ├── cursor-icon v1.2.0 +│ ├── dpi v0.1.2 +│ ├── libc v0.2.180 +│ ├── memmap2 v0.9.9 +│ ├── percent-encoding v2.3.2 +│ ├── raw-window-handle v0.6.2 +│ ├── rustix v0.38.44 +│ ├── sctk-adwaita v0.10.1 +│ ├── smithay-client-toolkit v0.19.2 +│ ├── smol_str v0.2.2 +│ ├── tracing v0.1.44 +│ ├── wayland-backend v0.3.12 +│ │ [build-dependencies] +│ ├── wayland-client v0.31.12 +│ ├── wayland-protocols v0.32.10 +│ ├── wayland-protocols-plasma v0.3.10 +│ ├── x11-dl v2.21.0 (*) +│ ├── x11rb v0.13.2 +│ └── xkbcommon-dl v0.4.2 +│ [build-dependencies] +│ └── cfg_aliases v0.2.1 +├── pin-project v1.1.10 +│ └── pin-project-internal v1.1.10 (proc-macro) +│ ├── proc-macro2 v1.0.106 (*) +│ ├── quote v1.0.44 (*) +│ └── syn v2.0.114 (*) +├── png v0.18.0 +│ ├── bitflags v2.10.0 +│ ├── crc32fast v1.5.0 +│ │ └── cfg-if v1.0.4 +│ ├── fdeflate v0.3.7 +│ │ └── simd-adler32 v0.3.8 +│ ├── flate2 v1.1.8 +│ │ ├── crc32fast v1.5.0 (*) +│ │ └── miniz_oxide v0.8.9 +│ └── miniz_oxide v0.8.9 (*) +├── regex v1.12.2 (*) +├── regex-cursor v0.1.5 (*) +├── replace_with v0.1.8 +├── ropey v1.6.1 (*) +├── run_times v0.1.0 +├── rust-analyzer v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ ├── anyhow v1.0.100 +│ ├── base64 v0.22.1 +│ ├── cargo_metadata v0.23.1 +│ │ ├── camino v1.2.2 +│ │ ├── cargo-platform v0.3.2 +│ │ ├── semver v1.0.27 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ └── thiserror v2.0.18 (*) +│ ├── cfg v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── intern v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── rustc-hash v2.1.1 +│ │ ├── span v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── syntax v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── tracing v0.1.44 (*) +│ │ └── tt v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ ├── crossbeam-channel v0.5.15 (*) +│ ├── dirs v6.0.0 +│ │ └── dirs-sys v0.5.0 +│ ├── dissimilar v1.0.10 +│ ├── helix-lsp-types v0.95.1 (https://git.bendn.org/helix#bcfbb875) (*) +│ ├── hir v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── arrayvec v0.7.6 +│ │ ├── base-db v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── cfg v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── either v1.15.0 +│ │ ├── hir-def v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── hir-expand v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── hir-ty v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── intern v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── itertools v0.14.0 (*) +│ │ ├── ra-ap-rustc_type_ir v0.143.0 +│ │ ├── rustc-hash v2.1.1 +│ │ ├── serde_json v1.0.149 (*) +│ │ ├── smallvec v1.15.1 +│ │ ├── span v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── stdx v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── syntax v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── tracing v0.1.44 (*) +│ │ ├── triomphe v0.1.15 +│ │ └── tt v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── hir-def v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── hir-ty v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── ide v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── arrayvec v0.7.6 +│ │ ├── cfg v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── cov-mark v2.2.0 +│ │ ├── dot v0.1.4 +│ │ ├── either v1.15.0 +│ │ ├── hir v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── ide-assists v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── ide-completion v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── ide-db v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── ide-diagnostics v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── ide-ssr v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── itertools v0.14.0 (*) +│ │ ├── macros v0.0.0 (proc-macro) (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── nohash-hasher v0.2.0 +│ │ ├── oorandom v11.1.5 +│ │ ├── profile v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── pulldown-cmark v0.9.6 +│ │ ├── pulldown-cmark-to-cmark v10.0.4 +│ │ ├── rustc_apfloat v0.2.3+llvm-462a31f5a5ab +│ │ ├── smallvec v1.15.1 +│ │ ├── span v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── stdx v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── syntax v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── toolchain v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── tracing v0.1.44 (*) +│ │ ├── triomphe v0.1.15 +│ │ └── url v2.5.8 (*) +│ ├── ide-completion v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── ide-db v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── ide-ssr v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── indexmap v2.13.0 (*) +│ ├── itertools v0.14.0 (*) +│ ├── load-cargo v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── anyhow v1.0.100 +│ │ ├── crossbeam-channel v0.5.15 (*) +│ │ ├── hir-expand v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── ide-db v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── intern v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── itertools v0.14.0 (*) +│ │ ├── proc-macro-api v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── project-model v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── span v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── tracing v0.1.44 (*) +│ │ ├── tt v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ │ ├── vfs v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ └── vfs-notify v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ ├── lsp-server v0.7.9 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── memchr v2.7.6 +│ ├── num_cpus v1.17.0 +│ │ └── libc v0.2.180 +│ ├── oorandom v11.1.5 +│ ├── parking_lot v0.12.5 (*) +│ ├── parser v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── drop_bomb v0.1.5 +│ │ ├── edition v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ ├── ra-ap-rustc_lexer v0.143.0 +│ │ ├── rustc-literal-escaper v0.0.4 +│ │ ├── tracing v0.1.44 (*) +│ │ └── winnow v0.7.14 +│ ├── paths v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) +│ │ └── camino v1.2.2 (*) +│ ├── proc-macro-api v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── process-wrap v8.2.1 +│ │ ├── indexmap v2.13.0 (*) +│ │ ├── nix v0.30.1 (*) +│ │ └── tracing v0.1.44 (*) +│ ├── profile v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── project-model v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── ra-ap-rustc_type_ir v0.143.0 (*) +│ ├── rayon v1.11.0 (*) +│ ├── rustc-hash v2.1.1 +│ ├── scip v0.5.2 +│ │ └── protobuf v3.7.1 +│ ├── semver v1.0.27 (*) +│ ├── serde v1.0.228 (*) +│ ├── serde_derive v1.0.228 (proc-macro) (*) +│ ├── serde_json v1.0.149 (*) +│ ├── smallvec v1.15.1 +│ ├── stdx v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── syntax v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── tenthash v1.1.0 +│ ├── toml v0.9.11+spec-1.1.0 (*) +│ ├── toolchain v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── tracing v0.1.44 (*) +│ ├── tracing-subscriber v0.3.22 +│ │ ├── sharded-slab v0.1.7 +│ │ ├── thread_local v1.1.9 +│ │ ├── time v0.3.46 +│ │ ├── tracing-core v0.1.36 +│ │ └── tracing-log v0.2.0 +│ ├── tracing-tree v0.4.1 +│ │ ├── nu-ansi-term v0.50.3 +│ │ ├── tracing-core v0.1.36 (*) +│ │ ├── tracing-log v0.2.0 (*) +│ │ └── tracing-subscriber v0.3.22 (*) +│ ├── triomphe v0.1.15 +│ ├── vfs v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── vfs-notify v0.0.0 (https://git.bendn.org/rust-analyzer#286d7dd4) (*) +│ ├── walkdir v2.5.0 +│ │ └── same-file v1.0.6 +│ └── xflags v0.3.2 +│ └── xflags-macros v0.3.2 (proc-macro) +├── rust-fsm v0.8.0 (https://git.bendn.org/rust-fsm#16afc8ee) +│ ├── aquamarine v0.6.0 (proc-macro) +│ │ ├── include_dir v0.7.4 +│ │ ├── itertools v0.10.5 +│ │ ├── proc-macro-error2 v2.0.1 +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.114 (*) +│ ├── replace_with v0.1.8 +│ └── rust-fsm-dsl v0.8.0 (proc-macro) (https://git.bendn.org/rust-fsm#16afc8ee) +│ ├── proc-macro2 v1.0.106 (*) +│ ├── quote v1.0.44 (*) +│ └── syn v2.0.114 (*) +├── rustc-hash v2.1.1 +├── scopeguard v1.2.0 +├── serde v1.0.228 (*) +├── serde_derive v1.0.228 (proc-macro) (*) +├── serde_json v1.0.149 (*) +├── softbuffer v0.4.8 +│ ├── as-raw-xcb-connection v1.0.1 +│ ├── bytemuck v1.25.0 (*) +│ ├── drm v0.14.1 +│ │ ├── bitflags v2.10.0 +│ │ ├── bytemuck v1.25.0 (*) +│ │ ├── drm-ffi v0.9.0 +│ │ ├── drm-fourcc v2.2.0 +│ │ └── rustix v0.38.44 (*) +│ ├── fastrand v2.3.0 +│ ├── memmap2 v0.9.9 (*) +│ ├── raw-window-handle v0.6.2 +│ ├── rustix v1.1.3 +│ │ ├── bitflags v2.10.0 +│ │ └── linux-raw-sys v0.11.0 +│ ├── tiny-xlib v0.2.4 +│ │ ├── as-raw-xcb-connection v1.0.1 +│ │ ├── ctor-lite v0.1.1 +│ │ ├── libloading v0.8.9 +│ │ └── tracing v0.1.44 (*) +│ │ [build-dependencies] +│ │ └── pkg-config v0.3.32 +│ ├── tracing v0.1.44 (*) +│ ├── wayland-backend v0.3.12 (*) +│ ├── wayland-client v0.31.12 (*) +│ ├── wayland-sys v0.31.8 +│ │ ├── dlib v0.5.2 (*) +│ │ ├── log v0.4.29 +│ │ └── once_cell v1.21.3 +│ │ [build-dependencies] +│ │ └── pkg-config v0.3.32 +│ └── x11rb v0.13.2 (*) +├── swash v0.2.6 (*) +├── swizzle v0.1.0 +├── test-log v0.2.19 +│ ├── env_logger v0.11.8 (*) +│ └── test-log-macros v0.2.19 (proc-macro) +│ ├── proc-macro2 v1.0.106 (*) +│ ├── quote v1.0.44 (*) +│ └── syn v2.0.114 (*) +├── tokio v1.49.0 +│ └── pin-project-lite v0.2.16 +├── tokio-util v0.7.18 +│ ├── bytes v1.11.0 +│ ├── futures-core v0.3.31 +│ ├── futures-sink v0.3.31 +│ ├── futures-util v0.3.31 +│ │ ├── futures-core v0.3.31 +│ │ ├── futures-macro v0.3.31 (proc-macro) +│ │ ├── futures-task v0.3.31 +│ │ ├── pin-project-lite v0.2.16 +│ │ ├── pin-utils v0.1.0 +│ │ └── slab v0.4.12 +│ ├── pin-project-lite v0.2.16 +│ └── tokio v1.49.0 (*) +├── tree-house v0.3.0 (*) +├── tree-sitter v0.25.10 +│ ├── regex v1.12.2 (*) +│ ├── regex-syntax v0.8.8 +│ ├── streaming-iterator v0.1.9 +│ └── tree-sitter-language v0.1.6 +│ [build-dependencies] +│ ├── cc v1.2.55 (*) +│ └── serde_json v1.0.149 +│ ├── indexmap v2.13.0 +│ ├── itoa v1.0.17 +│ ├── memchr v2.7.6 +│ ├── serde_core v1.0.228 +│ └── zmij v1.0.19 +├── url v2.5.8 (*) +├── walkdir v2.5.0 (*) +└── winit v0.30.12 (*) |