summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRory Dudley2024-03-30 20:15:12 -0600
committerRory Dudley2024-03-30 20:15:12 -0600
commit2439f63a1c0859fd454d4a67dc36b61ad6ab5eb8 (patch)
tree51926cec235e93eb759eacb5761e398dc50fc7f2
parentbc64d1917829623cea447871c548950460559232 (diff)
downloaddwarvish-2439f63a1c0859fd454d4a67dc36b61ad6ab5eb8.tar.gz
Add the 'alias' built-in command
The shell now has support for aliases (via alias foo=bar). The 'unalias' command is also available to remove aliases. Finally, Environment::aliases was changed to be a HashMap<String, String>, instead of a Vec<String>. Since the verse's verb might change (for instance, it is an environment variable, or an alias), add another check in Poem::recite, which simply continues, instead of running the spellchecker, if the verb is empty.
-rw-r--r--src/compose/environment.rs8
-rw-r--r--src/poem/anthology.rs13
-rw-r--r--src/poem/anthology/alias.rs47
-rw-r--r--src/poem/recite.rs26
4 files changed, 81 insertions, 13 deletions
diff --git a/src/compose/environment.rs b/src/compose/environment.rs
index 219a597..df83e4f 100644
--- a/src/compose/environment.rs
+++ b/src/compose/environment.rs
@@ -1,13 +1,15 @@
+use std::collections::HashMap;
+
pub struct Environment {
- pub aliases: Vec<String>,
+ pub aliases: HashMap<String, String>,
pub bins: Vec<String>,
}
impl Environment {
pub fn new() -> Self {
Environment {
- aliases: vec![],
- bins: vec![],
+ aliases: HashMap::new(),
+ bins: Vec::new(),
}
}
}
diff --git a/src/poem/anthology.rs b/src/poem/anthology.rs
index 7d97ab7..94b5f6b 100644
--- a/src/poem/anthology.rs
+++ b/src/poem/anthology.rs
@@ -1,12 +1,13 @@
-pub mod cd;
-pub mod exit;
-pub mod export;
-pub mod source;
+mod alias;
+mod cd;
+mod exit;
+mod export;
+mod source;
use crate::compose::Environment;
use crate::poem::Verse;
/// A static list of all the built-in commands
-static INDEX: [&str; 4] = ["cd", "exit", "export", "source"];
+static INDEX: [&str; 6] = ["alias", "cd", "exit", "export", "source", "unalias"];
/// Lookup the index of a built-in command
///
@@ -23,10 +24,12 @@ pub fn lookup(verb: &str) -> Option<usize> {
pub fn incant(verse: &Verse, index: usize, env: &mut Environment) -> i32 {
let verb = INDEX[index];
match verb {
+ "alias" => alias::incant(verse, &mut env.aliases),
"cd" => cd::incant(verse),
"exit" => exit::incant(),
"export" => export::incant(verse),
"source" => source::incant(verse, env),
+ "unalias" => alias::unincant(verse, &mut env.aliases),
_ => unreachable!(),
}
}
diff --git a/src/poem/anthology/alias.rs b/src/poem/anthology/alias.rs
new file mode 100644
index 0000000..6a8e739
--- /dev/null
+++ b/src/poem/anthology/alias.rs
@@ -0,0 +1,47 @@
+use crate::poem::Verse;
+use std::collections::HashMap;
+
+pub fn incant(verse: &Verse, aliases: &mut HashMap<String, String>) -> i32 {
+ match verse.clause() {
+ Some(clause) => {
+ for stanza in clause {
+ let (key, val) = match stanza.split_once("=") {
+ Some((key, val)) => (key, val),
+ None => continue,
+ };
+ aliases.insert(String::from(key), String::from(val));
+ }
+ }
+ None => {
+ for (key, val) in aliases {
+ if key.contains(' ') && val.contains(' ') {
+ println!("'{}'='{}'", key, val);
+ } else if key.contains(' ') {
+ println!("'{}'={}", key, val);
+ } else if val.contains(' ') {
+ println!("{}='{}'", key, val);
+ } else if val.is_empty() {
+ println!("{}=''", key);
+ } else {
+ println!("{}={}", key, val);
+ }
+ }
+ }
+ }
+ 0
+}
+
+pub fn unincant(verse: &Verse, aliases: &mut HashMap<String, String>) -> i32 {
+ match verse.clause() {
+ Some(clause) => {
+ for stanza in clause {
+ aliases.remove(&stanza);
+ }
+ }
+ None => {
+ eprintln!("unalias: not enough arguments");
+ return 1;
+ }
+ }
+ 0
+}
diff --git a/src/poem/recite.rs b/src/poem/recite.rs
index e37b7c6..9a425e8 100644
--- a/src/poem/recite.rs
+++ b/src/poem/recite.rs
@@ -54,6 +54,18 @@ impl Reciteable for Poem {
}
}
+ // 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 => {}
+ };
+
// Run interal poems
let v = verse.clone();
let mut new_stanza = None;
@@ -129,15 +141,19 @@ impl Reciteable for Poem {
// If it doesn't exist, try refreshing the binary cache, and check
// again
// If it still doesn't exist, print an error
- if !verse.spellcheck(&env.bins) {
- env.bins = path::refresh();
+ if !verse.verb().is_empty() {
if !verse.spellcheck(&env.bins) {
- eprintln!("dwvsh: {}: command not found", verse.verb());
+ env.bins = path::refresh();
+ if !verse.spellcheck(&env.bins) {
+ eprintln!("dwvsh: {}: command not found", verse.verb());
- if verse.meter != Rune::And {
- continue;
+ if verse.meter != Rune::And {
+ continue;
+ }
}
}
+ } else {
+ continue;
}
if stdout {