From 1885a200c40f3d200c53cb656e1c2b34e5677dd1 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Wed, 1 May 2024 22:17:39 +0200 Subject: [PATCH] feat: add logging for tui Signed-off-by: kjuulh --- Cargo.lock | 241 ++++++++++++++++++++++++- Cargo.toml | 5 +- crates/hyperlog-core/Cargo.toml | 8 +- crates/hyperlog-core/src/querier.rs | 13 +- crates/hyperlog-core/src/storage.rs | 9 + crates/hyperlog-tui/Cargo.toml | 16 ++ crates/hyperlog-tui/src/lib.rs | 138 ++++++++++++++ crates/hyperlog-tui/src/logging.rs | 77 ++++++++ crates/hyperlog/Cargo.toml | 9 +- crates/hyperlog/screens/outer-focus.md | 77 ++++++++ crates/hyperlog/src/cli.rs | 17 +- crates/hyperlog/src/main.rs | 1 - 12 files changed, 600 insertions(+), 11 deletions(-) create mode 100644 crates/hyperlog-tui/Cargo.toml create mode 100644 crates/hyperlog-tui/src/lib.rs create mode 100644 crates/hyperlog-tui/src/logging.rs create mode 100644 crates/hyperlog/screens/outer-focus.md diff --git a/Cargo.lock b/Cargo.lock index 6e0fe54..c23a1ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.16" @@ -211,7 +220,7 @@ checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -237,6 +246,21 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + +[[package]] +name = "castaway" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.0.79" @@ -297,6 +321,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "compact_str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "ryu", + "static_assertions", +] + [[package]] name = "console" version = "0.15.8" @@ -363,6 +400,32 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.4.2", + "crossterm_winapi", + "futures-core", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -405,6 +468,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs" version = "5.0.1" @@ -804,6 +876,7 @@ dependencies = [ "dirs", "dotenv", "hyperlog-core", + "hyperlog-tui", "serde", "serde_json", "similar-asserts", @@ -838,6 +911,20 @@ dependencies = [ "uuid", ] +[[package]] +name = "hyperlog-tui" +version = "0.1.0" +dependencies = [ + "anyhow", + "crossterm", + "directories", + "hyperlog-core", + "ratatui", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "idna" version = "0.4.0" @@ -858,6 +945,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -966,6 +1059,24 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matchit" version = "0.7.0" @@ -1007,6 +1118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] @@ -1281,6 +1393,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "ratatui" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a564a852040e82671dc50a37d88f3aa83bbc690dfc6844cfe7a2591620206a80" +dependencies = [ + "bitflags 2.4.2", + "cassowary", + "compact_str", + "crossterm", + "indoc", + "itertools", + "lru", + "paste", + "stability", + "strum", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -1301,11 +1433,49 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.3.7", + "regex-syntax 0.7.5", +] + [[package]] name = "regex-automata" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "ring" @@ -1509,6 +1679,27 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1827,6 +2018,22 @@ dependencies = [ "uuid", ] +[[package]] +name = "stability" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" +dependencies = [ + "quote", + "syn 2.0.48", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "stringprep" version = "0.1.4" @@ -1844,6 +2051,28 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "subtle" version = "2.5.0" @@ -2115,10 +2344,14 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] @@ -2156,6 +2389,12 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + [[package]] name = "unicode_categories" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index a108e2c..df62aa1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,12 +3,13 @@ members = ["crates/*"] resolver = "2" [workspace.dependencies] -hyperlog-core = {path = "crates/hyperlog-core"} +hyperlog-core = { path = "crates/hyperlog-core" } +hyperlog-tui = { path = "crates/hyperlog-tui" } anyhow = { version = "1" } tokio = { version = "1", features = ["full"] } tracing = { version = "0.1", features = ["log"] } -tracing-subscriber = { version = "0.3.18" } +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } clap = { version = "4", features = ["derive", "env"] } dotenv = { version = "0.15" } axum = { version = "0.7" } diff --git a/crates/hyperlog-core/Cargo.toml b/crates/hyperlog-core/Cargo.toml index 089786c..3d6af74 100644 --- a/crates/hyperlog-core/Cargo.toml +++ b/crates/hyperlog-core/Cargo.toml @@ -13,7 +13,13 @@ dotenv.workspace = true axum.workspace = true serde = { version = "1.0.197", features = ["derive"] } -sqlx = { version = "0.7.3", features = ["runtime-tokio", "tls-rustls", "postgres", "uuid", "time"] } +sqlx = { version = "0.7.3", features = [ + "runtime-tokio", + "tls-rustls", + "postgres", + "uuid", + "time", +] } uuid = { version = "1.7.0", features = ["v4"] } tower-http = { version = "0.5.2", features = ["cors", "trace"] } serde_json = "1.0.116" diff --git a/crates/hyperlog-core/src/querier.rs b/crates/hyperlog-core/src/querier.rs index 98ca177..f121f79 100644 --- a/crates/hyperlog-core/src/querier.rs +++ b/crates/hyperlog-core/src/querier.rs @@ -14,9 +14,18 @@ impl Querier { root: &str, path: impl IntoIterator>, ) -> Option { - let path = path.into_iter().map(|i| i.into()).collect::>(); + let path = path + .into_iter() + .map(|i| i.into()) + .filter(|i| !i.is_empty()) + .collect::>(); - tracing::debug!("quering: {}, len: ({}))", path.join("."), path.len()); + tracing::debug!( + "quering: root:({}), path:({}), len: ({}))", + root, + path.join("."), + path.len() + ); self.engine .get(root, &path.iter().map(|i| i.as_str()).collect::>()) diff --git a/crates/hyperlog-core/src/storage.rs b/crates/hyperlog-core/src/storage.rs index b3a2177..e073820 100644 --- a/crates/hyperlog-core/src/storage.rs +++ b/crates/hyperlog-core/src/storage.rs @@ -10,6 +10,7 @@ pub struct LockFile(PathBuf); impl Drop for LockFile { fn drop(&mut self) { + tracing::debug!("removing lockfile"); std::fs::remove_file(&self.0).expect("to be able to delete lockfile") } } @@ -76,6 +77,14 @@ impl Storage { Ok(()) } + pub fn clear_lock_file(self) { + let mut lock_file = self.lock_file.lock().unwrap(); + + if lock_file.is_some() { + *lock_file = None; + } + } + fn state(&self) -> anyhow::Result { self.cache().map(|c| c.join("graph.json")) } diff --git a/crates/hyperlog-tui/Cargo.toml b/crates/hyperlog-tui/Cargo.toml new file mode 100644 index 0000000..530c3a9 --- /dev/null +++ b/crates/hyperlog-tui/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "hyperlog-tui" +version = "0.1.0" +edition = "2021" + +[dependencies] +hyperlog-core.workspace = true + +anyhow.workspace = true +tokio.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true + +ratatui = "0.26.2" +crossterm = { version = "0.27.0", features = ["event-stream"] } +directories = "5.0.1" diff --git a/crates/hyperlog-tui/src/lib.rs b/crates/hyperlog-tui/src/lib.rs new file mode 100644 index 0000000..908034e --- /dev/null +++ b/crates/hyperlog-tui/src/lib.rs @@ -0,0 +1,138 @@ +use std::{ + io::{self, Stdout}, + ops::{Deref, DerefMut}, + time::Duration, +}; + +use anyhow::{Context, Result}; +use crossterm::{ + event::{self, Event, KeyCode}, + execute, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, +}; +use hyperlog_core::state::State; +use ratatui::{backend::CrosstermBackend, prelude::*, widgets::*, Frame, Terminal}; + +struct TerminalInstance { + terminal: Terminal>, +} + +impl TerminalInstance { + fn new() -> Result { + Ok(Self { + terminal: setup_terminal().context("setup failed")?, + }) + } +} + +impl Deref for TerminalInstance { + type Target = Terminal>; + + fn deref(&self) -> &Self::Target { + &self.terminal + } +} + +impl DerefMut for TerminalInstance { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.terminal + } +} + +impl Drop for TerminalInstance { + fn drop(&mut self) { + if let Err(e) = restore_terminal(&mut self.terminal).context("restore terminal failed") { + tracing::error!("failed to restore terminal: {}", e); + } + } +} + +pub async fn execute(state: &State) -> Result<()> { + tracing::debug!("starting hyperlog tui"); + + logging::initialize_panic_handler()?; + logging::initialize_logging()?; + + let mut terminal = TerminalInstance::new()?; + run(&mut terminal, state).context("app loop failed")?; + + Ok(()) +} + +fn run(terminal: &mut Terminal>, state: &State) -> Result<()> { + loop { + terminal.draw(|f| crate::render_app(f, &state))?; + if should_quit()? { + break; + } + } + Ok(()) +} + +fn render_app(frame: &mut Frame, state: &State) { + let chunks = + Layout::vertical(vec![Constraint::Length(2), Constraint::Min(0)]).split(frame.size()); + + let heading = Paragraph::new(text::Line::from( + Span::styled("hyperlog", Style::default()).fg(Color::Green), + )); + let block_heading = Block::default().borders(Borders::BOTTOM); + + frame.render_widget(heading.block(block_heading), chunks[0]); + + let Rect { width, height, .. } = chunks[1]; + + let height = height as usize; + let width = width as usize; + + let mut lines = Vec::new(); + for y in 0..height { + if !y % 2 == 0 { + lines.push(text::Line::default()); + } else { + lines.push(text::Line::raw(" ~ ".repeat(width / 3))); + } + } + let background = Paragraph::new(lines); + + let bg_block = Block::default() + .fg(Color::DarkGray) + .bold() + .padding(Padding { + left: 4, + right: 4, + top: 2, + bottom: 2, + }); + + if let Some(graph) = state.querier.get("something", Vec::::new()) {} + + frame.render_widget(background.block(bg_block), chunks[1]); +} + +fn should_quit() -> Result { + if event::poll(Duration::from_millis(250)).context("event poll failed")? { + if let Event::Key(key) = event::read().context("event read failed")? { + return Ok(KeyCode::Char('q') == key.code); + } + } + Ok(false) +} + +fn setup_terminal() -> Result>> { + let mut stdout = io::stdout(); + enable_raw_mode().context("failed to enable raw mode")?; + execute!(stdout, EnterAlternateScreen).context("unable to enter alternate screen")?; + Terminal::new(CrosstermBackend::new(stdout)).context("creating terminal failed") +} + +/// Restore the terminal. This is where you disable raw mode, leave the alternate screen, and show +/// the cursor. +fn restore_terminal(terminal: &mut Terminal>) -> Result<()> { + disable_raw_mode().context("failed to disable raw mode")?; + execute!(terminal.backend_mut(), LeaveAlternateScreen) + .context("unable to switch to main screen")?; + terminal.show_cursor().context("unable to show cursor") +} + +mod logging; diff --git a/crates/hyperlog-tui/src/logging.rs b/crates/hyperlog-tui/src/logging.rs new file mode 100644 index 0000000..5a6fd44 --- /dev/null +++ b/crates/hyperlog-tui/src/logging.rs @@ -0,0 +1,77 @@ +use std::path::PathBuf; + +use directories::ProjectDirs; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer}; + +pub fn initialize_logging() -> anyhow::Result<()> { + let project = match ProjectDirs::from("io", "kjuulh", env!("CARGO_PKG_NAME")) { + Some(p) => p.data_local_dir().to_path_buf(), + None => PathBuf::from(".").join(".data"), + }; + + std::fs::create_dir_all(&project)?; + let log_path = project.join("hyperlog.log"); + + //println!("logging to: {}", log_path.display()); + + let log_file = std::fs::File::create(log_path)?; + std::env::set_var( + "RUST_LOG", + std::env::var("RUST_LOG") + .or_else(|_| std::env::var("HYPERLOG_LOG_LEVEL")) + .unwrap_or_else(|_| format!("{}=info", env!("CARGO_CRATE_NAME"))), + ); + + let file_subscriber = tracing_subscriber::fmt::layer() + .with_file(true) + .with_line_number(true) + .with_writer(log_file) + .with_target(false) + .with_ansi(false) + .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env()); + tracing_subscriber::registry() + .with(file_subscriber) + //.with(ErrorLayer::default()) + .init(); + Ok(()) +} + +pub fn initialize_panic_handler() -> anyhow::Result<()> { + std::panic::set_hook(Box::new(move |panic_info| { + // if let Ok(mut t) = crate::tui::Tui::new() { + // if let Err(r) = t.exit() { + // tracing::error!("Unable to exit Terminal: {:?}", r); + // } + // } + + #[cfg(not(debug_assertions))] + { + use human_panic::{handle_dump, print_msg, Metadata}; + let meta = Metadata { + version: env!("CARGO_PKG_VERSION").into(), + name: env!("CARGO_PKG_NAME").into(), + authors: env!("CARGO_PKG_AUTHORS").replace(':', ", ").into(), + homepage: env!("CARGO_PKG_HOMEPAGE").into(), + }; + + let file_path = handle_dump(&meta, panic_info); + // prints human-panic message + print_msg(file_path, &meta) + .expect("human-panic: printing error message to console failed"); + //eprintln!("{}", panic_hook.panic_report(panic_info)); // prints color-eyre stack trace to stderr + } + let msg = format!("{}", panic_info); + tracing::error!("Error: {}", msg); + + // #[cfg(debug_assertions)] + // { + // // Better Panic stacktrace that is only enabled when debugging. + // better_panic::Settings::auto() + // .most_recent_first(false) + // .lineno_suffix(true) + // .verbosity(better_panic::Verbosity::Full) + // .create_panic_handler()(panic_info); + // } + })); + Ok(()) +} diff --git a/crates/hyperlog/Cargo.toml b/crates/hyperlog/Cargo.toml index 194b01b..4cdf0e2 100644 --- a/crates/hyperlog/Cargo.toml +++ b/crates/hyperlog/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] hyperlog-core.workspace = true +hyperlog-tui.workspace = true anyhow.workspace = true tokio.workspace = true @@ -15,7 +16,13 @@ dotenv.workspace = true axum.workspace = true serde = { version = "1.0.197", features = ["derive"] } -sqlx = { version = "0.7.3", features = ["runtime-tokio", "tls-rustls", "postgres", "uuid", "time"] } +sqlx = { version = "0.7.3", features = [ + "runtime-tokio", + "tls-rustls", + "postgres", + "uuid", + "time", +] } uuid = { version = "1.7.0", features = ["v4"] } tower-http = { version = "0.5.2", features = ["cors", "trace"] } serde_json = "1.0.116" diff --git a/crates/hyperlog/screens/outer-focus.md b/crates/hyperlog/screens/outer-focus.md new file mode 100644 index 0000000..e738a3c --- /dev/null +++ b/crates/hyperlog/screens/outer-focus.md @@ -0,0 +1,77 @@ +hyperlog +-------- +kjuulh: + - (summary: items(10)) -> projects/** + - [ ] wash the dishes + + ... + + - project A + + - sub project B (items: 10) + + ... + + - sub project C (items: 0) + + - project B + + - sub project A + + - project C + + - sub project A + + - project D + + - sub project A + +--- + +Traversing into the nested section + +hyperlog +-------- +kjuulh: + - (summary: items(10)) -> projects/** + - **project A** + + - sub project B (items: 10) + - [ ] Something + - [ ] Something B (High priority, due wednesday) + - [ ] Something C + + ... + + - sub project C (items: 0) + + - [ ] Something + - [ ] Something B (High priority, due wednesday) + - [ ] Something C + - [ ] Something D + - [ ] Something E + + ... + + - project B + + +--- + +Traversing into the final section + +hyperlog +-------- +- **project A** + + - **sub project B (items: 10)** + + - [ ] Something + - [ ] Something B (High priority, due wednesday) + - [ ] Something C + - [ ] Something E + - [ ] Something D + + - sub project C (items: 0) + + ... diff --git a/crates/hyperlog/src/cli.rs b/crates/hyperlog/src/cli.rs index e3cc2fd..ae5f005 100644 --- a/crates/hyperlog/src/cli.rs +++ b/crates/hyperlog/src/cli.rs @@ -6,7 +6,7 @@ use hyperlog_core::{commander, state}; use crate::server::serve; #[derive(Parser)] -#[command(author, version, about, long_about = None, subcommand_required = true)] +#[command(author, version, about, long_about = None)] struct Command { #[command(subcommand)] command: Option, @@ -27,6 +27,8 @@ enum Commands { commands: QueryCommands, }, Info {}, + + ClearLock {}, } #[derive(Subcommand)] @@ -59,6 +61,10 @@ enum QueryCommands { pub async fn execute() -> anyhow::Result<()> { let cli = Command::parse(); + if cli.command.is_some() { + tracing_subscriber::fmt::init(); + } + let state = state::State::new()?; match cli.command { @@ -100,8 +106,13 @@ pub async fn execute() -> anyhow::Result<()> { Some(Commands::Info {}) => { println!("graph stored at: {}", state.storage.info()?) } - - None => {} + Some(Commands::ClearLock {}) => { + state.storage.clear_lock_file(); + println!("cleared lock file"); + } + None => { + hyperlog_tui::execute(&state).await?; + } } Ok(()) diff --git a/crates/hyperlog/src/main.rs b/crates/hyperlog/src/main.rs index 552c00a..adad57b 100644 --- a/crates/hyperlog/src/main.rs +++ b/crates/hyperlog/src/main.rs @@ -5,7 +5,6 @@ pub(crate) mod state; #[tokio::main] async fn main() -> anyhow::Result<()> { dotenv::dotenv().ok(); - tracing_subscriber::fmt::init(); cli::execute().await?;