Fix the warnings to output for the between passwords and write some tests for it, also write tests for some environment variables.
This commit is contained in:
@@ -26,19 +26,24 @@ impl LK {
|
|||||||
let comment = name.borrow().comment.clone();
|
let comment = name.borrow().comment.clone();
|
||||||
match comment {
|
match comment {
|
||||||
Some(comment) => {
|
Some(comment) => {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
let new = RE.replace(comment.as_str(), |c: &Captures| {
|
let new = RE
|
||||||
let folder = c[1].to_string();
|
.replace(comment.as_str(), |c: &Captures| {
|
||||||
match self.db.get(&folder) {
|
let folder = c[1].to_string();
|
||||||
Some(entry) => {
|
match self.db.get(&folder) {
|
||||||
name.borrow_mut().parent = Some(entry.clone());
|
Some(entry) => {
|
||||||
changed = true;
|
name.borrow_mut().parent = Some(entry.clone());
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
}
|
}
|
||||||
None => (),
|
""
|
||||||
}
|
})
|
||||||
""
|
.trim()
|
||||||
}).to_string();
|
.to_string();
|
||||||
if changed && new != comment { name.borrow_mut().comment = if new.len() > 0 { Some(new) } else { None } }
|
if changed && new != comment {
|
||||||
|
name.borrow_mut().comment = if new.len() > 0 { Some(new) } else { None }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-35
@@ -9,43 +9,10 @@ mod skey;
|
|||||||
mod structs;
|
mod structs;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use rpassword::prompt_password;
|
use crate::structs::init;
|
||||||
use rustyline::Editor;
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
|
||||||
|
|
||||||
use crate::lk::LK;
|
|
||||||
use crate::parser::command_parser;
|
|
||||||
use crate::repl::{LKEval, LKRead};
|
|
||||||
use crate::structs::{Command, LKErr, INIT_FILE};
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let lk = Rc::new(RefCell::new(LK::new()));
|
let mut lkread = init();
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
LKEval::new(Command::Error(LKErr::ParseError(err)), lk.clone(), prompt_password).eval().print();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => (),
|
|
||||||
Err(err) => {
|
|
||||||
LKEval::new(
|
|
||||||
Command::Error(LKErr::Error(
|
|
||||||
format!("Failed to read init file {:?}: {}", INIT_FILE.to_str(), err).as_str(),
|
|
||||||
)),
|
|
||||||
lk.clone(),
|
|
||||||
prompt_password,
|
|
||||||
)
|
|
||||||
.eval()
|
|
||||||
.print();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut lkread = LKRead::new(Editor::<()>::new().unwrap(), String::from("❯ "), lk.clone());
|
|
||||||
|
|
||||||
while lkread.read().eval().print() {
|
while lkread.read().eval().print() {
|
||||||
lkread.refresh();
|
lkread.refresh();
|
||||||
|
|||||||
+25
-17
@@ -17,25 +17,25 @@ use crate::utils::{call_cmd_with_input, get_cmd_args_from_command, get_copy_comm
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LKRead {
|
pub struct LKRead {
|
||||||
rl: Editor<()>,
|
pub rl: Editor<()>,
|
||||||
prompt: String,
|
pub prompt: String,
|
||||||
state: Rc<RefCell<LK>>,
|
pub state: Rc<RefCell<LK>>,
|
||||||
cmd: String,
|
pub cmd: String,
|
||||||
read_password: fn(String) -> std::io::Result<String>,
|
pub read_password: fn(String) -> std::io::Result<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LKEval<'a> {
|
pub struct LKEval<'a> {
|
||||||
cmd: Command<'a>,
|
pub cmd: Command<'a>,
|
||||||
state: Rc<RefCell<LK>>,
|
pub state: Rc<RefCell<LK>>,
|
||||||
read_password: fn(String) -> std::io::Result<String>,
|
pub read_password: fn(String) -> std::io::Result<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct LKPrint {
|
pub struct LKPrint {
|
||||||
out: LKOut,
|
pub out: LKOut,
|
||||||
quit: bool,
|
pub quit: bool,
|
||||||
state: Rc<RefCell<LK>>,
|
pub state: Rc<RefCell<LK>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LKRead {
|
impl LKRead {
|
||||||
@@ -129,8 +129,8 @@ impl<'a> LKEval<'a> {
|
|||||||
match (self.read_password)("Master: ".to_string()) {
|
match (self.read_password)("Master: ".to_string()) {
|
||||||
Ok(password) => {
|
Ok(password) => {
|
||||||
let name = "/".to_string();
|
let name = "/".to_string();
|
||||||
self.state.borrow_mut().secrets.insert(name.to_string(), password.clone());
|
|
||||||
self.cmd_correct(&out, &name, true, Some(password.clone()));
|
self.cmd_correct(&out, &name, true, Some(password.clone()));
|
||||||
|
self.state.borrow_mut().secrets.insert(name, password.clone());
|
||||||
Some(password)
|
Some(password)
|
||||||
}
|
}
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
@@ -147,14 +147,16 @@ impl<'a> LKEval<'a> {
|
|||||||
};
|
};
|
||||||
if password.is_some() && password.as_ref().unwrap().len() > 0 {
|
if password.is_some() && password.as_ref().unwrap().len() > 0 {
|
||||||
let name = pn.borrow().name.to_string();
|
let name = pn.borrow().name.to_string();
|
||||||
self.state.borrow_mut().secrets.insert(name.to_string(), password.as_ref().unwrap().clone());
|
|
||||||
self.cmd_correct(&out, &name, true, Some(password.as_ref().unwrap().clone()));
|
self.cmd_correct(&out, &name, true, Some(password.as_ref().unwrap().clone()));
|
||||||
|
self.state.borrow_mut().secrets.insert(name, password.as_ref().unwrap().clone());
|
||||||
password
|
password
|
||||||
} else {
|
} else {
|
||||||
match self.read_master(&out, pn.clone(), read) {
|
match self.read_master(&out, pn.clone(), read) {
|
||||||
Some(master) => {
|
Some(master) => {
|
||||||
let password = pn.borrow().encode(master.as_str());
|
let password = pn.borrow().encode(master.as_str());
|
||||||
self.state.borrow_mut().secrets.insert(pn.borrow().name.to_string(), password.clone());
|
let name = pn.borrow().name.to_string();
|
||||||
|
self.cmd_correct(&out, &name, true, Some(master));
|
||||||
|
self.state.borrow_mut().secrets.insert(name, password.clone());
|
||||||
Some(password)
|
Some(password)
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
@@ -270,7 +272,9 @@ impl<'a> LKEval<'a> {
|
|||||||
fn save_dump(data: &HashMap<Name, PasswordRef>, script: &String) -> std::io::Result<()> {
|
fn save_dump(data: &HashMap<Name, PasswordRef>, script: &String) -> std::io::Result<()> {
|
||||||
let file = fs::File::create(script)?;
|
let file = fs::File::create(script)?;
|
||||||
let mut writer = BufWriter::new(file);
|
let mut writer = BufWriter::new(file);
|
||||||
for (_, pwd) in data {
|
let mut vals = data.values().map(|v| v.clone()).collect::<Vec<PasswordRef>>();
|
||||||
|
vals.sort_by(|a, b| a.borrow().name.cmp(&b.borrow().name));
|
||||||
|
for pwd in vals {
|
||||||
writeln!(writer, "add {}", pwd.borrow().to_string())?
|
writeln!(writer, "add {}", pwd.borrow().to_string())?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -439,7 +443,9 @@ impl<'a> LKEval<'a> {
|
|||||||
fix = true;
|
fix = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fix { state.fix_hierarchy(); }
|
if fix {
|
||||||
|
state.fix_hierarchy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Command::Comment(name, comment) => match self.get_password(name) {
|
Command::Comment(name, comment) => match self.get_password(name) {
|
||||||
Some(pwd) => {
|
Some(pwd) => {
|
||||||
@@ -701,7 +707,9 @@ mod tests {
|
|||||||
vec!["san bud most noon jaw cash".to_string()],
|
vec!["san bud most noon jaw cash".to_string()],
|
||||||
vec![
|
vec![
|
||||||
"warning: password / is not marked as correct".to_string(),
|
"warning: password / is not marked as correct".to_string(),
|
||||||
"warning: password t3 is not marked as correct".to_string()
|
"warning: password t1 is not marked as correct".to_string(),
|
||||||
|
"warning: password t2 is not marked as correct".to_string(),
|
||||||
|
"warning: password t3 is not marked as correct".to_string(),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
|
|||||||
+149
-25
@@ -1,33 +1,45 @@
|
|||||||
use crate::password::{Comment, Name, PasswordRef};
|
use crate::password::{Comment, Name, PasswordRef};
|
||||||
use home::home_dir;
|
use home::home_dir;
|
||||||
use std::cell::RefCell;
|
use rpassword::prompt_password;
|
||||||
|
use rustyline::Editor;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::io::{BufWriter, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
use crate::lk::LK;
|
||||||
|
use crate::parser::command_parser;
|
||||||
|
use crate::repl::{LKEval, LKRead};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref HISTORY_FILE: Box<Path> = {
|
pub static ref HISTORY_FILE: Box<Path> = {
|
||||||
match std::env::var("LESSKEY_HISTORY") {
|
match std::env::var("HEL_HISTORY") {
|
||||||
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
||||||
_ => home_dir().unwrap().join(".lesskey_history").into_boxed_path(),
|
_ => home_dir().unwrap().join(".hel_history").into_boxed_path(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pub static ref PROMPT_SETTING: String = {
|
||||||
|
match std::env::var("HEL_PROMPT") {
|
||||||
|
Ok(v) => v,
|
||||||
|
_ => "> ".to_string(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
pub static ref INIT_FILE: Box<Path> = {
|
pub static ref INIT_FILE: Box<Path> = {
|
||||||
match std::env::var("LESSKEY_INIT") {
|
match std::env::var("HEL_INIT") {
|
||||||
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
||||||
_ => home_dir().unwrap().join(".lesskeyrc").into_boxed_path(),
|
_ => home_dir().unwrap().join(".helrc").into_boxed_path(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
pub static ref CORRECT_FILE: Box<Path> = {
|
pub static ref CORRECT_FILE: Box<Path> = {
|
||||||
match std::env::var("LESSKEY_CORRECT") {
|
match std::env::var("HEL_CORRECT") {
|
||||||
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
||||||
_ => home_dir().unwrap().join(".lesskey_correct").into_boxed_path(),
|
_ => home_dir().unwrap().join(".hel_correct").into_boxed_path(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
pub static ref DUMP_FILE: Box<Path> = {
|
pub static ref DUMP_FILE: Box<Path> = {
|
||||||
match std::env::var("LESSKEY_DUMP") {
|
match std::env::var("HEL_DUMP") {
|
||||||
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
||||||
_ => home_dir().unwrap().join(".lesskey_dump").into_boxed_path(),
|
_ => home_dir().unwrap().join(".hel_dump").into_boxed_path(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -247,20 +259,132 @@ impl fmt::Display for Radix {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
pub fn init() -> LKRead {
|
||||||
impl fmt::Display for Radix {
|
let lk = Rc::new(RefCell::new(LK::new()));
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
let sign = if self.x < 0 { '-' } else { ' ' };
|
match std::fs::read_to_string(INIT_FILE.to_str().unwrap()) {
|
||||||
let mut x: u32 = self.x.abs() as u32;
|
Ok(script) => match command_parser::script(&script) {
|
||||||
write!(f, "{}{}", sign, (0..).map(|_| {
|
Ok(cmd_list) => {
|
||||||
let m = x % self.radix;
|
for cmd in cmd_list {
|
||||||
x /= self.radix;
|
LKEval::new(cmd, lk.clone(), prompt_password).eval().print();
|
||||||
(x, std::char::from_digit(m, self.radix).unwrap())
|
}
|
||||||
})
|
}
|
||||||
.take_while(|a| a.0 > 0).map(|b| b.1).collect::<String>()
|
Err(err) => {
|
||||||
.chars().rev().collect::<String>()
|
LKEval::new(Command::Error(LKErr::ParseError(err)), lk.clone(), prompt_password).eval().print();
|
||||||
)?;
|
}
|
||||||
Ok(())
|
},
|
||||||
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => (),
|
||||||
|
Err(err) => {
|
||||||
|
LKEval::new(
|
||||||
|
Command::Error(LKErr::Error(
|
||||||
|
format!("Failed to read init file {:?}: {}", INIT_FILE.to_str(), err).as_str(),
|
||||||
|
)),
|
||||||
|
lk.clone(),
|
||||||
|
prompt_password,
|
||||||
|
)
|
||||||
|
.eval()
|
||||||
|
.print();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LKRead::new(Editor::<()>::new().unwrap(), PROMPT_SETTING.to_string(), lk.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::password::Password;
|
||||||
|
use chrono::naive::NaiveDate;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_env() {
|
||||||
|
std::env::set_var("HEL_HISTORY", "./test_history");
|
||||||
|
std::env::set_var("HEL_INIT", "./test_init");
|
||||||
|
std::env::set_var("HEL_DUMP", "./test_dump");
|
||||||
|
std::env::set_var("HEL_CORRECT", "./test_correct");
|
||||||
|
std::env::set_var("HEL_PB", "./test_pb");
|
||||||
|
std::env::set_var("HEL_PROMPT", "test> ");
|
||||||
|
|
||||||
|
fn create_init() {
|
||||||
|
let file = std::fs::File::create("test_init").unwrap();
|
||||||
|
let mut writer = BufWriter::new(file);
|
||||||
|
writeln!(writer, "add t1 r 99 2022-10-10").expect("write");
|
||||||
|
writeln!(writer, "add t2 r 99 2022-10-10 test ^t1").expect("write");
|
||||||
|
writeln!(writer, "add t3 r 99 2022-10-10 ^t2 aoeu").expect("write");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
{
|
||||||
|
std::fs::remove_file("test_history");
|
||||||
|
std::fs::remove_file("test_init");
|
||||||
|
std::fs::remove_file("test_dump");
|
||||||
|
std::fs::remove_file("test_correct");
|
||||||
|
std::fs::remove_file("test_pb");
|
||||||
|
}
|
||||||
|
|
||||||
|
create_init();
|
||||||
|
let lkread = init();
|
||||||
|
assert_eq!(lkread.prompt, "test> ");
|
||||||
|
assert_eq!(lkread.state.borrow().db.contains_key("t1"), true);
|
||||||
|
|
||||||
|
let t1 = Rc::new(RefCell::new(Password::new(
|
||||||
|
None,
|
||||||
|
"t1".to_string(),
|
||||||
|
None,
|
||||||
|
Mode::Regular,
|
||||||
|
99,
|
||||||
|
NaiveDate::from_ymd_opt(2022, 10, 10).unwrap(),
|
||||||
|
None,
|
||||||
|
)));
|
||||||
|
let t2 = Rc::new(RefCell::new(Password::new(
|
||||||
|
None,
|
||||||
|
"t2".to_string(),
|
||||||
|
None,
|
||||||
|
Mode::Regular,
|
||||||
|
99,
|
||||||
|
NaiveDate::from_ymd_opt(2022, 10, 10).unwrap(),
|
||||||
|
Some("test".to_string()),
|
||||||
|
)));
|
||||||
|
t2.borrow_mut().parent = Some(t1.clone());
|
||||||
|
let t3 = Rc::new(RefCell::new(Password::new(
|
||||||
|
None,
|
||||||
|
"t3".to_string(),
|
||||||
|
None,
|
||||||
|
Mode::Regular,
|
||||||
|
99,
|
||||||
|
NaiveDate::from_ymd_opt(2022, 10, 10).unwrap(),
|
||||||
|
Some("aoeu".to_string()),
|
||||||
|
)));
|
||||||
|
t3.borrow_mut().parent = Some(t2.clone());
|
||||||
|
assert_eq!(*lkread.state.borrow().db.get("t1").unwrap().borrow(), *t1.borrow());
|
||||||
|
assert_eq!(*lkread.state.borrow().db.get("t2").unwrap().borrow(), *t2.borrow());
|
||||||
|
assert_eq!(*lkread.state.borrow().db.get("t3").unwrap().borrow(), *t3.borrow());
|
||||||
|
|
||||||
|
LKEval::new(command_parser::cmd("dump").unwrap(), lkread.state.clone(), prompt_password)
|
||||||
|
.eval()
|
||||||
|
.print();
|
||||||
|
assert_eq!(
|
||||||
|
std::fs::read_to_string("test_dump").expect("read"),
|
||||||
|
"add t1 R 99 2022-10-10\nadd t2 R 99 2022-10-10 test ^t1\nadd t3 R 99 2022-10-10 aoeu ^t2\n".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
let pr = LKEval::new(command_parser::cmd("enc t2").unwrap(), lkread.state.clone(), |v| {
|
||||||
|
if v == "/" {
|
||||||
|
Ok("a".to_string())
|
||||||
|
} else {
|
||||||
|
Ok("".to_string())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.eval();
|
||||||
|
assert_eq!(
|
||||||
|
pr.out,
|
||||||
|
LKOut::from_vecs(
|
||||||
|
vec!["mid date os gaur gear let".to_string()],
|
||||||
|
vec![
|
||||||
|
"warning: password / is not marked as correct".to_string(),
|
||||||
|
"warning: password t1 is not marked as correct".to_string(),
|
||||||
|
"warning: password t2 is not marked as correct".to_string(),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ pub fn get_cmd_args_from_command(command: &str) -> io::Result<(String, Vec<Strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_copy_command_from_env() -> (String, Vec<String>) {
|
pub fn get_copy_command_from_env() -> (String, Vec<String>) {
|
||||||
let cmd_os_str = env::var_os("LESSKEY_PB").unwrap_or_else(|| match env::consts::OS {
|
let cmd_os_str = env::var_os("HEL_PB").unwrap_or_else(|| match env::consts::OS {
|
||||||
_ if env::var("TMUX").is_ok() => OsString::from("tmux load-buffer -"),
|
_ if env::var("TMUX").is_ok() => OsString::from("tmux load-buffer -"),
|
||||||
"macos" => OsString::from("pbcopy"),
|
"macos" => OsString::from("pbcopy"),
|
||||||
"linux" => OsString::from("xclip"),
|
"linux" => OsString::from("xclip"),
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
add t1 R 99 2022-10-10
|
||||||
|
add t2 R 99 2022-10-10 test ^t1
|
||||||
|
add t3 R 99 2022-10-10 aoeu ^t2
|
||||||
Reference in New Issue
Block a user