A simple CPU rendered GUI IDE experience.
use bendncode
| -rw-r--r-- | Cargo.toml | 7 | ||||
| -rw-r--r-- | src/bar.rs | 6 | ||||
| -rw-r--r-- | src/commands.rs | 1 | ||||
| -rw-r--r-- | src/edi.rs | 40 | ||||
| -rw-r--r-- | src/edi/input_handlers/click.rs | 26 | ||||
| -rw-r--r-- | src/edi/input_handlers/keyboard.rs | 12 | ||||
| -rw-r--r-- | src/edi/st.rs | 2 | ||||
| -rw-r--r-- | src/gotolist.rs | 1 | ||||
| -rw-r--r-- | src/hov.rs | 2 | ||||
| -rw-r--r-- | src/main.rs | 30 | ||||
| -rw-r--r-- | src/menu.rs | 3 | ||||
| -rw-r--r-- | src/menu/generic.rs | 27 | ||||
| -rw-r--r-- | src/runnables.rs | 1 | ||||
| -rw-r--r-- | src/sym.rs | 1 | ||||
| -rw-r--r-- | src/text.rs | 11 | ||||
| -rw-r--r-- | src/text/inlay.rs | 6 | ||||
| -rw-r--r-- | src/text/semantic_tokens.rs | 3 |
17 files changed, 114 insertions, 65 deletions
@@ -39,9 +39,9 @@ rust-analyzer = { git = "https://git.bendn.org/rust-analyzer" } serde_json = "1.0.150" serde = { version = "1.0.228", features = ["unstable"] } serde_derive = "1.0.228" -log = "0.4.30" +log = "0.4.31" crossbeam = { version = "0.8.4", features = ["nightly", "crossbeam-channel"] } -test-log = "0.2.20" +test-log = "0.2.21" env_logger = "0.11.10" url = "2.5.8" tokio = { version = "1.52.3", features = ["rt-multi-thread", "sync", "time"] } @@ -61,7 +61,6 @@ walkdir = "2.5.0" niri = { package = "niri-ipc", version = "25.11.0" } libc = "0.2.186" rustc-hash = "=2.1.1" -bendy = { version = "0.6.1", features = ["serde"] } git2 = "0.20.4" imara-diff = "0.2.0" vecto = "0.1.1" @@ -77,6 +76,7 @@ ftools = { git = "https://git.bendn.org/ftools" } json_value_merge = "2.0.1" annotate-snippets = "0.12.16" toml = "1.1.2" +bendncode = { git = "https://git.bendn.org/bendncode" } [profile.dev.package] rust-analyzer.opt-level = 3 fimg.opt-level = 3 @@ -89,7 +89,6 @@ debug-assertions = false [profile.release.package] fimg.debug-assertions = true rust-analyzer.debug-assertions = false -hir-ty.debug-assertions = false [profile.release] debug = 2 @@ -164,6 +164,12 @@ impl Bar { x.letter = Some(c); }); } + State::GoToL(x) => format!("list of {}", x.name()) + .chars() + .zip(row) + .for_each(|(c, x)| { + x.letter = Some(c); + }), State::Save => unreachable!(), _ => {} } diff --git a/src/commands.rs b/src/commands.rs index 1273cfe..2a56aac 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -129,6 +129,7 @@ commands!( pub enum Cmds {} impl MenuData for Cmds { + const NAME: &'static str = "commands"; const HEIGHT: usize = 30; type Data = (); type Element<'a> = Cmd; @@ -49,7 +49,7 @@ use crate::text::cursor::{Ronge, ceach}; use crate::text::hist::{ClickHistory, Hist}; use crate::text::{LOADER, Mapping, RopeExt, SortTedits, TextArea}; use crate::{ - BoolRequest, CDo, CompletionAction, CompletionState, alt, ctrl, + BoolRequest, CDo, CompletionAction, CompletionState, Freq, alt, ctrl, filter, hash, shift, sym, trm, }; @@ -184,7 +184,7 @@ fn rooter( } impl Editor { - pub fn new() -> rootcause::Result<Self> { + pub fn new() -> rootcause::Result<(Self, Freq)> { let mut me = Self::default(); let o = std::env::args() @@ -219,16 +219,24 @@ impl Editor { .and_then(|(ws, x)| (vsc_settings::load(&x, &ws)).ok()); let mut loaded_state = false; + let mut freq = default(); if let Some(ws) = me.workspace.as_deref() && let h = hash(&ws) - && let at = cfgdir().join(format!("{h:x}")).join(STORE) + && let cf = cfgdir().join(format!("{h:x}")) + && let at = cf.join(SSTORE) && at.exists() { let x = std::fs::read(at)?; - let x = bendy::serde::from_bytes::<Editor>(&x)?; + let x = bendncode::from_bytes::<Editor>(&x)?; me = x; loaded_state = true; assert!(me.workspace.is_some()); + if let at = cf.join(FSTORE) + && at.exists() + { + let x = std::fs::read(at)?; + freq = bendncode::from_bytes::<Freq>(&x)?; + } } me.language = n; me.git_dir = me @@ -358,7 +366,7 @@ impl Editor { // }, // ); } - Ok(me) + Ok((me, freq)) } #[must_use = "please apply this"] @@ -625,7 +633,7 @@ impl Editor { .map(|[wo, or]| format!("gracilaria - {wo} - {or}")) } - pub fn store(&mut self) -> rootcause::Result<()> { + pub fn store(&mut self, fq: &Freq) -> rootcause::Result<()> { let ws = self.workspace.clone(); let tree = self.tree.clone(); let mtime = self.mtime.clone(); @@ -647,9 +655,11 @@ impl Editor { let cfgdir = cfgdir(); let p = cfgdir.join(format!("{hash:x}")); std::fs::create_dir_all(&p)?; - let b = bendy::serde::to_bytes(&self).unwrap(); - bendy::serde::from_bytes::<Editor>(&b)?; - std::fs::write(p.join(STORE), &b)?; + let b = bendncode::to_bytes(&self)?; + bendncode::from_bytes::<Editor>(&b)?; + std::fs::write(p.join(SSTORE), &b)?; + let b = bendncode::to_bytes(fq)?; + std::fs::write(p.join(FSTORE), &b)?; } Ok(()) } @@ -701,13 +711,5 @@ fn cfgdir() -> PathBuf { .unwrap_or("/tmp/".into()) .join("gracilaria") } -const STORE: &str = "state.torrent"; -#[track_caller] -#[allow(dead_code)] -fn rtt<T: serde::Serialize + serde::Deserialize<'static>>( - x: &T, -) -> Result<T, bendy::serde::Error> { - bendy::serde::from_bytes::<T>( - bendy::serde::to_bytes(x).unwrap().leak(), - ) -} +const SSTORE: &str = "state.bendn"; +const FSTORE: &str = "freq.bendn"; diff --git a/src/edi/input_handlers/click.rs b/src/edi/input_handlers/click.rs index 80e4065..4b0857d 100644 --- a/src/edi/input_handlers/click.rs +++ b/src/edi/input_handlers/click.rs @@ -17,10 +17,16 @@ impl Editor { .complete .consume(CompletionAction::Click) .inspect_err(|x| log::error!("transition comact {x:?}")); - let r = self.transition(Action::M(bt)); + + let Some(mut o) = self.transition(Action::M(bt)) else { return }; + if let Do::Reinsert = o { + let Some(o2) = self.transition(Action::M(bt)) else { return }; + o = o2; + }; + let text = &mut self.text; - match r { - Some(Do::ClickedHover | Do::MoveCursor) => { + match o { + Do::MoveCursor => { text.cursor.just( text.mapped_index_at(cursor_position), &text.rope, @@ -37,13 +43,13 @@ impl Editor { text.cursor.first().setc(&text.rope); self.refresh_document_highlights(); } - Some(Do::NavForward) => self.nav_forward(), - Some(Do::NavBack) => self.nav_back(), - Some(Do::ExtendSelectionToMouse) => { + Do::NavForward => self.nav_forward(), + Do::NavBack => self.nav_back(), + Do::ExtendSelectionToMouse => { let p = text.mapped_index_at(cursor_position); text.cursor.first_mut().extend_selection_to(p, &text.rope); } - Some(Do::StartSelection) => { + Do::StartSelection => { let p = text.mapped_index_at(cursor_position); let x = *text.cursor.first(); @@ -51,7 +57,7 @@ impl Editor { text.cursor.first_mut().extend_selection_to(p, &text.rope); self.hist.lc = text.cursor.clone(); } - Some(Do::GoToDefinition(tdpp)) => { + Do::GoToDefinition(tdpp) => { dbg!(&tdpp); if let Some(x) = self.requests.def.result.clone().or_else(|| { tdpp.zip(lsp!(self)).and_then(|(tdpp, lsp)| { @@ -72,7 +78,7 @@ impl Editor { log::error!("gtd: {e}"); } } - Some(Do::InsertCursorAtMouse) => { + Do::InsertCursorAtMouse => { text.cursor.add( text.mapped_index_at(cursor_position), &text.rope, @@ -81,7 +87,7 @@ impl Editor { self.chist.push(text.primary_cursor()); text.cursor.first().setc(&text.rope); } - None => {} + _ => unreachable!(), } } diff --git a/src/edi/input_handlers/keyboard.rs b/src/edi/input_handlers/keyboard.rs index 8250068..6001c60 100644 --- a/src/edi/input_handlers/keyboard.rs +++ b/src/edi/input_handlers/keyboard.rs @@ -38,6 +38,7 @@ impl Editor { else { return ControlFlow::Continue(()); }; + dbg!(&o2); o = o2; }; @@ -141,12 +142,10 @@ impl Editor { } } Do::SymbolsHandleKey => { - if let Some(lsp) = lsp!(self) { - let State::Symbols(Rq { result: Some(x), request }) = + 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, @@ -328,8 +327,7 @@ impl Editor { | Do::ExtendSelectionToMouse | Do::Hover | Do::InsertCursorAtMouse - | Do::SetHovering - | Do::ClickedHover => panic!(), + | Do::SetHovering => panic!(), Do::Save => match &self.origin { Some(_) => { self.transition(Action::Saved); diff --git a/src/edi/st.rs b/src/edi/st.rs index c145f21..673d652 100644 --- a/src/edi/st.rs +++ b/src/edi/st.rs @@ -96,7 +96,7 @@ Hovering(x) => { K(_) => Default [Reinsert], M(MouseButton::Left if ctrl()) => Default [GoToDefinition(x.request.map(|x| x.1.1).or(x.result.and_then(|x| x.of.iter().find_map(|x| x.tdpp()))))], - M(_) => _ [ClickedHover], + M(_) => Default [Reinsert], }, Command(_) => K(Key::Named(Escape)) => Default, Command(t) => K(Key::Named(Enter) if let Some(Ok(x)) = t.sel(None)) => Default [ProcessCommand((Commands, crate::commands::Cmd) => (t, x))], diff --git a/src/gotolist.rs b/src/gotolist.rs index 2e7b304..bed2abf 100644 --- a/src/gotolist.rs +++ b/src/gotolist.rs @@ -38,6 +38,7 @@ impl<'a> Key<'a> for (GoTo<'a>, Option<&'a str>) { } impl MenuData for GTL { + const NAME: &'static str = "!"; type Data = (Vec<(GoTo<'static>, Option<String>)>, Option<O>); type Element<'a> = (GoTo<'a>, Option<&'a str>); @@ -310,7 +310,7 @@ fn t() { let (w, h) = (400, 8000); let (c, r) = dsb::fit(&crate::FONT, ppem, lh, (w, h)); - let cells = markdown2(c, &p(include_str!("vec.md")).unwrap()); + let cells = markdown2(c, &p(include_str!("vec.md")).unwrap(), None); dbg!(l(&p(include_str!("vec.md")).unwrap())); dbg!(cells.len() / c); dbg!(w, h); diff --git a/src/main.rs b/src/main.rs index 9f46bc6..f35d444 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,6 @@ mod runnables; mod sym; mod trm; -use std::any::TypeId; use std::fmt::{Debug, Display}; use std::hash::Hash; use std::mem::MaybeUninit; @@ -115,33 +114,44 @@ const FG: [u8; 3] = [204, 202, 194]; const BORDER: [u8; 3] = col!("#ffffff"); static mut __ED: MaybeUninit<Editor> = MaybeUninit::uninit(); +static mut __FREQ: MaybeUninit<Freq> = MaybeUninit::uninit(); +static mut __CLEAN: bool = false; extern "C" fn cleanup() { - unsafe { __ED.assume_init_mut().store().unwrap() }; + unsafe { + if __CLEAN == false { + __CLEAN = true; + match __ED.assume_init_mut().store(__FREQ.assume_init_mut()) { + Ok(_) => {} + Err(e) => eprintln!("{e}"), + }; + } + } } extern "C" fn sigint(_: i32) { cleanup(); std::process::exit(12); } -type Freq = FxHashMap<TypeId, FxHashMap<u64, u16>>; +type FID = u8; +type Freq = FxHashMap<FID, FxHashMap<u64, u16>>; pub(crate) fn entry(event_loop: EventLoop) { unsafe { - __ED.write(match Editor::new() { + let (ed, freq) = match Editor::new() { Err(e) => { eprintln!("failure to launch: {e}"); return; } Ok(x) => x, - }) + }; + __ED.write(ed); + __FREQ.write(freq); }; assert_eq!(unsafe { atexit(cleanup) }, 0); unsafe { signal(libc::SIGINT, sigint as *const () as usize) }; let ed: &'static mut Editor = unsafe { __ED.assume_init_mut() }; - - let mut freq: Freq = default(); + let freq = unsafe { __FREQ.assume_init_mut() }; let ppem = 18.0; let ls = 20.0; // let ed = Box::leak(Box::new(ed)); - let mut fonts = dsb::Fonts::new( F::FontRef(*FONT, &[]), F::FontRef(*BFONT, &[]), @@ -313,7 +323,7 @@ pub(crate) fn entry(event_loop: EventLoop) { WindowEvent::PointerButton { button: ButtonSource::Mouse(MouseButton::Left), .. - } => unsafe { CLICKING = false }, + } => unsafe { CLICKING = false }, WindowEvent::MouseWheel { device_id: _, delta: MouseScrollDelta::LineDelta(_, rows), @@ -350,7 +360,7 @@ pub(crate) fn entry(event_loop: EventLoop) { ) { return; } - if ed.keyboard(event, window,&mut freq).is_break() { + if ed.keyboard(event, window, freq).is_break() { elwt.exit(); } window.request_redraw(); diff --git a/src/menu.rs b/src/menu.rs index 7186908..ca5cb47 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -1,5 +1,4 @@ pub mod generic; -use std::any::TypeId; use std::borrow::Cow; use std::cmp::Reverse; use std::sync::LazyLock; @@ -51,7 +50,7 @@ pub fn score<'a, T: Key<'a>, D: MenuData<Element<'a> = T> + 'static>( .map(move |y| { if let Some(f) = freq && filter == "" - && let Some(f) = f.get(&TypeId::of::<D>()) + && let Some(f) = f.get(&D::ID) { return ( f.get(&D::hashed(&y).unwrap()) diff --git a/src/menu/generic.rs b/src/menu/generic.rs index 51be7e7..d2b2395 100644 --- a/src/menu/generic.rs +++ b/src/menu/generic.rs @@ -1,4 +1,3 @@ -use std::any::TypeId; use std::fmt::Debug; use std::hash::Hash; use std::path::Path; @@ -6,9 +5,9 @@ use std::path::Path; use Default::default; use dsb::Cell; -use crate::Freq; use crate::menu::{Key, back, filter, next, score}; use crate::text::TextArea; +use crate::{FID, Freq}; pub struct GenericMenu<T: MenuData> { pub data: T::Data, @@ -53,7 +52,24 @@ pub enum CorA { Complete, Accept, } -pub trait MenuData: Sized + 'static { + +pub trait ID { + const ID: FID; +} +impl ID for crate::commands::Cmds { + const ID: u8 = 0; +} +impl ID for crate::gotolist::GTL { + const ID: u8 = 1; +} +impl ID for crate::runnables::Runb { + const ID: u8 = 2; +} +impl ID for crate::sym::Symb { + const ID: u8 = 3; +} +pub trait MenuData: Sized + 'static + ID { + const NAME: &'static str; const HEIGHT: usize = 30; type Data; type Element<'a>: Key<'a>; @@ -127,6 +143,9 @@ impl<T: MenuData + 'static> GenericMenu<T> { // coz its bottom up back::<{ T::HEIGHT }>(n, &mut self.selection, &mut self.vo); } + pub fn name(&self) -> &'static str { + T::NAME + } pub fn sel( &self, @@ -144,7 +163,7 @@ impl<T: MenuData + 'static> GenericMenu<T> { "if calling with freq, please impl hash", ); - *fq.entry(TypeId::of::<T>()) + *fq.entry(T::ID) .or_default() .entry(x) .or_default() += 1; diff --git a/src/runnables.rs b/src/runnables.rs index ee3970d..287868c 100644 --- a/src/runnables.rs +++ b/src/runnables.rs @@ -16,6 +16,7 @@ use crate::trm; pub enum Runb {} impl MenuData for Runb { + const NAME: &'static str = "runnables"; type Data = Vec<Runnable>; type Element<'a> = &'a Runnable; @@ -17,6 +17,7 @@ use crate::rnd::simplify_path; use crate::text::{Bookmarks, col, color_, set_a}; pub enum Symb {} impl MenuData for Symb { + const NAME: &'static str = "symbols"; type Data = ( SymbolsList, Vec<SymbolInformation>, diff --git a/src/text.rs b/src/text.rs index 923a23d..4c56712 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1353,7 +1353,7 @@ fn apply() { } "#, ); - + use lsp_types::*; t.apply_snippet(&TextEdit { range: lsp_types::Range { start: Position { line: 0, character: 8 }, @@ -1386,7 +1386,7 @@ fn apply2() { }", ); - use lsp_types::Range; + use lsp_types::*; let mut th = [ TextEdit { range: Range { @@ -1468,7 +1468,7 @@ fn inlays() { let mut t = TextArea::default(); _ = t.insert("let x = 4;"); t.set_inlay(&[InlayHint { - position: Position { line: 0, character: 4 }, + position: lsp_types::Position { line: 0, character: 4 }, label: InlayHintLabel::String("u".into()), kind: Some(lsp_types::InlayHintKind::TYPE), text_edits: None, @@ -1486,7 +1486,10 @@ fn inlays() { Char('t', 2, 2), Char(' ', 3, 3), Fake( - &Marking { position: 4, data: Box::new([('u', None)]) }, + Cow::Owned(Marking { + position: 4, + data: vec![('u', None)].into_boxed_slice(), + }), 0, 4, 'u' diff --git a/src/text/inlay.rs b/src/text/inlay.rs index 37b98cf..6712069 100644 --- a/src/text/inlay.rs +++ b/src/text/inlay.rs @@ -37,7 +37,7 @@ impl TextArea { pub fn set_inlay(&mut self, inlay: &[InlayHint]) { self.inlays = inlay .iter() - .map(|i| { + .filter_map(|i| { let mut label = match &i.label { InlayHintLabel::String(x) => x.chars().map(|x| (x, None)).collect::<Vec<_>>(), @@ -56,8 +56,8 @@ impl TextArea { if i.padding_right == Some(true) { label.push((' ', None)); } - let position = self.l_position(i.position).unwrap() as _; - Marking { position, data: label.into() } + let position = self.l_position(i.position)? as _; + Some(Marking { position, data: label.into() }) }) .collect(); } diff --git a/src/text/semantic_tokens.rs b/src/text/semantic_tokens.rs index f7c414a..8b09851 100644 --- a/src/text/semantic_tokens.rs +++ b/src/text/semantic_tokens.rs @@ -14,8 +14,11 @@ use crate::text::manipulations::Manip; Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, )] pub struct TokenD { + #[serde(rename = "0")] pub range: (u32, u32), + #[serde(rename = "1")] pub ty: u32, + #[serde(rename = "2")] pub modifiers: u32, } impl TokenD { |