From c9357c60ee37ff15cef60b5fbd665c51c3363eab Mon Sep 17 00:00:00 2001 From: lebkuchen Date: Sat, 22 Jun 2024 22:49:16 +0200 Subject: [PATCH 1/2] profile flag --- src/main.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0fba58d..0256ab7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -77,6 +77,38 @@ pub fn icon_cache_get(name: &'static str, size: u16) -> widget::icon::Icon { icon_cache.get(name, size) } +fn parse_flag<'a>(arg: &'a str) -> Option<(Arg<'a>, &'a str)> { + if let Some(arg) = arg.strip_prefix("--") { + return arg + .split_once('=') + .filter(|(flag, value)| !value.is_empty() && !flag.is_empty()) + .map(|(flag, value)| (Arg::Long(flag), value)); + } else if let Some(arg) = arg.strip_prefix('-') { + return arg + .is_char_boundary(1) + .then(|| arg.split_at(1)) + .filter(|(_, value)| !value.is_empty()) + .map(|(flag, value)| (Arg::Short(flag.as_bytes()[0]), value)); + } + return None; +} +#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)] +enum Arg<'a> { + Long(&'a str), + Short(u8), +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_flag() { + assert_eq!(parse_flag("--profile=0"), Some((Arg::Long("profile"), "0"))); + assert_eq!(parse_flag("-P0"), Some((Arg::Short(b'P'), "0"))); + } +} + /// Runs application with these settings #[rustfmt::skip] fn main() -> Result<(), Box> { @@ -84,6 +116,7 @@ fn main() -> Result<(), Box> { let mut shell_args = Vec::new(); let mut parse_flags = true; let mut daemonize = true; + let mut profile = None; for arg in env::args().skip(1) { if parse_flags { match arg.as_str() { @@ -94,9 +127,13 @@ fn main() -> Result<(), Box> { "--no-daemon" => { daemonize = false; } - _ => { - //TODO: should this throw an error? - log::warn!("ignored argument {:?}", arg); + arg => { + match parse_flag(arg) { + Some((Arg::Short(b'P') | Arg::Long("profile"), value)) => + profile = Some(value.to_string()), + //TODO: should this throw an error? + _ => eprintln!("ignored argument: {}", arg), + } } } } else if shell_program_opt.is_none() { @@ -139,6 +176,18 @@ fn main() -> Result<(), Box> { } }; + + let mut profile_id: Option = None; + if let Some(profile) = profile { + if let Some((id, _)) = config.profiles.iter().find(|(_, k)|&k.name == &profile) { + profile_id = Some(*id); + } else if let Ok(raw_id) = profile.parse::() { + if config.profiles.contains_key(&ProfileId(raw_id)){ + profile_id = Some(ProfileId(raw_id)) + } + } + } + let startup_options = if let Some(shell_program) = shell_program_opt { let options = tty::Options { shell: Some(tty::Shell::new(shell_program, shell_args)), @@ -160,10 +209,13 @@ fn main() -> Result<(), Box> { settings = settings.size_limits(Limits::NONE.min_width(360.0).min_height(180.0)); let flags = Flags { + + startup_profile: profile_id, config_handler, config, startup_options, term_config, + }; cosmic::app::run::(settings, flags)?; @@ -175,6 +227,7 @@ pub struct Flags { config_handler: Option, config: Config, startup_options: Option, + startup_profile: Option, term_config: term::Config, } @@ -404,6 +457,7 @@ pub struct App { term_event_tx_opt: Option>, startup_options: Option, + startup_profile: Option, term_config: term::Config, color_scheme_errors: Vec, color_scheme_expanded: Option<(ColorSchemeKind, Option)>, @@ -1513,6 +1567,7 @@ impl Application for App { find_search_id: widget::Id::unique(), find_search_value: String::new(), startup_options: flags.startup_options, + startup_profile: flags.startup_profile, term_config: flags.term_config, term_event_tx_opt: None, color_scheme_errors: Vec::new(), @@ -2347,10 +2402,11 @@ impl Application for App { return self.update_title(Some(pane)); } Message::TabNew => { + let profile = self.startup_profile.take(); return self.create_and_focus_new_terminal( self.pane_model.focus, - self.get_default_profile(), - ) + profile.or_else(|| self.get_default_profile()), + ); } Message::TabNewNoProfile => { return self.create_and_focus_new_terminal(self.pane_model.focus, None) From 8425cd180ad57cfda36178fc1674b9f3b785097b Mon Sep 17 00:00:00 2001 From: Dominic Gerhauser Date: Fri, 17 Jan 2025 17:54:41 +0100 Subject: [PATCH 2/2] profile flag: add help message for typos --- Cargo.lock | 17 ++++++++++++----- Cargo.toml | 1 + src/main.rs | 19 ++++++++++++++++++- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a847b25..2a32481 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1312,6 +1312,7 @@ dependencies = [ "alacritty_terminal", "cosmic-files", "cosmic-text", + "edit-distance", "env_logger 0.10.2", "fork", "hex_color", @@ -1750,6 +1751,12 @@ dependencies = [ "linux-raw-sys 0.6.5", ] +[[package]] +name = "edit-distance" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3f497e87b038c09a155dfd169faa5ec940d0644635555ef6bd464ac20e97397" + [[package]] name = "either" version = "1.13.0" @@ -1832,7 +1839,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3510,7 +3517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -5149,7 +5156,7 @@ dependencies = [ "itoa", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5672,7 +5679,7 @@ dependencies = [ "getrandom", "once_cell", "rustix 0.38.43", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6645,7 +6652,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f1842a6..6277ae9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ icu_collator = "1.5" icu_provider = { version = "1.5", features = ["sync"] } rust-embed = "8" url = "2.5" +edit-distance = "2.1.3" [dependencies.cosmic-files] git = "https://github.com/pop-os/cosmic-files.git" diff --git a/src/main.rs b/src/main.rs index 0256ab7..e2ccb1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -77,10 +77,16 @@ pub fn icon_cache_get(name: &'static str, size: u16) -> widget::icon::Icon { icon_cache.get(name, size) } +const NO_BOOL_FLAGS: &[&str] = &["profile"]; fn parse_flag<'a>(arg: &'a str) -> Option<(Arg<'a>, &'a str)> { if let Some(arg) = arg.strip_prefix("--") { + let arg = arg.split_once('='); + if let Some((flag, _)) = arg { + if !NO_BOOL_FLAGS.contains(&flag) { + did_you_mean(flag); + } + } return arg - .split_once('=') .filter(|(flag, value)| !value.is_empty() && !flag.is_empty()) .map(|(flag, value)| (Arg::Long(flag), value)); } else if let Some(arg) = arg.strip_prefix('-') { @@ -92,6 +98,17 @@ fn parse_flag<'a>(arg: &'a str) -> Option<(Arg<'a>, &'a str)> { } return None; } +#[cold] +fn did_you_mean(flag: &str) { + if let Some((_, val)) = NO_BOOL_FLAGS + .iter() + .map(|val| (edit_distance::edit_distance(val, flag), val)) + .max_by_key(|&(score, _)| score) + .filter(|&(score, _)| score <= 2) + { + eprintln!("Did you mean: {val}"); + } +} #[derive(Debug, PartialEq, PartialOrd, Clone, Copy)] enum Arg<'a> { Long(&'a str),