diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-20 18:55:41 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-20 18:55:41 +0300 |
| commit | 836fd7e585af15cc1ccb0d4f04586ffec28d2a3c (patch) | |
| tree | a3bf07e7af7ffd884a38fce3d65f8c2243bc0615 /src/cli.rs | |
| parent | be66f33d2acde30d25794bcead991e5e7b7eaff8 (diff) | |
feat: add keybinding v2
refs #154
refs #201
refs #202
refs #219
Diffstat (limited to 'src/cli.rs')
| -rw-r--r-- | src/cli.rs | 116 |
1 files changed, 115 insertions, 1 deletions
@@ -1,6 +1,6 @@ use std::io::{BufRead, BufReader, Write}; use std::os::unix::net::UnixStream; -use std::time::Duration; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use serde::Serialize; @@ -33,6 +33,7 @@ pub fn maybe_run(args: &[String]) -> std::io::Result<CommandOutcome> { exit_code } "status" => run_status_command(&args[2..])?, + "config" => run_config_command(&args[2..])?, "workspace" => run_workspace_command(&args[2..])?, "tab" => run_tab_command(&args[2..])?, "agent" => run_agent_command(&args[2..])?, @@ -95,6 +96,114 @@ fn run_status_command(args: &[String]) -> std::io::Result<i32> { } } +fn run_config_command(args: &[String]) -> std::io::Result<i32> { + let Some(subcommand) = args.first().map(|arg| arg.as_str()) else { + print_config_help(); + return Ok(2); + }; + + match subcommand { + "reset-keys" => config_reset_keys(&args[1..]), + "help" | "--help" | "-h" => { + print_config_help(); + Ok(0) + } + _ => { + print_config_help(); + Ok(2) + } + } +} + +fn config_reset_keys(args: &[String]) -> std::io::Result<i32> { + if !args.is_empty() { + eprintln!("usage: herdr config reset-keys"); + return Ok(2); + } + + let path = crate::config::config_path(); + if !path.exists() { + println!( + "No config file found at {}. Built-in v2 keybindings already apply.", + path.display() + ); + return Ok(0); + } + + let content = std::fs::read_to_string(&path)?; + let parsed = match content.parse::<toml::Value>() { + Ok(value) => value, + Err(err) => { + eprintln!( + "config file at {} is invalid TOML: {err}. Fix it manually or move it aside to use defaults.", + path.display() + ); + return Ok(1); + } + }; + let Some(table) = parsed.as_table() else { + eprintln!( + "config file at {} is invalid TOML: top-level config must be a table.", + path.display() + ); + return Ok(1); + }; + + if !table.contains_key("keys") { + println!( + "No [keys] config found in {}. Built-in v2 keybindings already apply.", + path.display() + ); + return Ok(0); + } + + let (updated, removed) = crate::config::remove_keybinding_config_sections(&content); + if !removed { + eprintln!( + "could not safely remove keybinding config from {} without rewriting comments; edit the file manually or remove the top-level keys setting.", + path.display() + ); + return Ok(1); + } + if let Err(err) = updated.parse::<toml::Value>() { + eprintln!( + "removing keybinding config would make {} invalid TOML: {err}; leaving config unchanged", + path.display() + ); + return Ok(1); + } + + let backup_path = key_config_backup_path(&path); + std::fs::copy(&path, &backup_path)?; + std::fs::write(&path, updated)?; + + println!("Created backup: {}", backup_path.display()); + println!( + "Removed [keys], [keys.indexed], and [[keys.command]] from {}.", + path.display() + ); + println!("Built-in v2 keybindings will apply after Herdr restarts or reloads config."); + println!("If a Herdr server is running, run `herdr server reload-config` to apply this now."); + println!( + "To restore: cp {} {}", + backup_path.display(), + path.display() + ); + Ok(0) +} + +fn key_config_backup_path(path: &std::path::Path) -> std::path::PathBuf { + let timestamp = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|duration| duration.as_secs()) + .unwrap_or(0); + let file_name = path + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or("config.toml"); + path.with_file_name(format!("{file_name}.bak-keybind-v2-{timestamp}")) +} + #[derive(Debug, Clone, PartialEq, Eq)] enum ServerRuntimeStatus { Running { @@ -2071,6 +2180,11 @@ fn print_status_help() { eprintln!(" herdr status client show local client binary status"); } +fn print_config_help() { + eprintln!("herdr config commands:"); + eprintln!(" herdr config reset-keys back up config.toml and remove custom keybindings"); +} + fn print_workspace_help() { eprintln!("herdr workspace commands:"); eprintln!(" herdr workspace list"); |
