proper prompt coloring and password masking
This commit is contained in:
		| @@ -6,7 +6,7 @@ version = "0.1.0" | ||||
| edition = "2021" | ||||
|  | ||||
| [dependencies] | ||||
| rustyline = "11" | ||||
| rustyline = {version = "11", features = ["derive"]} | ||||
| color-eyre = "0.6" | ||||
| tokio = { version = "1.0", default-features = false, features = ["macros"] } | ||||
| tracing = "0.1" | ||||
| @@ -15,5 +15,5 @@ clap = { version = "4.2", default-features = false, features = ["suggestions", " | ||||
| dirs = "5.0" | ||||
| connectbox = { path = "../connectbox" } | ||||
| color-print = "0.3" | ||||
| ascii_table = { version = "4.0", features = ["auto_table_width"] } | ||||
| ascii_table = "4.0" | ||||
| once_cell = "1.17" | ||||
|   | ||||
| @@ -54,8 +54,8 @@ pub(crate) enum PortForwardsCommand { | ||||
|         /// ID of the port. You can use `pfw show` to find it | ||||
|         id: u32, | ||||
|         /// Action to perform with the port. Can be either enable, disable or delete. | ||||
|         action: String | ||||
|     } | ||||
|         action: String, | ||||
|     }, | ||||
| } | ||||
|  | ||||
| pub(crate) fn shell_cmd() -> Command { | ||||
|   | ||||
| @@ -3,7 +3,10 @@ use std::vec; | ||||
| use ascii_table::{Align::Right, AsciiTable}; | ||||
| use color_eyre::Result; | ||||
| use color_print::cprintln; | ||||
| use connectbox::{models::{PortForwardEntry, PortForwardProtocol}, PortForwardAction}; | ||||
| use connectbox::{ | ||||
|     models::{PortForwardEntry, PortForwardProtocol}, | ||||
|     PortForwardAction, | ||||
| }; | ||||
| use once_cell::sync::OnceCell; | ||||
|  | ||||
| use crate::{cli::PortForwardsCommand, AppState}; | ||||
| @@ -101,24 +104,27 @@ pub(crate) async fn run(cmd: PortForwardsCommand, state: &AppState) -> Result<() | ||||
|                 } | ||||
|                 _ => { | ||||
|                     cprintln!("<red!>Invalid action {action:?}"); | ||||
|                     return Ok(()) | ||||
|                     return Ok(()); | ||||
|                 } | ||||
|             }; | ||||
|             let mut modified = false; | ||||
|             state.connect_box.edit_port_forwards(|p| { | ||||
|             state | ||||
|                 .connect_box | ||||
|                 .edit_port_forwards(|p| { | ||||
|                     if p.id == id { | ||||
|                         modified = true; | ||||
|                         action | ||||
|                     } else { | ||||
|                         PortForwardAction::Keep | ||||
|                     } | ||||
|             }).await?; | ||||
|                 }) | ||||
|                 .await?; | ||||
|             if !modified { | ||||
|                 cprintln!("<red!>No port with id {id} exists"); | ||||
|             } else { | ||||
|                 cprintln!("<green!>Done!") | ||||
|             } | ||||
|         }, | ||||
|         } | ||||
|     } | ||||
|     Ok(()) | ||||
| } | ||||
|   | ||||
| @@ -1,12 +1,16 @@ | ||||
| use color_print::{cprintln, cstr}; | ||||
|  | ||||
| use crate::{cli::ShellCommand, utils::QuotableArgs}; | ||||
| use clap::{FromArgMatches, Parser}; | ||||
| use cli::Args; | ||||
| use color_eyre::Result; | ||||
| use color_print::{cformat, cprintln, cstr}; | ||||
| use connectbox::ConnectBox; | ||||
| use rustyline::{error::ReadlineError, DefaultEditor}; | ||||
|  | ||||
| use crate::{cli::ShellCommand, utils::QuotableArgs}; | ||||
| use rustyline::{ | ||||
|     error::ReadlineError, | ||||
|     highlight::Highlighter, | ||||
|     history::{DefaultHistory, FileHistory, MemHistory}, | ||||
|     Completer, DefaultEditor, Editor, Helper, Hinter, Validator, | ||||
| }; | ||||
| use std::borrow::Cow; | ||||
|  | ||||
| mod cli; | ||||
| mod commands; | ||||
| @@ -16,6 +20,40 @@ pub(crate) struct AppState { | ||||
|     connect_box: ConnectBox, | ||||
| } | ||||
|  | ||||
| #[derive(Completer, Helper, Hinter, Validator)] | ||||
| struct GreenPrompt; | ||||
|  | ||||
| impl Highlighter for GreenPrompt { | ||||
|     fn highlight_prompt<'b, 's: 'b, 'p: 'b>( | ||||
|         &'s self, | ||||
|         prompt: &'p str, | ||||
|         _default: bool, | ||||
|     ) -> std::borrow::Cow<'b, str> { | ||||
|         cformat!("<green!>{prompt}").into() | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Completer, Helper, Hinter, Validator)] | ||||
| struct PasswordPrompt; | ||||
|  | ||||
| impl Highlighter for PasswordPrompt { | ||||
|     fn highlight_prompt<'b, 's: 'b, 'p: 'b>( | ||||
|         &'s self, | ||||
|         prompt: &'p str, | ||||
|         _default: bool, | ||||
|     ) -> std::borrow::Cow<'b, str> { | ||||
|         cformat!("<red!>{prompt}").into() | ||||
|     } | ||||
|  | ||||
|     fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> { | ||||
|         "*".repeat(line.len()).into() | ||||
|     } | ||||
|  | ||||
|     fn highlight_char(&self, _line: &str, _pos: usize) -> bool { | ||||
|         true | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[tokio::main(flavor = "current_thread")] | ||||
| async fn main() -> Result<()> { | ||||
|     let args = Args::parse(); | ||||
| @@ -26,10 +64,14 @@ async fn main() -> Result<()> { | ||||
|         .with_max_level(args.log_level) | ||||
|         .init(); | ||||
|  | ||||
|     let mut rl = DefaultEditor::new()?; | ||||
|     let mut rl = Editor::new()?; | ||||
|     rl.set_helper(Some(GreenPrompt)); | ||||
|  | ||||
|     let password = if let Some(password) = args.password { | ||||
|         password | ||||
|     } else { | ||||
|         let mut rl = Editor::new()?; | ||||
|         rl.set_helper(Some(PasswordPrompt)); | ||||
|         rl.readline("Password: ")? | ||||
|     }; | ||||
|     let history_path = dirs::data_dir() | ||||
| @@ -43,7 +85,7 @@ async fn main() -> Result<()> { | ||||
|     let state = AppState { connect_box }; | ||||
|  | ||||
|     loop { | ||||
|         match rl.readline(cstr!("\n<green!> > ")) { | ||||
|         match rl.readline("\n >> ") { | ||||
|             Ok(line) => { | ||||
|                 if line.chars().all(char::is_whitespace) { | ||||
|                     continue; | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| use std::fmt::Display; | ||||
| use std::net::Ipv4Addr; | ||||
| use std::time::Duration; | ||||
| use std::{fmt::Display, net::Ipv4Addr, time::Duration}; | ||||
|  | ||||
| use serde::de::{self, Error, Unexpected}; | ||||
| use serde::{Deserialize, Deserializer}; | ||||
| use serde::{ | ||||
|     de::{self, Error, Unexpected}, | ||||
|     Deserialize, Deserializer, | ||||
| }; | ||||
|  | ||||
| #[derive(Deserialize, Debug)] | ||||
| pub struct LanUserTable { | ||||
|   | ||||
							
								
								
									
										2
									
								
								rustfmt.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								rustfmt.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| unstable_features = true | ||||
| imports_granularity = "Crate" | ||||
		Reference in New Issue
	
	Block a user