A file-based task manager
0
fork

Configure Feed

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

fzf-pick prop find's key/value when not supplied

tsk prop find — fzf-pick key, then value (with <any> to skip)
tsk prop find KEY — list every task with KEY set (existing semantics)
tsk prop find KEY VAL — direct match (existing)

Mirrors the recent prop set ergonomics. The <any> sentinel in the
value picker means "match any value for this key" so the user can
still narrow on key alone via fzf.

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

+32 -3
+32 -3
src/main.rs
··· 331 331 task_id: TaskId, 332 332 key: String, 333 333 }, 334 - /// Find every task whose property KEY equals VALUE (or that has KEY set 335 - /// at all when VALUE is omitted). 336 - Find { key: String, value: Option<String> }, 334 + /// Find every task whose property KEY equals VALUE. With VALUE omitted, 335 + /// matches any task that has KEY set. With both omitted, fzf-picks the 336 + /// key first, then the value (with `<any>` to skip value-narrowing). 337 + Find { 338 + key: Option<String>, 339 + value: Option<String>, 340 + }, 337 341 } 338 342 339 343 #[derive(Subcommand)] ··· 1101 1105 ws.unset_property(id, &key)?; 1102 1106 } 1103 1107 PropAction::Find { key, value } => { 1108 + const ANY_SENTINEL: &str = "<any>"; 1109 + let prompt_value = key.is_none() && value.is_none(); 1110 + let key = match key { 1111 + Some(k) => k, 1112 + None => { 1113 + let candidates = ws.all_property_keys()?; 1114 + fzf::select::<_, String, _>(candidates, ["--prompt=property> "])? 1115 + .ok_or_else(|| errors::Error::Parse("No property selected".into()))? 1116 + } 1117 + }; 1118 + // Value-prompt only when neither key nor value was supplied — 1119 + // `tsk prop find KEY` keeps its "any task with KEY set" meaning. 1120 + let value = match (value, prompt_value) { 1121 + (Some(v), _) => Some(v), 1122 + (None, false) => None, 1123 + (None, true) => { 1124 + let mut candidates = ws.property_values_for(&key)?; 1125 + candidates.insert(0, ANY_SENTINEL.to_string()); 1126 + let picked = fzf::select::<_, String, _>(candidates, ["--prompt=value> "])?; 1127 + match picked.as_deref() { 1128 + Some(ANY_SENTINEL) | None => None, 1129 + Some(v) => Some(v.to_string()), 1130 + } 1131 + } 1132 + }; 1104 1133 for id in ws.find_by_property(&key, value.as_deref())? { 1105 1134 println!("{id}"); 1106 1135 }