From d9e455fefee6d09e2f1759c40304b33405f3a0f2 Mon Sep 17 00:00:00 2001 From: Amolith Date: Wed, 25 Feb 2026 20:11:34 +0000 Subject: [PATCH] Adopt comfy-table for consistent CLI output formatting Replace hardcoded format!() spacing with comfy-table across all commands. Fix missing effort column in list output. --- Cargo.lock | 131 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/cmd/list.rs | 27 +++++----- src/cmd/ready.rs | 23 ++++---- src/cmd/search.rs | 12 ++++- 5 files changed, 170 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dbec37daf114bf3dad0f1821c93aab2af2b1a63d..b88477759168a9baede7b52e2c5090b99623eb47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,18 +193,61 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "comfy-table" +version = "7.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958c5d6ecf1f214b4c2bbbbf6ab9523a864bd136dcf71a7e8904799acfe1ad47" +dependencies = [ + "crossterm", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags", + "crossterm_winapi", + "document-features", + "parking_lot", + "rustix", + "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 = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -396,6 +439,21 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.29" @@ -435,6 +493,29 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -505,6 +586,15 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.12.3" @@ -567,6 +657,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "semver" version = "1.0.27" @@ -670,6 +766,18 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -794,6 +902,28 @@ dependencies = [ "semver", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.62.2" @@ -958,6 +1088,7 @@ dependencies = [ "assert_cmd", "chrono", "clap", + "comfy-table", "predicates", "rusqlite", "serde", diff --git a/Cargo.toml b/Cargo.toml index 0d28a4b99ba99416bc96efcd31c4e7c3f5196c06..27239288aca701119cfee2d85c87cd0ae3c69a2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ path = "src/main.rs" anyhow = "1" chrono = { version = "0.4", default-features = false, features = ["clock"] } clap = { version = "4", features = ["derive"] } +comfy-table = "7.2.2" rusqlite = { version = "0.34", features = ["bundled"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/src/cmd/list.rs b/src/cmd/list.rs index 0eb1784aaca055706be249e3d440678747b14df5..4ed3edac48ce541e7bc1066cbf41d366924de6f7 100644 --- a/src/cmd/list.rs +++ b/src/cmd/list.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use comfy_table::presets::NOTHING; +use comfy_table::Table; use std::path::Path; use crate::db; @@ -66,20 +68,19 @@ pub fn run( println!("{}", serde_json::to_string(&details)?); } else { let c = crate::color::stdout_theme(); + let mut table = Table::new(); + table.load_preset(NOTHING); for t in &tasks { - println!( - "{}{:<12}{} {}{:<12}{} {}{:<4}{} {}", - c.bold, - t.id, - c.reset, - c.yellow, - format!("[{}]", t.status), - c.reset, - c.red, - db::priority_label(t.priority), - c.reset, - t.title, - ); + table.add_row(vec![ + format!("{}{}{}", c.bold, t.id, c.reset), + format!("{}[{}]{}", c.yellow, t.status, c.reset), + format!("{}{}{}", c.red, db::priority_label(t.priority), c.reset), + format!("{}{}{}", c.blue, db::effort_label(t.effort), c.reset), + t.title.clone(), + ]); + } + if !tasks.is_empty() { + println!("{table}"); } } diff --git a/src/cmd/ready.rs b/src/cmd/ready.rs index 9fe4d6f784b4c3ba52aa3c6ce33a42349b155fcd..88b12cc6cfe89b18eecc19738ac0aaee2f869272 100644 --- a/src/cmd/ready.rs +++ b/src/cmd/ready.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use comfy_table::presets::NOTHING; +use comfy_table::Table; use std::path::Path; use crate::db; @@ -37,17 +39,18 @@ pub fn run(root: &Path, json: bool) -> Result<()> { println!("{}", serde_json::to_string(&summary)?); } else { let c = crate::color::stdout_theme(); + let mut table = Table::new(); + table.load_preset(NOTHING); for t in &tasks { - println!( - "{}{:<12}{} {}{:<8}{} {}", - c.green, - t.id, - c.reset, - c.red, - db::priority_label(t.priority), - c.reset, - t.title - ); + table.add_row(vec![ + format!("{}{}{}", c.green, t.id, c.reset), + format!("{}{}{}", c.red, db::priority_label(t.priority), c.reset), + format!("{}{}{}", c.blue, db::effort_label(t.effort), c.reset), + t.title.clone(), + ]); + } + if !tasks.is_empty() { + println!("{table}"); } } diff --git a/src/cmd/search.rs b/src/cmd/search.rs index 12cebb75af4f84e77f6bccf09bd15a3e272edbb1..e85f678128ce807c30121bab8a20aef2dff24c3b 100644 --- a/src/cmd/search.rs +++ b/src/cmd/search.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use comfy_table::presets::NOTHING; +use comfy_table::Table; use std::path::Path; use crate::db; @@ -31,8 +33,16 @@ pub fn run(root: &Path, query: &str, json: bool) -> Result<()> { println!("{}", serde_json::to_string(&summary)?); } else { let c = crate::color::stdout_theme(); + let mut table = Table::new(); + table.load_preset(NOTHING); for t in &tasks { - println!("{}{}{} {}", c.bold, t.id, c.reset, t.title); + table.add_row(vec![ + format!("{}{}{}", c.bold, t.id, c.reset), + t.title.clone(), + ]); + } + if !tasks.is_empty() { + println!("{table}"); } }