summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRory Dudley2024-04-04 00:47:24 -0600
committerRory Dudley2024-04-04 00:47:24 -0600
commit9b3e4dd71ec1491e3580e079e9be1b42117a74c9 (patch)
tree6bf49aee7b725e87f34b124eb20def50e475c26c
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().
-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