Add source command and prepare to expand the file names in source command.

This commit is contained in:
Oleksandr Kozachuk
2022-12-17 15:58:41 +01:00
parent 9347bc3972
commit e05d98b2ba
5 changed files with 43 additions and 3 deletions
+1
View File
@@ -20,3 +20,4 @@ sha1 = "0.10.5"
base64 = "0.20.0" base64 = "0.20.0"
rpassword = "7.2.0" rpassword = "7.2.0"
shlex = "1.1.0" shlex = "1.1.0"
shellexpand = "3.0.0"
+2
View File
@@ -17,6 +17,7 @@ peg::parser! {
/ mv_cmd() / mv_cmd()
/ rm_cmd() / rm_cmd()
/ pb_cmd() / pb_cmd()
/ source_cmd()
/ enc_cmd() / enc_cmd()
/ pass_cmd() / pass_cmd()
/ noop_cmd() / noop_cmd()
@@ -77,6 +78,7 @@ peg::parser! {
rule help_cmd() -> Command<'input> = "help" { Command::Help } rule help_cmd() -> Command<'input> = "help" { Command::Help }
rule quit_cmd() -> Command<'input> = "quit" { Command::Quit } rule quit_cmd() -> Command<'input> = "quit" { Command::Quit }
rule pb_cmd() -> Command<'input> = "pb" _ e:$(([' '..='~'])+) { Command::PasteBuffer(e.to_string()) } rule pb_cmd() -> Command<'input> = "pb" _ e:$(([' '..='~'])+) { Command::PasteBuffer(e.to_string()) }
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 ls_cmd() -> Command<'input> = "ls" f:comment()? { Command::Ls(f.unwrap_or(".".to_string())) }
rule add_cmd() -> Command<'input> = "add" _ name:name() { Command::Add(Rc::new(RefCell::new(name))) } rule add_cmd() -> Command<'input> = "add" _ name:name() { Command::Add(Rc::new(RefCell::new(name))) }
rule error_cmd() -> Command<'input> = "error" _ e:$(([' '..='~'])+) { Command::Error(LKErr::Error(e)) } rule error_cmd() -> Command<'input> = "error" _ e:$(([' '..='~'])+) { Command::Error(LKErr::Error(e)) }
+30 -1
View File
@@ -3,12 +3,13 @@ use rpassword::prompt_password;
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
use rustyline::Editor; use rustyline::Editor;
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use std::path::PathBuf;
use crate::lk::LK; use crate::lk::LK;
use crate::parser::command_parser; use crate::parser::command_parser;
use crate::password::{fix_password_recursion, PasswordRef}; use crate::password::{fix_password_recursion, PasswordRef};
use crate::structs::{Command, LKErr, Radix, HISTORY_FILE}; use crate::structs::{Command, LKErr, Radix, HISTORY_FILE};
use crate::utils::{ call_cmd_with_input, get_copy_command_from_env }; use crate::utils::{ call_cmd_with_input, get_copy_command_from_env, get_cmd_args_from_command };
#[derive(Debug)] #[derive(Debug)]
pub struct LKRead { pub struct LKRead {
@@ -203,6 +204,33 @@ impl<'a> LKEval<'a> {
}; };
} }
fn cmd_source(&self, out: &mut Vec<String>, source: &String) {
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.push(format!("error: failed to parse command {:?}: {}", source, e.to_string())); return; },
};
match call_cmd_with_input(&cmd, &args, "") {
Ok(o) => o,
Err(e) => { out.push(format!("error: failed to execute command {}: {}", cmd, e.to_string())); return; },
}
} else {
let script = PathBuf::from(source);
match std::fs::read_to_string(script) {
Ok(script) => script,
Err(err) => { out.push(format!("error: failed to read file {}: {}", source, err.to_string())); return; }
}
};
match command_parser::script(&script) {
Ok(cmd_list) => {
for cmd in cmd_list {
LKEval::new(cmd, self.state.clone(), prompt_password).eval().print();
}
}
Err(err) => { out.push(format!("error: {}", err.to_string())); return; }
};
}
fn cmd_ls(&self, out: &mut Vec<String>, filter: String) { fn cmd_ls(&self, out: &mut Vec<String>, filter: String) {
let re = match Regex::new(&filter) { let re = match Regex::new(&filter) {
Ok(re) => re, Ok(re) => re,
@@ -268,6 +296,7 @@ impl<'a> LKEval<'a> {
}, },
Command::Enc(name) => self.cmd_enc(&mut out, name), Command::Enc(name) => self.cmd_enc(&mut out, name),
Command::PasteBuffer(command) => self.cmd_pb(&mut out, command), Command::PasteBuffer(command) => self.cmd_pb(&mut out, command),
Command::Source(script) => self.cmd_source(&mut out, script),
Command::Pass(name) => match self.get_password(name) { Command::Pass(name) => match self.get_password(name) {
Some(p) => { Some(p) => {
self.state.borrow_mut().secrets.insert( self.state.borrow_mut().secrets.insert(
+1
View File
@@ -27,6 +27,7 @@ pub enum Command<'a> {
Enc(Name), Enc(Name),
Pass(Name), Pass(Name),
PasteBuffer(String), PasteBuffer(String),
Source(String),
Comment(Name, Comment), Comment(Name, Comment),
Error(LKErr<'a>), Error(LKErr<'a>),
Noop, Noop,
+9 -2
View File
@@ -23,6 +23,14 @@ pub fn call_cmd_with_input(cmd: &str, args: &Vec<String>, input: &str) -> io::Re
} }
} }
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((args[0].clone(), args[1..].to_vec()))
}
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("LESSKEY_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 -"),
@@ -30,8 +38,7 @@ pub fn get_copy_command_from_env() -> (String, Vec<String>) {
"linux" => OsString::from("xclip"), "linux" => OsString::from("xclip"),
_ => OsString::from("cat"), _ => OsString::from("cat"),
}); });
let args = split(&cmd_os_str.to_string_lossy()).unwrap_or_else(|| vec!["cat".to_string()]); get_cmd_args_from_command(&cmd_os_str.to_string_lossy()).unwrap_or_else(|_| ("cat".to_string(), vec![]))
(args[0].clone(), args[1..].to_vec())
} }
#[cfg(test)] #[cfg(test)]