diff --git a/CHANGELOG.md b/CHANGELOG.md index 804b2b1..653fa72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to components of this project since 0.5.14 will be documente The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Compile-time and runtime environment variable `_PR_LIB` specifying `lib` directories for storing modules, separated by `:` + - When not provided, it will search in `PATH` + ## [0.6.2] - 2024-12-10 ### Added diff --git a/core/src/shell.rs b/core/src/shell.rs index 9336ae8..6932fb5 100644 --- a/core/src/shell.rs +++ b/core/src/shell.rs @@ -54,35 +54,95 @@ impl Data { let command = last_command(&shell).trim().to_string(); let alias = alias_map(&shell); let mode = run_mode(); - let (executables, modules, fallbacks) = { - let path_executables = get_path_files(); - let mut executables = vec![]; - let mut modules = vec![]; - let mut fallbacks = vec![]; - for exe in path_executables { - if exe.starts_with("_pay-respects-module-") { - modules.push(exe.to_string()); - } else if exe.starts_with("_pay-respects-fallback-") { - fallbacks.push(exe.to_string()); - } else { - executables.push(exe.to_string()); - } + let (executables, modules, fallbacks); + let lib_dir = { + if let Ok(lib_dir) = std::env::var("_PR_LIB") { + Some(lib_dir) + } else { + option_env!("_PR_LIB").map(|dir| dir.to_string()) } - modules.sort_unstable(); - fallbacks.sort_unstable(); - if alias.is_some() { - let alias = alias.as_ref().unwrap(); - for command in alias.keys() { - if executables.contains(command) { - continue; - } - executables.push(command.to_string()); - } - } - - (executables, modules, fallbacks) }; + #[cfg(debug_assertions)] + eprintln!("lib_dir: {:?}", lib_dir); + + if lib_dir.is_none() { + (executables, modules, fallbacks) = { + let path_executables = get_path_files(); + let mut executables = vec![]; + let mut modules = vec![]; + let mut fallbacks = vec![]; + for exe in path_executables { + if exe.starts_with("_pay-respects-module-") { + modules.push(exe.to_string()); + } else if exe.starts_with("_pay-respects-fallback-") { + fallbacks.push(exe.to_string()); + } else { + executables.push(exe.to_string()); + } + } + modules.sort_unstable(); + fallbacks.sort_unstable(); + if alias.is_some() { + let alias = alias.as_ref().unwrap(); + for command in alias.keys() { + if executables.contains(command) { + continue; + } + executables.push(command.to_string()); + } + } + + (executables, modules, fallbacks) + }; + } else { + (executables, modules, fallbacks) = { + let mut modules = vec![]; + let mut fallbacks = vec![]; + let lib_dir = lib_dir.unwrap(); + let mut executables = get_path_files(); + if alias.is_some() { + let alias = alias.as_ref().unwrap(); + for command in alias.keys() { + if executables.contains(command) { + continue; + } + executables.push(command.to_string()); + } + } + + let path = lib_dir.split(':').collect::>(); + for p in path { + let files = match std::fs::read_dir(p) { + Ok(files) => files, + Err(_) => continue, + }; + for file in files { + let file = file.unwrap(); + let file_name = file.file_name().into_string().unwrap(); + let file_path = file.path(); + + if file_name.starts_with("_pay-respects-module-") { + modules.push(file_path.to_string_lossy().to_string()); + } else if file_name.starts_with("_pay-respects-fallback-") { + fallbacks.push(file_path.to_string_lossy().to_string()); + } + } + } + + modules.sort_unstable(); + fallbacks.sort_unstable(); + + (executables, modules, fallbacks) + }; + } + + #[cfg(debug_assertions)] + { + eprintln!("modules: {:?}", modules); + eprintln!("fallbacks: {:?}", fallbacks); + } + let mut init = Data { shell, command, diff --git a/core/src/suggestions.rs b/core/src/suggestions.rs index 272bd48..141dba0 100644 --- a/core/src/suggestions.rs +++ b/core/src/suggestions.rs @@ -10,7 +10,10 @@ use crate::shell::{add_candidates_no_dup, module_output, shell_evaluated_command use crate::style::highlight_difference; pub fn suggest_candidates(data: &mut Data) { - let executable = &data.split[0].rsplit(std::path::MAIN_SEPARATOR).next().unwrap(); + let executable = &data.split[0] + .rsplit(std::path::MAIN_SEPARATOR) + .next() + .unwrap(); let command = &data.command; let privilege = &data.privilege; let mut suggest_candidates = vec![]; diff --git a/modules.md b/modules.md index 5c3f2af..b70bc79 100644 --- a/modules.md +++ b/modules.md @@ -42,3 +42,14 @@ Your module should print: Expose your module as executable (`chmod u+x`) in `PATH`, and done! +## `LIB` directories + +If exposing modules in `PATH` annoys you, you can set the `_PR_LIB` environment variable to specify directories to find the modules, separated by `:` (analogous to `PATH`). The variable can be set either runtime or compile-time. + +Example would be: +```shell +export _PR_LIB_DIR="/usr/lib:$HOME/.local/bin" +``` +This is not the default as there is no general standard about where the `lib` directories are located and depends on distribution (`/usr/lib`, `/usr/libexec`, `/data/data/com.termux/files/usr/libexec`, etc.). Programs usually have a hard-coded path looking for `lib`. If you are a package maintainer for a distribution, setting this value when compiling, so it fits into your distribution standard. + +If you installed the module with `cargo install`, the binary will be placed in `~/.cargo/bin` which should be in the `PATH` anyway.