proper prompt coloring and password masking

This commit is contained in:
lemonsh 2023-05-28 18:12:40 +02:00
parent 9703d984bb
commit a3c8ef9f74
6 changed files with 77 additions and 27 deletions

View File

@ -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"

View File

@ -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 {

View File

@ -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| {
if p.id == id {
modified = true;
action
} else {
PortForwardAction::Keep
}
}).await?;
state
.connect_box
.edit_port_forwards(|p| {
if p.id == id {
modified = true;
action
} else {
PortForwardAction::Keep
}
})
.await?;
if !modified {
cprintln!("<red!>No port with id {id} exists");
} else {
cprintln!("<green!>Done!")
}
},
}
}
Ok(())
}

View File

@ -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;

View File

@ -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
View File

@ -0,0 +1,2 @@
unstable_features = true
imports_granularity = "Crate"