summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compose.rs2
-rw-r--r--src/compose/environment.rs2
-rw-r--r--src/poem.rs72
-rw-r--r--src/poem/read.rs24
4 files changed, 56 insertions, 44 deletions
diff --git a/src/compose.rs b/src/compose.rs
index 46f04a7..dfbbaef 100644
--- a/src/compose.rs
+++ b/src/compose.rs
@@ -53,7 +53,7 @@ fn rrr(path: PathBuf, env: &mut Environment) {
}
};
- let poem = match Poem::read(poetry, &Environment::new()) {
+ let poem = match Poem::read(poetry, &mut Environment::new()) {
Ok(poem) => poem,
Err(e) => {
eprintln!(
diff --git a/src/compose/environment.rs b/src/compose/environment.rs
index df83e4f..7107d57 100644
--- a/src/compose/environment.rs
+++ b/src/compose/environment.rs
@@ -3,6 +3,7 @@ use std::collections::HashMap;
pub struct Environment {
pub aliases: HashMap<String, String>,
pub bins: Vec<String>,
+ pub cs: u8,
}
impl Environment {
@@ -10,6 +11,7 @@ impl Environment {
Environment {
aliases: HashMap::new(),
bins: Vec::new(),
+ cs: 0,
}
}
}
diff --git a/src/poem.rs b/src/poem.rs
index db57e55..362eaaa 100644
--- a/src/poem.rs
+++ b/src/poem.rs
@@ -19,7 +19,7 @@ mod tests {
#[test]
fn it_parses_a_verse_with_no_meter() {
- let poem = Poem::read("cargo build --release".to_string(), &Environment::new());
+ let poem = Poem::read("cargo build --release".to_string(), &mut Environment::new());
assert!(poem.is_ok());
let poem = poem.unwrap();
assert_eq!(poem.first().unwrap().verb(), "cargo");
@@ -27,7 +27,7 @@ mod tests {
#[test]
fn it_parses_a_verse_with_the_couplet_meter() {
- let poem = Poem::read("ls -la | lolcat".to_string(), &Environment::new());
+ let poem = Poem::read("ls -la | lolcat".to_string(), &mut Environment::new());
assert!(poem.is_ok());
let poem = poem.unwrap();
assert_eq!(poem.first().unwrap().verb(), "ls");
@@ -36,7 +36,7 @@ mod tests {
#[test]
fn it_parses_a_verse_with_the_quiet_meter() {
- let poem = Poem::read("sleep 20 &".to_string(), &Environment::new());
+ let poem = Poem::read("sleep 20 &".to_string(), &mut Environment::new());
assert!(poem.is_ok());
let poem = poem.unwrap();
assert_eq!(poem.first().unwrap().verb(), "sleep");
@@ -45,7 +45,7 @@ mod tests {
#[test]
fn it_parses_a_verse_with_the_and_meter() {
- let poem = Poem::read("sleep 2 && ls -la".to_string(), &Environment::new());
+ let poem = Poem::read("sleep 2 && ls -la".to_string(), &mut Environment::new());
assert!(poem.is_ok());
let poem = poem.unwrap();
assert_eq!(poem.first().unwrap().verb(), "sleep");
@@ -54,7 +54,7 @@ mod tests {
#[test]
fn it_parses_a_verse_with_the_continue_meter() {
- let poem = Poem::read("sleep 2; ls -la".to_string(), &Environment::new());
+ let poem = Poem::read("sleep 2; ls -la".to_string(), &mut Environment::new());
assert!(poem.is_ok());
let poem = poem.unwrap();
assert_eq!(poem.first().unwrap().verb(), "sleep");
@@ -63,7 +63,7 @@ mod tests {
#[test]
fn it_parses_a_verse_with_the_read_rune() {
- let poem = Poem::read("lolcat < src/main.rs".to_string(), &Environment::new());
+ let poem = Poem::read("lolcat < src/main.rs".to_string(), &mut Environment::new());
assert!(poem.is_ok());
let mut verses = poem.unwrap().into_iter();
let verse = verses.next().unwrap();
@@ -88,7 +88,7 @@ mod tests {
fn it_parses_a_verse_with_the_write_rune() {
let poem = Poem::read(
"cat src/main.rs > /dev/null".to_string(),
- &Environment::new(),
+ &mut Environment::new(),
);
assert!(poem.is_ok());
let mut verses = poem.unwrap().into_iter();
@@ -114,7 +114,7 @@ mod tests {
fn it_parses_a_verse_with_the_write2_rune() {
let poem = Poem::read(
"cat src/main.rs 2> /dev/null".to_string(),
- &Environment::new(),
+ &mut Environment::new(),
);
assert!(poem.is_ok());
let mut verses = poem.unwrap().into_iter();
@@ -140,7 +140,7 @@ mod tests {
fn it_parses_a_verse_with_the_write_all_rune() {
let poem = Poem::read(
"cat src/main.rs &> /dev/null".to_string(),
- &Environment::new(),
+ &mut Environment::new(),
);
assert!(poem.is_ok());
let mut verses = poem.unwrap().into_iter();
@@ -173,7 +173,7 @@ mod tests {
fn it_parses_a_verse_with_the_addendum_rune() {
let poem = Poem::read(
"cat src/main.rs >> /dev/null".to_string(),
- &Environment::new(),
+ &mut Environment::new(),
);
assert!(poem.is_ok());
let mut verses = poem.unwrap().into_iter();
@@ -199,7 +199,7 @@ mod tests {
fn it_parses_a_verse_with_the_addendum2_rune() {
let poem = Poem::read(
"cat src/main.rs 2>> /dev/null".to_string(),
- &Environment::new(),
+ &mut Environment::new(),
);
assert!(poem.is_ok());
let mut verses = poem.unwrap().into_iter();
@@ -225,7 +225,7 @@ mod tests {
fn it_parses_a_verse_with_the_addendum_all_rune() {
let poem = Poem::read(
"cat src/main.rs &>> /dev/null".to_string(),
- &Environment::new(),
+ &mut Environment::new(),
);
assert!(poem.is_ok());
let mut verses = poem.unwrap().into_iter();
@@ -256,31 +256,31 @@ mod tests {
#[test]
fn it_throws_a_parse_error_if_no_files_are_specified_for_the_read_rune() {
- let poem = Poem::read("lolcat <".to_string(), &Environment::new());
+ let poem = Poem::read("lolcat <".to_string(), &mut Environment::new());
assert!(poem.is_err());
- let poem = Poem::read("lolcat <;".to_string(), &Environment::new());
+ let poem = Poem::read("lolcat <;".to_string(), &mut Environment::new());
assert!(poem.is_err());
- let poem = Poem::read("lolcat < && ls -la".to_string(), &Environment::new());
+ let poem = Poem::read("lolcat < && ls -la".to_string(), &mut Environment::new());
assert!(poem.is_err());
}
#[test]
fn it_throws_a_parse_error_if_no_files_are_specified_for_the_write_rune() {
- let poem = Poem::read("cat src/main.rs >".to_string(), &Environment::new());
+ let poem = Poem::read("cat src/main.rs >".to_string(), &mut Environment::new());
assert!(poem.is_err());
- let poem = Poem::read("cat src/main.rs >;".to_string(), &Environment::new());
+ let poem = Poem::read("cat src/main.rs >;".to_string(), &mut Environment::new());
assert!(poem.is_err());
- let poem = Poem::read("cat > && ls -la".to_string(), &Environment::new());
+ let poem = Poem::read("cat > && ls -la".to_string(), &mut Environment::new());
assert!(poem.is_err());
}
#[test]
fn it_throws_a_parse_error_if_no_files_are_specified_for_the_addendum_rune() {
- let poem = Poem::read("cat src/main.rs >>".to_string(), &Environment::new());
+ let poem = Poem::read("cat src/main.rs >>".to_string(), &mut Environment::new());
assert!(poem.is_err());
- let poem = Poem::read("cat src/main.rs >>;".to_string(), &Environment::new());
+ let poem = Poem::read("cat src/main.rs >>;".to_string(), &mut Environment::new());
assert!(poem.is_err());
- let poem = Poem::read("cat >> && ls -la".to_string(), &Environment::new());
+ let poem = Poem::read("cat >> && ls -la".to_string(), &mut Environment::new());
assert!(poem.is_err());
}
@@ -288,7 +288,7 @@ mod tests {
fn it_parses_a_complex_verse_with_lots_of_different_meters() {
let poem = Poem::read(
"ls -la | lolcat && echo hello | lolcat && sleep 2 &".to_string(),
- &Environment::new(),
+ &mut Environment::new(),
);
assert!(poem.is_ok());
let mut verses = poem.unwrap().into_iter();
@@ -319,25 +319,25 @@ mod tests {
#[test]
fn it_parses_the_continue_meter_without_a_stanza() {
- let poem = Poem::read(";;;;;;;".to_string(), &Environment::new());
+ let poem = Poem::read(";;;;;;;".to_string(), &mut Environment::new());
assert!(poem.is_ok());
}
#[test]
fn it_errors_if_the_couplet_meter_is_used_without_a_stanza() {
- let poem = Poem::read("|".to_string(), &Environment::new());
+ let poem = Poem::read("|".to_string(), &mut Environment::new());
assert!(poem.is_err());
}
#[test]
fn it_errors_if_the_quiet_meter_is_used_without_a_stanza() {
- let poem = Poem::read("&".to_string(), &Environment::new());
+ let poem = Poem::read("&".to_string(), &mut Environment::new());
assert!(poem.is_err());
}
#[test]
fn it_errors_if_the_and_meter_is_used_without_a_stanza() {
- let poem = Poem::read("&&".to_string(), &Environment::new());
+ let poem = Poem::read("&&".to_string(), &mut Environment::new());
assert!(poem.is_err());
}
@@ -348,7 +348,7 @@ mod tests {
sleep 2
";
- let poem = Poem::read(file.to_string(), &Environment::new());
+ let poem = Poem::read(file.to_string(), &mut Environment::new());
assert!(poem.is_ok());
let poem = poem.unwrap();
@@ -388,7 +388,7 @@ mod tests {
wc -l src/**/*.rs | lolcat; ls -la | grep git
";
- let poem = Poem::read(file.to_string(), &Environment::new());
+ let poem = Poem::read(file.to_string(), &mut Environment::new());
assert!(poem.is_ok());
let poem = poem.unwrap();
@@ -398,36 +398,36 @@ mod tests {
#[test]
fn it_catches_parser_errors_related_to_invalid_use_of_special_runes() {
let poetry = "cat file.txt &&&".to_string();
- assert_eq!(Poem::read(poetry, &Environment::new()).is_err(), true);
+ assert_eq!(Poem::read(poetry, &mut Environment::new()).is_err(), true);
let poetry = "cat file.txt&&|".to_string();
- assert_eq!(Poem::read(poetry, &Environment::new()).is_err(), true);
+ assert_eq!(Poem::read(poetry, &mut Environment::new()).is_err(), true);
let poetry = "cat <".to_string();
- assert_eq!(Poem::read(poetry, &Environment::new()).is_err(), true);
+ assert_eq!(Poem::read(poetry, &mut Environment::new()).is_err(), true);
}
#[test]
fn it_catches_parser_errors_related_to_strings() {
let poetry = "echo 'hello".to_string();
- assert_eq!(Poem::read(poetry, &Environment::new()).is_err(), true);
+ assert_eq!(Poem::read(poetry, &mut Environment::new()).is_err(), true);
let poetry = "echo \"hello".to_string();
- assert_eq!(Poem::read(poetry, &Environment::new()).is_err(), true);
+ assert_eq!(Poem::read(poetry, &mut Environment::new()).is_err(), true);
let poetry = "`true".to_string();
- assert_eq!(Poem::read(poetry, &Environment::new()).is_err(), true);
+ assert_eq!(Poem::read(poetry, &mut Environment::new()).is_err(), true);
}
#[test]
fn it_interprets_tilda_as_home() {
let poetry = "cd ~".to_string();
- let poem = Poem::read(poetry, &Environment::new()).unwrap();
+ let poem = Poem::read(poetry, &mut Environment::new()).unwrap();
assert_eq!(poem[0].verb(), "cd");
assert_eq!(poem[0].clause(), Some(vec![env!("HOME").to_string()]));
let poetry = "cd ~/Code/dwarvish".to_string();
- let poem = Poem::read(poetry, &Environment::new()).unwrap();
+ let poem = Poem::read(poetry, &mut Environment::new()).unwrap();
assert_eq!(poem[0].verb(), "cd");
assert_eq!(
poem[0].clause(),
diff --git a/src/poem/read.rs b/src/poem/read.rs
index da13f76..3c4a720 100644
--- a/src/poem/read.rs
+++ b/src/poem/read.rs
@@ -42,8 +42,12 @@ impl fmt::Display for Mishap {
/// A [Poem] can add more [Verse]s to itself
trait Appendable {
type Type;
- fn add(&mut self, verse: &mut Self::Type, meter: Rune, env: &Environment)
- -> Result<(), Mishap>;
+ fn add(
+ &mut self,
+ verse: &mut Self::Type,
+ meter: Rune,
+ env: &mut Environment,
+ ) -> Result<(), Mishap>;
}
impl Appendable for Poem {
@@ -57,7 +61,7 @@ impl Appendable for Poem {
&mut self,
verse: &mut Self::Type,
meter: Rune,
- env: &Environment,
+ env: &mut Environment,
) -> Result<(), Mishap> {
if verse.is_empty() {
return Ok(());
@@ -81,10 +85,16 @@ impl Appendable for Poem {
// Check for aliases
match env.aliases.get(&verse.verb()) {
- Some(alias) => {
+ Some(alias) if env.cs == 0 => {
+ // Increase the callstack
+ env.cs = 1;
+
// Interpret the alias (could be a complex poem)
let mut poem = Poem::read(alias.to_string(), env)?;
+ // Decrease the callstack
+ env.cs = 0;
+
// Try and get the last verse
let lv = match poem.last_mut() {
Some(lv) => lv,
@@ -109,7 +119,7 @@ impl Appendable for Poem {
self.push(v.clone());
}
}
- None => {
+ Some(_) | None => {
// Push verse(s)
self.push(verse.clone());
}
@@ -125,7 +135,7 @@ impl Appendable for Poem {
/// A [Poem] can parse poetry
pub trait Readable {
- fn read(poetry: String, env: &Environment) -> Result<Poem, Mishap>;
+ fn read(poetry: String, env: &mut Environment) -> Result<Poem, Mishap>;
}
impl Readable for Poem {
@@ -135,7 +145,7 @@ impl Readable for Poem {
/// machine-runnable [Poem]. If there is a parse error, [Poem::read] may
/// return a [Mishap]. See [Poem::recite][super::recite] for how each
/// [Verse] in a [Poem] is called.
- fn read(poetry: String, env: &Environment) -> Result<Poem, Mishap> {
+ fn read(poetry: String, env: &mut Environment) -> Result<Poem, Mishap> {
// Get all the characters in the input string as an iterator
let mut chars = poetry.chars().into_iter();