summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRory Dudley2024-03-28 21:05:00 -0600
committerRory Dudley2024-03-28 21:05:00 -0600
commit14a74aea0f02da53e0f61c572da2c5244ed80551 (patch)
treec43c5aaf46001e3743f7749cc4ebfa0baa06ad96
parent527cc04ffb9ea627ca678fe8fb07fe9330420eab (diff)
downloaddwarvish-14a74aea0f02da53e0f61c572da2c5244ed80551.tar.gz
The anthology module
The anthology module was added to run built-in commands. The 'cd' and 'exit' built-ins were moved from the main recite() loop to this module. Additionally, the 'export' and 'source' built-ins were added.
-rw-r--r--src/poem.rs1
-rw-r--r--src/poem/anthology.rs32
-rw-r--r--src/poem/anthology/cd.rs20
-rw-r--r--src/poem/anthology/exit.rs5
-rw-r--r--src/poem/anthology/export.rs23
-rw-r--r--src/poem/anthology/source.rs46
-rw-r--r--src/poem/recite.rs120
7 files changed, 190 insertions, 57 deletions
diff --git a/src/poem.rs b/src/poem.rs
index 069fb79..0eda6b7 100644
--- a/src/poem.rs
+++ b/src/poem.rs
@@ -1,3 +1,4 @@
+mod anthology;
mod elements;
use elements::verse::Verse;
pub mod read;
diff --git a/src/poem/anthology.rs b/src/poem/anthology.rs
new file mode 100644
index 0000000..2781081
--- /dev/null
+++ b/src/poem/anthology.rs
@@ -0,0 +1,32 @@
+pub mod cd;
+pub mod exit;
+pub mod export;
+pub mod source;
+use crate::poem::Verse;
+use std::path::Path;
+
+/// A static list of all the built-in commands
+static INDEX: [&str; 4] = ["cd", "exit", "export", "source"];
+
+/// Lookup the index of a built-in command
+///
+/// Looks up the index of a built-in command in [INDEX], accounting for aliases
+pub fn lookup(verb: &str) -> Option<usize> {
+ let verb = match verb {
+ "quit" => "exit", // Alias 'quit' to 'exit'
+ "set" => "export", // Alias 'set' to 'export'
+ _ => verb,
+ };
+ INDEX.iter().position(|v| v.to_string() == verb)
+}
+
+pub fn incant(verse: &Verse, index: usize, path: &Vec<&Path>, bins: &mut Vec<String>) -> i32 {
+ let verb = INDEX[index];
+ match verb {
+ "cd" => cd::incant(verse),
+ "exit" => exit::incant(),
+ "export" => export::incant(verse),
+ "source" => source::incant(verse, path, bins),
+ _ => unreachable!(),
+ }
+}
diff --git a/src/poem/anthology/cd.rs b/src/poem/anthology/cd.rs
new file mode 100644
index 0000000..3b48f60
--- /dev/null
+++ b/src/poem/anthology/cd.rs
@@ -0,0 +1,20 @@
+use crate::poem::Verse;
+
+pub fn incant(verse: &Verse) -> i32 {
+ let path = match verse.clause() {
+ Some(path) => path[0].to_string(),
+ None => env!("HOME").to_string(),
+ };
+
+ match std::env::set_current_dir(&path) {
+ Ok(_) => 0,
+ Err(e) => {
+ eprintln!(
+ "cd: unable to change into {}: {}",
+ path,
+ e.to_string().to_lowercase()
+ );
+ 1
+ }
+ }
+}
diff --git a/src/poem/anthology/exit.rs b/src/poem/anthology/exit.rs
new file mode 100644
index 0000000..ecb14f1
--- /dev/null
+++ b/src/poem/anthology/exit.rs
@@ -0,0 +1,5 @@
+use std::process::exit;
+
+pub fn incant() -> i32 {
+ exit(0);
+}
diff --git a/src/poem/anthology/export.rs b/src/poem/anthology/export.rs
new file mode 100644
index 0000000..76dfd99
--- /dev/null
+++ b/src/poem/anthology/export.rs
@@ -0,0 +1,23 @@
+use crate::poem::Verse;
+use std::env;
+
+pub fn incant(verse: &Verse) -> i32 {
+ match verse.clause() {
+ Some(clause) => {
+ for stanza in clause {
+ let (key, val) = match stanza.split_once("=") {
+ Some((key, val)) => (key, val),
+ None => continue,
+ };
+ env::set_var(key, val);
+ }
+ }
+ None => {
+ for (key, val) in env::vars() {
+ println!("{}={}", key, val);
+ }
+ }
+ }
+
+ 0
+}
diff --git a/src/poem/anthology/source.rs b/src/poem/anthology/source.rs
new file mode 100644
index 0000000..1449994
--- /dev/null
+++ b/src/poem/anthology/source.rs
@@ -0,0 +1,46 @@
+use crate::poem::Verse;
+use crate::poem::{read::Readable, recite::Reciteable, Poem};
+use std::fs;
+use std::path::Path;
+
+pub fn incant(verse: &Verse, path: &Vec<&Path>, bins: &mut Vec<String>) -> i32 {
+ let files = match verse.clause() {
+ Some(clause) => clause,
+ None => {
+ eprintln!("source: not enough arguments");
+ return 1;
+ }
+ };
+
+ for file in files {
+ let poetry = match fs::read_to_string(&file) {
+ Ok(contents) => contents,
+ Err(e) => {
+ eprintln!(
+ "source: could not load {}: {}",
+ file,
+ e.to_string().to_lowercase()
+ );
+ return 127;
+ }
+ };
+
+ let poem = match Poem::read(poetry) {
+ Ok(poem) => poem,
+ Err(e) => {
+ eprintln!("dwvsh: {}", e.to_string().to_lowercase());
+ continue;
+ }
+ };
+
+ match poem.recite(path, bins, None) {
+ Ok(_) => {}
+ Err(e) => {
+ eprintln!("dwvsh: {}", e.to_string().to_lowercase());
+ continue;
+ }
+ }
+ }
+
+ 0
+}
diff --git a/src/poem/recite.rs b/src/poem/recite.rs
index f28436e..a88007d 100644
--- a/src/poem/recite.rs
+++ b/src/poem/recite.rs
@@ -1,9 +1,9 @@
mod ps;
use super::Poem;
use crate::path;
+use crate::poem::anthology;
use crate::poem::elements::rune::Rune;
use std::env;
-use std::process::exit;
use std::{
io,
path::Path,
@@ -129,67 +129,73 @@ impl Reciteable for Poem {
None => {}
}
- // Check if the user wants to exit the shell
- if verse.verb() == "exit" || verse.verb() == "quit" {
- exit(0);
- }
-
- // Check if the user wants to change directories
- if verse.verb() == "cd" {
- let path = match verse.clause() {
- Some(path) => path[0].to_string(),
- None => env!("HOME").to_string(),
- };
-
- match std::env::set_current_dir(&path) {
- Ok(_) => continue,
- Err(e) => {
- eprintln!(
- "cd: unable to change into {}: {}",
- path,
- e.to_string().to_lowercase()
- );
- continue;
- }
- }
- }
-
- // Check if the verb exists
- // 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(bins) {
- *bins = path::refresh(path);
+ // // Check if the user wants to exit the shell
+ // if verse.verb() == "exit" || verse.verb() == "quit" {
+ // exit(0);
+ // }
+ //
+ // // Check if the user wants to change directories
+ // if verse.verb() == "cd" {
+ // let path = match verse.clause() {
+ // Some(path) => path[0].to_string(),
+ // None => env!("HOME").to_string(),
+ // };
+ //
+ // match std::env::set_current_dir(&path) {
+ // Ok(_) => continue,
+ // Err(e) => {
+ // eprintln!(
+ // "cd: unable to change into {}: {}",
+ // path,
+ // e.to_string().to_lowercase()
+ // );
+ // continue;
+ // }
+ // }
+ // }
+
+ // Incant the verse if it's a built-in
+ let index = anthology::lookup(&verse.verb());
+ let status = if index.is_some() {
+ anthology::incant(&verse, index.unwrap(), path, bins)
+ } else {
+ // Incant the verse, based on its meter
+ // Check if the verb exists
+ // 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(bins) {
- eprintln!("dwvsh: {}: command not found", verse.verb());
+ *bins = path::refresh(path);
+ if !verse.spellcheck(bins) {
+ eprintln!("dwvsh: {}: command not found", verse.verb());
- if verse.meter != Rune::And {
- continue;
+ if verse.meter != Rune::And {
+ continue;
+ }
}
}
- }
- // Incant the verse, based on its meter
- let status = if stdout {
- match verse.io {
- Rune::Read => Rune::incant_read(&mut verse, &mut out, &mut pids)?,
- Rune::Write => Rune::incant_write(&mut verse, &mut out, &mut pids)?,
- Rune::Addendum => Rune::incant_addendum(&mut verse, &mut out, &mut pids)?,
- _ => match verse.meter {
- Rune::None => Rune::incant_none(&verse, &mut out)?,
- Rune::Couplet => Rune::incant_couplet(&verse, &mut out)?,
- Rune::Quiet => Rune::incant_quiet(&verse, &mut out, &mut pids)?,
- Rune::And => Rune::incant_and(&verse, &mut out)?,
- Rune::Continue => Rune::incant_continue(&verse, &mut out)?,
- _ => unreachable!(),
- },
- }
- } else {
- match verse.io {
- Rune::Read => Rune::incant_read(&mut verse, &mut out, &mut pids)?,
- Rune::Write => Rune::incant_write(&mut verse, &mut out, &mut pids)?,
- Rune::Addendum => Rune::incant_addendum(&mut verse, &mut out, &mut pids)?,
- _ => Rune::incant_couplet(&verse, &mut out)?,
+ if stdout {
+ match verse.io {
+ Rune::Read => Rune::incant_read(&mut verse, &mut out, &mut pids)?,
+ Rune::Write => Rune::incant_write(&mut verse, &mut out, &mut pids)?,
+ Rune::Addendum => Rune::incant_addendum(&mut verse, &mut out, &mut pids)?,
+ _ => match verse.meter {
+ Rune::None => Rune::incant_none(&verse, &mut out)?,
+ Rune::Couplet => Rune::incant_couplet(&verse, &mut out)?,
+ Rune::Quiet => Rune::incant_quiet(&verse, &mut out, &mut pids)?,
+ Rune::And => Rune::incant_and(&verse, &mut out)?,
+ Rune::Continue => Rune::incant_continue(&verse, &mut out)?,
+ _ => unreachable!(),
+ },
+ }
+ } else {
+ match verse.io {
+ Rune::Read => Rune::incant_read(&mut verse, &mut out, &mut pids)?,
+ Rune::Write => Rune::incant_write(&mut verse, &mut out, &mut pids)?,
+ Rune::Addendum => Rune::incant_addendum(&mut verse, &mut out, &mut pids)?,
+ _ => Rune::incant_couplet(&verse, &mut out)?,
+ }
}
};