notes editor over the vault (Obsidian-compatible)
git clone https://git.lucas.co/cce-notes.git
fix(cli): `cce-notes show` is the show command, not a note named "show"
from_args matched a bare `show` as an open target, so the one command
that only brings the instance up could not be typed: `cce-notes show`
forwarded `open show` and the running window said "No note named show".
`show` is now a verb like `daily` and `search`; a note by that name
opens with an explicit `open`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CLAUDE.md | 4 ++++
src/instance.rs | 10 +++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index 338a8e9..d393fc3 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -164,8 +164,12 @@ today, which a long note can churn).
cce-notes [--vault <dir>] [open] <note>[#heading] [line] # line is 1-based
cce-notes daily [YYYY-MM-DD]
cce-notes search <query> # the search pane holding it (#tag works)
+cce-notes [show] # just bring the instance up
```
+`daily`, `search` and `show` are verbs, not note names: a note called one
+of them opens with an explicit `open` (`cce-notes open show`).
+
A second launch forwards its command to the running instance and exits.
Keys come from input.kdl's `cce-notes` domain: `quick_switcher` (ctrl+o),
`toggle_mode` (ctrl+e), `toggle_source` (ctrl+shift+e: live preview ↔
diff --git a/src/instance.rs b/src/instance.rs
index 5b6336e..84abf9e 100644
--- a/src/instance.rs
+++ b/src/instance.rs
@@ -43,11 +43,13 @@ pub enum Command {
impl Command {
/// The command line's own arguments as a socket command:
/// `cce-notes [open] <path> [line]`, `cce-notes daily [date]`,
- /// `cce-notes search <query…>`, or nothing.
+ /// `cce-notes search <query…>`, `cce-notes show`, or nothing (also
+ /// `show`). The verbs are reserved, as `daily` and `search` always were:
+ /// a note named `show` opens with `cce-notes open show`.
pub fn from_args(args: &[String]) -> Result<Command, String> {
let words: Vec<&str> = args.iter().map(String::as_str).collect();
match words.as_slice() {
- [] => Ok(Command::Show),
+ [] | ["show"] => Ok(Command::Show),
["daily"] => Ok(Command::Daily(None)),
["daily", d] => parse_date(d).map(|d| Command::Daily(Some(d))),
["search", rest @ ..] => Ok(Command::Search(rest.join(" "))),
@@ -56,7 +58,7 @@ impl Command {
let line = line.parse::<usize>().map_err(|_| format!("not a line number: {line}"))?;
Ok(Command::Open { target: absolute(target), line: Some(line) })
}
- _ => Err("usage: cce-notes [open] <note> [line] | daily [YYYY-MM-DD] | search <query>".into()),
+ _ => Err("usage: cce-notes [open] <note> [line] | daily [YYYY-MM-DD] | search <query> | show".into()),
}
}
@@ -162,6 +164,8 @@ mod tests {
fn args_and_lines_round_trip() {
let cases = [
(vec![], Command::Show),
+ (vec!["show"], Command::Show),
+ (vec!["open", "show"], Command::Open { target: "show".into(), line: None }),
(vec!["Note"], Command::Open { target: "Note".into(), line: None }),
(vec!["open", "My Note#Sec", "12"], Command::Open { target: "My Note#Sec".into(), line: Some(12) }),
(vec!["daily"], Command::Daily(None)),