diff --git a/.gitlab-ci.yml b/._gitlab-ci.yml similarity index 100% rename from .gitlab-ci.yml rename to ._gitlab-ci.yml diff --git a/Cargo.lock b/Cargo.lock index 766acb9..dc95538 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -375,6 +375,7 @@ dependencies = [ "once_cell", "regex", "rustyline", + "rustyline-derive", "shlex", "sysinfo", "uname", @@ -505,6 +506,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustyline-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "107c3d5d7f370ac09efa62a78375f94d94b8a33c61d8c278b96683fb4dbf2d8d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "scopeguard" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 1333d8e..1aa8263 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ dirs = "4.0" once_cell = "1.17" regex = "1.7" rustyline = "10.1" +rustyline-derive = "0.7" shlex = "1.1" sysinfo = "0.27" uname = "0.1" diff --git a/src/builtins/fetch.rs b/src/builtins/fetch.rs index 7ba16aa..f07ea29 100644 --- a/src/builtins/fetch.rs +++ b/src/builtins/fetch.rs @@ -35,10 +35,10 @@ impl Builtin for Fetch { println!("{} {}", "UPTIME".red().bold(), format_uptime(sys.uptime())); println!("{} {}", "CPU".magenta().bold(), sys.cpus()[0].brand()); println!( - "{} {}MB / {}MB", + "{} {}MiB / {}MiB", "MEMORY".cyan().bold(), - bytes_to_mega_bytes(sys.used_memory()), - bytes_to_mega_bytes(sys.total_memory()) + bytes_to_mebi_bytes(sys.used_memory()), + bytes_to_mebi_bytes(sys.total_memory()) ); Ok(()) @@ -53,7 +53,7 @@ fn format_uptime(uptime: u64) -> String { format!("{:.0}h {:.0}m {:.0}s", h, m, s) } -fn bytes_to_mega_bytes(bytes: u64) -> u64 { +fn bytes_to_mebi_bytes(bytes: u64) -> u64 { bytes / 1024 / 1024 } @@ -75,4 +75,9 @@ mod tests { fn test_format_uptime_hours() { assert_eq!(format_uptime(3735), "1h 2m 15s"); } + + #[test] + fn test_bytes_to_mebi_bytes() { + assert_eq!(bytes_to_mebi_bytes(7628144640), 7274); + } } diff --git a/src/builtins/help.rs b/src/builtins/help.rs new file mode 100644 index 0000000..4fbe17e --- /dev/null +++ b/src/builtins/help.rs @@ -0,0 +1,25 @@ +use crate::builtins::{Builtin, BuiltinConfig}; +use crate::error::ShellError; + +pub struct Help; + +impl Builtin for Help { + fn execute(&mut self, _: &mut BuiltinConfig, _: Vec) -> Result<(), ShellError> { + let commands = + "cd changes current working directory + change-prompt changes prompt style (default, bashlike, simpledirectory) + exit exits the shell + fetch prints out system information + help displays this command + ls lists contents of directory + open shows content of files + pwd shows path to current working directory + segfault exit but through segfault + sus shows amogus"; + + for line in commands.lines() { + println!("{}", line.trim_start()); + } + Ok(()) + } +} \ No newline at end of file diff --git a/src/builtins/ls.rs b/src/builtins/ls.rs index 6f9e258..09372c2 100644 --- a/src/builtins/ls.rs +++ b/src/builtins/ls.rs @@ -16,12 +16,9 @@ impl Builtin for Ls { //for entry in entries.by_ref().into_iter() {} for entry in entries { - let entry = match entry { - Ok(e) => e, - Err(_) => { - println!("Couldn't get directory entry"); - continue; - } + let Ok(entry) = entry else { + eprintln!("Couldn't get directory entry"); + continue; }; let metadata = match metadata(entry.path()) { Ok(m) => m, diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index b2d257a..22470e4 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -6,9 +6,12 @@ mod cd; mod change_prompt; mod exit; mod fetch; +mod help; mod ls; mod open; mod pwd; +mod segfault; +mod sus; pub struct BuiltinConfig { pub prompt_style: PromptStyle, @@ -31,10 +34,13 @@ const BUILTINS: Lazy)>> = Lazy::new(|| { ("cd", Box::new(cd::Cd)), ("change-prompt", Box::new(change_prompt::ChangePrompt)), ("exit", Box::new(exit::Exit)), - ("pwd", Box::new(pwd::Pwd)), - ("open", Box::new(open::Open)), ("fetch", Box::new(fetch::Fetch)), + ("help", Box::new(help::Help)), ("ls", Box::new(ls::Ls)), + ("open", Box::new(open::Open)), + ("pwd", Box::new(pwd::Pwd)), + ("segfault", Box::new(segfault::Segfault)), + ("sus", Box::new(sus::Sus)), ] }); @@ -76,6 +82,11 @@ mod tests { assert_eq!(is_builtin("pwd"), true); } + #[test] + fn test_is_builtin_help() { + assert_eq!(is_builtin("help"), true); + } + #[test] fn test_is_builtin_ls() { assert_eq!(is_builtin("ls"), true); @@ -91,6 +102,11 @@ mod tests { assert_eq!(is_builtin("change-prompt"), true); } + #[test] + fn test_is_builtin_sus() { + assert_eq!(is_builtin("sus"), true); + } + #[test] fn test_is_builtin_notabuiltin() { assert_eq!(is_builtin("notabuiltin"), false) diff --git a/src/builtins/segfault.rs b/src/builtins/segfault.rs new file mode 100644 index 0000000..396d234 --- /dev/null +++ b/src/builtins/segfault.rs @@ -0,0 +1,11 @@ +use crate::builtins::{Builtin, BuiltinConfig}; +use crate::error::ShellError; + +pub struct Segfault; + +impl Builtin for Segfault { + fn execute(&mut self, _: &mut BuiltinConfig, _: Vec) -> Result<(), ShellError> { + unsafe { std::ptr::null_mut::().write(69) }; + Ok(()) + } +} diff --git a/src/builtins/sus.rs b/src/builtins/sus.rs new file mode 100644 index 0000000..cb01dcb --- /dev/null +++ b/src/builtins/sus.rs @@ -0,0 +1,31 @@ +use crate::builtins::{Builtin, BuiltinConfig}; +use crate::error::ShellError; + +pub struct Sus; + +impl Builtin for Sus { + fn execute(&mut self, _: &mut BuiltinConfig, _: Vec) -> Result<(), ShellError> { + println!( + " + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣤⣤⣤⣤⣶⣦⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡿⠛⠉⠙⠛⠛⠛⠛⠻⢿⣿⣷⣤⡀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⠋⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠈⢻⣿⣿⡄⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⣸⣿⡏⠀⠀⠀⣠⣶⣾⣿⣿⣿⠿⠿⠿⢿⣿⣿⣿⣄⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⣿⣿⠁⠀⠀⢰⣿⣿⣯⠁⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣷⡄⠀ + ⠀⠀⣀⣤⣴⣶⣶⣿⡟⠀⠀⠀⢸⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣷⠀ + ⠀⢰⣿⡟⠋⠉⣹⣿⡇⠀⠀⠀⠘⣿⣿⣿⣿⣷⣦⣤⣤⣤⣶⣶⣶⣶⣿⣿⣿⠀ + ⠀⢸⣿⡇⠀⠀⣿⣿⡇⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀ + ⠀⣸⣿⡇⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠉⠻⠿⣿⣿⣿⣿⡿⠿⠿⠛⢻⣿⡇⠀⠀ + ⠀⣿⣿⠁⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣧⠀⠀ + ⠀⢿⣿⡆⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⡇⠀⠀ + ⠀⠸⣿⣧⡀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠃⠀⠀ + ⠀⠀⠛⢿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⣰⣿⣿⣷⣶⣶⣶⣶⠶⠀⢠⣿⣿⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⣿⣿⡇⠀⣽⣿⡏⠁⠀⠀⢸⣿⡇⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⣿⣿⡇⠀⢹⣿⡆⠀⠀⠀⣸⣿⠇⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⢿⣿⣦⣄⣀⣠⣴⣿⣿⠁⠀⠈⠻⣿⣿⣿⣿⡿⠏⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠈⠛⠻⠿⠿⠿⠿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + " + ); + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index f7ad6e4..e79b195 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,11 @@ use crate::builtins::BuiltinConfig; use crate::prompt::Prompt; use colored::Colorize; use execute::interpret; +use rustyline::completion::FilenameCompleter; use rustyline::config::Configurer; use rustyline::error::ReadlineError; -use rustyline::{Editor, Result}; +use rustyline::{CompletionType, Config, Editor, Result}; +use rustyline_derive::{Completer, Helper, Highlighter, Hinter, Validator}; use whoami::username; mod builtins; @@ -14,13 +16,28 @@ mod parse; mod preprocess; mod prompt; +#[derive(Completer, Helper, Highlighter, Hinter, Validator)] +struct EditorHelper { + #[rustyline(Completer)] + completer: FilenameCompleter, +} + fn main() -> Result<()> { let (ctrlc_send, ctrlc_recv) = crossbeam_channel::unbounded::<()>(); let _ = ctrlc::set_handler(move || { let _ = ctrlc_send.send(()); }); - let mut rl = Editor::<()>::new()?; + let config = Config::builder() + .completion_type(CompletionType::List) + .build(); + + let helper = EditorHelper { + completer: FilenameCompleter::new(), + }; + + let mut rl = Editor::with_config(config)?; + rl.set_helper(Some(helper)); rl.set_auto_add_history(true); let mut prompt = Prompt::new();