aboutsummaryrefslogtreecommitdiff
path: root/crates/whirl_prompt/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2021-05-20 17:05:59 -0700
committerFuwn <[email protected]>2021-05-20 17:05:59 -0700
commit9e2121baf98b6fdc15cde6c387a7845a0b3f95d6 (patch)
tree15460f59799a9f655ac5b213e4b8a8903d1e57e4 /crates/whirl_prompt/src
parentfeat(readme): add sqlfluff as a dev dep (diff)
downloadwhirl-9e2121baf98b6fdc15cde6c387a7845a0b3f95d6.tar.xz
whirl-9e2121baf98b6fdc15cde6c387a7845a0b3f95d6.zip
refactor(global): move crates around, stricter module isolation
Diffstat (limited to 'crates/whirl_prompt/src')
-rw-r--r--crates/whirl_prompt/src/builtins/mod.rs108
-rw-r--r--crates/whirl_prompt/src/builtins/structures.rs34
-rw-r--r--crates/whirl_prompt/src/constants.rs19
-rw-r--r--crates/whirl_prompt/src/lib.rs150
-rw-r--r--crates/whirl_prompt/src/structure.rs10
5 files changed, 321 insertions, 0 deletions
diff --git a/crates/whirl_prompt/src/builtins/mod.rs b/crates/whirl_prompt/src/builtins/mod.rs
new file mode 100644
index 0000000..0359443
--- /dev/null
+++ b/crates/whirl_prompt/src/builtins/mod.rs
@@ -0,0 +1,108 @@
+// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective
+// SPDX-License-Identifier: GPL-3.0-only
+
+pub mod structures;
+
+use std::io::Write;
+
+use sysinfo::SystemExt;
+use whirl_config::Config;
+
+use crate::constants::{FILES, HELPABLES_BUILTINS, HELPABLES_BUILTIN_CONFIG};
+
+pub fn builtin_echo(args: &[String]) -> i32 {
+ println!("{}", args.join(" "));
+ 0
+}
+
+pub fn builtin_history(history: &[String]) -> i32 {
+ for (index, cmd) in history.iter().enumerate() {
+ println!("{} {}", index, cmd.trim());
+ }
+ 0
+}
+
+pub fn builtin_help() -> i32 {
+ for help in HELPABLES_BUILTINS.iter() {
+ println!("{}", help);
+ }
+
+ 0
+}
+
+pub fn builtin_ls() -> i32 {
+ for file in &FILES {
+ print!("{} ", file);
+ }
+ println!();
+
+ 0
+}
+
+pub async fn builtin_cat(args: &[String]) -> i32 {
+ let file;
+ if let Some(file_name) = args.get(0) {
+ file = file_name.to_string();
+ } else {
+ return 0;
+ };
+
+ match file.as_str() {
+ "README.rst" => {
+ let mut easy = curl::easy::Easy::new();
+
+ easy
+ .url("https://raw.githubusercontent.com/Whirlsplash/whirl/develop/README.rst")
+ .unwrap();
+
+ let mut transfer = easy.transfer();
+ transfer
+ .write_function(|data| {
+ std::io::stdout().write_all(data).unwrap();
+ Ok(data.len())
+ })
+ .unwrap();
+ transfer.perform().unwrap();
+ }
+ "Whirl.toml" => {
+ colour::red_ln!("NOTE: This is just a wrapper for `config show`.");
+ println!("{:#?}", Config::get());
+ }
+ _ => println!("/cat: {}: no such file or directory", file),
+ }
+
+ 0
+}
+
+pub fn builtin_config(args: &[String]) -> i32 {
+ match args.get(0) {
+ Some(sub) =>
+ match sub.as_str() {
+ "show" => println!("{:#?}", Config::get()),
+ "help" | "--help" | "-h" =>
+ for help in HELPABLES_BUILTIN_CONFIG.iter() {
+ println!("{}", help);
+ },
+ "refresh" => Config::refresh(),
+ _ => println!("invalid arguments provided"),
+ },
+ None => println!("invalid amount arguments provided"),
+ }
+ 0
+}
+
+pub fn builtin_fetch() -> i32 {
+ // rfetch: https://github.com/Mangeshrex/rfetch
+
+ let mut sys = sysinfo::System::new();
+ sys.refresh_processes();
+
+ println!(" ");
+ println!(" .-. os {}", env!("CARGO_PKG_NAME"));
+ println!(" oo| ker {}", env!("CARGO_PKG_VERSION"));
+ println!(" / '\\ sh /wsh");
+ println!(" (\\_;/) up null");
+ println!(" ");
+
+ 0
+}
diff --git a/crates/whirl_prompt/src/builtins/structures.rs b/crates/whirl_prompt/src/builtins/structures.rs
new file mode 100644
index 0000000..4217a38
--- /dev/null
+++ b/crates/whirl_prompt/src/builtins/structures.rs
@@ -0,0 +1,34 @@
+// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective
+// SPDX-License-Identifier: GPL-3.0-only
+
+use std::str::FromStr;
+
+pub enum BuiltIn {
+ Echo,
+ History,
+ Exit,
+ Null,
+ Help,
+ Ls,
+ Cat,
+ Config,
+ Fetch,
+}
+impl FromStr for BuiltIn {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "echo" => Ok(BuiltIn::Echo),
+ "history" => Ok(BuiltIn::History),
+ "exit" => Ok(BuiltIn::Exit),
+ "null" => Ok(BuiltIn::Null),
+ "help" => Ok(BuiltIn::Help),
+ "ls" => Ok(BuiltIn::Ls),
+ "cat" => Ok(BuiltIn::Cat),
+ "config" => Ok(BuiltIn::Config),
+ "fetch" => Ok(BuiltIn::Fetch),
+ _ => Err(()),
+ }
+ }
+}
diff --git a/crates/whirl_prompt/src/constants.rs b/crates/whirl_prompt/src/constants.rs
new file mode 100644
index 0000000..c173a57
--- /dev/null
+++ b/crates/whirl_prompt/src/constants.rs
@@ -0,0 +1,19 @@
+// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective
+// SPDX-License-Identifier: GPL-3.0-only
+
+pub const FILES: [&str; 2] = ["README.rst", "Whirl.toml"];
+pub const HELPABLES_BUILTINS: [&str; 8] = [
+ "cat - display the contents of a present file",
+ "config - manipulate the configuration",
+ "echo - display a line of predefined text",
+ "exit - end the process",
+ "fetch - a neofetch like utility loosely based on rfetch",
+ "help - you are here",
+ "history - display the command history",
+ "ls - display the present files",
+];
+pub const HELPABLES_BUILTIN_CONFIG: [&str; 3] = [
+ "help - you are here",
+ "refresh - reload the configuration file",
+ "show - display the current configuration",
+];
diff --git a/crates/whirl_prompt/src/lib.rs b/crates/whirl_prompt/src/lib.rs
new file mode 100644
index 0000000..32b247f
--- /dev/null
+++ b/crates/whirl_prompt/src/lib.rs
@@ -0,0 +1,150 @@
+// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective
+// SPDX-License-Identifier: GPL-3.0-only
+
+#![feature(
+ type_ascription,
+ hash_set_entry,
+ type_name_of_val,
+ decl_macro,
+ proc_macro_hygiene
+)]
+#![warn(rust_2018_idioms)]
+#![recursion_limit = "128"]
+
+mod builtins;
+mod constants;
+mod structure;
+
+use std::{io, io::Write, str::FromStr};
+
+use whirl_config::Config;
+
+use crate::{
+ builtins::{
+ builtin_cat,
+ builtin_config,
+ builtin_echo,
+ builtin_fetch,
+ builtin_help,
+ builtin_history,
+ builtin_ls,
+ structures::BuiltIn,
+ },
+ structure::Command,
+};
+
+pub struct Prompt {
+ history: Vec<String>,
+}
+impl Prompt {
+ pub async fn handle() -> ! {
+ let mut prompt = Prompt {
+ history: vec![]
+ };
+
+ loop {
+ Prompt::write_prompt();
+ let command = prompt.read_command();
+ prompt
+ .process_command(Prompt::tokenize_command(command))
+ .await;
+ }
+ }
+
+ fn write_prompt() {
+ print!("{} ", Config::get().whirlsplash.prompt.ps1);
+ io::stdout().flush().unwrap();
+ }
+
+ fn read_command(&mut self) -> String {
+ let mut input = String::new();
+ io::stdin()
+ .read_line(&mut input)
+ .expect("failed to read command from stdin");
+
+ if input.len() <= 2 {
+ input = "null".to_string();
+ }
+
+ input
+ }
+
+ fn tokenize_command(c: String) -> Command {
+ let mut command_split: Vec<String> = c.split_whitespace().map(|s| s.to_string()).collect();
+
+ Command {
+ keyword: command_split.remove(0),
+ args: command_split,
+ }
+ }
+
+ // TODO: Find a way to make this access itself `history` doesn't have to be
+ // passed everytime.
+ async fn process_command(&mut self, c: Command) -> i32 {
+ let exit_code = match BuiltIn::from_str(&c.keyword) {
+ Ok(BuiltIn::Echo) => builtin_echo(&c.args),
+ Ok(BuiltIn::Exit) => std::process::exit(0),
+ Ok(BuiltIn::History) => builtin_history(&self.history),
+ Ok(BuiltIn::Null) => 0,
+ Ok(BuiltIn::Help) => builtin_help(),
+ Ok(BuiltIn::Ls) => builtin_ls(),
+ Ok(BuiltIn::Cat) => builtin_cat(&c.args).await,
+ Ok(BuiltIn::Config) => builtin_config(&c.args),
+ Ok(BuiltIn::Fetch) => builtin_fetch(),
+ _ => {
+ println!("wsh: command not found: {}", &c.keyword);
+ 1
+ }
+ };
+
+ if c.keyword != "null" {
+ self.history.push(c.to_line());
+ }
+
+ exit_code
+ }
+}
+
+#[cfg(test)]
+mod tokenize_command {
+ use crate::Prompt;
+
+ #[test]
+ #[ignore]
+ fn empty_command() { assert_eq!("", Prompt::tokenize_command("".to_string()).keyword) }
+
+ #[test]
+ fn test_keyword() { assert_eq!("test", Prompt::tokenize_command("test".to_string()).keyword) }
+
+ #[test]
+ fn no_arg() { assert_eq!(0, Prompt::tokenize_command("test".to_string()).args.len()) }
+
+ #[test]
+ fn one_arg() {
+ assert_eq!(
+ 1,
+ Prompt::tokenize_command("test one".to_string()).args.len()
+ )
+ }
+
+ #[test]
+ fn multi_arg() {
+ assert_eq!(
+ 3,
+ Prompt::tokenize_command("test one two three".to_string())
+ .args
+ .len()
+ )
+ }
+
+ #[test]
+ #[ignore]
+ fn quotes() {
+ assert_eq!(
+ 2,
+ Prompt::tokenize_command("test \"one two\" three".to_string())
+ .args
+ .len()
+ )
+ }
+}
diff --git a/crates/whirl_prompt/src/structure.rs b/crates/whirl_prompt/src/structure.rs
new file mode 100644
index 0000000..4603d37
--- /dev/null
+++ b/crates/whirl_prompt/src/structure.rs
@@ -0,0 +1,10 @@
+// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective
+// SPDX-License-Identifier: GPL-3.0-only
+
+pub struct Command {
+ pub keyword: String,
+ pub args: Vec<String>,
+}
+impl Command {
+ pub fn to_line(&self) -> String { format!("{} {}", self.keyword, self.args.join(" ")) }
+}