From 9e9ed659650a2c8af9c3c8c8e0f6c23a6c45f090 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Mon, 4 Oct 2021 17:32:10 +0300 Subject: feat: allow optional tagging of address book entries Sponsored-by: author --- clab.md | 15 +++++++++++++++ sample.yaml | 9 +++++++++ src/main.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 sample.yaml diff --git a/clab.md b/clab.md index b437cbc..de09758 100644 --- a/clab.md +++ b/clab.md @@ -67,6 +67,7 @@ then stdout is exactly "clab found matches:\nalice@example.com\tAlice Atherthon\ - name: Alice Atherthon email: work: alice@example.com + tags: [co-worker] last_checked: 2021-09 - name: Bob Bobbington email: @@ -75,6 +76,20 @@ then stdout is exactly "clab found matches:\nalice@example.com\tAlice Atherthon\ ~~~ +# Search by tag + +This scenario verifies that `clab` can find entries based on tags. + +~~~scenario +given an installed clab +given file .local/share/clab/address-book.yaml from address-book.yaml + +when I run clab tagged co-worker +then command is successful +then stdout contains "Alice Atherthon" +then stdout doesn't contain "Bob" +~~~ + # Full text search This scenario verifies that `clab` does a full text search. diff --git a/sample.yaml b/sample.yaml new file mode 100644 index 0000000..9b63c6c --- /dev/null +++ b/sample.yaml @@ -0,0 +1,9 @@ +- name: Alice Atherthon + email: + work: alice@example.com + tags: [co-worker] + last_checked: 2021-09 +- name: Bob Bobbington + email: + personal: bob@example.com + last_checked: 2021-09 diff --git a/src/main.rs b/src/main.rs index d25fdaa..2d847dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ fn main() -> anyhow::Result<()> { Cmd::Lint(x) => x.run(&opt, &book), Cmd::List(x) => x.run(&opt, &book)?, Cmd::Search(x) => x.run(&opt, &book)?, + Cmd::Tagged(x) => x.run(&opt, &book)?, Cmd::MuttQuery(x) => x.run(&opt, &book), } Ok(()) @@ -42,6 +43,7 @@ struct Entry { phone: Option>, irc: Option>, address: Option>, + tags: Option>, last_checked: String, } @@ -116,6 +118,7 @@ enum Cmd { Lint(LintCommand), List(ListCommand), Search(SearchCommand), + Tagged(TaggedCommand), MuttQuery(MuttCommand), } @@ -170,6 +173,33 @@ impl SearchCommand { } } +#[derive(Debug, StructOpt)] +#[structopt(alias = "find")] +struct TaggedCommand { + #[structopt()] + wanted_tags: Vec, +} + +impl TaggedCommand { + fn run(&self, _opt: &Opt, book: &AddressBook) -> anyhow::Result<()> { + let matches: Vec = book.iter().filter(|e| self.is_match(e)).cloned().collect(); + output_entries(&matches) + } + + fn is_match(&self, entry: &Entry) -> bool { + if let Some(actual_tags) = &entry.tags { + for wanted_tag in self.wanted_tags.iter() { + if !actual_tags.contains(wanted_tag) { + return false; + } + } + true + } else { + false + } + } +} + #[derive(Debug, StructOpt)] struct MuttCommand { #[structopt()] -- cgit v1.2.1