diff options
-rw-r--r-- | src/compose.rs | 2 | ||||
-rw-r--r-- | src/compose/environment.rs | 2 | ||||
-rw-r--r-- | src/poem.rs | 72 | ||||
-rw-r--r-- | src/poem/read.rs | 24 |
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(); |