summaryrefslogtreecommitdiffstats
path: root/src/poem
diff options
context:
space:
mode:
Diffstat (limited to 'src/poem')
-rw-r--r--src/poem/anthology/alias.rs2
-rw-r--r--src/poem/anthology/source.rs2
-rw-r--r--src/poem/read.rs34
-rw-r--r--src/poem/read/parse.rs32
-rw-r--r--src/poem/recite.rs25
5 files changed, 54 insertions, 41 deletions
diff --git a/src/poem/anthology/alias.rs b/src/poem/anthology/alias.rs
index 0183ec2..4c9b7b6 100644
--- a/src/poem/anthology/alias.rs
+++ b/src/poem/anthology/alias.rs
@@ -39,7 +39,7 @@ pub fn incant(verse: &Verse, out: &mut String, aliases: &mut HashMap<String, Str
}
if verse.couplet {
- *out = lines.join("\n");
+ *out = format!("{}\n", lines.join("\n"));
} else {
println!("{}", lines.join("\n"));
}
diff --git a/src/poem/anthology/source.rs b/src/poem/anthology/source.rs
index 77d1330..182fef4 100644
--- a/src/poem/anthology/source.rs
+++ b/src/poem/anthology/source.rs
@@ -34,7 +34,7 @@ pub fn incant(verse: &Verse, out: &mut String, env: &mut Environment) -> i32 {
}
};
- let poem = match Poem::read(poetry) {
+ let poem = match Poem::read(poetry, env) {
Ok(poem) => poem,
Err(e) => {
eprintln!("dwvsh: {}", e.to_string().to_lowercase());
diff --git a/src/poem/read.rs b/src/poem/read.rs
index d88cf0d..0af7fec 100644
--- a/src/poem/read.rs
+++ b/src/poem/read.rs
@@ -4,7 +4,8 @@ use super::{
};
use core::fmt;
mod parse;
-use crate::{next, poem, remark, string};
+use crate::compose::Environment;
+use crate::{append, next, poem, remark, string};
#[derive(Debug, PartialEq, Eq)]
pub enum Mishap {
@@ -51,20 +52,25 @@ impl Appendable for Poem {
/// Push a [Verse] to the [Poem] after checking that the [Verse] is not
/// empty. Also sets the meter of the [Verse].
fn add(&mut self, verse: &mut Self::Type, last: Rune, meter: Rune) {
- if !verse.is_empty() {
- verse.meter = meter;
- if last == Rune::Couplet || meter == Rune::Couplet {
- verse.couplet = true;
- }
- self.push(verse.clone());
- verse.clear();
+ if verse.is_empty() {
+ return;
+ }
+
+ // Check the meter
+ verse.meter = meter;
+ if last == Rune::Couplet || meter == Rune::Couplet {
+ verse.couplet = true;
}
+
+ // Push verse(s) and clear the current verse stack
+ self.push(verse.clone());
+ verse.clear();
}
}
/// A [Poem] can parse poetry
pub trait Readable {
- fn read(poetry: String) -> Result<Poem, Mishap>;
+ fn read(poetry: String, env: &Environment) -> Result<Poem, Mishap>;
}
impl Readable for Poem {
@@ -74,7 +80,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) -> Result<Poem, Mishap> {
+ fn read(poetry: String, env: &Environment) -> Result<Poem, Mishap> {
// Get all the characters in the input string as an iterator
let mut chars = poetry.chars().into_iter();
@@ -118,7 +124,8 @@ impl Readable for Poem {
}
// Push the verse and break
- poem.add(&mut verse, last, Rune::None);
+ // poem.add(&mut verse, last, Rune::None);
+ append!(poem, last, Rune::None, verse, env);
break;
}
};
@@ -207,7 +214,7 @@ impl Readable for Poem {
// Indicates a sub-poem
Rune::Poem => {
- poem!(chars, j, i, c, verse, word);
+ poem!(chars, j, i, c, verse, word, env);
}
// Indicates a file operation (<, >, or >>)
@@ -221,7 +228,8 @@ impl Readable for Poem {
// These meters indicate the end of a verse
Rune::Couplet | Rune::Quiet | Rune::And | Rune::Continue => {
verse.add(&mut word);
- poem.add(&mut verse, last, rune);
+ // poem.add(&mut verse, last, rune);
+ append!(poem, last, rune, verse, env);
}
// Interpret ~ as $HOME
diff --git a/src/poem/read/parse.rs b/src/poem/read/parse.rs
index 0836eea..70367c4 100644
--- a/src/poem/read/parse.rs
+++ b/src/poem/read/parse.rs
@@ -63,7 +63,7 @@ macro_rules! remark {
/// Same as the [string!] macro, but don't `continue`
#[macro_export]
macro_rules! poem {
- ($chars:expr, $j:expr, $i:expr, $c:expr, $verse:expr, $word:expr) => {
+ ($chars:expr, $j:expr, $i:expr, $c:expr, $verse:expr, $word:expr, $env:expr) => {
let token = $c;
let mut poetry = Word::new();
loop {
@@ -76,7 +76,7 @@ macro_rules! poem {
}
}
}
- let sp = Poem::read(poetry.iter().collect());
+ let sp = Poem::read(poetry.iter().collect(), $env);
let sp = match sp {
Ok(sp) => sp,
Err(e) => return Err(e),
@@ -85,3 +85,31 @@ macro_rules! poem {
$word.push('\x0b');
};
}
+
+/// Append a verse to the poem
+///
+/// Append a verse to poem, first checking for aliases in the environment, and
+/// processing the alias first, if necessary.
+#[macro_export]
+macro_rules! append {
+ ($poem:expr, $last:expr, $meter:expr, $verse:expr, $env:expr) => {
+ if !$verse.is_empty() {
+ match $env.aliases.get(&$verse.verb()) {
+ Some(alias) => {
+ let alias = alias.to_string();
+ let mut poem = Poem::read(alias, $env)?;
+ let len = poem.len();
+ for (i, verse) in poem.iter_mut().enumerate() {
+ if $verse.clause().is_some() && i + 1 == len {
+ verse.stanza.append(&mut $verse.clause().unwrap());
+ }
+ $poem.push(verse.clone());
+ }
+ }
+ None => {
+ $poem.add(&mut $verse, $last, $meter);
+ }
+ }
+ }
+ };
+}
diff --git a/src/poem/recite.rs b/src/poem/recite.rs
index 1f24d14..4038e37 100644
--- a/src/poem/recite.rs
+++ b/src/poem/recite.rs
@@ -4,7 +4,6 @@ use crate::compose::Environment;
use crate::path;
use crate::poem::anthology;
use crate::poem::elements::rune::Rune;
-use crate::poem::read::Readable;
use std::env;
use std::{
io,
@@ -26,30 +25,8 @@ impl Reciteable for Poem {
// Keep track of pids for background processes
let mut pids: Arc<Mutex<Vec<i32>>> = Arc::new(Mutex::new(Vec::new()));
- // Check for aliases
- let mut vv = Poem::new();
- for verse in self.iter() {
- let alias = match env.aliases.get(&verse.verb()) {
- Some(alias) => alias,
- None => {
- vv.push(verse.clone());
- continue;
- }
- }
- .to_string();
-
- let mut poem = Poem::read(alias).unwrap();
- let len = poem.len();
- for (i, new_verse) in poem.iter_mut().enumerate() {
- if verse.clause().is_some() && i + 1 == len {
- new_verse.stanza.append(&mut verse.clause().unwrap());
- }
- vv.push(new_verse.clone());
- }
- }
-
// Loop through each verse in the poem
- for verse in vv.iter() {
+ for verse in self.iter() {
// Verse may need to be mutable
let mut verse = verse.clone();