proper prompt coloring and password masking
This commit is contained in:
parent
9703d984bb
commit
a3c8ef9f74
@ -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"
|
Loading…
x
Reference in New Issue
Block a user