From 4ddb608563d985060d69594d1004550a680ae3bd Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Wed, 31 Aug 2022 22:48:38 +0000 Subject: Add IPC config subcommand This patch adds a new mechanism for changing configuration options without editing the configuration file, by sending options to running instances through `alacritty msg`. Each window will load Alacritty's configuration file by default and then accept IPC messages for config updates using the `alacritty msg config` subcommand. By default all windows will be updated, individual windows can be addressed using `alacritty msg config --window-id "$ALACRITTY_WINDOW_ID"`. Each option will replace the config's current value and cannot be reset until Alacritty is restarted or the option is overwritten with a new value. Configuration options are passed in the format `field.subfield=value`, where `value` is interpreted as yaml. Closes #472. --- alacritty/src/cli.rs | 48 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) (limited to 'alacritty/src/cli.rs') diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index e9c563d4..e7aae207 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -81,14 +81,7 @@ impl Options { let mut options = Self::parse(); // Convert `--option` flags into serde `Value`. - for option in &options.option { - match option_as_value(option) { - Ok(value) => { - options.config_options = serde_utils::merge(options.config_options, value); - }, - Err(_) => eprintln!("Invalid CLI config option: {:?}", option), - } - } + options.config_options = options_as_value(&options.option); options } @@ -132,7 +125,18 @@ impl Options { } } -/// Format an option in the format of `parent.field=value` to a serde Value. +/// Combine multiple options into a [`serde_yaml::Value`]. +pub fn options_as_value(options: &[String]) -> Value { + options.iter().fold(Value::default(), |value, option| match option_as_value(option) { + Ok(new_value) => serde_utils::merge(value, new_value), + Err(_) => { + eprintln!("Ignoring invalid option: {:?}", option); + value + }, + }) +} + +/// Parse an option in the format of `parent.field=value` as a serde Value. fn option_as_value(option: &str) -> Result { let mut yaml_text = String::with_capacity(option.len()); let mut closing_brackets = String::new(); @@ -266,7 +270,7 @@ pub enum Subcommands { #[derive(Args, Debug)] pub struct MessageOptions { /// IPC socket connection path override. - #[clap(long, short, value_hint = ValueHint::FilePath)] + #[clap(short, long, value_hint = ValueHint::FilePath)] pub socket: Option, /// Message which should be sent. @@ -280,9 +284,12 @@ pub struct MessageOptions { pub enum SocketMessage { /// Create a new window in the same Alacritty process. CreateWindow(WindowOptions), + + /// Update the Alacritty configuration. + Config(IpcConfig), } -/// Subset of options that we pass to a 'create-window' subcommand. +/// Subset of options that we pass to 'create-window' IPC subcommand. #[derive(Serialize, Deserialize, Args, Default, Clone, Debug, PartialEq, Eq)] pub struct WindowOptions { /// Terminal options which can be passed via IPC. @@ -294,6 +301,25 @@ pub struct WindowOptions { pub window_identity: WindowIdentity, } +/// Parameters to the `config` IPC subcommand. +#[cfg(unix)] +#[derive(Args, Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)] +pub struct IpcConfig { + /// Configuration file options [example: cursor.style=Beam]. + #[clap(required = true, value_name = "CONFIG_OPTIONS")] + pub options: Vec, + + /// Window ID for the new config. + /// + /// Use `-1` to apply this change to all windows. + #[clap(short, long, allow_hyphen_values = true, env = "ALACRITTY_WINDOW_ID")] + pub window_id: Option, + + /// Clear all runtime configuration changes. + #[clap(short, long, conflicts_with = "options")] + pub reset: bool, +} + #[cfg(test)] mod tests { use super::*; -- cgit