From a69fceb12644d54ab5f05390d0cfa025a6d66351 Mon Sep 17 00:00:00 2001 From: Oleksandr Kozachuk Date: Sat, 24 Dec 2022 13:53:53 +0100 Subject: [PATCH] Add ld command, like ls but sort by date. Fix quit command in scripts, output passwords with spaces when no prefix given (align output by name, somewhat). --- src/commands.rs | 19 ++++++++++++------- src/main.rs | 2 +- src/parser.rs | 2 ++ src/password.rs | 2 +- src/repl.rs | 5 +++-- src/structs.rs | 7 ++++--- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 56bf0eb..b45c6d6 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -215,20 +215,20 @@ impl<'a> LKEval<'a> { }; } - pub fn cmd_source(&self, out: &LKOut, source: &String) { + pub fn cmd_source(&self, out: &LKOut, source: &String) -> bool { let script = if source.trim().ends_with("|") { let (cmd, args) = match get_cmd_args_from_command(source.trim().trim_end_matches('|')) { Ok(c) => c, Err(e) => { out.e(format!("error: failed to parse command {:?}: {}", source, e.to_string())); - return; + return false; } }; match call_cmd_with_input(&cmd, &args, "") { Ok(o) => o, Err(e) => { out.e(format!("error: failed to execute command {}: {}", cmd, e.to_string())); - return; + return false; } } } else { @@ -237,7 +237,7 @@ impl<'a> LKEval<'a> { Ok(script) => script, Err(e) => { out.e(format!("error: failed to read file {}: {}", source, e.to_string())); - return; + return false; } } }; @@ -246,13 +246,14 @@ impl<'a> LKEval<'a> { for cmd in cmd_list { let print = LKEval::new(cmd, self.state.clone(), prompt_password).eval(); print.out.copy(&out); + if print.quit { return true; } } } Err(e) => { out.e(format!("error: {}", e.to_string())); - return; } }; + false } pub fn cmd_dump(&self, out: &LKOut, script: &Option) { @@ -308,7 +309,10 @@ impl<'a> LKEval<'a> { } } - pub fn cmd_ls(&self, out: &LKOut, filter: String) { + pub fn cmd_ls(&self, out: &LKOut, filter: String, sort_by: F) + where + F: Fn(&PasswordRef, &PasswordRef) -> std::cmp::Ordering, + { let re = match Regex::new(&filter) { Ok(re) => re, Err(e) => { @@ -326,7 +330,8 @@ impl<'a> LKEval<'a> { tmp.push(name.clone()); } } - tmp.sort_by(|a, b| a.borrow().name.cmp(&b.borrow().name)); + tmp.sort_by(|a,b| a.borrow().name.cmp(&b.borrow().name)); + tmp.sort_by(sort_by); self.state.borrow_mut().ls.clear(); let mut counter = 1; for pwd in tmp { diff --git a/src/main.rs b/src/main.rs index a1d38ec..650c414 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ mod utils; use crate::structs::init; pub fn main() { - let mut lkread = init(); + let mut lkread = match init() { Some(r) => r, None => { return; } }; while lkread.read().eval().print() { lkread.refresh(); diff --git a/src/parser.rs b/src/parser.rs index 9b95b59..4f16973 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -14,6 +14,7 @@ peg::parser! { / quit_cmd() / error_cmd() / ls_cmd() + / ld_cmd() / mv_cmd() / rm_cmd() / pb_cmd() @@ -90,6 +91,7 @@ peg::parser! { rule dump_def_cmd() -> Command<'input> = "dump" { Command::Dump(None) } rule source_cmd() -> Command<'input> = "source" _ s:$(([' '..='~'])+) { Command::Source(s.to_string()) } rule ls_cmd() -> Command<'input> = "ls" f:comment()? { Command::Ls(f.unwrap_or(".".to_string())) } + rule ld_cmd() -> Command<'input> = "ld" f:comment()? { Command::Ld(f.unwrap_or(".".to_string())) } rule add_cmd() -> Command<'input> = "add" _ name:name() { Command::Add(Rc::new(RefCell::new(name))) } rule gen_cmd() -> Command<'input> = "gen" n:num()? _ name:name() { Command::Gen(match n { Some(n) => n, None => 10_u32 }, Rc::new(RefCell::new(name))) diff --git a/src/password.rs b/src/password.rs index 133f64c..5e89ac5 100644 --- a/src/password.rs +++ b/src/password.rs @@ -113,7 +113,7 @@ impl std::string::ToString for Password { Some(s) => format!(" ^{}", s.borrow().name), None => "".to_string(), }; - format!("{}{} {}{} {} {}{}{}", prefix, self.name, length, self.mode, self.seq, self.date, comment, parent) + format!("{:>6}{} {}{} {} {}{}{}", prefix, self.name, length, self.mode, self.seq, self.date, comment, parent) } } diff --git a/src/repl.rs b/src/repl.rs index 6a9dad7..f3361df 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -96,7 +96,8 @@ impl<'a> LKEval<'a> { out.e("Bye!".to_string()); quit = true; } - Command::Ls(filter) => self.cmd_ls(&out, filter.to_string()), + Command::Ls(filter) => self.cmd_ls(&out, filter.to_string(), |a,b| a.borrow().name.cmp(&b.borrow().name)), + Command::Ld(filter) => self.cmd_ls(&out, filter.to_string(), |a,b| b.borrow().date.cmp(&a.borrow().date)), Command::Add(name) => self.cmd_add(&out, &name), Command::Comment(name, comment) => self.cmd_comment(&out, &name, &comment), Command::Rm(name) => match self.get_password(name) { @@ -109,7 +110,7 @@ impl<'a> LKEval<'a> { Command::Enc(name) => { self.cmd_enc(&out, name); } Command::Gen(num, name) => self.cmd_gen(&out, &num, &name), Command::PasteBuffer(command) => self.cmd_pb(&out, command), - Command::Source(script) => self.cmd_source(&out, script), + Command::Source(script) => { quit = self.cmd_source(&out, script); } Command::Dump(script) => self.cmd_dump(&out, script), Command::Pass(name) => self.cmd_pass(&out, &name), Command::UnPass(name) => match self.state.borrow_mut().secrets.remove(name) { diff --git a/src/structs.rs b/src/structs.rs index 75f3d13..44c078f 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -57,6 +57,7 @@ pub enum LKErr<'a> { pub enum Command<'a> { Add(PasswordRef), Ls(String), + Ld(String), Mv(Name, Name), Rm(Name), Enc(Name), @@ -259,14 +260,14 @@ impl fmt::Display for Radix { } } -pub fn init() -> LKRead { +pub fn init() -> Option { let lk = Rc::new(RefCell::new(LK::new())); match std::fs::read_to_string(INIT_FILE.to_str().unwrap()) { Ok(script) => match command_parser::script(&script) { Ok(cmd_list) => { for cmd in cmd_list { - LKEval::new(cmd, lk.clone(), prompt_password).eval().print(); + if !LKEval::new(cmd, lk.clone(), prompt_password).eval().print() { return None; } } } Err(err) => { @@ -286,7 +287,7 @@ pub fn init() -> LKRead { .print(); } } - LKRead::new(Editor::<()>::new().unwrap(), PROMPT_SETTING.to_string(), lk.clone()) + Some(LKRead::new(Editor::<()>::new().unwrap(), PROMPT_SETTING.to_string(), lk.clone())) } #[cfg(test)]