diff --git a/grammar.pest b/grammar.pest index 663e94e..22bdb88 100644 --- a/grammar.pest +++ b/grammar.pest @@ -35,7 +35,8 @@ anon_command = { "cmd" ~ NEWLINE* ~ OPENBR cmd_body = { ((cmd_settings|vars_def|shell_def) ~ NEWLINE)* ~ quick_command } vars_def = { "vars" ~ var_def ~ (DEF_SEP* ~ var_def)* } DEF_SEP = _{"," ~ NEWLINE*} -var_def = { symbol } +var_def = { symbol ~ default_var? } +default_var = { "=" ~ normal_string } cmd_settings = { "set" ~ symbol ~ (DEF_SEP* ~ symbol)* } shell_def = {"shell" ~ (string|word)+ } diff --git a/src/core.rs b/src/core.rs index c4bafc0..82468d2 100644 --- a/src/core.rs +++ b/src/core.rs @@ -132,12 +132,12 @@ fn run_command( let val = if let Some(val) = arg_vals.get(i) { val } else { - history = query_env_var(var, history).context("querying env var")?; + history = query_env_var(&var.name, &var.value, history).context("querying env var")?; history.last().unwrap() }; // uppon calling exec, the env vars are kept, so just setting them here // means setting them for the callee - env::set_var(var, val); + env::set_var(&var.name, val); } term.clear_last_lines(cmd.env_vars.len() - arg_vals.len()) .context("Clearing input lines")?; @@ -233,7 +233,11 @@ struct RlHelper { } impl Highlighter for RlHelper {} -fn query_env_var(name: &str, mut hist: Vec) -> Result> { +fn query_env_var( + name: &str, + default_val: &Option, + mut hist: Vec, +) -> Result> { let mut rl = rustyline::Editor::new()?; rl.set_helper(Some(RlHelper { completer: FilenameCompleter::new(), @@ -241,8 +245,22 @@ fn query_env_var(name: &str, mut hist: Vec) -> Result> { for h in &hist { rl.add_history_entry(h)?; } - let line = rl.readline(&format!("Value for {name}: "))?; - hist.push(line); + let line = rl.readline(&format!( + "Value for {name}{default}: ", + default = if let Some(default_val) = default_val { + format!(" ({default_val})") + } else { + String::new() + } + ))?; + + if line.is_empty() { + if let Some(default_val) = default_val { + hist.push(default_val.to_string()); + } + } else { + hist.push(line); + } Ok(hist) } diff --git a/src/parser.rs b/src/parser.rs index a36c8ad..83659b3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -32,7 +32,7 @@ pub struct Command { pub settings: Vec, pub name: Option, pub shell: Option, - pub env_vars: Vec, + pub env_vars: Vec, } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -47,6 +47,12 @@ pub struct ShellDef { pub args: Vec, } +#[derive(Debug, Clone)] +pub struct VarDef { + pub name: String, + pub value: Option, +} + #[derive(Debug, Clone)] struct RawMenu<'a> { display_name: Option, @@ -231,7 +237,7 @@ fn parse_anon_command(p: Pair<'_, Rule>) -> Command { #[derive(Default)] struct CmdBodyParser { settings: Option>, - vars: Option>, + vars: Option>, shell_def: Option, } @@ -278,14 +284,25 @@ fn parse_cmd_settings(p: Pair<'_, Rule>) -> Vec { res } -fn parse_vars_def(p: Pair<'_, Rule>) -> Vec { +fn parse_vars_def(p: Pair<'_, Rule>) -> Vec { + fn parse_var_def(p: Pair<'_, Rule>) -> VarDef { + assert!(p.as_rule() == Rule::var_def, "unexpected rule: {p:#?}"); + let mut p = p.into_inner(); + let name_def = p.next().unwrap(); + let value_def = p.next(); + + let name = name_def.as_str().to_string(); + let value = value_def.map(|v| { + assert!(v.as_rule() == Rule::default_var, "unexpected rule: {p:#?}"); + // v(default_var) -> normal_string -> normal_content + v.inext().inext().as_str().to_string() + }); + + VarDef { name, value } + } + assert!(p.as_rule() == Rule::vars_def); - p.into_inner() - .map(|p| { - assert!(p.as_rule() == Rule::var_def, "unexpected rule: {p:#?}"); - p.inext().as_str().to_string() - }) - .collect() + p.into_inner().map(parse_var_def).collect() } fn parse_quick_command(pair: Pair<'_, Rule>) -> (Option, StringExpr) {