feat: hide done tasks by default in backlog show
Done tasks are hidden by default. Pass --done to show only done tasks.
Works with both human and JSON output formats.
change zywmuyqxtmwunuxsumkmtmrtvsmzslvo
commit 4340a7369df1cac56592370edb8daef15d3bbac9
author Alpha Chen <alpha@kejadlen.dev>
date
parent qolxqyon
diff --git a/src/bin/ranger/commands/backlog.rs b/src/bin/ranger/commands/backlog.rs
index 2d151b9..086244b 100644
--- a/src/bin/ranger/commands/backlog.rs
+++ b/src/bin/ranger/commands/backlog.rs
@@ -25,6 +25,10 @@ pub enum BacklogCommands {
         /// Backlog name
         #[arg(env = "RANGER_DEFAULT_BACKLOG")]
         name: String,
+
+        /// Show only done tasks
+        #[arg(long)]
+        done: bool,
     },
     /// Rebalance task positions in a backlog
     Rebalance {
@@ -51,12 +55,18 @@ pub async fn run(pool: &SqlitePool, command: BacklogCommands, json: bool) -> Res
             let count = ops::task::rebalance(&mut conn, backlog.id).await?;
             println!("Rebalanced {count} tasks in {name}");
         }
-        BacklogCommands::Show { name } => {
+        BacklogCommands::Show { name, done } => {
             let backlog = ops::backlog::get_by_name(&mut conn, &name).await?;
 
+            let states: Vec<State> = if done {
+                vec![State::Done]
+            } else {
+                vec![State::InProgress, State::Queued, State::Icebox]
+            };
+
             if json {
                 let mut state_groups = serde_json::Map::new();
-                for state in [State::Done, State::InProgress, State::Queued, State::Icebox] {
+                for state in &states {
                     let filter = ListFilter {
                         state: Some(state.clone()),
                         ..Default::default()
@@ -78,7 +88,7 @@ pub async fn run(pool: &SqlitePool, command: BacklogCommands, json: bool) -> Res
 
                 print_backlog_detail(&backlog);
 
-                for state in [State::Done, State::InProgress, State::Queued, State::Icebox] {
+                for state in &states {
                     let filter = ListFilter {
                         state: Some(state.clone()),
                         ..Default::default()
diff --git a/src/bin/ranger/main.rs b/src/bin/ranger/main.rs
index eb9772c..eb990ca 100644
--- a/src/bin/ranger/main.rs
+++ b/src/bin/ranger/main.rs
@@ -105,7 +105,7 @@ async fn main() -> color_eyre::Result<()> {
             let backlog_name = std::env::var("RANGER_DEFAULT_BACKLOG").ok();
             match backlog_name {
                 Some(name) => {
-                    let show_cmd = commands::backlog::BacklogCommands::Show { name };
+                    let show_cmd = commands::backlog::BacklogCommands::Show { name, done: false };
                     commands::backlog::run(&pool, show_cmd, cli.json).await?;
                 }
                 None => {
diff --git a/tests/cli.rs b/tests/cli.rs
index 09d3d5d..f7b27ce 100644
--- a/tests/cli.rs
+++ b/tests/cli.rs
@@ -278,6 +278,69 @@ fn full_workflow() {
     let stdout = String::from_utf8(output.stdout).unwrap();
     assert!(stdout.contains("Ranger"));
 
+    // Mark a task as done for the --done test
+    let output = ranger(db_path)
+        .args(["task", "edit", &t1_key[..4], "--state", "done"])
+        .output()
+        .unwrap();
+    assert!(output.status.success());
+
+    // Backlog show hides done tasks by default
+    let output = ranger(db_path).args(["backlog", "show"]).output().unwrap();
+    assert!(output.status.success());
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    assert!(
+        !stdout.contains("[done]"),
+        "should not show done section by default"
+    );
+
+    // Backlog show --done shows only done tasks
+    let output = ranger(db_path)
+        .args(["backlog", "show", "--done"])
+        .output()
+        .unwrap();
+    assert!(output.status.success());
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    assert!(
+        stdout.contains("[done]"),
+        "should show done section with --done"
+    );
+    assert!(
+        !stdout.contains("[in_progress]"),
+        "--done should not show in_progress"
+    );
+    assert!(
+        !stdout.contains("[queued]"),
+        "--done should not show queued"
+    );
+    assert!(
+        !stdout.contains("[icebox]"),
+        "--done should not show icebox"
+    );
+
+    // Backlog show --done with JSON shows only done tasks
+    let output = ranger(db_path)
+        .args(["backlog", "show", "--done", "--json"])
+        .output()
+        .unwrap();
+    assert!(output.status.success());
+    let detail: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
+    assert!(detail["tasks"]["done"].is_array());
+    assert!(detail["tasks"]["queued"].is_null());
+    assert!(detail["tasks"]["in_progress"].is_null());
+
+    // Backlog show JSON without --done excludes done tasks
+    let output = ranger(db_path)
+        .args(["backlog", "show", "--json"])
+        .output()
+        .unwrap();
+    assert!(output.status.success());
+    let detail: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
+    assert!(
+        detail["tasks"]["done"].is_null(),
+        "JSON should exclude done without --done"
+    );
+
     // Shell completions (no DB needed, but pass one anyway for the helper)
     for shell in ["bash", "zsh", "fish", "elvish", "powershell"] {
         let output = ranger(db_path)