diff options
-rw-r--r-- | clab.md | 15 | ||||
-rw-r--r-- | sample.yaml | 9 | ||||
-rw-r--r-- | src/main.rs | 30 |
3 files changed, 54 insertions, 0 deletions
@@ -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<HashMap<String, String>>, irc: Option<HashMap<String, String>>, address: Option<HashMap<String, String>>, + tags: Option<Vec<String>>, last_checked: String, } @@ -116,6 +118,7 @@ enum Cmd { Lint(LintCommand), List(ListCommand), Search(SearchCommand), + Tagged(TaggedCommand), MuttQuery(MuttCommand), } @@ -171,6 +174,33 @@ impl SearchCommand { } #[derive(Debug, StructOpt)] +#[structopt(alias = "find")] +struct TaggedCommand { + #[structopt()] + wanted_tags: Vec<String>, +} + +impl TaggedCommand { + fn run(&self, _opt: &Opt, book: &AddressBook) -> anyhow::Result<()> { + let matches: Vec<Entry> = 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()] word: String, |