summaryrefslogtreecommitdiffstats
path: root/src/poem
diff options
context:
space:
mode:
authorRory Dudley2024-04-04 00:47:24 -0600
committerRory Dudley2024-04-04 00:47:24 -0600
commit9b3e4dd71ec1491e3580e079e9be1b42117a74c9 (patch)
tree6bf49aee7b725e87f34b124eb20def50e475c26c /src/poem
parentbeb11773f6ac17d0b97f908311ac5989e1a0a5ae (diff)
downloaddwarvish-9b3e4dd71ec1491e3580e079e9be1b42117a74c9.tar.gz
Add better support for aliases
Make sure to interpret alias values as their own poems, since aliases can be fairly complex.
Notes
Notes: Previously, I was doing a simple find and replace for aliases within each verse. However, aliases can be fairly complex, containing their own range of meters, commands, and io operations. This could cause problems, since a verse should never have, for instance, a pipe (`|`) in the middle of it. This patch fixes it, so that we iterate once through the poem, generating a new poem based on aliases that are found. In order to avoid two loops in the recite() function, it might make sense to offload handling aliases to read().
Diffstat (limited to 'src/poem')
-rw-r--r--src/poem/anthology.rs6
-rw-r--r--src/poem/anthology/alias.rs24
-rw-r--r--src/poem/anthology/source.rs10
-rw-r--r--src/poem/recite.rs39
4 files changed, 50 insertions, 29 deletions
diff --git a/src/poem/anthology.rs b/src/poem/anthology.rs
index e48e6c6..79f48f2 100644
--- a/src/poem/anthology.rs
+++ b/src/poem/anthology.rs
@@ -43,14 +43,14 @@ pub fn lookup(verb: &str) -> Option<usize> {
/// ...
/// }
/// ```
-pub fn incant(verse: &Verse, index: usize, env: &mut Environment) -> i32 {
+pub fn incant(verse: &Verse, out: &mut String, index: usize, env: &mut Environment) -> i32 {
let verb = INDEX[index];
match verb {
- "alias" => alias::incant(verse, &mut env.aliases),
+ "alias" => alias::incant(verse, out, &mut env.aliases),
"cd" => cd::incant(verse),
"exit" => exit::incant(),
"export" => export::incant(verse),
- "source" => source::incant(verse, env),
+ "source" => source::incant(verse, out, env),
"unalias" => alias::unincant(verse, &mut env.aliases),
"unset" => export::unincant(verse),
_ => unreachable!(),
diff --git a/src/poem/anthology/alias.rs b/src/poem/anthology/alias.rs
index 96682db..0183ec2 100644
--- a/src/poem/anthology/alias.rs
+++ b/src/poem/anthology/alias.rs
@@ -10,7 +10,7 @@ use std::collections::HashMap;
/// ```sh
/// alias vim=nvim
/// ```
-pub fn incant(verse: &Verse, aliases: &mut HashMap<String, String>) -> i32 {
+pub fn incant(verse: &Verse, out: &mut String, aliases: &mut HashMap<String, String>) -> i32 {
match verse.clause() {
Some(clause) => {
for stanza in clause {
@@ -22,18 +22,26 @@ pub fn incant(verse: &Verse, aliases: &mut HashMap<String, String>) -> i32 {
}
}
None => {
+ let mut lines = Vec::new();
for (key, val) in aliases {
- if key.contains(' ') && val.contains(' ') {
- println!("'{}'='{}'", key, val);
+ let line = if key.contains(' ') && val.contains(' ') {
+ format!("'{}'='{}'", key, val)
} else if key.contains(' ') {
- println!("'{}'={}", key, val);
+ format!("'{}'={}", key, val)
} else if val.contains(' ') {
- println!("{}='{}'", key, val);
+ format!("{}='{}'", key, val)
} else if val.is_empty() {
- println!("{}=''", key);
+ format!("{}=''", key)
} else {
- println!("{}={}", key, val);
- }
+ format!("{}={}", key, val)
+ };
+ lines.push(line);
+ }
+
+ if verse.couplet {
+ *out = lines.join("\n");
+ } else {
+ println!("{}", lines.join("\n"));
}
}
}
diff --git a/src/poem/anthology/source.rs b/src/poem/anthology/source.rs
index ed4ed13..77d1330 100644
--- a/src/poem/anthology/source.rs
+++ b/src/poem/anthology/source.rs
@@ -12,7 +12,7 @@ use std::fs;
/// ```sh
/// source ~/.dwvshrc
/// ```
-pub fn incant(verse: &Verse, env: &mut Environment) -> i32 {
+pub fn incant(verse: &Verse, out: &mut String, env: &mut Environment) -> i32 {
let files = match verse.clause() {
Some(clause) => clause,
None => {
@@ -42,13 +42,15 @@ pub fn incant(verse: &Verse, env: &mut Environment) -> i32 {
}
};
- match poem.recite(env, None) {
- Ok(_) => {}
+ let stdout = if verse.couplet { Some(true) } else { None };
+
+ *out = match poem.recite(env, stdout) {
+ Ok(out) => out,
Err(e) => {
eprintln!("dwvsh: {}", e.to_string().to_lowercase());
continue;
}
- }
+ };
}
0
diff --git a/src/poem/recite.rs b/src/poem/recite.rs
index 45d4d2e..1f24d14 100644
--- a/src/poem/recite.rs
+++ b/src/poem/recite.rs
@@ -4,6 +4,7 @@ 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,
@@ -25,8 +26,30 @@ impl Reciteable for Poem {
// Keep track of pids for background processes
let mut pids: Arc<Mutex<Vec<i32>>> = Arc::new(Mutex::new(Vec::new()));
- // Loop through each verse in the poem
+ // 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() {
// Verse may need to be mutable
let mut verse = verse.clone();
@@ -59,18 +82,6 @@ impl Reciteable for Poem {
*word = word.replace('\x0e', "$");
}
- // Check for aliases
- match env.aliases.get(&verse.verb()) {
- Some(verb) => {
- let mut split: Vec<String> = verb.split(" ").map(|s| s.to_string()).collect();
- let mut old_stanza = verse.stanza.clone();
- old_stanza.remove(0);
- split.append(&mut old_stanza);
- verse.stanza = split;
- }
- None => {}
- };
-
// Check if verse is a builtin
let index = anthology::lookup(&verse.verb());
@@ -142,7 +153,7 @@ impl Reciteable for Poem {
// Incant the verse if it's a built-in
let status = if index.is_some() {
- anthology::incant(&verse, index.unwrap(), env)
+ anthology::incant(&verse, &mut out, index.unwrap(), env)
} else {
// Checking for environment variables and running internal
// poems may mean that the verb is empty now, so check it once