summary refs log tree commit diff
path: root/src/main.rs
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@gmail.com>2020-12-28 16:29:24 -0800
committerIrene Knapp <ireneista@gmail.com>2020-12-28 16:29:24 -0800
commitdb31e770be89cc3e693ffef470878267efeff406 (patch)
treef09c7dab9d2b9db0a09650d071b6577e001e5b98 /src/main.rs
parentbcd2e282af2b6cd7991d8d1c5ebef4e4e4a1c745 (diff)
the which builtin now sorta works. yay!
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs62
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)
+}
+