A file-based task manager
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add tsk namespace tasks for the full namespace task listing

Complement to tsk list (which only shows the active queue): walks the
namespace's id mapping and prints every (human id, title) bound there,
including dropped tasks. Defaults to the active namespace; an optional
positional name targets a specific one.

Tests: workspace test confirms dropped tasks remain visible since
their namespace binding is preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+48
+1
AGENTS.md
··· 45 45 46 46 ``` 47 47 tsk namespace current # what you're reading/writing as 48 + tsk namespace tasks # every (id, title) bound here, ignoring queue 48 49 tsk queue current # what your push/list/drop affect 49 50 tsk switch <name> # switch namespace (no arg = fzf-pick) 50 51 tsk queue switch <name>
+9
src/lib.rs
··· 251 251 /// Switch active namespace. With no name, fzf-picks from existing 252 252 /// namespaces (plus a `<new>` sentinel for creating one on the fly). 253 253 Switch { name: Option<String> }, 254 + /// List every task bound in a namespace (defaults to active), 255 + /// regardless of which queue (if any) it's on. One row per id. 256 + Tasks { name: Option<String> }, 254 257 } 255 258 256 259 #[derive(Subcommand)] ··· 723 726 } 724 727 NamespaceAction::Current => println!("{}", ws.namespace()), 725 728 NamespaceAction::Switch { name } => return resolve_and_switch_namespace(&ws, name), 729 + NamespaceAction::Tasks { name } => { 730 + let target = name.unwrap_or_else(|| ws.namespace()); 731 + for entry in ws.list_namespace_tasks(&target)? { 732 + println!("{}\t{}", entry.id, entry.title); 733 + } 734 + } 726 735 } 727 736 Ok(()) 728 737 }
+38
src/workspace.rs
··· 412 412 Ok(out) 413 413 } 414 414 415 + /// Every (human id, stable id, title) bound in the given namespace, 416 + /// sorted by human id ascending. Independent of any queue. 417 + pub fn list_namespace_tasks(&self, name: &str) -> Result<Vec<StackEntry>> { 418 + let repo = self.repo()?; 419 + let ns = namespace::read(&repo, name)?; 420 + let mut out = Vec::with_capacity(ns.mapping.len()); 421 + for (human, stable) in ns.mapping { 422 + let title = object::read(&repo, &stable)? 423 + .map(|t| t.title().to_string()) 424 + .unwrap_or_default(); 425 + out.push(StackEntry { 426 + id: Id(human), 427 + stable, 428 + title, 429 + }); 430 + } 431 + Ok(out) 432 + } 433 + 415 434 /// One commit on a tsk ref (task / namespace / queue). 416 435 pub fn log_ref(&self, refname: &str) -> Result<Vec<LogCommit>> { 417 436 let repo = self.repo()?; ··· 884 903 assert_eq!(pulled.0, id.0); 885 904 let stack = ws.read_stack().unwrap(); 886 905 assert_eq!(stack.len(), 1); 906 + } 907 + 908 + #[test] 909 + fn list_namespace_tasks_shows_all_bindings_including_dropped() { 910 + let (_d, ws) = fresh_workspace(); 911 + let t1 = ws.new_task("alpha".into(), "".into()).unwrap(); 912 + let id1 = t1.id; 913 + ws.push_task(t1).unwrap(); 914 + let t2 = ws.new_task("beta".into(), "".into()).unwrap(); 915 + let id2 = t2.id; 916 + ws.push_task(t2).unwrap(); 917 + // Dropped tasks keep their namespace binding (per status property design). 918 + ws.drop(TaskIdentifier::Id(id1)).unwrap(); 919 + 920 + let listed = ws.list_namespace_tasks("tsk").unwrap(); 921 + let ids: Vec<_> = listed.iter().map(|e| e.id).collect(); 922 + assert_eq!(ids, vec![id1, id2]); 923 + let titles: Vec<_> = listed.iter().map(|e| e.title.as_str()).collect(); 924 + assert_eq!(titles, vec!["alpha", "beta"]); 887 925 } 888 926 889 927 #[test]