From 5a147791dcec5f01f66a6aa04a078d5185e2a632 Mon Sep 17 00:00:00 2001 From: Anas Elgarhy Date: Sun, 5 Oct 2025 20:34:38 +0300 Subject: [PATCH 1/3] feat(cli): add the ability to specify a custom keybinding/symbols file via the cli Introduce `-k`,`--key-bindings`, `-s`, and `--key-symbols` arguments to allow the user from specifying a custom config files without having to change the global ones this change is meant to address github issue: #2714 --- src/args.rs | 28 ++++++++++++++++++++++++++++ src/keys/key_config.rs | 33 ++++++++++++++++++++++++++++----- src/main.rs | 2 +- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/args.rs b/src/args.rs index b03d88a806..ffded183ab 100644 --- a/src/args.rs +++ b/src/args.rs @@ -16,6 +16,8 @@ pub struct CliArgs { pub theme: PathBuf, pub repo_path: RepoPath, pub notify_watcher: bool, + pub key_bindings_path: Option, + pub key_symbols_path: Option, } pub fn process_cmdline() -> Result { @@ -60,10 +62,20 @@ pub fn process_cmdline() -> Result { let notify_watcher: bool = *arg_matches.get_one("watcher").unwrap_or(&false); + let key_bindings_path = arg_matches + .get_one::("key_bindings") + .map(PathBuf::from); + + let key_symbols_path = arg_matches + .get_one::("key_symbols") + .map(PathBuf::from); + Ok(CliArgs { theme, repo_path, notify_watcher, + key_bindings_path, + key_symbols_path, }) } @@ -82,6 +94,22 @@ fn app() -> ClapApp { {all-args}{after-help} ", + ) + .arg( + Arg::new("key_bindings") + .help("Use a custom keybindings file") + .short('k') + .long("key-bindings") + .value_name("KEY_LIST_FILENAME") + .num_args(1), + ) + .arg( + Arg::new("key_symbols") + .help("Use a custom symbols file") + .short('s') + .long("key-symblos") + .value_name("KEY_SYMBOLS_FILENAME") + .num_args(1), ) .arg( Arg::new("theme") diff --git a/src/keys/key_config.rs b/src/keys/key_config.rs index fe6a987765..0f2b31297b 100644 --- a/src/keys/key_config.rs +++ b/src/keys/key_config.rs @@ -1,8 +1,11 @@ -use anyhow::Result; +use anyhow::{anyhow, Result}; use crossterm::event::{KeyCode, KeyModifiers}; use std::{fs::canonicalize, path::PathBuf, rc::Rc}; -use crate::{args::get_app_config_path, strings::symbol}; +use crate::{ + args::{get_app_config_path, CliArgs}, + strings::symbol, +}; use super::{ key_list::{GituiKeyEvent, KeysList}, @@ -34,9 +37,29 @@ impl KeyConfig { .map_or_else(|_| Ok(symbols_file), Ok) } - pub fn init() -> Result { - let keys = KeysList::init(Self::get_config_file()?); - let symbols = KeySymbols::init(Self::get_symbols_file()?); + pub fn init(cli_args: &CliArgs) -> Result { + let keys = if let Some(path) = &cli_args.key_bindings_path { + if !path.exists() { + return Err(anyhow!( + "The custom key bindings file dosen't exists" + )); + } + KeysList::init(path.to_path_buf()) + } else { + KeysList::init(Self::get_config_file()?) + }; + + let symbols = if let Some(path) = &cli_args.key_symbols_path { + if !path.exists() { + return Err(anyhow!( + "The custom key symbols file dosen't exists" + )); + } + KeySymbols::init(path.to_path_buf()) + } else { + KeySymbols::init(Self::get_symbols_file()?) + }; + Ok(Self { keys, symbols }) } diff --git a/src/main.rs b/src/main.rs index de1e6afce1..f6e9b041d2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -166,7 +166,7 @@ fn main() -> Result<()> { asyncgit::register_tracing_logging(); ensure_valid_path(&cliargs.repo_path)?; - let key_config = KeyConfig::init() + let key_config = KeyConfig::init(&cliargs) .map_err(|e| log_eprintln!("KeyConfig loading error: {e}")) .unwrap_or_default(); let theme = Theme::init(&cliargs.theme); From 70dc4af59f9b7a8ee81610793a626eed1c3e3b28 Mon Sep 17 00:00:00 2001 From: Anas Elgarhy Date: Sun, 5 Oct 2025 22:29:32 +0300 Subject: [PATCH 2/3] fix(tests): dont take &CliArgs --- src/keys/key_config.rs | 22 +++++++++++----------- src/main.rs | 9 ++++++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/keys/key_config.rs b/src/keys/key_config.rs index 0f2b31297b..db50c0a913 100644 --- a/src/keys/key_config.rs +++ b/src/keys/key_config.rs @@ -2,10 +2,7 @@ use anyhow::{anyhow, Result}; use crossterm::event::{KeyCode, KeyModifiers}; use std::{fs::canonicalize, path::PathBuf, rc::Rc}; -use crate::{ - args::{get_app_config_path, CliArgs}, - strings::symbol, -}; +use crate::{args::get_app_config_path, strings::symbol}; use super::{ key_list::{GituiKeyEvent, KeysList}, @@ -37,8 +34,11 @@ impl KeyConfig { .map_or_else(|_| Ok(symbols_file), Ok) } - pub fn init(cli_args: &CliArgs) -> Result { - let keys = if let Some(path) = &cli_args.key_bindings_path { + pub fn init( + key_bindings_path: Option<&PathBuf>, + key_symbols_path: Option<&PathBuf>, + ) -> Result { + let keys = if let Some(path) = key_bindings_path { if !path.exists() { return Err(anyhow!( "The custom key bindings file dosen't exists" @@ -49,7 +49,7 @@ impl KeyConfig { KeysList::init(Self::get_config_file()?) }; - let symbols = if let Some(path) = &cli_args.key_symbols_path { + let symbols = if let Some(path) = key_symbols_path { if !path.exists() { return Err(anyhow!( "The custom key symbols file dosen't exists" @@ -216,7 +216,7 @@ mod tests { // testing let result = std::panic::catch_unwind(|| { - let loaded_config = KeyConfig::init().unwrap(); + let loaded_config = KeyConfig::init(None, None).unwrap(); assert_eq!( loaded_config.keys.move_down, KeysList::default().move_down @@ -231,7 +231,7 @@ mod tests { &original_key_symbols_path, ) .unwrap(); - let loaded_config = KeyConfig::init().unwrap(); + let loaded_config = KeyConfig::init(None, None).unwrap(); assert_eq!( loaded_config.keys.move_down, KeysList::default().move_down @@ -243,7 +243,7 @@ mod tests { &original_key_list_path, ) .unwrap(); - let loaded_config = KeyConfig::init().unwrap(); + let loaded_config = KeyConfig::init(None, None).unwrap(); assert_eq!( loaded_config.keys.move_down, GituiKeyEvent::new( @@ -254,7 +254,7 @@ mod tests { assert_eq!(loaded_config.symbols.esc, "Esc"); fs::remove_file(&original_key_symbols_path).unwrap(); - let loaded_config = KeyConfig::init().unwrap(); + let loaded_config = KeyConfig::init(None, None).unwrap(); assert_eq!( loaded_config.keys.move_down, GituiKeyEvent::new( diff --git a/src/main.rs b/src/main.rs index f6e9b041d2..e509c3f29f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -166,9 +166,12 @@ fn main() -> Result<()> { asyncgit::register_tracing_logging(); ensure_valid_path(&cliargs.repo_path)?; - let key_config = KeyConfig::init(&cliargs) - .map_err(|e| log_eprintln!("KeyConfig loading error: {e}")) - .unwrap_or_default(); + let key_config = KeyConfig::init( + cliargs.key_bindings_path.as_ref(), + cliargs.key_symbols_path.as_ref(), + ) + .map_err(|e| log_eprintln!("KeyConfig loading error: {e}")) + .unwrap_or_default(); let theme = Theme::init(&cliargs.theme); setup_terminal()?; From 367f9991499a8f1e168f241a26a531f86bded18c Mon Sep 17 00:00:00 2001 From: Anas Elgarhy Date: Sun, 5 Oct 2025 22:41:04 +0300 Subject: [PATCH 3/3] fix(args.rs): fix clippy errors --- src/keys/key_config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/keys/key_config.rs b/src/keys/key_config.rs index db50c0a913..c63e23e54c 100644 --- a/src/keys/key_config.rs +++ b/src/keys/key_config.rs @@ -44,7 +44,7 @@ impl KeyConfig { "The custom key bindings file dosen't exists" )); } - KeysList::init(path.to_path_buf()) + KeysList::init(path.clone()) } else { KeysList::init(Self::get_config_file()?) }; @@ -55,7 +55,7 @@ impl KeyConfig { "The custom key symbols file dosen't exists" )); } - KeySymbols::init(path.to_path_buf()) + KeySymbols::init(path.clone()) } else { KeySymbols::init(Self::get_symbols_file()?) };