Default list to open and in-progress tasks

Amolith created

Change summary

src/cli.rs             |  4 ++++
src/cmd/list.rs        |  4 ++++
src/cmd/mod.rs         |  2 ++
tests/cli_list_show.rs | 31 +++++++++++++++++++++++++++++++
4 files changed, 41 insertions(+)

Detailed changes

src/cli.rs 🔗

@@ -72,6 +72,10 @@ pub enum Command {
         /// Filter by label
         #[arg(short, long)]
         label: Option<String>,
+
+        /// Show all tasks including closed
+        #[arg(short, long)]
+        all: bool,
     },
 
     /// Show task details

src/cmd/list.rs 🔗

@@ -13,6 +13,7 @@ pub fn run(
     priority: Option<Priority>,
     effort: Option<Effort>,
     label: Option<&str>,
+    all: bool,
     json: bool,
 ) -> Result<()> {
     let store = db::open(root)?;
@@ -21,6 +22,9 @@ pub fn run(
     if let Some(s) = status {
         let parsed = Status::parse(s)?;
         tasks.retain(|t| t.status == parsed);
+    } else if !all {
+        // By default, show open and in-progress tasks but not closed.
+        tasks.retain(|t| t.status == Status::Open || t.status == Status::InProgress);
     }
     if let Some(p) = priority {
         tasks.retain(|t| t.priority == p);

src/cmd/mod.rs 🔗

@@ -66,6 +66,7 @@ pub fn dispatch(cli: &Cli) -> Result<()> {
             priority,
             effort,
             label,
+            all,
         } => {
             let root = require_root()?;
             let pri = priority.as_deref().map(Priority::parse).transpose()?;
@@ -76,6 +77,7 @@ pub fn dispatch(cli: &Cli) -> Result<()> {
                 pri,
                 eff,
                 label.as_deref(),
+                *all,
                 cli.json,
             )
         }

tests/cli_list_show.rs 🔗

@@ -77,6 +77,37 @@ fn list_filter_by_status() {
     assert_eq!(v.as_array().unwrap().len(), 0);
 }
 
+#[test]
+fn list_hides_closed_by_default() {
+    let tmp = init_tmp();
+    let id = create_task(&tmp, "Will close");
+
+    td(&tmp)
+        .args(["done", &id])
+        .current_dir(&tmp)
+        .assert()
+        .success();
+
+    // Default list should not show the closed task.
+    let out = td(&tmp)
+        .args(["--json", "list"])
+        .current_dir(&tmp)
+        .output()
+        .unwrap();
+    let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
+    assert_eq!(v.as_array().unwrap().len(), 0);
+
+    // --all should include it.
+    let out = td(&tmp)
+        .args(["--json", "list", "--all"])
+        .current_dir(&tmp)
+        .output()
+        .unwrap();
+    let v: serde_json::Value = serde_json::from_slice(&out.stdout).unwrap();
+    assert_eq!(v.as_array().unwrap().len(), 1);
+    assert_eq!(v[0]["title"].as_str().unwrap(), "Will close");
+}
+
 #[test]
 fn list_filter_by_priority() {
     let tmp = init_tmp();