diff --git a/README.md b/README.md index c2fc73d..ed6e852 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ### Termfolio --- - Portfolio website inspired by shells, terminals and CLI utilities. -- Customizable and configurable +- Customizable and configurable through JSON - Work in Progress, needs refactoring and optimization. - Built using the Leptos framework for Rust WASM. diff --git a/screenshot.png b/screenshot.png index 599b3c7..9942a69 100644 Binary files a/screenshot.png and b/screenshot.png differ diff --git a/src/base/prompt/general.rs b/src/base/prompt/general.rs index 5a7d819..63de767 100644 --- a/src/base/prompt/general.rs +++ b/src/base/prompt/general.rs @@ -1,4 +1,4 @@ -use crate::commands::Command; +use crate::commands::command; use leptos::{ReadSignal, Signal, SignalGetUntracked, SignalUpdate, WriteSignal}; use leptos_use::ColorMode; use std::collections::VecDeque; @@ -40,7 +40,7 @@ pub async fn general_commands( r#"Theme changed to: {new_theme}"# )); } - _ => set_out(Command::process(val.0, val.1).await), + _ => set_out(command(val.0, val.1).await), } updater.update(|hist| { diff --git a/src/base/prompt/keyboard.rs b/src/base/prompt/keyboard.rs index a5dc105..a8ee155 100644 --- a/src/base/prompt/keyboard.rs +++ b/src/base/prompt/keyboard.rs @@ -2,7 +2,7 @@ use crate::commands::autocomplete; use leptos::{ ev::{keydown, KeyboardEvent}, html::Input, - NodeRef, ReadSignal, SignalGetUntracked, SignalUpdate, WriteSignal, + NodeRef, ReadSignal, SignalGet, SignalUpdate, WriteSignal, }; use leptos_use::use_event_listener; use std::{cmp::Ordering, collections::VecDeque}; @@ -15,9 +15,9 @@ pub fn keyboard_commands( submitter: WriteSignal, ) { let _ = use_event_listener(input_element, keydown, move |ev: KeyboardEvent| { - let index = history_index.get_untracked().into(); - let hist = history.get_untracked(); - let inp = input_element.get_untracked().unwrap(); + let hist = history.get(); + let index = history_index.get().into(); + let inp = input_element.get().unwrap(); match &ev.key()[..] { //Previous command in history @@ -25,18 +25,23 @@ pub fn keyboard_commands( ev.prevent_default(); if index < hist.len() { inp.set_value(&hist[index]); - set_history_index.update(|history_index| *history_index += 1); + set_history_index.update(move |history_index| *history_index += 1); } } + //Next command in history - "ArrowDown" => { - match index.cmp(&1) { - Ordering::Greater => inp.set_value(&hist[index - 2]), - Ordering::Equal => inp.set_value(""), - Ordering::Less => (), // No action needed if index < 1 + "ArrowDown" => match index.cmp(&1) { + Ordering::Greater => { + inp.set_value(&hist[index - 2]); + set_history_index.update(move |history_index| *history_index -= 1); } - set_history_index.update(|history_index| *history_index -= 1); - } + Ordering::Equal => { + inp.set_value(""); + set_history_index.update(move |history_index| *history_index -= 1); + } + Ordering::Less => (), + }, + //Autocomplete "Tab" => { ev.prevent_default(); @@ -45,15 +50,23 @@ pub fn keyboard_commands( _ => {} } - //Clear - if (ev.ctrl_key() || ev.meta_key()) && (ev.key() == "l" || ev.key() == "L") { - ev.prevent_default(); - submitter.update(|prompts| { - *prompts = 0; - }); - submitter.update(|prompts| { - *prompts += 1; - }); + //Ctrl + if ev.ctrl_key() || ev.meta_key() { + // Clear + match &ev.key()[..] { + "l" | "L" => { + ev.prevent_default(); + submitter.update(|prompts| { + *prompts = 0; + }); + submitter.update(|prompts| { + *prompts += 1; + }); + } + // Can add Ctrl + P / N for history, + // but will interfere with new window shortcut + _ => {} + } } }); } diff --git a/src/base/prompt/themes.rs b/src/base/prompt/themes.rs index c5bb0cc..4bcbd65 100644 --- a/src/base/prompt/themes.rs +++ b/src/base/prompt/themes.rs @@ -5,12 +5,12 @@ use leptos_use::{ }; // Last theme will be default -static THEMES: [&str; 4] = ["catppuccin", "nord", "classic", "tokyo-night"]; +static THEMES: [&str; 4] = ["catppuccin", "nord", "default", "tokyonight"]; pub fn theme_changer() -> (Signal, impl Fn() + Clone) { let UseColorModeReturn { mode, set_mode, .. } = use_color_mode_with_options( UseColorModeOptions::default() - .custom_modes(THEMES.iter().map(|&s| s.to_string()).collect()) + .custom_modes(THEMES.into_iter().map(String::from).collect()) .initial_value(ColorMode::from(THEMES.last().unwrap().to_string())), ); diff --git a/src/commands.rs b/src/commands.rs index 57e7fdf..10fd75d 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -2,110 +2,52 @@ mod fetch; mod texts; pub use fetch::get_prompt; -pub enum Command { - Help, - About, - Github, - Repos, - Links, - Credits, - Bash(Bash), -} - -impl Command { - fn from(inp0: &str, inp1: &str) -> Self { - match inp0 { - "help" | "termfolio" => Self::Help, - "about" => Self::About, - "github" | "neofetch" => Self::Github, - "repos" | "onefetch" => Self::Repos, - "links" => Self::Links, - "credits" => Self::Credits, - _ => Command::Bash(Bash::from(inp0, inp1)), - } - } - - async fn printout(&self) -> String { - match self { - Self::Help => String::from(texts::HELP), - Self::About => fetch::get_about(), - Self::Github => fetch::get_github().await, - Self::Repos => fetch::get_repos().await, - Self::Links => fetch::get_contacts().to_string(), - Self::Credits => String::from(texts::CREDITS), - Self::Bash(bash) => Bash::printout(bash), - } - } - - pub async fn process(inp0: &str, inp1: &str) -> String { - let command = Self::from(inp0, inp1); - Self::printout(&command).await - } -} - -pub enum Bash { - Go, - Create, - Destroy, - Duplicate, - Move, - Show, - Search, - Where, - Edit, - Power, - You, - Echo(String), - Nothing, - Invalid(String), -} +pub async fn command(inp0: &str, inp1: &str) -> String { + let result = match inp0 { + "help" | "termfolio" => texts::HELP, + "about" => &fetch::get_about(), + "github" | "neofetch" | "fastfetch" => &fetch::get_github().await, + "repos" | "onefetch" => &fetch::get_repos().await, + "links" => fetch::get_contacts(), + "credits" => texts::CREDITS, -impl Bash { - pub fn from(inp0: &str, inp1: &str) -> Self { - match inp0 { - "cd" => Self::Go, - "mkdir" | "touch" => Self::Create, - "rm" | "rmdir" => Self::Destroy, - "cp" => Self::Duplicate, - "mv" => Self::Move, - "ls" | "cat" => Self::Show, - "grep" | "which" | "find" => Self::Search, - "pwd" => Self::Where, - "nano" | "vi" | "vim" | "nvim" | "emacs" | "hx" => Self::Edit, - "su" | "sudo" | "chmod" => Self::Power, - "whoami" => Self::You, - "echo" => Self::Echo(String::from(inp1)), - "" => Self::Nothing, - _ => Self::Invalid(String::from(inp0)), - } - } + "cd" => "Nowhere to go.", + "mkdir" | "touch" => "Nowhere to create.", + "rm" | "rmdir" => "Nothing to destroy.", + "cp" => "Nothing to duplicate.", + "mv" => "Nowhere to move.", + "ls" | "cat" => "Nothing to see.", + "grep" | "which" | "find" => "Nowhere to search.", + "pwd" => "You are here.", + "nano" | "vi" | "vim" | "nvim" | "hx" => "Great editor.", + "emacs" => "Great mail client", + "su" | "sudo" | "chmod" => "With great power comes great responsibility.", + "whoami" => "Despite everything, it's still you.", + "exit" => "Hasta la vista.", + "echo" => inp1.trim(), + "" => "", + _ => &format!("{inp0}: command not found"), + }; - pub fn printout(&self) -> String { - match self { - Self::Go => String::from("Nowhere to go."), - Self::Create => String::from("Nowhere to create."), - Self::Destroy => String::from("Nothing to destroy."), - Self::Duplicate => String::from("Nothing to duplicate."), - Self::Move => String::from("Nowhere to move."), - Self::Show => String::from("Nothing to see."), - Self::Search => String::from("Nowhere to search."), - Self::Where => String::from("You are here."), - Self::Edit => String::from("Nothing to change."), - Self::Power => String::from("With great power comes great responsibility."), - Self::You => String::from("Despite everything, it's still you."), - Self::Echo(s) => String::from(s), - Self::Nothing => String::new(), - Self::Invalid(s) => format!("{s}: command not found",), - } - } + result.to_string() } pub fn autocomplete(inp: &str) -> &str { let inp = inp.trim(); let comms = [ - "help", "history", "about", "github", "repos", "links", "theme", "wal", "credits", - "onefetch", "neofetch", + "help", + "history", + "about", + "github", + "repos", + "links", + "theme", + "wal", + "credits", + "onefetch", + "neofetch", + "fastfetch", ]; if !inp.is_empty() { diff --git a/src/commands/fetch.rs b/src/commands/fetch.rs index 271a8d2..2a4d83f 100644 --- a/src/commands/fetch.rs +++ b/src/commands/fetch.rs @@ -21,21 +21,21 @@ static CONTACTS: OnceLock = OnceLock::new(); // Once Functions fn read_config() -> Option { - CONFIG.get_or_init(|| match serde_json::from_str::(JSON) { - Ok(config) => Some(config), - Err(_) => None, - }); - - CONFIG.get().cloned()? + CONFIG + .get_or_init(|| match serde_json::from_str::(JSON) { + Ok(config) => Some(config), + Err(_) => None, + }) + .clone() } pub fn get_prompt() -> String { - PROMPT.get_or_init(|| match read_config() { - Some(config) => format!("{}@termfolio~$ ", config.github), - _ => String::from("user@termfolio~$ "), - }); - - PROMPT.get().cloned().unwrap() + PROMPT + .get_or_init(|| match read_config() { + Some(config) => format!("{}@termfolio~$ ", config.github), + _ => String::from("user@termfolio~$ "), + }) + .clone() } pub fn get_about() -> String { diff --git a/src/commands/texts.rs b/src/commands/texts.rs index 402b3b5..b635df6 100644 --- a/src/commands/texts.rs +++ b/src/commands/texts.rs @@ -1,17 +1,16 @@ -pub const HELP: &str = r#" ________________ __ _____________ __ ________ - /_ __/ ____/ __ \/ |/ / ____/ __ \/ / / _/ __ \ - / / / __/ / /_/ / /|_/ / /_ / / / / / / // / / / - / / / /___/ _, _/ / / / __/ / /_/ / /____/ // /_/ / -/_/ /_____/_/ |_/_/ /_/_/ \____/_____/___/\____/ +pub const HELP: &str = r#" _____________ __ ___________ __ ________ +/_ __/ __/ _ \/ |/ / __/ __ \/ / / _/ __ \ + / / / _// , _/ /|_/ / _// /_/ / /___/ // /_/ / +/_/ /___/_/|_/_/ /_/_/ \____/____/___/\____/ Hello, welcome to Termfolio [WIP]. Type one of these commands - about - View about me - neofetch - View about Github profile - onefetch - View about my pinned repos / projects + neofetch / fastfetch / github - View about Github profile + onefetch / repos - View about my pinned repos/projects links - View contact info and links help - View this help section - theme - Cycle through themes + theme / wal - Cycle through themes credits - View credits and repo history - View command history clear - Clear screen @@ -19,12 +18,10 @@ Hello, welcome to Termfolio [WIP]. Type one of these You can use arrow keys to scroll through history, and also use Ctrl+L to clear the screen"#; -pub const CREDITS: &str = r#" _____ ______________ _________ _____ _ _____ _____ -|_ _| ___| ___ \ \/ || ___| _ | | |_ _| _ | - | | | |__ | |_/ / . . || |_ | | | | | | | | | | | - | | | __|| /| |\/| || _| | | | | | | | | | | | - | | | |___| |\ \| | | || | \ \_/ / |_____| |_\ \_/ / - \_/ \____/\_| \_\_| |_/\_| \___/\_____/\___/ \___/ +pub const CREDITS: &str = r#" _____________ __ ___________ __ ________ +/_ __/ __/ _ \/ |/ / __/ __ \/ / / _/ __ \ + / / / _// , _/ /|_/ / _// /_/ / /___/ // /_/ / +/_/ /___/_/|_/_/ /_/_/ \____/____/___/\____/ Terminal style portfolio website. diff --git a/styles/styles.css b/styles/styles.css index 33790ad..e148deb 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -1,6 +1,6 @@ :root { --white: #c0caf5; - --black: #17171e; + --black: #1a1b26; --green: #2ac3de; --red: #bb9af7; --blue: #7aa2f7; diff --git a/styles/themes.css b/styles/themes.css index 690b281..f78e9f7 100644 --- a/styles/themes.css +++ b/styles/themes.css @@ -24,11 +24,11 @@ --dblue: #81a1c1; } -.classic { +.default { --white: White; --black: Black; --green: LimeGreen; - --red: Crimson; + --red: Red; --blue: DodgerBlue; --yellow: Gold; --orange: OrangeRed;