From 595c0cfb0bd270109c8cf1ef73cc30ac06d3aca4 Mon Sep 17 00:00:00 2001 From: cutelisp Date: Tue, 24 Jun 2025 19:57:33 +0100 Subject: [PATCH] Add toggle & togglelocal command --- internal/action/command.go | 127 ++++++++++++++++++++++++++---------- internal/config/settings.go | 5 +- runtime/help/commands.md | 17 +++-- 3 files changed, 109 insertions(+), 40 deletions(-) diff --git a/internal/action/command.go b/internal/action/command.go index d46ae49d53..7cb5e523bc 100644 --- a/internal/action/command.go +++ b/internal/action/command.go @@ -32,39 +32,41 @@ var commands map[string]Command func InitCommands() { commands = map[string]Command{ - "set": {(*BufPane).SetCmd, OptionValueComplete}, - "reset": {(*BufPane).ResetCmd, OptionValueComplete}, - "setlocal": {(*BufPane).SetLocalCmd, OptionValueComplete}, - "show": {(*BufPane).ShowCmd, OptionComplete}, - "showkey": {(*BufPane).ShowKeyCmd, nil}, - "run": {(*BufPane).RunCmd, nil}, - "bind": {(*BufPane).BindCmd, nil}, - "unbind": {(*BufPane).UnbindCmd, nil}, - "quit": {(*BufPane).QuitCmd, nil}, - "goto": {(*BufPane).GotoCmd, nil}, - "jump": {(*BufPane).JumpCmd, nil}, - "save": {(*BufPane).SaveCmd, nil}, - "replace": {(*BufPane).ReplaceCmd, nil}, - "replaceall": {(*BufPane).ReplaceAllCmd, nil}, - "vsplit": {(*BufPane).VSplitCmd, buffer.FileComplete}, - "hsplit": {(*BufPane).HSplitCmd, buffer.FileComplete}, - "tab": {(*BufPane).NewTabCmd, buffer.FileComplete}, - "help": {(*BufPane).HelpCmd, HelpComplete}, - "eval": {(*BufPane).EvalCmd, nil}, - "log": {(*BufPane).ToggleLogCmd, nil}, - "plugin": {(*BufPane).PluginCmd, PluginComplete}, - "reload": {(*BufPane).ReloadCmd, nil}, - "reopen": {(*BufPane).ReopenCmd, nil}, - "cd": {(*BufPane).CdCmd, buffer.FileComplete}, - "pwd": {(*BufPane).PwdCmd, nil}, - "open": {(*BufPane).OpenCmd, buffer.FileComplete}, - "tabmove": {(*BufPane).TabMoveCmd, nil}, - "tabswitch": {(*BufPane).TabSwitchCmd, nil}, - "term": {(*BufPane).TermCmd, nil}, - "memusage": {(*BufPane).MemUsageCmd, nil}, - "retab": {(*BufPane).RetabCmd, nil}, - "raw": {(*BufPane).RawCmd, nil}, - "textfilter": {(*BufPane).TextFilterCmd, nil}, + "set": {(*BufPane).SetCmd, OptionValueComplete}, + "setlocal": {(*BufPane).SetLocalCmd, OptionValueComplete}, + "toggle": {(*BufPane).ToggleCmd, OptionValueComplete}, + "togglelocal": {(*BufPane).ToggleLocalCmd, OptionValueComplete}, + "reset": {(*BufPane).ResetCmd, OptionValueComplete}, + "show": {(*BufPane).ShowCmd, OptionComplete}, + "showkey": {(*BufPane).ShowKeyCmd, nil}, + "run": {(*BufPane).RunCmd, nil}, + "bind": {(*BufPane).BindCmd, nil}, + "unbind": {(*BufPane).UnbindCmd, nil}, + "quit": {(*BufPane).QuitCmd, nil}, + "goto": {(*BufPane).GotoCmd, nil}, + "jump": {(*BufPane).JumpCmd, nil}, + "save": {(*BufPane).SaveCmd, nil}, + "replace": {(*BufPane).ReplaceCmd, nil}, + "replaceall": {(*BufPane).ReplaceAllCmd, nil}, + "vsplit": {(*BufPane).VSplitCmd, buffer.FileComplete}, + "hsplit": {(*BufPane).HSplitCmd, buffer.FileComplete}, + "tab": {(*BufPane).NewTabCmd, buffer.FileComplete}, + "help": {(*BufPane).HelpCmd, HelpComplete}, + "eval": {(*BufPane).EvalCmd, nil}, + "log": {(*BufPane).ToggleLogCmd, nil}, + "plugin": {(*BufPane).PluginCmd, PluginComplete}, + "reload": {(*BufPane).ReloadCmd, nil}, + "reopen": {(*BufPane).ReopenCmd, nil}, + "cd": {(*BufPane).CdCmd, buffer.FileComplete}, + "pwd": {(*BufPane).PwdCmd, nil}, + "open": {(*BufPane).OpenCmd, buffer.FileComplete}, + "tabmove": {(*BufPane).TabMoveCmd, nil}, + "tabswitch": {(*BufPane).TabSwitchCmd, nil}, + "term": {(*BufPane).TermCmd, nil}, + "memusage": {(*BufPane).MemUsageCmd, nil}, + "retab": {(*BufPane).RetabCmd, nil}, + "raw": {(*BufPane).RawCmd, nil}, + "textfilter": {(*BufPane).TextFilterCmd, nil}, } } @@ -730,6 +732,65 @@ func (h *BufPane) SetLocalCmd(args []string) { } } +func (h *BufPane) toggleOption(option string, local bool) error { + var curVal, newVal any + + if local { + curVal = h.Buf.Settings[option] + } else { + curVal = config.GetGlobalOption(option) + } + if curVal == nil { + return config.ErrInvalidOption + } + + if choices, ok := config.OptionChoices[option]; ok && len(choices) == 2 { + if curVal == choices[0] { + newVal = choices[1] + } else { + newVal = choices[0] + } + } else if curValBool, ok := curVal.(bool); ok { + newVal = !curValBool + } else { + return config.ErrOptNotToggleable + } + + if local { + if err := h.Buf.SetOptionNative(option, newVal); err != nil { + return err + } + } else { + if err := SetGlobalOptionNative(option, newVal); err != nil { + return err + } + } + + return nil +} + +// ToggleCmd toggles a toggleable option +func (h *BufPane) ToggleCmd(args []string) { + if len(args) < 1 { + InfoBar.Error("Not enough arguments: provide a toggleable option") + return + } + if err := h.toggleOption(args[0], false); err != nil { + InfoBar.Error(err) + } +} + +// ToggleCmd toggles a toggleable option local to the buffer +func (h *BufPane) ToggleLocalCmd(args []string) { + if len(args) < 1 { + InfoBar.Error("Not enough arguments: provide a toggleable option") + return + } + if err := h.toggleOption(args[0], true); err != nil { + InfoBar.Error(err) + } +} + // ShowCmd shows the value of the given option func (h *BufPane) ShowCmd(args []string) { if len(args) < 1 { diff --git a/internal/config/settings.go b/internal/config/settings.go index edfa76c004..52d4575214 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -139,8 +139,9 @@ var LocalSettings = []string{ } var ( - ErrInvalidOption = errors.New("Invalid option") - ErrInvalidValue = errors.New("Invalid value") + ErrInvalidOption = errors.New("Invalid option") + ErrInvalidValue = errors.New("Invalid value") + ErrOptNotToggleable = errors.New("Option not toggleable") // The options that the user can set GlobalSettings map[string]any diff --git a/runtime/help/commands.md b/runtime/help/commands.md index a20c8c3954..73b25fbce2 100644 --- a/runtime/help/commands.md +++ b/runtime/help/commands.md @@ -72,8 +72,20 @@ quotes here but these are not necessary when entering the command in micro. * `setlocal 'option' 'value'`: sets the option to value locally (only in the current buffer). This will *not* modify `settings.json`. +* `toggle 'option'`: toggles the option. Only works with options that accept + exactly two values. This will modify your `settings.json` with the new value. + +* `togglelocal 'option'`: toggles the option locally (only in the + current buffer). Only works with options that accept exactly two values. + This will *not* modify `settings.json`. + +* `reset 'option'`: resets the given option to its default value. + * `show 'option'`: shows the current value of the given option. +* `showkey 'key'`: Show the action(s) bound to a given key. For example + running `> showkey Ctrl-c` will display `Copy`. + * `run 'sh-command'`: runs the given shell command in the background. The command's output will be displayed in one line when it finishes running. @@ -129,8 +141,6 @@ quotes here but these are not necessary when entering the command in micro. * `reopen`: Reopens the current file from disk. -* `reset 'option'`: resets the given option to its default value - * `retab`: Replaces all leading tabs with spaces or leading spaces with tabs depending on the value of `tabstospaces`. @@ -139,9 +149,6 @@ quotes here but these are not necessary when entering the command in micro. the terminal and helps you see which bindings aren't possible and why. This is most useful for debugging keybindings. -* `showkey 'key'`: Show the action(s) bound to a given key. For example - running `> showkey Ctrl-c` will display `Copy`. - * `term ['exec']`: Open a terminal emulator running the given executable. If no executable is given, this will open the default shell in the terminal emulator.