diff options
author | Irene Knapp <ireneista@gmail.com> | 2020-12-28 16:29:24 -0800 |
---|---|---|
committer | Irene Knapp <ireneista@gmail.com> | 2020-12-28 16:29:24 -0800 |
commit | db31e770be89cc3e693ffef470878267efeff406 (patch) | |
tree | f09c7dab9d2b9db0a09650d071b6577e001e5b98 /src/main.rs | |
parent | bcd2e282af2b6cd7991d8d1c5ebef4e4e4a1c745 (diff) |
the which builtin now sorta works. yay!
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/src/main.rs b/src/main.rs index 60c14ca..3b7d26d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,9 @@ use crate::prelude::*; +use std::collections::HashMap; +use std::collections::HashSet; use std::io; use std::io::prelude::*; +use std::os::unix::fs::PermissionsExt; #[macro_use] extern crate lalrpop_util; @@ -71,10 +74,29 @@ fn execute(input: &str) -> Result<()> { println!("{}", input); match invocation.as_slice() { - ["paths", path_list, ..] => { - let paths = path::parse_path_list(path_list)?; - for path in &paths { - println!("{}", path); + ["environment", ..] => { + let environment = read_environment()?; + println!("{:?}", environment); + } + ["which", command_name, ..] => { + let file_name: path::FileName = command_name.parse()?; + let search_paths = get_search_paths()?; + let mut executable_path: Option<path::AbsoluteFilePath> = None; + for search_path in &search_paths { + let candidate_path = search_path.concat_file_name(&file_name); + match candidate_path.to_sys_path().metadata() { + Ok(metadata) => { + if metadata.is_file() + && metadata.permissions().mode() & 0o111 != 0 + { + println!("{} {:?}", candidate_path, metadata); + executable_path = Some(candidate_path); + break; + } + }, + Err(_) => { }, + } + } }, _ => { @@ -84,3 +106,35 @@ fn execute(input: &str) -> Result<()> { Ok(()) } + + +fn read_environment() -> Result<HashMap<String,String>> { + Ok(std::env::vars().collect()) +} + + +fn get_environment(variable_name: &str) -> Result<Option<String>> { + Ok(std::env::vars() + .find(|(key, _)| key == variable_name) + .map(|(_, value)| value)) +} + + +fn get_search_paths() -> Result<Vec<path::AbsoluteDirectoryPath>> { + let paths = get_environment("PATH")?.unwrap_or_default(); + let paths = path::parse_path_list(&paths)?; + + let mut result = Vec::new(); + let mut seen = HashSet::new(); + for path in paths { + if seen.contains(&path) { + continue; + } + + seen.insert(path.clone()); + result.push(path); + } + + Ok(result) +} + |