···11use eframe::egui;
22use egui_graphs::{SettingsInteraction, SettingsNavigation};
33+use futures::executor::block_on;
44+use tokio::sync::mpsc::UnboundedReceiver;
55+use tracing::debug;
3644-use crate::types::FilamentsHandle;
77+use crate::{
88+ tui::Signal,
99+ types::{Filaments, Index, KastenHandle},
1010+};
511612/// The `Filaments Visualizer`, which is an instance of `eframe`, which uses `egui`
713pub struct FilViz {
88- fh: FilamentsHandle,
1414+ kh: KastenHandle,
1515+ signal_rx: UnboundedReceiver<Signal>,
1616+ filaments: Filaments,
917}
10181119impl FilViz {
1220 /// Create a new instance of the `FiLViz`
1313- const fn new(_cc: &eframe::CreationContext<'_>, fh: FilamentsHandle) -> Self {
2121+ fn new(
2222+ _cc: &eframe::CreationContext<'_>,
2323+ kh: KastenHandle,
2424+ signal_rx: UnboundedReceiver<Signal>,
2525+ index: &Index,
2626+ ) -> Self {
1427 // Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_global_style.
1528 // Restore app state using cc.storage (requires the "persistence" feature).
1629 // Use the cc.gl (a glow::Context) to create graphics shaders and buffers that you can use
1730 // for e.g. egui::PaintCallback.
1818- Self { fh }
3131+ Self {
3232+ kh,
3333+ signal_rx,
3434+ filaments: index.into(),
3535+ }
1936 }
20372138 /// Create and run the `FilViz`.
2222- pub fn run(fh: FilamentsHandle) -> color_eyre::Result<()> {
3939+ pub fn run(
4040+ kh: KastenHandle,
4141+ signal_rx: UnboundedReceiver<Signal>,
4242+ index: &Index,
4343+ ) -> color_eyre::Result<()> {
2344 let native_options = eframe::NativeOptions::default();
2445 eframe::run_native(
2546 "Filaments Visualizer",
2647 native_options,
2727- Box::new(|cc| Ok(Box::new(Self::new(cc, fh)))),
4848+ Box::new(|cc| Ok(Box::new(Self::new(cc, kh, signal_rx, index)))),
2849 )?;
29503051 Ok(())
···3758impl eframe::App for FilViz {
3859 fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
3960 egui::CentralPanel::default().show_inside(ui, |ui| {
4040- let g = &mut self.fh.lock().expect("Lock must not be poisoned").graph;
6161+ // let g = &mut self.fh.lock().expect("Lock must not be poisoned").graph;
6262+ let g = &mut self.filaments.graph;
41634264 let mut view = egui_graphs::GraphView::<_, _, _, _, _, _, S, L>::new(g)
4365 .with_interactions(
···6284 egui::warn_if_debug_build(ui);
6385 });
6486 });
8787+ }
8888+8989+ fn logic(&mut self, _ctx: &egui::Context, _frame: &mut eframe::Frame) {
9090+ if let Ok(signal) = self.signal_rx.try_recv() {
9191+ debug!("received signal in filaments: {signal}");
9292+9393+ #[allow(clippy::single_match)]
9494+ match signal {
9595+ Signal::CreatedZettel { zid } => {
9696+ block_on(async {
9797+ let index = &self.kh.read().await.index;
9898+ self.filaments.insert_zettel(zid, index);
9999+ });
100100+ }
101101+102102+ _ => {}
103103+ }
104104+ }
65105 }
66106}
67107
+15-16
src/main.rs
···99 config::Config,
1010 gui::FilViz,
1111 tui::TuiApp,
1212- types::{Deimos, Filaments, Kasten, KastenHandle},
1212+ types::{Kasten, KastenHandle},
1313};
1414use clap::Parser;
1515-use tokio::sync::RwLock;
1515+use tokio::sync::{RwLock, mpsc};
1616use tracing::debug;
17171818mod cli;
···48484949 debug!("Kasten Handle: {kh:#?}");
50505151+ let (signal_tx, signal_rx) = mpsc::unbounded_channel();
5252+5153 // then we spawn the tui on its own thread
5254 let tui_handle = std::thread::spawn({
5355 // arc stuff
···5860 move || -> color_eyre::Result<()> {
5961 // block the tui on the same runtime as above
6062 tui_rt.block_on(async {
6161- let mut tui = TuiApp::new(args.tick_rate, args.frame_rate, kh).await?;
6363+ let mut tui = TuiApp::new(args.tick_rate, args.frame_rate, kh, signal_tx).await?;
6264 tui.run().await?;
6365 // just close everything as soon as the tui is done running
6466 process::exit(0);
···6668 }
6769 });
68706969- let fh = rt.block_on(async {
7070- Arc::new(std::sync::Mutex::new(Filaments::from(
7171- &kh.read().await.index,
7272- )))
7373- });
7471 // spawn deimos
7575- {
7676- let fh = fh.clone();
7272+ // {
77737878- rt.spawn(async {
7979- let deimos = Deimos::new(kh, fh);
8080- deimos.watch().await
8181- });
8282- }
7474+ // rt.spawn(async {
7575+ // let deimos = Deimos::new(kh, fh);
7676+ // deimos.watch().await
7777+ // });
7878+ // }
83798480 // if they asked for the visualizer, we give them the visualizer
8581 if args.visualizer {
8682 // enter the guard so egui_async works properly
8783 let _rt_guard = rt.enter();
8888- FilViz::run(fh)?;
8484+8585+ let index = rt.block_on(async { kh.read().await.index.clone() });
8686+8787+ FilViz::run(kh, signal_rx, &index)?;
8988 }
90899190 // join on the tui
+12-3
src/tui/app.rs
···2929 kh: KastenHandle,
3030 signal_tx: UnboundedSender<Signal>,
3131 signal_rx: UnboundedReceiver<Signal>,
3232+ viz_signal_tx: UnboundedSender<Signal>,
3233}
33343435/// The different regions of the application that the user can
···45464647impl App {
4748 /// Construct a new `App` instance.
4848- pub async fn new(tick_rate: f64, frame_rate: f64, kh: KastenHandle) -> Result<Self> {
4949+ pub async fn new(
5050+ tick_rate: f64,
5151+ frame_rate: f64,
5252+ kh: KastenHandle,
5353+ viz_signal_tx: UnboundedSender<Signal>,
5454+ ) -> Result<Self> {
4955 let (signal_tx, signal_rx) = mpsc::unbounded_channel();
50565157 Ok(Self {
···6167 kh,
6268 signal_tx,
6369 signal_rx,
7070+ viz_signal_tx,
6471 })
6572 }
6673···162169 while let Ok(signal) = self.signal_rx.try_recv() {
163170 if signal != Signal::Tick && signal != Signal::Render {
164171 debug!("handling signal: {signal:?}");
172172+ // we dont care if the receiver is dropped, its fine
173173+ let _ = self.viz_signal_tx.send(signal.clone());
165174 }
166175167176 match signal.clone() {
···176185177186 let hx = spawn({
178187 let file_path = path.clone();
179179- let fil_dir = self.config.fil_dir.clone();
188188+ let _fil_dir = self.config.fil_dir.clone();
180189 move || -> Result<()> {
181190 Command::new("hx")
182191 .stdin(std::process::Stdio::inherit())
183192 .stdout(std::process::Stdio::inherit())
184193 .stderr(std::process::Stdio::inherit())
185194 .arg(file_path)
186186- .arg(format!("-w {}", fil_dir.display()))
195195+ // .arg(format!("-w {}", fil_dir.display()))
187196 .status()?;
188197189198 Ok(())
+16-1
src/tui/components/zk/mod.rs
···240240 .await
241241 .with_context(|| "Failed to create a new Zettel!")?;
242242243243- let path = z.absolute_path(&kt.index).to_path_buf();
243243+ // let path = z.absolute_path(&kt.index).to_path_buf();
244244+245245+ drop(kt);
246246+247247+ return Ok(Some(Signal::CreatedZettel { zid: z.id }));
248248+249249+ // return Ok(Some(Signal::Helix { path }));
250250+ }
251251+ Signal::CreatedZettel { zid } => {
252252+ // what the fuck am i going to do in here
253253+254254+ let kt = self.kh.read().await;
255255+256256+ let path = kt.index.get_zod(&zid).path.clone();
257257+258258+ // let path = z.absolute_path(&kt.index).to_path_buf();
244259245260 drop(kt);
246261
+6-1
src/tui/signal.rs
···2828 MoveDown,
2929 MoveUp,
30303131- /// New `Zettel`
3131+ /// Create a New `Zettel`
3232 NewZettel,
3333+3434+ CreatedZettel {
3535+ zid: ZettelId,
3636+ },
3737+3338 /// User asks to open a `Zettel`
3439 OpenZettel,
3540 /// The user is done editing a `Zettel`
+37-36
src/types/deimos.rs
···11-use color_eyre::eyre::Context;
22-use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Result, Watcher as _};
33-use tracing::{error, info};
11+// use color_eyre::eyre::Context;
22+// use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Result, Watcher as _};
33+// use tracing::{error, info};
4455-use crate::types::{KastenHandle, filaments::FilamentsHandle};
55+use crate::types::KastenHandle;
6677#[derive(Debug)]
88+#[expect(dead_code)]
89pub struct Deimos {
910 kh: KastenHandle,
1010- fh: FilamentsHandle,
1111+ // fh: FilamentsHandle,
1112}
12131313-impl Deimos {
1414- pub const fn new(kh: KastenHandle, fh: FilamentsHandle) -> Self {
1515- Self { kh, fh }
1616- }
1414+// impl Deimos {
1515+// pub const fn new(kh: KastenHandle, fh: FilamentsHandle) -> Self {
1616+// Self { kh, fh }
1717+// }
17181818- /// Watches the `Filaments Directory` for file changes and updates
1919- /// the internal state of the kasten and the `Filaments` displayed in the
2020- /// gui.
2121- ///
2222- /// NOTE: This function must be spawned as a top level await
2323- pub async fn watch(&self) -> color_eyre::Result<()> {
2424- info!("deimos spawned!");
1919+// /// Watches the `Filaments Directory` for file changes and updates
2020+// /// the internal state of the kasten and the `Filaments` displayed in the
2121+// /// gui.
2222+// ///
2323+// /// NOTE: This function must be spawned as a top level await
2424+// pub async fn watch(&self) -> color_eyre::Result<()> {
2525+// info!("deimos spawned!");
25262626- let (tx, mut rx) = tokio::sync::mpsc::channel::<Result<Event>>(10);
2727- let mut watcher = RecommendedWatcher::new(
2828- move |res| tx.blocking_send(res).expect("failed to send event"),
2929- Config::default(),
3030- )?;
2727+// let (tx, mut rx) = tokio::sync::mpsc::channel::<Result<Event>>(10);
2828+// let mut watcher = RecommendedWatcher::new(
2929+// move |res| tx.blocking_send(res).expect("failed to send event"),
3030+// Config::default(),
3131+// )?;
31323232- watcher
3333- .watch(&self.kh.read().await.root, RecursiveMode::Recursive)
3434- .with_context(|| "failed to start the FS watcher")?;
3333+// watcher
3434+// .watch(&self.kh.read().await.root, RecursiveMode::Recursive)
3535+// .with_context(|| "failed to start the FS watcher")?;
35363636- while let Some(res) = rx.recv().await {
3737- let kt = &mut *self.kh.write().await;
3838- let fh = &mut *self.fh.lock().expect("Lock must not be poisoned");
3737+// while let Some(res) = rx.recv().await {
3838+// let kt = &mut *self.kh.write().await;
3939+// let fh = &mut *self.fh.lock().expect("Lock must not be poisoned");
39404040- match res {
4141- Ok(event) => info!("event: {event:?}"),
4242- Err(e) => error!("watch error: {e:?}"),
4343- }
4141+// match res {
4242+// Ok(event) => info!("event: {event:?}"),
4343+// Err(e) => error!("watch error: {e:?}"),
4444+// }
44454545- *fh = (&kt.index).into();
4646- }
4646+// *fh = (&kt.index).into();
4747+// }
47484848- Ok(())
4949- }
5050-}
4949+// Ok(())
5050+// }
5151+// }
+28-16
src/types/filaments.rs
···11-#![expect(dead_code)]
22-use std::{cmp::max, collections::HashMap, sync::Arc};
11+use std::{cmp::max, collections::HashMap};
3243use eframe::emath;
54use egui_graphs::{
66- Graph,
55+ Graph, Node,
76 petgraph::{Directed, graph::NodeIndex, prelude::StableGraph},
87};
981010-use crate::types::{Index, Link, ZettelId};
99+use crate::types::{Index, Link, ZettelId, index::ZettelOnDisk};
11101211pub type ZkGraph = Graph<ZettelId, Link, Directed>;
1312···2322 zid_to_gid: HashMap<ZettelId, NodeIndex>,
2423}
25242626-pub type FilamentsHandle = Arc<std::sync::Mutex<Filaments>>;
2525+impl Filaments {
2626+ pub fn insert_zettel(&mut self, zid: ZettelId, index: &Index) {
2727+ let zod = index.get_zod(&zid);
2828+2929+ let node_idx = self
3030+ .graph
3131+ .add_node_custom(zid.clone(), |node| Self::custom_node_closure(zod, node));
3232+3333+ let _ = self.zid_to_gid.insert(zid, node_idx);
3434+ }
3535+3636+ fn custom_node_closure(zod: &ZettelOnDisk, node: &mut Node<ZettelId, Link>) {
3737+ node.set_label(zod.fm.title.clone());
3838+ let disp = node.display_mut();
3939+ disp.radius = 50.0;
4040+4141+ // randomize position
4242+ let x = rand::random_range(0.0..=100.0);
4343+ let y = rand::random_range(0.0..=100.0);
4444+ node.set_location(emath::Pos2 { x, y });
4545+ node.set_hovered(true);
4646+ }
4747+}
27482849impl From<&Index> for Filaments {
2950 fn from(value: &Index) -> Self {
···3758 ));
38593960 for (zid, zod) in value.zods() {
4040- let node_idx = graph.add_node_custom(zid.clone(), |node| {
4141- node.set_label(zod.fm.title.clone());
4242- let disp = node.display_mut();
4343- disp.radius = 50.0;
4444-4545- // randomize position
4646- let x = rand::random_range(0.0..=100.0);
4747- let y = rand::random_range(0.0..=100.0);
4848- node.set_location(emath::Pos2 { x, y });
4949- node.set_hovered(true);
5050- });
6161+ let node_idx =
6262+ graph.add_node_custom(zid.clone(), |node| Self::custom_node_closure(zod, node));
51635264 let _ = zid_to_gid.insert(zid.clone(), node_idx);
5365 }
+1-1
src/types/mod.rs
···23232424mod filaments;
2525pub use filaments::Filaments;
2626-pub use filaments::FilamentsHandle;
27262827mod index;
2928pub use index::Index;
···3635pub use frontmatter::FrontMatter;
37363837mod deimos;
3838+#[expect(unused_imports)]
3939pub use deimos::Deimos;