summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-10-04 17:32:10 +0300
committerLars Wirzenius <liw@liw.fi>2021-10-04 17:32:10 +0300
commit9e9ed659650a2c8af9c3c8c8e0f6c23a6c45f090 (patch)
treeecbe230cde864aaf67ce8a4903f7811dc412e36d
parenta44d3847590e5c24c78b2b129c464bd80b0d29ab (diff)
downloadclab-9e9ed659650a2c8af9c3c8c8e0f6c23a6c45f090.tar.gz
feat: allow optional tagging of address book entries
Sponsored-by: author
-rw-r--r--clab.md15
-rw-r--r--sample.yaml9
-rw-r--r--src/main.rs30
3 files changed, 54 insertions, 0 deletions
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<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,