diff --git a/Cargo.lock b/Cargo.lock index ee8d96b..b50755f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,6 +24,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" + [[package]] name = "cc" version = "1.2.26" @@ -39,18 +45,70 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "lock_api" version = "0.4.13" @@ -61,6 +119,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + [[package]] name = "memchr" version = "2.7.4" @@ -102,6 +166,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "parking_lot" version = "0.12.4" @@ -158,12 +234,25 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "rush" version = "0.1.0" dependencies = [ "mlua", + "shellexpand", "shlex", + "whoami", ] [[package]] @@ -204,6 +293,15 @@ dependencies = [ "syn", ] +[[package]] +name = "shellexpand" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" +dependencies = [ + "dirs", +] + [[package]] name = "shlex" version = "1.3.0" @@ -227,12 +325,131 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "whoami" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" +dependencies = [ + "redox_syscall", + "wasite", + "web-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 741c43c..59630fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,5 @@ edition = "2024" [dependencies] shlex = "1.3.0" mlua = { version = "0.10.5", features = ["lua54"] } +shellexpand = "3.1.1" +whoami = "1.6.0" diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..745d2dc --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +chain_width = 40 diff --git a/src/core.rs b/src/core.rs index 129594e..3fb9b94 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,9 +1,11 @@ use std::io::{self, Write}; use std::process::Command; -pub fn display_prompt() { - print!("> "); - io::stdout().flush().expect("unable to flush buffer"); +pub fn display_prompt(ps1: &str) { + print!("{}", ps1); + io::stdout() + .flush() + .expect("unable to flush buffer"); } pub fn get_input() -> String { diff --git a/src/inbuilt.rs b/src/inbuilt.rs index 5f9ad79..1aad682 100644 --- a/src/inbuilt.rs +++ b/src/inbuilt.rs @@ -17,6 +17,7 @@ pub fn help() { println!(); println!("Customization Options:"); println!(" shellAliases - Define custom aliases for commands"); + println!(" prompt - Define custom prompt"); println!(); println!("Note: This is a basic implementation. More features and options will be added in future versions."); diff --git a/src/main.rs b/src/main.rs index 6b139e0..68c0957 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,12 @@ mod core; -use crate::core::*; +use core::*; mod inbuilt; -use crate::inbuilt::*; +use inbuilt::*; use mlua::prelude::*; +use std::env; +use whoami::{username, devicename}; // Helper function for resolving aliases. fn resolve_alias(config: &mlua::Table, cmd: &str) -> Option { @@ -14,6 +16,45 @@ fn resolve_alias(config: &mlua::Table, cmd: &str) -> Option { .and_then(|aliases| aliases.get(cmd).ok()) } +// Return prompt from configuration file with expansion performed. +// Otherwise return default prompt. +fn resolve_prompt(config: &mlua::Table) -> String { + let default_prompt = "[${user}@${host}:${cwd}]$".to_string(); + + let prompt = config + .get::("prompt") + .unwrap_or(default_prompt) + + " "; + + shellexpand::env_with_context_no_errors(&prompt, context).to_string() +} + +// Format current working directory. +fn fmt_cwd() -> String { + let home = env::var("HOME").unwrap_or_default(); + let cwd = env::current_dir() + .ok() + .and_then(|p| p.to_str().map(String::from)) + .unwrap_or_default(); + + // Replace $HOME with ~. + if cwd.starts_with(&home) { + cwd.replacen(&home, "~", 1) + } else { + cwd + } +} + +// Context for shell expansion. +fn context(s: &str) -> Option { + match s { + "user" => Some(username()), + "host" => Some(devicename()), + "cwd" => Some(fmt_cwd()), + _ => None, + } +} + fn main() { // Create a new Lua state and load the safe subset of the standard libraries. let lua = Lua::new(); @@ -31,8 +72,10 @@ fn main() { // Read, Evaluate, Print and Loop. loop { + // Update prompt string. + let prompt = resolve_prompt(&config); // Display the prompt for the user. - display_prompt(); + display_prompt(&prompt); // Get the users input. let input = get_input(); @@ -57,7 +100,7 @@ fn main() { args.extend(get_args(&alias_tokens)); } - // Execute inbuilt command if match found, otherwise execute external command with + // Execute inbuilt command if match found, otherwise execute external command with // arguments. match cmd.as_str() { "cd" => cd(&args),