Split project into three workspaces: hel (the library), helcli (the tool) and helwasm (the wasm code). Move wasm incompatible code to extra modules in utils.rs to be implementable separately for wasm.
This commit is contained in:
+2
-25
@@ -1,25 +1,2 @@
|
||||
[package]
|
||||
name = "hel"
|
||||
version = "0.1.0"
|
||||
authors = ["ok2"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.23"
|
||||
peg = "0.8.1"
|
||||
anyhow = "1.0.66"
|
||||
lazy_static = "1.4.0"
|
||||
regex = "1.6.0"
|
||||
rustyline = "10.0.0"
|
||||
thiserror = "1.0.37"
|
||||
anyerror = "0.1.7"
|
||||
home = "0.5.4"
|
||||
sha1 = "0.10.5"
|
||||
base64 = "0.20.0"
|
||||
rpassword = "7.2.0"
|
||||
shlex = "1.1.0"
|
||||
shellexpand = "3.0.0"
|
||||
scopeguard = "1.1.0"
|
||||
rand = "0.8.5"
|
||||
[workspace]
|
||||
members = ["hel", "helcli", "helwasm"]
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "hel"
|
||||
version = "0.1.0"
|
||||
authors = ["ok2"]
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "hel"
|
||||
crate-type = ["lib"]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
peg = "0.8.1"
|
||||
anyhow = "1.0.66"
|
||||
lazy_static = "1.4.0"
|
||||
regex = "1.6.0"
|
||||
thiserror = "1.0.37"
|
||||
anyerror = "0.1.7"
|
||||
sha1 = "0.10.5"
|
||||
base64 = "0.20.0"
|
||||
rpassword = "7.2.0"
|
||||
shlex = "1.1.0"
|
||||
shellexpand = "3.0.0"
|
||||
scopeguard = "1.1.0"
|
||||
|
||||
[target.'cfg(not(wasm))'.dependencies]
|
||||
chrono = "0.4.23"
|
||||
rand = "0.8.5"
|
||||
home = "0.5.4"
|
||||
rustyline = "10.0.0"
|
||||
@@ -1,4 +1,3 @@
|
||||
use rand::{thread_rng, Rng};
|
||||
use regex::Regex;
|
||||
use rpassword::prompt_password;
|
||||
use sha1::{Digest, Sha1};
|
||||
@@ -13,7 +12,7 @@ use crate::password::fix_password_recursion;
|
||||
use crate::password::{Name, Password, PasswordRef};
|
||||
use crate::repl::LKEval;
|
||||
use crate::structs::{LKOut, Radix, CORRECT_FILE, DUMP_FILE};
|
||||
use crate::utils::{call_cmd_with_input, get_cmd_args_from_command, get_copy_command_from_env};
|
||||
use crate::utils::{call_cmd_with_input, get_cmd_args_from_command, get_copy_command_from_env, rnd};
|
||||
|
||||
impl<'a> LKEval<'a> {
|
||||
pub fn get_password(&self, name: &String) -> Option<PasswordRef> {
|
||||
@@ -429,7 +428,6 @@ impl<'a> LKEval<'a> {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"^.+?(G+|X+)$").unwrap();
|
||||
}
|
||||
let mut rng = thread_rng();
|
||||
let num: usize = (*num).try_into().unwrap();
|
||||
let pwd = name.borrow();
|
||||
let mut genpwds: Vec<PasswordRef> = Vec::new();
|
||||
@@ -445,7 +443,7 @@ impl<'a> LKEval<'a> {
|
||||
}
|
||||
} else {
|
||||
let name = pwd.name.trim_end_matches('X');
|
||||
let num = rng.gen_range(1..10_u32.pow(gen.len().try_into().unwrap()));
|
||||
let num = rnd::range(1, 10_u32.pow(gen.len().try_into().unwrap()));
|
||||
let npwd = Password::from_password(&pwd);
|
||||
npwd.borrow_mut().name = format!("{}{}", name, num).to_string();
|
||||
genpwds.push(npwd);
|
||||
@@ -0,0 +1,15 @@
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[allow(unused_imports)]
|
||||
#[macro_use(defer)]
|
||||
extern crate scopeguard;
|
||||
|
||||
pub mod commands;
|
||||
pub mod lk;
|
||||
pub mod parser;
|
||||
pub mod password;
|
||||
pub mod repl;
|
||||
pub mod skey;
|
||||
pub mod structs;
|
||||
pub mod utils;
|
||||
|
||||
@@ -2,8 +2,7 @@ extern crate peg;
|
||||
|
||||
use crate::password::Password;
|
||||
use crate::structs::{Command, LKErr, Mode};
|
||||
use chrono::naive::NaiveDate;
|
||||
use chrono::Local;
|
||||
use crate::utils::date::Date;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
peg::parser! {
|
||||
@@ -42,21 +41,21 @@ peg::parser! {
|
||||
rule sname() -> Password = &(word() _ num()? mode() _ date()) pn:word() _ pl:num()? pm:mode() _ pd:date() pc:comment()?
|
||||
{ Password::new(None, pn, pl, pm, 99, pd, pc) }
|
||||
rule nname() -> Password = &(word() _ num()? mode()) pn:word() _ pl:num()? pm:mode()
|
||||
{ Password::new(None, pn, pl, pm, 99, Local::now().naive_local().date(), None) }
|
||||
{ Password::new(None, pn, pl, pm, 99, Date::now(), None) }
|
||||
rule qname() -> Password = &(word()) pn:word()
|
||||
{ Password::new(None, pn, None, Mode::NoSpaceCamel, 99, Local::now().naive_local().date(), None) }
|
||||
{ Password::new(None, pn, None, Mode::NoSpaceCamel, 99, Date::now(), None) }
|
||||
pub rule name() -> Password = name:(jname() / pname() / mname() / sname() / nname() / qname())? {?
|
||||
match name { Some(n) => Ok(n), None => Err("failed to parse password description") }
|
||||
}
|
||||
|
||||
rule ndate() -> NaiveDate = y:$("-"? ['0'..='9']*<1,4>) "-" m:$(['0'..='9']*<1,2>) "-" d:$(['0'..='9']*<1,2>) {?
|
||||
rule ndate() -> Date = y:$("-"? ['0'..='9']*<1,4>) "-" m:$(['0'..='9']*<1,2>) "-" d:$(['0'..='9']*<1,2>) {?
|
||||
let year: i32 = match y.parse() { Ok(n) => n, Err(_) => return Err("year") };
|
||||
let month: u32 = match m.parse() { Ok(n) => n, Err(_) => return Err("month") };
|
||||
let day: u32 = match d.parse() { Ok(n) => n, Err(_) => return Err("day") };
|
||||
NaiveDate::from_ymd_opt(year, month, day).ok_or("date")
|
||||
Date::try_new(year, month, day)
|
||||
}
|
||||
rule cdate() -> NaiveDate = "now" { Local::now().naive_local().date() }
|
||||
rule date() -> NaiveDate = d:(ndate() / cdate()) { d }
|
||||
rule cdate() -> Date = "now" { Date::now() }
|
||||
rule date() -> Date = d:(ndate() / cdate()) { d }
|
||||
rule umode() -> Mode = ("U" / "u") m:$("R" / "r" / "N" / "n" / "H" / "h" / "B" / "b") {?
|
||||
match m.to_uppercase().as_str() {
|
||||
"R" => Ok(Mode::RegularUpcase),
|
||||
@@ -126,7 +125,7 @@ add t3 C 99 2022-12-14"###
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
}))),
|
||||
Command::Add(Rc::new(RefCell::new(Password {
|
||||
@@ -136,7 +135,7 @@ add t3 C 99 2022-12-14"###
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
}))),
|
||||
Command::Add(Rc::new(RefCell::new(Password {
|
||||
@@ -146,7 +145,7 @@ add t3 C 99 2022-12-14"###
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
})))
|
||||
])
|
||||
@@ -166,7 +165,7 @@ add t3 C 99 2022-12-14
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
}))),
|
||||
Command::Add(Rc::new(RefCell::new(Password {
|
||||
@@ -176,7 +175,7 @@ add t3 C 99 2022-12-14
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
}))),
|
||||
Command::Add(Rc::new(RefCell::new(Password {
|
||||
@@ -186,7 +185,7 @@ add t3 C 99 2022-12-14
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
}))),
|
||||
Command::Noop
|
||||
@@ -208,7 +207,7 @@ add t3 C 99 2022-12-14
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
}))),
|
||||
Command::Add(Rc::new(RefCell::new(Password {
|
||||
@@ -218,7 +217,7 @@ add t3 C 99 2022-12-14
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
}))),
|
||||
Command::Add(Rc::new(RefCell::new(Password {
|
||||
@@ -228,7 +227,7 @@ add t3 C 99 2022-12-14
|
||||
length: None,
|
||||
mode: Mode::NoSpaceCamel,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2022, 12, 14).unwrap(),
|
||||
date: Date::new(2022, 12, 14),
|
||||
comment: None
|
||||
}))),
|
||||
Command::Noop,
|
||||
@@ -248,7 +247,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::Regular,
|
||||
length: None,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("xx.ableton@domain.info https://www.ableton.com".to_string())
|
||||
})
|
||||
);
|
||||
@@ -261,7 +260,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::RegularUpcase,
|
||||
length: None,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("xx.ableton@domain.info https://www.ableton.com".to_string())
|
||||
})
|
||||
);
|
||||
@@ -274,7 +273,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::RegularUpcase,
|
||||
length: None,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: None
|
||||
})
|
||||
);
|
||||
@@ -287,7 +286,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::Regular,
|
||||
length: None,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("xx.ableton@domain.info https://www.ableton.com".to_string())
|
||||
})
|
||||
);
|
||||
@@ -300,7 +299,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::NoSpace,
|
||||
length: None,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("xx.ableton@domain.info https://www.ableton.com".to_string())
|
||||
})
|
||||
);
|
||||
@@ -313,7 +312,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::NoSpaceUpcase,
|
||||
length: None,
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("xx.ableton@domain.info https://www.ableton.com".to_string())
|
||||
})
|
||||
);
|
||||
@@ -326,7 +325,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::Regular,
|
||||
length: Some(20),
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("a b c".to_string())
|
||||
})
|
||||
);
|
||||
@@ -339,7 +338,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::RegularUpcase,
|
||||
length: Some(20),
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("a b c".to_string())
|
||||
})
|
||||
);
|
||||
@@ -352,7 +351,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::HexUpcase,
|
||||
length: Some(20),
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("a b c".to_string())
|
||||
})
|
||||
);
|
||||
@@ -365,7 +364,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::Base64Upcase,
|
||||
length: Some(20),
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("a b c".to_string())
|
||||
})
|
||||
);
|
||||
@@ -378,7 +377,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::Decimal,
|
||||
length: Some(20),
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("a b c".to_string())
|
||||
})
|
||||
);
|
||||
@@ -391,7 +390,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::Decimal,
|
||||
length: Some(20),
|
||||
seq: 98,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("a b c".to_string())
|
||||
})
|
||||
);
|
||||
@@ -404,7 +403,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::NoSpaceCamel,
|
||||
length: Some(20),
|
||||
seq: 98,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("a b c".to_string())
|
||||
})
|
||||
);
|
||||
@@ -417,7 +416,7 @@ add t3 C 99 2022-12-14
|
||||
mode: Mode::Decimal,
|
||||
length: Some(20),
|
||||
seq: 99,
|
||||
date: NaiveDate::from_ymd_opt(2020, 12, 09).unwrap(),
|
||||
date: Date::new(2020, 12, 09),
|
||||
comment: Some("a b c".to_string())
|
||||
})
|
||||
);
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::skey::SKey;
|
||||
use crate::structs::Mode;
|
||||
use chrono::naive::NaiveDate;
|
||||
use crate::utils::date::Date;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
pub type Name = String;
|
||||
@@ -10,7 +10,6 @@ pub type PasswordRef = Rc<RefCell<Password>>;
|
||||
pub type Parent = Option<PasswordRef>;
|
||||
pub type Length = Option<u32>;
|
||||
pub type Seq = u32;
|
||||
pub type Date = NaiveDate;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Password {
|
||||
@@ -173,7 +172,7 @@ mod tests {
|
||||
None,
|
||||
Mode::Regular,
|
||||
99,
|
||||
NaiveDate::from_ymd_opt(2022, 12, 3).unwrap(),
|
||||
Date::new(2022, 12, 3),
|
||||
None,
|
||||
)));
|
||||
|
||||
@@ -187,7 +186,7 @@ mod tests {
|
||||
None,
|
||||
Mode::Regular,
|
||||
99,
|
||||
NaiveDate::from_ymd_opt(2022, 12, 3).unwrap(),
|
||||
Date::new(2022, 12, 3),
|
||||
None,
|
||||
)));
|
||||
p2.borrow_mut().parent = Some(p1.clone());
|
||||
@@ -197,7 +196,7 @@ mod tests {
|
||||
None,
|
||||
Mode::Regular,
|
||||
99,
|
||||
NaiveDate::from_ymd_opt(2022, 12, 3).unwrap(),
|
||||
Date::new(2022, 12, 3),
|
||||
None,
|
||||
)));
|
||||
p3.borrow_mut().parent = Some(p2.clone());
|
||||
@@ -207,7 +206,7 @@ mod tests {
|
||||
None,
|
||||
Mode::Regular,
|
||||
99,
|
||||
NaiveDate::from_ymd_opt(2022, 12, 3).unwrap(),
|
||||
Date::new(2022, 12, 3),
|
||||
None,
|
||||
)));
|
||||
p4.borrow_mut().parent = Some(p3.clone());
|
||||
@@ -217,7 +216,7 @@ mod tests {
|
||||
None,
|
||||
Mode::Regular,
|
||||
99,
|
||||
NaiveDate::from_ymd_opt(2022, 12, 3).unwrap(),
|
||||
Date::new(2022, 12, 3),
|
||||
None,
|
||||
)));
|
||||
p5.borrow_mut().parent = Some(p4.clone());
|
||||
@@ -230,7 +229,7 @@ mod tests {
|
||||
#[test]
|
||||
fn exec_encode_test() {
|
||||
let sec = "my secret";
|
||||
let dat = NaiveDate::from_ymd_opt(2022, 12, 3).unwrap();
|
||||
let dat = Date::new(2022, 12, 3);
|
||||
|
||||
let mut pwd = Password::new(None, "test1".to_string(), None, Mode::Regular, 99, dat, None);
|
||||
assert_eq!(pwd.encode(sec), "ross beau week held yoga anti");
|
||||
@@ -1,15 +1,14 @@
|
||||
use rpassword::prompt_password;
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::Editor;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::lk::LK;
|
||||
use crate::parser::command_parser;
|
||||
use crate::structs::{Command, LKErr, LKOut, HISTORY_FILE};
|
||||
use crate::utils::editor::Editor;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LKRead {
|
||||
pub rl: Editor<()>,
|
||||
pub rl: Editor,
|
||||
pub prompt: String,
|
||||
pub state: Rc<RefCell<LK>>,
|
||||
pub cmd: String,
|
||||
@@ -31,7 +30,7 @@ pub struct LKPrint {
|
||||
}
|
||||
|
||||
impl LKRead {
|
||||
pub fn new(rl: Editor<()>, prompt: String, state: Rc<RefCell<LK>>) -> Self {
|
||||
pub fn new(rl: Editor, prompt: String, state: Rc<RefCell<LK>>) -> Self {
|
||||
Self {
|
||||
rl,
|
||||
prompt,
|
||||
@@ -53,7 +52,7 @@ impl LKRead {
|
||||
}
|
||||
self.cmd = match self.rl.readline(&*self.prompt) {
|
||||
Ok(str) => str,
|
||||
Err(ReadlineError::Eof | ReadlineError::Interrupted) => "quit".to_string(),
|
||||
Err(LKErr::EOF) => "quit".to_string(),
|
||||
Err(err) => {
|
||||
return LKEval::new(
|
||||
Command::Error(LKErr::ReadError(err.to_string())),
|
||||
@@ -128,6 +127,7 @@ impl<'a> LKEval<'a> {
|
||||
Command::Error(error) => match error {
|
||||
LKErr::ParseError(e) => out.e(e.to_string()),
|
||||
LKErr::ReadError(e) => out.e(e.to_string()),
|
||||
LKErr::EOF => out.e("error: end of file".to_string()),
|
||||
LKErr::Error(e) => out.e(format!("error: {}", e.to_string())),
|
||||
},
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
use crate::password::{Comment, Name, PasswordRef};
|
||||
use home::home_dir;
|
||||
use rpassword::prompt_password;
|
||||
use rustyline::Editor;
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
@@ -9,12 +7,14 @@ use std::{cell::RefCell, rc::Rc};
|
||||
use crate::lk::LK;
|
||||
use crate::parser::command_parser;
|
||||
use crate::repl::{LKEval, LKRead};
|
||||
use crate::utils::home;
|
||||
use crate::utils::editor::Editor;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref HISTORY_FILE: Box<Path> = {
|
||||
match std::env::var("HEL_HISTORY") {
|
||||
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
||||
_ => home_dir().unwrap().join(".hel_history").into_boxed_path(),
|
||||
_ => home::dir().join(".hel_history").into_boxed_path(),
|
||||
}
|
||||
};
|
||||
pub static ref PROMPT_SETTING: String = {
|
||||
@@ -26,19 +26,19 @@ lazy_static! {
|
||||
pub static ref INIT_FILE: Box<Path> = {
|
||||
match std::env::var("HEL_INIT") {
|
||||
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
||||
_ => home_dir().unwrap().join(".helrc").into_boxed_path(),
|
||||
_ => home::dir().join(".helrc").into_boxed_path(),
|
||||
}
|
||||
};
|
||||
pub static ref CORRECT_FILE: Box<Path> = {
|
||||
match std::env::var("HEL_CORRECT") {
|
||||
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
||||
_ => home_dir().unwrap().join(".hel_correct").into_boxed_path(),
|
||||
_ => home::dir().join(".hel_correct").into_boxed_path(),
|
||||
}
|
||||
};
|
||||
pub static ref DUMP_FILE: Box<Path> = {
|
||||
match std::env::var("HEL_DUMP") {
|
||||
Ok(v) => Path::new(shellexpand::full(&v).unwrap().into_owned().as_str()).to_path_buf().into_boxed_path(),
|
||||
_ => home_dir().unwrap().join(".hel_dump").into_boxed_path(),
|
||||
_ => home::dir().join(".hel_dump").into_boxed_path(),
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -47,6 +47,8 @@ lazy_static! {
|
||||
pub enum LKErr<'a> {
|
||||
#[error("Error: {0}")]
|
||||
Error(&'a str),
|
||||
#[error("Error: end of file")]
|
||||
EOF,
|
||||
#[error("Failed to read the line: {0}")]
|
||||
ReadError(String),
|
||||
#[error("Failed to parse: {0}")]
|
||||
@@ -288,7 +290,7 @@ pub fn init() -> Option<LKRead> {
|
||||
.print();
|
||||
}
|
||||
}
|
||||
Some(LKRead::new(Editor::<()>::new().unwrap(), PROMPT_SETTING.to_string(), lk.clone()))
|
||||
Some(LKRead::new(Editor::new(), PROMPT_SETTING.to_string(), lk.clone()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -0,0 +1,179 @@
|
||||
use shlex::split;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
#[cfg(not(wasm))]
|
||||
pub mod date {
|
||||
use chrono::naive::NaiveDate;
|
||||
use chrono::Local;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct Date {
|
||||
date: NaiveDate
|
||||
}
|
||||
|
||||
impl Date {
|
||||
pub fn new(year: i32, month: u32, day: u32) -> Self {
|
||||
Self { date: NaiveDate::from_ymd_opt(year, month, day).unwrap() }
|
||||
}
|
||||
|
||||
pub fn try_new(year: i32, month: u32, day: u32) -> Result<Self, &'static str> {
|
||||
match NaiveDate::from_ymd_opt(year, month, day) {
|
||||
Some(d) => Ok(Self { date: d }),
|
||||
None => Err("error: failed to parse the date"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn now() -> Self {
|
||||
Self { date: Local::now().naive_local().date() }
|
||||
}
|
||||
|
||||
pub fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
||||
self.date.cmp(&other.date)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Date {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.date.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(wasm))]
|
||||
pub mod rnd {
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
pub fn range(start: u32, end: u32) -> u32 {
|
||||
thread_rng().gen_range(start..end)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub mod home {
|
||||
use home::home_dir;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn dir() -> PathBuf {
|
||||
home_dir().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub mod editor {
|
||||
use crate::structs::LKErr;
|
||||
use rustyline::error::ReadlineError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Editor {
|
||||
editor: rustyline::Editor<()>,
|
||||
}
|
||||
|
||||
impl Editor {
|
||||
pub fn new() -> Self {
|
||||
Self { editor: rustyline::Editor::<()>::new().unwrap() }
|
||||
}
|
||||
|
||||
pub fn clear_history(&mut self) {
|
||||
self.editor.clear_history();
|
||||
}
|
||||
|
||||
pub fn add_history_entry(&mut self, entry: &str) {
|
||||
self.editor.add_history_entry(entry);
|
||||
}
|
||||
|
||||
pub fn load_history<'a>(&mut self, fname: &str) -> Result<(), LKErr<'a>> {
|
||||
match self.editor.load_history(&fname) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(_) => Err(LKErr::Error("failed to read history file")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_history<'a>(&mut self, fname: &str) -> Result<(), LKErr<'a>> {
|
||||
match self.editor.save_history(&fname) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(ReadlineError::Eof | ReadlineError::Interrupted) => Err(LKErr::EOF),
|
||||
Err(_) => Err(LKErr::Error("failed to write history file")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readline<'a>(&mut self, prompt: &str) -> Result<String, LKErr<'a>> {
|
||||
match self.editor.readline(&prompt) {
|
||||
Ok(line) => Ok(line),
|
||||
Err(_) => Err(LKErr::Error("failed to read from input")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_cmd_with_input(cmd: &str, args: &Vec<String>, input: &str) -> io::Result<String> {
|
||||
let mut cmd = Command::new(cmd).args(args).stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
|
||||
let mut stdin = cmd.stdin.take().unwrap();
|
||||
let stdout = cmd.stdout.as_mut().unwrap();
|
||||
let in_data = input.to_string();
|
||||
let write_handle = std::thread::spawn(move || stdin.write_all(in_data.as_bytes()));
|
||||
let mut output = Vec::new();
|
||||
stdout.read_to_end(&mut output)?;
|
||||
match write_handle.join() {
|
||||
Ok(_) => (),
|
||||
Err(_) => return Err(io::Error::new(io::ErrorKind::Other, "Failed to run command")),
|
||||
}
|
||||
match String::from_utf8(output) {
|
||||
Ok(x) => Ok(x),
|
||||
Err(err) => Err(io::Error::new(io::ErrorKind::InvalidData, err.utf8_error())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cmd_args_from_command(command: &str) -> io::Result<(String, Vec<String>)> {
|
||||
let args = match split(command) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("Failed to parse the command: {:?}", command),
|
||||
))
|
||||
}
|
||||
};
|
||||
Ok((shellexpand::full(&args[0]).unwrap().into_owned(), args[1..].to_vec()))
|
||||
}
|
||||
|
||||
pub fn get_copy_command_from_env() -> (String, Vec<String>) {
|
||||
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 -"),
|
||||
"macos" => OsString::from("pbcopy"),
|
||||
"linux" => OsString::from("xclip"),
|
||||
_ => OsString::from("cat"),
|
||||
});
|
||||
get_cmd_args_from_command(&cmd_os_str.to_string_lossy()).unwrap_or_else(|_| ("cat".to_string(), vec![]))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn cmd_exec_test() {
|
||||
assert_eq!(call_cmd_with_input("true", &vec![], "").unwrap(), "".to_string());
|
||||
assert_eq!(call_cmd_with_input("cat", &vec![], "ok").unwrap(), "ok".to_string());
|
||||
assert_eq!(
|
||||
call_cmd_with_input(
|
||||
"cat",
|
||||
&vec![],
|
||||
r###"line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4"###
|
||||
)
|
||||
.unwrap(),
|
||||
"line 1\nline 2\nline 3\nline 4".to_string()
|
||||
);
|
||||
assert_ne!(call_cmd_with_input("cat", &vec![], "notok").unwrap(), "ok".to_string());
|
||||
assert_eq!(
|
||||
call_cmd_with_input("echo", &vec!["-n".to_string(), "test is ok".to_string()], "").unwrap(),
|
||||
"test is ok".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "helcli"
|
||||
version = "0.1.0"
|
||||
authors = ["ok2"]
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "hel"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
hel = { version = "0.1.0", path = "../hel" }
|
||||
rustyline = "10.0.0"
|
||||
@@ -0,0 +1,12 @@
|
||||
extern crate hel;
|
||||
|
||||
use hel::structs::init;
|
||||
|
||||
pub fn main() {
|
||||
let mut lkread = match init() { Some(r) => r, None => { return; } };
|
||||
|
||||
while lkread.read().eval().print() {
|
||||
lkread.refresh();
|
||||
}
|
||||
lkread.quit();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "helwasm"
|
||||
version = "0.1.0"
|
||||
authors = ["ok2"]
|
||||
edition = "2021"
|
||||
|
||||
[target.'cfg(wasm32)']
|
||||
[lib]
|
||||
name = "helwasm"
|
||||
path = "src/lib.rs"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
hel = { version = "0.1.0", path = "../hel" }
|
||||
wasm-bindgen = "0.2.83"
|
||||
@@ -0,0 +1,8 @@
|
||||
extern crate hel;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn add(a: i32, b: i32) -> i32 {
|
||||
a + b + 1
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
#![recursion_limit = "1024"]
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[allow(unused_imports)]
|
||||
#[macro_use(defer)]
|
||||
extern crate scopeguard;
|
||||
|
||||
mod commands;
|
||||
mod lk;
|
||||
mod parser;
|
||||
mod password;
|
||||
mod repl;
|
||||
mod skey;
|
||||
mod structs;
|
||||
mod utils;
|
||||
|
||||
use crate::structs::init;
|
||||
|
||||
pub fn main() {
|
||||
let mut lkread = match init() { Some(r) => r, None => { return; } };
|
||||
|
||||
while lkread.read().eval().print() {
|
||||
lkread.refresh();
|
||||
}
|
||||
lkread.quit();
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
use shlex::split;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
pub fn call_cmd_with_input(cmd: &str, args: &Vec<String>, input: &str) -> io::Result<String> {
|
||||
let mut cmd = Command::new(cmd).args(args).stdin(Stdio::piped()).stdout(Stdio::piped()).spawn()?;
|
||||
let mut stdin = cmd.stdin.take().unwrap();
|
||||
let stdout = cmd.stdout.as_mut().unwrap();
|
||||
let in_data = input.to_string();
|
||||
let write_handle = std::thread::spawn(move || stdin.write_all(in_data.as_bytes()));
|
||||
let mut output = Vec::new();
|
||||
stdout.read_to_end(&mut output)?;
|
||||
match write_handle.join() {
|
||||
Ok(_) => (),
|
||||
Err(_) => return Err(io::Error::new(io::ErrorKind::Other, "Failed to run command")),
|
||||
}
|
||||
match String::from_utf8(output) {
|
||||
Ok(x) => Ok(x),
|
||||
Err(err) => Err(io::Error::new(io::ErrorKind::InvalidData, err.utf8_error())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cmd_args_from_command(command: &str) -> io::Result<(String, Vec<String>)> {
|
||||
let args = match split(command) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("Failed to parse the command: {:?}", command),
|
||||
))
|
||||
}
|
||||
};
|
||||
Ok((shellexpand::full(&args[0]).unwrap().into_owned(), args[1..].to_vec()))
|
||||
}
|
||||
|
||||
pub fn get_copy_command_from_env() -> (String, Vec<String>) {
|
||||
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 -"),
|
||||
"macos" => OsString::from("pbcopy"),
|
||||
"linux" => OsString::from("xclip"),
|
||||
_ => OsString::from("cat"),
|
||||
});
|
||||
get_cmd_args_from_command(&cmd_os_str.to_string_lossy()).unwrap_or_else(|_| ("cat".to_string(), vec![]))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn cmd_exec_test() {
|
||||
assert_eq!(call_cmd_with_input("true", &vec![], "").unwrap(), "".to_string());
|
||||
assert_eq!(call_cmd_with_input("cat", &vec![], "ok").unwrap(), "ok".to_string());
|
||||
assert_eq!(
|
||||
call_cmd_with_input(
|
||||
"cat",
|
||||
&vec![],
|
||||
r###"line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4"###
|
||||
)
|
||||
.unwrap(),
|
||||
"line 1\nline 2\nline 3\nline 4".to_string()
|
||||
);
|
||||
assert_ne!(call_cmd_with_input("cat", &vec![], "notok").unwrap(), "ok".to_string());
|
||||
assert_eq!(
|
||||
call_cmd_with_input("echo", &vec!["-n".to_string(), "test is ok".to_string()], "").unwrap(),
|
||||
"test is ok".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user