My personal-knowledge-system, with deeply integrated task tracking and long term goal planning capabilities.
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: deimos scaffolding

+161 -14
+77
Cargo.lock
··· 2326 2326 "egui_graphs", 2327 2327 "futures", 2328 2328 "human-panic", 2329 + "notify", 2329 2330 "nucleo-matcher", 2330 2331 "pulldown-cmark", 2331 2332 "rand 0.10.0", ··· 2475 2476 checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" 2476 2477 dependencies = [ 2477 2478 "percent-encoding", 2479 + ] 2480 + 2481 + [[package]] 2482 + name = "fsevent-sys" 2483 + version = "4.1.0" 2484 + source = "registry+https://github.com/rust-lang/crates.io-index" 2485 + checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" 2486 + dependencies = [ 2487 + "libc", 2478 2488 ] 2479 2489 2480 2490 [[package]] ··· 3924 3934 ] 3925 3935 3926 3936 [[package]] 3937 + name = "inotify" 3938 + version = "0.11.1" 3939 + source = "registry+https://github.com/rust-lang/crates.io-index" 3940 + checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" 3941 + dependencies = [ 3942 + "bitflags 2.11.0", 3943 + "inotify-sys", 3944 + "libc", 3945 + ] 3946 + 3947 + [[package]] 3948 + name = "inotify-sys" 3949 + version = "0.1.5" 3950 + source = "registry+https://github.com/rust-lang/crates.io-index" 3951 + checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" 3952 + dependencies = [ 3953 + "libc", 3954 + ] 3955 + 3956 + [[package]] 3927 3957 name = "instability" 3928 3958 version = "0.3.11" 3929 3959 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4103 4133 version = "3.1.0" 4104 4134 source = "registry+https://github.com/rust-lang/crates.io-index" 4105 4135 checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" 4136 + 4137 + [[package]] 4138 + name = "kqueue" 4139 + version = "1.1.1" 4140 + source = "registry+https://github.com/rust-lang/crates.io-index" 4141 + checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" 4142 + dependencies = [ 4143 + "kqueue-sys", 4144 + "libc", 4145 + ] 4146 + 4147 + [[package]] 4148 + name = "kqueue-sys" 4149 + version = "1.0.4" 4150 + source = "registry+https://github.com/rust-lang/crates.io-index" 4151 + checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" 4152 + dependencies = [ 4153 + "bitflags 1.3.2", 4154 + "libc", 4155 + ] 4106 4156 4107 4157 [[package]] 4108 4158 name = "kstring" ··· 4555 4605 dependencies = [ 4556 4606 "memchr", 4557 4607 "minimal-lexical", 4608 + ] 4609 + 4610 + [[package]] 4611 + name = "notify" 4612 + version = "8.2.0" 4613 + source = "registry+https://github.com/rust-lang/crates.io-index" 4614 + checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" 4615 + dependencies = [ 4616 + "bitflags 2.11.0", 4617 + "fsevent-sys", 4618 + "inotify", 4619 + "kqueue", 4620 + "libc", 4621 + "log", 4622 + "mio", 4623 + "notify-types", 4624 + "walkdir", 4625 + "windows-sys 0.60.2", 4626 + ] 4627 + 4628 + [[package]] 4629 + name = "notify-types" 4630 + version = "2.1.0" 4631 + source = "registry+https://github.com/rust-lang/crates.io-index" 4632 + checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" 4633 + dependencies = [ 4634 + "bitflags 2.11.0", 4558 4635 ] 4559 4636 4560 4637 [[package]]
+1
Cargo.toml
··· 82 82 nucleo-matcher = "0.3.1" 83 83 ron = "0.12.1" 84 84 tower-lsp = "0.20.0" 85 + notify = "8.2.0" 85 86 86 87 [build-dependencies] 87 88 anyhow = "1.0.102"
+8 -10
src/gui/mod.rs
··· 1 1 use eframe::egui; 2 2 use egui_graphs::{SettingsInteraction, SettingsNavigation}; 3 3 4 - use crate::types::{Filaments, Index}; 4 + use crate::types::FilamentsHandle; 5 5 6 6 /// The `Filaments Visualizer`, which is an instance of `eframe`, which uses `egui` 7 7 pub struct FilViz { 8 - filaments: Filaments, 8 + fh: FilamentsHandle, 9 9 } 10 10 11 11 impl FilViz { 12 12 /// Create a new instance of the `FiLViz` 13 - fn new(_cc: &eframe::CreationContext<'_>, idx: &Index) -> Self { 13 + const fn new(_cc: &eframe::CreationContext<'_>, fh: FilamentsHandle) -> Self { 14 14 // Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_global_style. 15 15 // Restore app state using cc.storage (requires the "persistence" feature). 16 16 // Use the cc.gl (a glow::Context) to create graphics shaders and buffers that you can use 17 17 // for e.g. egui::PaintCallback. 18 - Self { 19 - filaments: Filaments::from(idx), 20 - } 18 + Self { fh } 21 19 } 22 20 23 21 /// Create and run the `FilViz`. 24 - pub fn run(idx: &Index) -> color_eyre::Result<()> { 22 + pub fn run(fh: FilamentsHandle) -> color_eyre::Result<()> { 25 23 let native_options = eframe::NativeOptions::default(); 26 24 eframe::run_native( 27 25 "Filaments Visualizer", 28 26 native_options, 29 - Box::new(|cc| Ok(Box::new(Self::new(cc, idx)))), 27 + Box::new(|cc| Ok(Box::new(Self::new(cc, fh)))), 30 28 )?; 31 29 32 30 Ok(()) ··· 39 37 impl eframe::App for FilViz { 40 38 fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) { 41 39 egui::CentralPanel::default().show_inside(ui, |ui| { 42 - let g = &mut self.filaments.graph; 40 + let g = &mut self.fh.lock().expect("Lock must not be poisoned").graph; 43 41 44 42 let mut view = egui_graphs::GraphView::<_, _, _, _, _, _, S, L>::new(g) 45 43 .with_interactions( ··· 52 50 .with_edge_selection_multi_enabled(false), 53 51 ) 54 52 .with_navigations( 55 - &SettingsNavigation::new().with_fit_to_screen_padding(0.5), // .with_zoom_and_pan_enabled(true) 53 + &SettingsNavigation::new().with_fit_to_screen_padding(0.2), // .with_zoom_and_pan_enabled(true) 56 54 // .with_fit_to_screen_enabled(false), 57 55 ); 58 56
+17 -3
src/main.rs
··· 9 9 config::Config, 10 10 gui::FilViz, 11 11 tui::TuiApp, 12 - types::{Kasten, KastenHandle}, 12 + types::{Deimos, Filaments, Kasten, KastenHandle}, 13 13 }; 14 14 use clap::Parser; 15 15 use tokio::sync::RwLock; ··· 66 66 } 67 67 }); 68 68 69 + let fh = rt.block_on(async { 70 + Arc::new(std::sync::Mutex::new(Filaments::from( 71 + &kh.read().await.index, 72 + ))) 73 + }); 74 + // spawn deimos 75 + { 76 + let fh = fh.clone(); 77 + 78 + rt.spawn(async { 79 + let deimos = Deimos::new(kh, fh); 80 + deimos.watch().await 81 + }); 82 + } 83 + 69 84 // if they asked for the visualizer, we give them the visualizer 70 85 if args.visualizer { 71 86 // enter the guard so egui_async works properly 72 87 let _rt_guard = rt.enter(); 73 - let index = rt.block_on(async { kh.read().await.index.clone() }); 74 - FilViz::run(&index)?; 88 + FilViz::run(fh)?; 75 89 } 76 90 77 91 // join on the tui
+50
src/types/deimos.rs
··· 1 + use color_eyre::eyre::Context; 2 + use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Result, Watcher as _}; 3 + use tracing::{error, info}; 4 + 5 + use crate::types::{KastenHandle, filaments::FilamentsHandle}; 6 + 7 + #[derive(Debug)] 8 + pub struct Deimos { 9 + kh: KastenHandle, 10 + fh: FilamentsHandle, 11 + } 12 + 13 + impl Deimos { 14 + pub const fn new(kh: KastenHandle, fh: FilamentsHandle) -> Self { 15 + Self { kh, fh } 16 + } 17 + 18 + /// Watches the `Filaments Directory` for file changes and updates 19 + /// the internal state of the kasten and the `Filaments` displayed in the 20 + /// gui. 21 + /// 22 + /// NOTE: This function must be spawned as a top level await 23 + pub async fn watch(&self) -> color_eyre::Result<()> { 24 + info!("deimos spawned!"); 25 + 26 + let (tx, mut rx) = tokio::sync::mpsc::channel::<Result<Event>>(10); 27 + let mut watcher = RecommendedWatcher::new( 28 + move |res| tx.blocking_send(res).expect("failed to send event"), 29 + Config::default(), 30 + )?; 31 + 32 + watcher 33 + .watch(&self.kh.read().await.root, RecursiveMode::Recursive) 34 + .with_context(|| "failed to start the FS watcher")?; 35 + 36 + while let Some(res) = rx.recv().await { 37 + let kt = &mut *self.kh.write().await; 38 + let fh = &mut *self.fh.lock().expect("Lock must not be poisoned"); 39 + 40 + match res { 41 + Ok(event) => info!("event: {event:?}"), 42 + Err(e) => error!("watch error: {e:?}"), 43 + } 44 + 45 + *fh = (&kt.index).into(); 46 + } 47 + 48 + Ok(()) 49 + } 50 + }
+4 -1
src/types/filaments.rs
··· 1 1 #![expect(dead_code)] 2 - use std::{cmp::max, collections::HashMap}; 2 + use std::{cmp::max, collections::HashMap, sync::Arc}; 3 3 4 4 use eframe::emath; 5 5 use egui_graphs::{ ··· 16 16 /// Arbitrarily chosen minimum number of edges 17 17 const GRAPH_MIN_EDGES: usize = GRAPH_MIN_NODES * 3; 18 18 19 + #[derive(Debug)] 19 20 pub struct Filaments { 20 21 pub graph: ZkGraph, 21 22 /// simple conversions 22 23 zid_to_gid: HashMap<ZettelId, NodeIndex>, 23 24 } 25 + 26 + pub type FilamentsHandle = Arc<std::sync::Mutex<Filaments>>; 24 27 25 28 impl From<&Index> for Filaments { 26 29 fn from(value: &Index) -> Self {
+4
src/types/mod.rs
··· 23 23 24 24 mod filaments; 25 25 pub use filaments::Filaments; 26 + pub use filaments::FilamentsHandle; 26 27 27 28 mod index; 28 29 pub use index::Index; ··· 33 34 34 35 mod frontmatter; 35 36 pub use frontmatter::FrontMatter; 37 + 38 + mod deimos; 39 + pub use deimos::Deimos;