summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRory Dudley2024-09-28 14:57:03 -0600
committerRory Dudley2024-09-28 19:54:50 -0600
commit243a8c53ae03713b3d6b4f5bf82859f9c93be6ed (patch)
tree2bca8a92ec89707eebb00fd8b46f32e3a82466bb
parent97ca3fa5197599ec28b19d5b2048f7c24e4c8bbc (diff)
downloaddwarvish-243a8c53ae03713b3d6b4f5bf82859f9c93be6ed.tar.gz
Add support for inline environment variables
This patch adds the 'Notes' rune (`=`), which allows for passing environment variables, inline, to a binary, like so: EDITOR=vim sudo visudo Signed-off-by: Rory Dudley <rory@netc.lu>
-rw-r--r--src/poem/elements/rune.rs5
-rw-r--r--src/poem/elements/verse.rs20
-rw-r--r--src/poem/read.rs16
3 files changed, 40 insertions, 1 deletions
diff --git a/src/poem/elements/rune.rs b/src/poem/elements/rune.rs
index 79d53d0..8573583 100644
--- a/src/poem/elements/rune.rs
+++ b/src/poem/elements/rune.rs
@@ -35,6 +35,10 @@ pub enum Rune {
/// A subcommand to run first (`\``)
Poem,
+ /// Denotes an environment variable (`=`),
+ /// only if the verse is empty so far
+ Notes,
+
/// Read files into STDIN (`<`)
Read,
@@ -89,6 +93,7 @@ impl fmt::Display for Rune {
Rune::Remark => "#",
Rune::String => "\"",
Rune::Poem => "`",
+ Rune::Notes => "=",
Rune::Read => "<",
Rune::Write => ">",
Rune::Write2 => "2>",
diff --git a/src/poem/elements/verse.rs b/src/poem/elements/verse.rs
index 9ebd31d..4d5f31c 100644
--- a/src/poem/elements/verse.rs
+++ b/src/poem/elements/verse.rs
@@ -23,6 +23,9 @@ use std::sync::{Arc, Mutex};
/// input on `STDIN` from the previous [Verse].
#[derive(Debug, Clone)]
pub struct Verse {
+ /// Environment variables to fork with
+ pub notes: Stanza,
+
/// A command and its arguments (also see [Stanza])
pub stanza: Stanza,
@@ -119,6 +122,7 @@ impl Verse {
/// [Rune::None], and `couplet` set to 0.
pub fn new() -> Self {
Verse {
+ notes: Stanza::new(),
stanza: Stanza::new(),
couplet: 0,
io: Vec::new(),
@@ -148,6 +152,20 @@ impl Verse {
}
}
+ /// Set the [Verse]'s command's environment
+ ///
+ /// Use self.notate to set inline environment variables
+ pub fn notate(&self, command: &mut Command) {
+ for var in self.notes.clone() {
+ let split: Vec<&str> = var.split("=").collect();
+ if split.len() == 1 {
+ command.env(split[0], "");
+ } else {
+ command.env(split[0], split[1]);
+ }
+ }
+ }
+
/// Alias to [Verse].stanza.push()
pub fn push(&mut self, word: String) {
self.stanza.push(word);
@@ -202,6 +220,7 @@ impl Verse {
// Push the word
match channel {
+ Some(Rune::Notes) => self.notes.push(word.iter().collect()),
Some(Rune::Read) => self.ip.push(word.iter().collect()),
Some(Rune::Write) | Some(Rune::Addendum) => self.op.push(word.iter().collect()),
Some(Rune::Write2) | Some(Rune::Addendum2) => self.ep.push(word.iter().collect()),
@@ -334,6 +353,7 @@ impl Verse {
}
_ => {
let mut command = Command::new(self.verb());
+ self.notate(&mut command);
incant!(self.verb(), command, out, pids, env, self)
}
}
diff --git a/src/poem/read.rs b/src/poem/read.rs
index 99e9aa6..baf6a1d 100644
--- a/src/poem/read.rs
+++ b/src/poem/read.rs
@@ -246,6 +246,7 @@ impl Readable for Poem {
'#' => Rune::Remark,
'\'' | '"' => Rune::String,
'`' => Rune::Poem,
+ '=' => Rune::Notes,
'<' => Rune::Read,
'>' => next(&mut chars, &mut i, Rune::Write, vec![(">", Rune::Addendum)]),
'1' => next(
@@ -352,7 +353,11 @@ impl Readable for Poem {
match rune {
// Indicates the end of a word (space dilineated)
Rune::Pause => {
+ if word.contains(&'=') && verse.is_empty() {
+ channel = Some(Rune::Notes);
+ }
verse.add(&mut word, channel);
+ channel = Some(rune);
}
Rune::Special => {
@@ -378,6 +383,15 @@ impl Readable for Poem {
poem!(chars, j, i, c, verse, word, env);
}
+ // Indicates an environment variable to fork with,
+ // if the verse's stanza is empty so far
+ // Rune::Environment => {
+ // word.push(c);
+ // if verse.is_empty() {
+ // channel = Some(rune);
+ // }
+ // }
+
// Indicates a file operation (<, >, or >>)
Rune::Read
| Rune::Write
@@ -388,7 +402,7 @@ impl Readable for Poem {
| Rune::AddendumAll => {
channel = Some(rune);
verse.add(&mut word, channel);
- channel = Some(rune);
+ // channel = Some(rune);
verse.io.push(rune);
}