From 6670cc4c24fe4cccd469d44003f1ec720a96f9f5 Mon Sep 17 00:00:00 2001 From: aaron-jack-manning Date: Sun, 21 Aug 2022 09:58:05 +1000 Subject: [PATCH] git text editor opening bug fixed; display functions for individual tasks and lists --- Cargo.lock | 280 +++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 2 + README.md | 4 - src/colour.rs | 5 +- src/config.rs | 6 +- src/error.rs | 9 ++ src/git.rs | 16 ++- src/main.rs | 21 +++- src/tasks.rs | 112 +++++++++++++++++++- 9 files changed, 420 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3eaf6a7..78a92a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,7 +19,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -65,7 +65,7 @@ dependencies = [ "serde", "time", "wasm-bindgen", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -115,7 +115,19 @@ checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" dependencies = [ "atty", "lazy_static", - "winapi", + "winapi 0.3.9", +] + +[[package]] +name = "comfy-table" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121d8a5b0346092c18a4b2fd6f620d7a06f0eb7ac0a45860939a0884bc579c56" +dependencies = [ + "crossterm", + "strum", + "strum_macros", + "unicode-width", ] [[package]] @@ -135,6 +147,31 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "crossterm" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +dependencies = [ + "bitflags", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi 0.3.9", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "directories" version = "2.0.2" @@ -153,7 +190,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -208,7 +245,7 @@ dependencies = [ "core-foundation-sys", "js-sys", "wasm-bindgen", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -241,6 +278,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -253,6 +300,16 @@ version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.17" @@ -277,6 +334,18 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -296,6 +365,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" + [[package]] name = "objc" version = "0.2.7" @@ -317,6 +392,29 @@ version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -374,6 +472,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_termios" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" +dependencies = [ + "redox_syscall", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -385,6 +492,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "rustversion" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" + [[package]] name = "scopeguard" version = "1.1.0" @@ -411,12 +524,67 @@ dependencies = [ "syn", ] +[[package]] +name = "signal-hook" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "syn" version = "1.0.99" @@ -437,6 +605,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termion" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" +dependencies = [ + "libc", + "numtoa", + "redox_syscall", + "redox_termios", +] + +[[package]] +name = "termsize" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e86d824a8e90f342ad3ef4bd51ef7119a9b681b0cc9f8ee7b2852f02ccd2517" +dependencies = [ + "atty", + "kernel32-sys", + "libc", + "termion", + "winapi 0.2.8", +] + [[package]] name = "textwrap" version = "0.15.0" @@ -471,7 +664,7 @@ checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -505,8 +698,10 @@ dependencies = [ "chrono", "clap", "colored", + "comfy-table", "confy", "serde", + "termsize", "toml", "trash", ] @@ -548,6 +743,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "url" version = "2.2.2" @@ -632,6 +833,12 @@ version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -642,6 +849,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -654,7 +867,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -669,37 +882,80 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.37.0", + "windows_i686_gnu 0.37.0", + "windows_i686_msvc 0.37.0", + "windows_x86_64_gnu 0.37.0", + "windows_x86_64_msvc 0.37.0", ] +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + [[package]] name = "windows_aarch64_msvc" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + [[package]] name = "windows_i686_gnu" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + [[package]] name = "windows_i686_msvc" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + [[package]] name = "windows_x86_64_gnu" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "windows_x86_64_msvc" version = "0.37.0" diff --git a/Cargo.toml b/Cargo.toml index 313dddc..1054150 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,9 @@ description = "A command line task manager with time tracking." chrono = { version = "0.4.22", features = ["serde"] } clap = { version = "3.2.17", features = ["derive"] } colored = "2.0.0" +comfy-table = "6.0.0" confy = "0.4.0" serde = { version = "1.0.143", features = ["derive"] } +termsize = "0.1.6" toml = "0.5.9" trash = "2.1.5" diff --git a/README.md b/README.md index def063e..98013d3 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ A (currently in development) to do app for the command line. ## Planned Features and Changes: -- Viewing individual tasks in full (command: `view`) - Options for editing additional config - `config` - `editor` subcommand for setting default text editor @@ -26,6 +25,3 @@ A (currently in development) to do app for the command line. - Error if any circular dependencies are introduced - Make sure dependencies written to file are only those that could be successfully created - Automatically added recurring notes - -## Bugs: -- Git commands which automatically open a text editor after don't work as expected diff --git a/src/colour.rs b/src/colour.rs index 8c50182..a36368f 100644 --- a/src/colour.rs +++ b/src/colour.rs @@ -25,7 +25,8 @@ pub fn file(text : &str) -> colored::ColoredString { text.truecolor(255, 184, 184).bold() } -// Pink +// Blue pub fn id(text : &str) -> colored::ColoredString { - text.truecolor(232, 67, 147).bold() + text.truecolor(52, 152, 219) } + diff --git a/src/config.rs b/src/config.rs index 2945e4c..04da6aa 100644 --- a/src/config.rs +++ b/src/config.rs @@ -64,12 +64,12 @@ impl Config { } /// Lists all vaults to stdout. - pub fn list_vaults(&self) { + pub fn list_vaults(&self) -> Result<(), error::Error> { let width = self.vaults.iter().fold(usize::MIN, |c, (n, _)| c.max(n.len())); if self.vaults.is_empty() { - println!("No vaults currently set up, try running: {}", colour::command("toru vault new ")); + Err(error::Error::Generic(format!("No vaults currently set up, try running: {}", colour::command("toru vault new ")))) } else { for (i, (name, path)) in self.vaults.iter().enumerate() { @@ -93,6 +93,8 @@ impl Config { println!(); } + + Ok(()) } } } diff --git a/src/error.rs b/src/error.rs index 887285c..0f0c0b9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,6 +12,7 @@ pub enum Error { TomlDe(toml::de::Error), TomlSer(toml::ser::Error), Utf8(str::Utf8Error), + Fmt(fmt::Error), Generic(String), } @@ -24,6 +25,7 @@ impl fmt::Display for Error { Error::TomlDe(err) => write!(f, "{} {}", colour::error("Internal Error:"), err), Error::TomlSer(err) => write!(f, "{} {}", colour::error("Internal Error:"), err), Error::Utf8(err) => write!(f, "{} {}", colour::error("Internal Error:"), err), + Error::Fmt(err) => write!(f, "{} {}", colour::error("Internal Error:"), err), Error::Generic(message) => write!(f, "{}", message), } } @@ -64,3 +66,10 @@ impl From for Error { Error::Utf8(err) } } + +impl From for Error { + fn from(err : fmt::Error) -> Self { + Error::Fmt(err) + } +} + diff --git a/src/git.rs b/src/git.rs index b1227a7..7904960 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,26 +1,22 @@ use crate::error; -use std::io; -use std::str; use std::path; use std::process; -use std::io::Write; pub fn run_command(args : Vec, vault_folder : &path::Path) -> Result<(), error::Error> { let mut command = process::Command::new("git"); - command + let mut child = command .current_dir(vault_folder) // Force colour output even though run from other process. .args(["-c", "color.ui=always"]) - .args(args); + .args(args) + .spawn()?; - let output = command.output()?; - let output_string = str::from_utf8(&output.stdout)?; - - print!("{}", output_string); - io::stdout().flush()?; + // No point handling the potential error code as Git will report the error directly with more + // info. + let _ = child.wait()?; Ok(()) } diff --git a/src/main.rs b/src/main.rs index b9166c9..8463790 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,6 +32,10 @@ enum Command { #[clap(short, long, value_enum)] priority : Option, }, + /// Displays the specified task in detail. + View { + id : tasks::Id, + }, /// Delete a task completely. Delete { id : tasks::Id, @@ -49,6 +53,14 @@ enum Command { Git { args : Vec, }, + /// Lists tasks according to the specified ordering and filters. + List { + // Need to have options for: + // - column to order by + // - ascending or descending + // - which columns to include + // - filters which exclude values + }, /// Commands for interacting with vaults. #[clap(subcommand)] Vault(VaultCommand), @@ -124,7 +136,7 @@ fn program() -> Result<(), error::Error> { println!("Deleted vault {}", colour::vault(&name)); }, List => { - config.list_vaults(); + config.list_vaults()?; }, Switch { name } => { config.switch(&name)?; @@ -144,6 +156,10 @@ fn program() -> Result<(), error::Error> { Delete { id } => { tasks::Task::delete_by_id(id, vault_folder)?; println!("Deleted task {}", colour::id(&id.to_string())); + }, + View { id } => { + let task = tasks::Task::load(id, vault_folder.clone(), true)?; + task.display()?; } Discard { id } => { let mut task = tasks::Task::load(id, vault_folder.clone(), false)?; @@ -160,6 +176,9 @@ fn program() -> Result<(), error::Error> { Git { args } => { git::run_command(args, vault_folder)?; }, + List {} => { + tasks::list(vault_folder)?; + } Vault(_) => unreachable!(), } diff --git a/src/tasks.rs b/src/tasks.rs index 06b00da..b8bec81 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -2,12 +2,14 @@ use crate::error; use crate::state; use crate::colour; +use std::io; use std::fs; +use std::fmt; use std::mem; use std::path; -use std::io; use std::io::{Write, Seek}; use std::collections::HashSet; +use colored::Colorize; pub type Id = u64; @@ -20,19 +22,42 @@ pub struct Task { #[derive(Default, Debug, Clone, clap::ValueEnum, serde::Serialize, serde::Deserialize)] pub enum Priority { #[default] - Unspecified, Low, Medium, High, } -#[derive(serde::Serialize, serde::Deserialize)] +impl fmt::Display for Priority { + fn fmt(&self, f : &mut fmt::Formatter<'_>) -> fmt::Result { + use Priority::*; + let priority = match self { + Low => "low", + Medium => "medium", + High => "high", + }; + write!(f, "{}", priority) + } +} + +impl Priority { + pub fn coloured(&self) -> String { + use Priority::*; + let priority = match self { + Low => "low".truecolor(46, 204, 113), + Medium => "medium".truecolor(241, 196, 15), + High => "high".truecolor(231, 76, 60), + }; + format!("{}", priority) + } +} + +#[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct TimeEntry { hours : u32, minutes : u8, } -#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct InternalTask { pub id : Id, pub name : String, @@ -152,6 +177,85 @@ impl Task { fs::remove_file(&path)?; Ok(()) } + + pub fn display(&self) -> Result<(), error::Error> { + + fn line(len : usize) { + for _ in 0..len { + print!("-"); + } + println!(); + } + + let id = &self.data.id.to_string(); + let heading = format!("[{}] {} {}", if self.data.complete {"X"} else {" "}, colour::id(&id), colour::task_name(&self.data.name)); + println!("{}", heading); + line(5 + self.data.name.len() + id.len()); + println!("Priority: {}", self.data.priority.coloured()); + println!("Tags: [{}]", format_hash_set(&self.data.tags)?); + println!("Created: {}", self.data.created); + + if let Some(info) = &self.data.info { + println!("Info:"); + // Figure out how to indent this properly: + println!("\t{}", info); + } + + Ok(()) + + // dependencies as a tree + } +} + +fn format_hash_set(set : &HashSet) -> Result { + let mut output = String::new(); + + for value in set.iter() { + fmt::write(&mut output, format_args!("{}, ", value))?; + } + + if output.len() != 0 { + output.pop(); + output.pop(); + } + + Ok(output) +} + +pub fn list(vault_folder : &path::Path) -> Result<(), error::Error> { + let ids : Vec = + fs::read_dir(vault_folder.join("notes")) + .unwrap() + .map(|entry| entry.unwrap().path()) + .filter(|p| p.is_file()) + .map(|p| p.file_stem().unwrap().to_str().unwrap().to_string()) + .filter_map(|n| n.parse::().ok()) + .collect(); + + let mut table = comfy_table::Table::new(); + + table + .load_preset(comfy_table::presets::UTF8_FULL) + .apply_modifier(comfy_table::modifiers::UTF8_ROUND_CORNERS); + + table.set_header(vec!["Id", "Name", "Tags", "Priority"]); + + for id in ids { + let task = Task::load(id, vault_folder.to_path_buf(), true)?; + + table.add_row( + vec![ + task.data.id.to_string(), + task.data.name, + format_hash_set(&task.data.tags)?, + task.data.priority.to_string() + ] + ); + } + + println!("{}", table); + + Ok(()) }