summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRory Dudley2024-06-14 20:29:32 -0400
committerRory Dudley2024-06-14 20:29:32 -0400
commitfedd4c31b0d1c6d036b1105a74b6e6a1f135f2b4 (patch)
tree3dc44055f9a452c8bbeb7e6ab1e45b65ebbb7417
parentc4cd1e2c165c4f34ebf67fa9350f8732b2aeca13 (diff)
downloaddwarvish-fedd4c31b0d1c6d036b1105a74b6e6a1f135f2b4.tar.gz
Add back spellcheck
This commit reworks spellcheck() so it is more verbose about what it returns. It also re-introduces the use of spellcheck() in Poem::recite(). Spellcheck now returns a value in the enum, Spelling: FullPath -> Indicates a full path was specified as the verb OnPath -> Indicates the verb is on the $PATH BuiltIn -> Indicates the verb is a built-in command None (Option) -> The verb does not exist This commit also removes some defunct (commented-out) code.
-rw-r--r--src/poem/anthology.rs41
-rw-r--r--src/poem/anthology/which.rs29
-rw-r--r--src/poem/elements/verse.rs31
-rw-r--r--src/poem/recite.rs51
4 files changed, 64 insertions, 88 deletions
diff --git a/src/poem/anthology.rs b/src/poem/anthology.rs
index a35eafb..086864c 100644
--- a/src/poem/anthology.rs
+++ b/src/poem/anthology.rs
@@ -29,38 +29,6 @@ pub fn lookup(verb: &str) -> Option<usize> {
INDEX.iter().position(|v| v.to_string() == verb)
}
-/// Run a builtin command, based on its verb
-///
-/// Use [lookup] to check if a verb is in the anthology's index (i.e. is a
-/// builtin), then call this with the current verse, the index found by
-/// [lookup], and the shell's global environment state.
-///
-/// # Example
-/// ```
-/// let index = anthology::lookup(verse.verb());
-/// if index.is_some() {
-/// anthology::incant(&verse, index.unwrap(), env);
-/// } else {
-/// // Run an external command
-/// ...
-/// }
-/// ```
-// pub fn incant(verse: &Verse, out: &mut Vec<u8>, index: usize, env: &mut Environment) -> i32 {
-// // let verb = INDEX[index];
-// // match verb {
-// // "alias" => alias::incant(verse, out, &mut env.aliases),
-// // "cd" => cd::incant(verse),
-// // "exit" => exit::incant(),
-// // "export" => export::incant(verse),
-// // "source" => source::incant(verse, out, env),
-// // "unalias" => alias::unincant(verse, &mut env.aliases),
-// // "unset" => export::unincant(verse),
-// // "which" => which::incant(verse, out, env),
-// // _ => unreachable!(),
-// // }
-// 0
-// }
-
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct AnthologyStdin {
data: Vec<u8>,
@@ -101,9 +69,9 @@ impl Anthology {
/// ```
/// let mut command = Anthology::new("alias");
/// ```
- pub fn new(verb: String) -> Self {
+ pub fn new(i: usize) -> Self {
Anthology {
- verb,
+ verb: INDEX[i].to_string(),
clause: None,
uin: false,
uout: false,
@@ -148,11 +116,8 @@ impl Anthology {
}
pub fn spawn(&mut self, env: &mut Environment) -> Result<Self, io::Error> {
- let index = lookup(self.verb.as_str()).unwrap();
- let verb = INDEX[index];
-
// Incant the built-in and set the output
- self.output = Some(match verb {
+ self.output = Some(match self.verb.as_str() {
"alias" => alias::incant(&self.clause, self.uout, &mut env.aliases),
"cd" => cd::incant(&self.clause, self.uerr),
"exit" => exit::incant(),
diff --git a/src/poem/anthology/which.rs b/src/poem/anthology/which.rs
index 6fe709c..0872dda 100644
--- a/src/poem/anthology/which.rs
+++ b/src/poem/anthology/which.rs
@@ -1,4 +1,5 @@
use crate::compose::Environment;
+use crate::poem::elements::verse::Spelling;
use crate::poem::Verse;
use std::os::unix::process::ExitStatusExt;
use std::process::{ExitStatus, Output};
@@ -22,26 +23,28 @@ pub fn incant(clause: &Option<Vec<String>>, uout: bool, uerr: bool, env: &Enviro
continue;
}
- // Check if it's a built-in
- match super::lookup(&word) {
- Some(_) => {
+ // Manually check the path
+ let mut verb = Verse::new();
+ verb.push(word.clone());
+ match verb.spellcheck(&env.bins) {
+ Some(Spelling::OnPath(i)) => {
+ output = format!("{}\n", env.bins[i]);
+ if uout {
+ out.append(&mut output.as_bytes().to_vec());
+ } else {
+ print!("{}", output);
+ }
+ }
+ Some(Spelling::BuiltIn(_)) => {
output = format!("{}: shell built-in command\n", word);
if uout {
out.append(&mut output.as_bytes().to_vec());
} else {
print!("{}", output);
}
- continue;
}
- None => {}
- }
-
- // Manually check the path
- let mut verb = Verse::new();
- verb.push(word.clone());
- match verb.spellcheck(&env.bins) {
- Some(i) => {
- output = format!("{}\n", env.bins[i]);
+ Some(Spelling::FullPath) => {
+ output = format!("{}\n", word);
if uout {
out.append(&mut output.as_bytes().to_vec());
} else {
diff --git a/src/poem/elements/verse.rs b/src/poem/elements/verse.rs
index 42d7c6a..b4f41ba 100644
--- a/src/poem/elements/verse.rs
+++ b/src/poem/elements/verse.rs
@@ -1,6 +1,7 @@
use super::rune::Rune;
use super::stanza::Stanza;
use super::word::Word;
+use crate::poem::anthology;
use crate::poem::anthology::Anthology;
use crate::poem::Poem;
mod logic;
@@ -32,6 +33,13 @@ pub struct Verse {
pub meter: Rune,
}
+#[derive(Debug, Clone)]
+pub enum Spelling {
+ FullPath,
+ OnPath(usize),
+ BuiltIn(usize),
+}
+
pub trait Forkable<T> {
fn fork(&mut self, env: &mut Environment) -> Result<T, io::Error>;
}
@@ -216,7 +224,7 @@ impl Verse {
/// stanza_success.spellcheck(bins) // -> Some(i)
/// stanza_fail.spellcheck(bins) // -> None
/// ```
- pub fn spellcheck(&self, bins: &Vec<String>) -> Option<usize> {
+ pub fn spellcheck(&self, bins: &Vec<String>) -> Option<Spelling> {
// An empty verb (i.e. the empty string) cannot be a program, so
// return false
// Thanks to the parsing in Poem::read, however, it's
@@ -225,6 +233,13 @@ impl Verse {
return None;
}
+ // Check for built-ins
+ let i = anthology::lookup(self.verb().as_str());
+ match i {
+ Some(i) => return Some(Spelling::BuiltIn(i)),
+ None => {}
+ };
+
// Only search the $PATH if a full or relative path was not given, or
// if the path given does not exist
if !Path::new(self.verb().as_str()).exists() {
@@ -232,7 +247,7 @@ impl Verse {
// Searches in $PATH order
for (i, path) in bins.iter().enumerate() {
if path.split('/').last().unwrap() == self.verb() {
- return Some(i);
+ return Some(Spelling::OnPath(i));
}
}
@@ -241,7 +256,7 @@ impl Verse {
}
// Return the length of bins if the full path or relative path exists
- Some(bins.len())
+ Some(Spelling::FullPath)
}
/// Run a command
@@ -256,7 +271,7 @@ impl Verse {
out: &mut Vec<u8>,
pids: &mut Arc<Mutex<Vec<i32>>>,
env: &mut Environment,
- anthology: Option<usize>,
+ spell: Option<Spelling>,
) -> Result<i32, io::Error> {
// Read files into 'out' if Rune::Read is present in the verse's IO
if self.io.contains(&Rune::Read) {
@@ -274,12 +289,12 @@ impl Verse {
}
// Build and run the command
- match anthology {
- Some(_) => {
- let mut command = Anthology::new(self.verb());
+ match spell {
+ Some(Spelling::BuiltIn(i)) => {
+ let mut command = Anthology::new(i);
incant!(self.verb(), command, out, pids, env, self)
}
- None => {
+ _ => {
let mut command = Command::new(self.verb());
incant!(self.verb(), command, out, pids, env, self)
}
diff --git a/src/poem/recite.rs b/src/poem/recite.rs
index b33cc87..b27ef75 100644
--- a/src/poem/recite.rs
+++ b/src/poem/recite.rs
@@ -1,5 +1,6 @@
use super::Poem;
use crate::compose::Environment;
+use crate::path;
use crate::poem::anthology;
use crate::poem::elements::rune::Rune;
use crate::poem::elements::stanza::Stanza;
@@ -141,36 +142,28 @@ impl Reciteable for Poem {
None => {}
};
+ // Check if the verse's verb exists
+ let mut spell = None;
+ if !verse.verb().is_empty() {
+ // Check if the verb exists on the PATH
+ // If it doesn't exist, try refreshing the binary cache, and check again
+ // If it still doesn't exist, print an error
+ spell = verse.spellcheck(&env.bins);
+ if !spell.is_some() {
+ env.bins = path::refresh();
+ spell = verse.spellcheck(&env.bins);
+ if !spell.is_some() {
+ eprintln!("dwvsh: {}: command not found", verse.verb());
+
+ if verse.meter != Rune::And {
+ continue;
+ }
+ }
+ }
+ }
+
// Incant the verse if it's a built-in
- let status =
- verse.incant(&mut out, &mut pids, env, anthology::lookup(&verse.verb()))?;
- // let status = if index.is_some() {
- // 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
- // // more
- // // If it is empty, just continue to the next verse
- // if !verse.verb().is_empty() {
- // // Check if the verb exists on the PATH
- // // 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).is_some() {
- // env.bins = path::refresh();
- // if !verse.spellcheck(&env.bins).is_some() {
- // eprintln!("dwvsh: {}: command not found", verse.verb());
- //
- // if verse.meter != Rune::And {
- // continue;
- // }
- // }
- // }
- // } else {
- // continue;
- // }
- // verse.incant(&mut out, &mut pids, anthology::lookup(&verse.verb()))?
- // };
+ let status = verse.incant(&mut out, &mut pids, env, spell)?;
// Break from the loop if the meter is not [Rune::Continue], and
// if the status is not 0