From 8b09b0094285bb832ab88ac001b1fe631b10bfb1 Mon Sep 17 00:00:00 2001 From: A-Walrus <58790821+A-Walrus@users.noreply.github.com> Date: Mon, 13 Feb 2023 04:40:31 +0200 Subject: [PATCH] Add :toggle-option command (#4085) This command toggles the value of boolean options --- book/src/generated/typable-cmd.md | 1 + helix-term/src/commands/typed.rs | 48 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md index 0ff501a33..7416ac327 100644 --- a/book/src/generated/typable-cmd.md +++ b/book/src/generated/typable-cmd.md @@ -61,6 +61,7 @@ | `:goto`, `:g` | Goto line number. | | `:set-language`, `:lang` | Set the language of current buffer. | | `:set-option`, `:set` | Set a config option at runtime.
For example to disable smart case search, use `:set search.smart-case false`. | +| `:toggle-option`, `:toggle` | Toggle a boolean config option at runtime.
For example to toggle smart case search, use `:toggle search.smart-case`. | | `:get-option`, `:get` | Get the current value of a config option. | | `:sort` | Sort ranges in selection. | | `:rsort` | Sort ranges in selection in reverse order. | diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 0cc1b7432..6b45b005a 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -7,6 +7,7 @@ use super::*; use helix_core::encoding; use helix_view::editor::{Action, CloseError, ConfigEvent}; +use serde_json::Value; use ui::completers::{self, Completer}; #[derive(Clone)] @@ -1646,6 +1647,46 @@ fn set_option( Ok(()) } +/// Toggle boolean config option at runtime. Access nested values by dot +/// syntax, for example to toggle smart case search, use `:toggle search.smart- +/// case`. +fn toggle_option( + cx: &mut compositor::Context, + args: &[Cow], + event: PromptEvent, +) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + + if args.len() != 1 { + anyhow::bail!("Bad arguments. Usage: `:toggle key`"); + } + let key = &args[0].to_lowercase(); + + let key_error = || anyhow::anyhow!("Unknown key `{}`", key); + + let mut config = serde_json::json!(&cx.editor.config().deref()); + let pointer = format!("/{}", key.replace('.', "/")); + let value = config.pointer_mut(&pointer).ok_or_else(key_error)?; + + if let Value::Bool(b) = *value { + *value = Value::Bool(!b); + } else { + anyhow::bail!("Key `{}` is not toggle-able", key) + } + + // This unwrap should never fail because we only replace one boolean value + // with another, maintaining a valid json config + let config = serde_json::from_value(config).unwrap(); + + cx.editor + .config_events + .0 + .send(ConfigEvent::Update(config))?; + Ok(()) +} + /// Change the language of the current buffer at runtime. fn language( cx: &mut compositor::Context, @@ -2384,6 +2425,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ fun: set_option, completer: Some(completers::setting), }, + TypableCommand { + name: "toggle-option", + aliases: &["toggle"], + doc: "Toggle a boolean config option at runtime.\nFor example to toggle smart case search, use `:toggle search.smart-case`.", + fun: toggle_option, + completer: Some(completers::setting), + }, TypableCommand { name: "get-option", aliases: &["get"],