aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-04-19 21:23:08 -0400
committerJesse Luehrs <doy@tozt.net>2020-04-19 21:23:08 -0400
commitbc543e4f26d3e29fe88a61457a924ab6ab238535 (patch)
treeb2acc53d5a9be23efb0cf2e26afa8132f4351d7f
parentce00f07e6cf16e41c1b658ff3161d5e18a62da3b (diff)
downloadrbw-bc543e4f26d3e29fe88a61457a924ab6ab238535.tar.gz
rbw-bc543e4f26d3e29fe88a61457a924ab6ab238535.zip
allow listing various different fields
-rw-r--r--src/bin/rbw/commands.rs41
-rw-r--r--src/bin/rbw/main.rs18
2 files changed, 55 insertions, 4 deletions
diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs
index 2385163..ff267eb 100644
--- a/src/bin/rbw/commands.rs
+++ b/src/bin/rbw/commands.rs
@@ -18,6 +18,25 @@ struct DecryptedHistoryEntry {
password: String,
}
+enum ListField {
+ Name,
+ Id,
+ User,
+}
+
+impl std::convert::TryFrom<&str> for ListField {
+ type Error = anyhow::Error;
+
+ fn try_from(s: &str) -> anyhow::Result<Self> {
+ Ok(match s {
+ "name" => Self::Name,
+ "id" => Self::Id,
+ "user" => Self::User,
+ _ => return Err(anyhow::anyhow!("unknown field {}", s)),
+ })
+ }
+}
+
const HELP: &str = r#"
# The first line of this file will be the password, and the remainder of the
# file (after any blank lines after the password) will be stored as a note.
@@ -76,7 +95,13 @@ pub fn sync() -> anyhow::Result<()> {
Ok(())
}
-pub fn list() -> anyhow::Result<()> {
+pub fn list(fields: &[&str]) -> anyhow::Result<()> {
+ let fields: Vec<ListField> = fields
+ .iter()
+ .copied()
+ .map(std::convert::TryFrom::try_from)
+ .collect::<anyhow::Result<_>>()?;
+
unlock()?;
let email = config_email()?;
@@ -92,7 +117,19 @@ pub fn list() -> anyhow::Result<()> {
ciphers.sort_unstable_by(|a, b| a.name.cmp(&b.name));
for cipher in ciphers {
- println!("{}", cipher.name);
+ let values: Vec<String> = fields
+ .iter()
+ .map(|field| match field {
+ ListField::Name => cipher.name.clone(),
+ ListField::Id => cipher.id.clone(),
+ ListField::User => cipher
+ .username
+ .as_ref()
+ .map(std::string::ToString::to_string)
+ .unwrap_or_else(|| "".to_string()),
+ })
+ .collect();
+ println!("{}", values.join("\t"));
}
Ok(())
diff --git a/src/bin/rbw/main.rs b/src/bin/rbw/main.rs
index 051a7bc..c95e319 100644
--- a/src/bin/rbw/main.rs
+++ b/src/bin/rbw/main.rs
@@ -26,7 +26,15 @@ fn main() {
.subcommand(clap::SubCommand::with_name("login"))
.subcommand(clap::SubCommand::with_name("unlock"))
.subcommand(clap::SubCommand::with_name("sync"))
- .subcommand(clap::SubCommand::with_name("list"))
+ .subcommand(
+ clap::SubCommand::with_name("list").arg(
+ clap::Arg::with_name("fields")
+ .long("fields")
+ .takes_value(true)
+ .use_delimiter(true)
+ .multiple(true),
+ ),
+ )
.subcommand(
clap::SubCommand::with_name("get")
.arg(clap::Arg::with_name("name").required(true))
@@ -115,7 +123,13 @@ fn main() {
("login", Some(_)) => commands::login().context("login"),
("unlock", Some(_)) => commands::unlock().context("unlock"),
("sync", Some(_)) => commands::sync().context("sync"),
- ("list", Some(_)) => commands::list().context("list"),
+ ("list", Some(smatches)) => commands::list(
+ &smatches
+ .values_of("fields")
+ .map(|it| it.collect())
+ .unwrap_or_else(|| vec!["name"]),
+ )
+ .context("list"),
// this unwrap is safe because name is marked .required(true)
("get", Some(smatches)) => commands::get(
smatches.value_of("name").unwrap(),