[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] 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
---
 src/poem/elements/rune.rs  |  5 +++++
 src/poem/elements/verse.rs | 20 ++++++++++++++++++++
 src/poem/read.rs           | 16 +++++++++++++++-
 3 files changed, 40 insertions(+), 1 deletion(-)

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);
                 }
 
-- 
cheers!~
Rory




Archive administrator: postmaster AT dwarvish DOT org