From 14a74aea0f02da53e0f61c572da2c5244ed80551 Mon Sep 17 00:00:00 2001 From: Rory Dudley Date: Thu, 28 Mar 2024 21:05:00 -0600 Subject: 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. --- src/poem/anthology.rs | 32 ++++++++++++ src/poem/anthology/cd.rs | 20 ++++++++ src/poem/anthology/exit.rs | 5 ++ src/poem/anthology/export.rs | 23 +++++++++ src/poem/anthology/source.rs | 46 +++++++++++++++++ src/poem/recite.rs | 120 +++++++++++++++++++++++-------------------- 6 files changed, 189 insertions(+), 57 deletions(-) create mode 100644 src/poem/anthology.rs create mode 100644 src/poem/anthology/cd.rs create mode 100644 src/poem/anthology/exit.rs create mode 100644 src/poem/anthology/export.rs create mode 100644 src/poem/anthology/source.rs (limited to 'src/poem') 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 { + 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) -> 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) -> 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)?, + } } }; -- cgit v1.2.3