summaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
authorRory Dudley2024-02-19 00:57:51 -0700
committerRory Dudley2024-02-19 00:57:51 -0700
commitb1a7db048e517ff262dc1dad0f0ea766af4bd021 (patch)
treebc7ebd313be07d9f5454fa4381f177984699cbe6 /src/main.rs
parent6cf0f1b12e880f3cd88f013a070406bfb303831a (diff)
downloaddwarvish-inotify.tar.gz
Support for inotifyinotify
This is a branch with some cursory support for using inotify to watch for changes in the user's $PATH.
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs105
1 files changed, 82 insertions, 23 deletions
diff --git a/src/main.rs b/src/main.rs
index 7fc8991..c11b939 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,20 +1,71 @@
use ctrlc;
+use notify::RecursiveMode;
+use notify::Watcher;
+use signals2::*;
use std::fs;
use std::io;
use std::io::Write;
use std::path::Path;
use std::process::Command;
-
-fn eval(paths: &[&str], prompt: &str) {
- let mut bins: Vec<String> = Vec::new();
-
- for path in paths {
- let files = fs::read_dir(path).expect("Unable to read files in your path");
+use std::sync::Arc;
+use std::sync::RwLock;
+
+fn prefresh(paths: &Vec<String>, bins: &mut Arc<RwLock<Vec<Vec<String>>>>, index: Option<i32>) {
+ let mut bins = bins.write().unwrap();
+ let index = index.unwrap_or(-1);
+
+ if index == -1 {
+ for (i, path) in paths.iter().enumerate() {
+ let files = fs::read_dir(path).expect("Unable to read files in your path");
+ bins.push(Vec::new());
+ for file in files {
+ bins[i].push(file.unwrap().path().display().to_string());
+ }
+ }
+ } else {
+ let index = index as usize;
+ let files = fs::read_dir(paths[index].as_str()).expect("Unable to read files in your path");
+ bins[index].clear();
for file in files {
- bins.push(file.unwrap().path().display().to_string());
+ bins[index].push(file.unwrap().path().display().to_string());
}
}
+}
+
+fn eval(paths: Vec<String>, prompt: &str) {
+ // Setup search for our paths
+ let mut bins = Arc::new(RwLock::new(Vec::new()));
+ prefresh(&paths, &mut bins, None);
+
+ // Handle file changes on paths
+ let sig: Signal<(i32,)> = Signal::new();
+ let arcbins = Arc::clone(&bins);
+ let p = paths.clone();
+ sig.connect(move |i| {
+ let mut arcbins = arcbins.clone();
+ prefresh(&paths, &mut arcbins, Some(i));
+ });
+
+ let mut watcher =
+ notify::recommended_watcher(move |res: Result<notify::event::Event, notify::Error>| {
+ match res {
+ Ok(event) => {
+ if event.kind.is_create() || event.kind.is_remove() {
+ sig.emit(0);
+ }
+ }
+ Err(_) => {}
+ }
+ })
+ .unwrap();
+
+ for path in p {
+ watcher
+ .watch(Path::new(path.as_str()), RecursiveMode::Recursive)
+ .unwrap();
+ }
+ // Main REPL
loop {
// Output the prompt
io::stdout().flush().unwrap();
@@ -43,7 +94,7 @@ fn eval(paths: &[&str], prompt: &str) {
// Parse command and arguments
let mut split = input.split(' ');
- let mut cmd = match split.next() {
+ let cmd = match split.next() {
Some(str) if str.trim().is_empty() => continue,
Some(str) => str.trim(),
None => continue,
@@ -77,13 +128,21 @@ fn eval(paths: &[&str], prompt: &str) {
// Check if the file exists, if given a pull or relative path
// TODO: Check if file at the path is executable (i.e. +x)
- if !Path::new(cmd).exists() {
- // Check if the command exists in $PATH if a full or relative path
- // was not given, or if the path does not exist
- cmd = match bins.iter().find(|b| b.split("/").last().unwrap() == cmd) {
- Some(cmd) => cmd,
+ let mut cmd = String::from(cmd);
+ if !Path::new(cmd.as_str()).exists() {
+ cmd = match bins
+ .read()
+ .unwrap()
+ .iter()
+ .flatten()
+ .map(|s| String::from(s))
+ .collect::<Vec<String>>()
+ .iter()
+ .find(|b| b.split("/").last().unwrap() == cmd)
+ {
+ Some(cmd) => String::from(cmd),
None => {
- println!("Command not found");
+ println!("dwvsh: error: command not found...");
continue;
}
};
@@ -104,19 +163,19 @@ fn eval(paths: &[&str], prompt: &str) {
fn main() {
// Define paths
// TODO: Hardcoded path should only be the fallback
- let paths = [
- "/bin",
- "/sbin",
- "/usr/bin",
- "/usr/sbin",
- "/usr/local/bin",
- "/usr/local/sbin",
+ let paths = vec![
+ "/bin".to_string(),
+ "/sbin".to_string(),
+ "/usr/bin".to_string(),
+ "/usr/sbin".to_string(),
+ "/usr/local/bin".to_string(),
+ "/usr/local/sbin".to_string(),
];
// Set the prompt
let prompt = "|> ";
- // Handle signals
+ // Handle SIGINT
ctrlc::set_handler(move || {
print!("\n{}", prompt);
io::stdout().flush().unwrap();
@@ -124,5 +183,5 @@ fn main() {
.expect("Unable to set <C-c> handler");
// Begin evaluating commands
- eval(&paths, prompt);
+ eval(paths, prompt);
}