From e856e9a3f794b88320e1b87bc9730a73cd80c981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6ran=20Karl?= <3951388+JoeKar@users.noreply.github.com> Date: Fri, 10 Nov 2023 20:46:57 +0100 Subject: [PATCH 1/3] settings: Move all options to the start of the file This will help with the overview of all available options and their optional validators. --- internal/config/settings.go | 200 ++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 99 deletions(-) diff --git a/internal/config/settings.go b/internal/config/settings.go index d5328ad92e..6ff512ecba 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -20,6 +20,107 @@ import ( type optionValidator func(string, interface{}) error +// a list of settings that need option validators +var optionValidators = map[string]optionValidator{ + "autosave": validateNonNegativeValue, + "clipboard": validateClipboard, + "colorcolumn": validateNonNegativeValue, + "colorscheme": validateColorscheme, + "detectlimit": validateNonNegativeValue, + "encoding": validateEncoding, + "fileformat": validateLineEnding, + "matchbracestyle": validateMatchBraceStyle, + "multiopen": validateMultiOpen, + "reload": validateReload, + "scrollmargin": validateNonNegativeValue, + "scrollspeed": validateNonNegativeValue, + "tabsize": validatePositiveValue, +} + +// a list of settings that can be globally and locally modified and their +// default values +var defaultCommonSettings = map[string]interface{}{ + "autoindent": true, + "autosu": false, + "backup": true, + "backupdir": "", + "basename": false, + "colorcolumn": float64(0), + "cursorline": true, + "detectlimit": float64(100), + "diffgutter": false, + "encoding": "utf-8", + "eofnewline": true, + "fastdirty": false, + "fileformat": defaultFileFormat(), + "filetype": "unknown", + "hlsearch": false, + "hltaberrors": false, + "hltrailingws": false, + "incsearch": true, + "ignorecase": true, + "indentchar": " ", + "keepautoindent": false, + "matchbrace": true, + "matchbracestyle": "underline", + "mkparents": false, + "permbackup": false, + "readonly": false, + "reload": "prompt", + "rmtrailingws": false, + "ruler": true, + "relativeruler": false, + "savecursor": false, + "saveundo": false, + "scrollbar": false, + "scrollmargin": float64(3), + "scrollspeed": float64(2), + "smartpaste": true, + "softwrap": false, + "splitbottom": true, + "splitright": true, + "statusformatl": "$(filename) $(modified)($(line),$(col)) $(status.paste)| ft:$(opt:filetype) | $(opt:fileformat) | $(opt:encoding)", + "statusformatr": "$(bind:ToggleKeyMenu): bindings, $(bind:ToggleHelp): help", + "statusline": true, + "syntax": true, + "tabmovement": false, + "tabsize": float64(4), + "tabstospaces": false, + "useprimary": true, + "wordwrap": false, +} + +// a list of settings that should only be globally modified and their +// default values +var DefaultGlobalOnlySettings = map[string]interface{}{ + "autosave": float64(0), + "clipboard": "external", + "colorscheme": "default", + "divchars": "|-", + "divreverse": true, + "fakecursor": false, + "infobar": true, + "keymenu": false, + "mouse": true, + "multiopen": "tab", + "parsecursor": false, + "paste": false, + "pluginchannels": []string{"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json"}, + "pluginrepos": []string{}, + "savehistory": true, + "scrollbarchar": "|", + "sucmd": "sudo", + "tabhighlight": false, + "tabreverse": true, + "xterm": false, +} + +// a list of settings that should never be globally modified +var LocalSettings = []string{ + "filetype", + "readonly", +} + var ( ErrInvalidOption = errors.New("Invalid option") ErrInvalidValue = errors.New("Invalid value") @@ -46,23 +147,6 @@ func init() { parsedSettings = make(map[string]interface{}) } -// Options with validators -var optionValidators = map[string]optionValidator{ - "autosave": validateNonNegativeValue, - "clipboard": validateClipboard, - "detectlimit": validateNonNegativeValue, - "tabsize": validatePositiveValue, - "scrollmargin": validateNonNegativeValue, - "scrollspeed": validateNonNegativeValue, - "colorscheme": validateColorscheme, - "colorcolumn": validateNonNegativeValue, - "fileformat": validateLineEnding, - "encoding": validateEncoding, - "multiopen": validateMultiOpen, - "reload": validateReload, - "matchbracestyle": validateMatchBraceStyle, -} - func ReadSettings() error { filename := filepath.Join(ConfigDir, "settings.json") if _, e := os.Stat(filename); e == nil { @@ -258,57 +342,6 @@ func GetGlobalOption(name string) interface{} { return GlobalSettings[name] } -var defaultCommonSettings = map[string]interface{}{ - "autoindent": true, - "autosu": false, - "backup": true, - "backupdir": "", - "basename": false, - "colorcolumn": float64(0), - "cursorline": true, - "detectlimit": float64(100), - "diffgutter": false, - "encoding": "utf-8", - "eofnewline": true, - "fastdirty": false, - "fileformat": defaultFileFormat(), - "filetype": "unknown", - "hlsearch": false, - "hltaberrors": false, - "hltrailingws": false, - "incsearch": true, - "ignorecase": true, - "indentchar": " ", - "keepautoindent": false, - "matchbrace": true, - "matchbracestyle": "underline", - "mkparents": false, - "permbackup": false, - "readonly": false, - "reload": "prompt", - "rmtrailingws": false, - "ruler": true, - "relativeruler": false, - "savecursor": false, - "saveundo": false, - "scrollbar": false, - "scrollmargin": float64(3), - "scrollspeed": float64(2), - "smartpaste": true, - "softwrap": false, - "splitbottom": true, - "splitright": true, - "statusformatl": "$(filename) $(modified)($(line),$(col)) $(status.paste)| ft:$(opt:filetype) | $(opt:fileformat) | $(opt:encoding)", - "statusformatr": "$(bind:ToggleKeyMenu): bindings, $(bind:ToggleHelp): help", - "statusline": true, - "syntax": true, - "tabmovement": false, - "tabsize": float64(4), - "tabstospaces": false, - "useprimary": true, - "wordwrap": false, -} - func defaultFileFormat() string { if runtime.GOOS == "windows" { return "dos" @@ -337,37 +370,6 @@ func DefaultCommonSettings() map[string]interface{} { return commonsettings } -// a list of settings that should only be globally modified and their -// default values -var DefaultGlobalOnlySettings = map[string]interface{}{ - "autosave": float64(0), - "clipboard": "external", - "colorscheme": "default", - "divchars": "|-", - "divreverse": true, - "fakecursor": false, - "infobar": true, - "keymenu": false, - "mouse": true, - "multiopen": "tab", - "parsecursor": false, - "paste": false, - "pluginchannels": []string{"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json"}, - "pluginrepos": []string{}, - "savehistory": true, - "scrollbarchar": "|", - "sucmd": "sudo", - "tabhighlight": false, - "tabreverse": true, - "xterm": false, -} - -// a list of settings that should never be globally modified -var LocalSettings = []string{ - "filetype", - "readonly", -} - // DefaultGlobalSettings returns the default global settings for micro // Note that colorscheme is a global only option func DefaultGlobalSettings() map[string]interface{} { From ff9db4265a4a46d6f2d0ffb055485ee1614ec5b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6ran=20Karl?= <3951388+JoeKar@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:23:40 +0100 Subject: [PATCH 2/3] settings: Add generic string option validator --- internal/config/settings.go | 115 +++++++++++------------------------- 1 file changed, 33 insertions(+), 82 deletions(-) diff --git a/internal/config/settings.go b/internal/config/settings.go index 6ff512ecba..9c9a9312ce 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -23,20 +23,29 @@ type optionValidator func(string, interface{}) error // a list of settings that need option validators var optionValidators = map[string]optionValidator{ "autosave": validateNonNegativeValue, - "clipboard": validateClipboard, + "clipboard": validateChoice, "colorcolumn": validateNonNegativeValue, "colorscheme": validateColorscheme, "detectlimit": validateNonNegativeValue, "encoding": validateEncoding, - "fileformat": validateLineEnding, - "matchbracestyle": validateMatchBraceStyle, - "multiopen": validateMultiOpen, - "reload": validateReload, + "fileformat": validateChoice, + "matchbracestyle": validateChoice, + "multiopen": validateChoice, + "reload": validateChoice, "scrollmargin": validateNonNegativeValue, "scrollspeed": validateNonNegativeValue, "tabsize": validatePositiveValue, } +// a list of settings with pre-defined choices +var optionChoices = map[string][]string{ + "clipboard": {"internal", "external", "terminal"}, + "fileformat": {"unix", "dos"}, + "matchbracestyle": {"underline", "highlight"}, + "multiopen": {"tab", "hsplit", "vsplit"}, + "reload": {"prompt", "auto", "disabled"}, +} + // a list of settings that can be globally and locally modified and their // default values var defaultCommonSettings = map[string]interface{}{ @@ -463,45 +472,35 @@ func validateNonNegativeValue(option string, value interface{}) error { return nil } -func validateColorscheme(option string, value interface{}) error { - colorscheme, ok := value.(string) - - if !ok { - return errors.New("Expected string type for colorscheme") - } - - if !ColorschemeExists(colorscheme) { - return errors.New(colorscheme + " is not a valid colorscheme") - } - - return nil -} - -func validateClipboard(option string, value interface{}) error { - val, ok := value.(string) +func validateChoice(option string, value interface{}) error { + if choices, ok := optionChoices[option]; ok { + val, ok := value.(string) + if !ok { + return errors.New("Expected string type for " + option) + } - if !ok { - return errors.New("Expected string type for clipboard") - } + for _, v := range choices { + if val == v { + return nil + } + } - switch val { - case "internal", "external", "terminal": - default: - return errors.New(option + " must be 'internal', 'external', or 'terminal'") + choicesStr := strings.Join(choices, ", ") + return errors.New(option + " must be one of: " + choicesStr) } - return nil + return errors.New("Option has no pre-defined choices") } -func validateLineEnding(option string, value interface{}) error { - endingType, ok := value.(string) +func validateColorscheme(option string, value interface{}) error { + colorscheme, ok := value.(string) if !ok { - return errors.New("Expected string type for file format") + return errors.New("Expected string type for colorscheme") } - if endingType != "unix" && endingType != "dos" { - return errors.New("File format must be either 'unix' or 'dos'") + if !ColorschemeExists(colorscheme) { + return errors.New(colorscheme + " is not a valid colorscheme") } return nil @@ -511,51 +510,3 @@ func validateEncoding(option string, value interface{}) error { _, err := htmlindex.Get(value.(string)) return err } - -func validateMultiOpen(option string, value interface{}) error { - val, ok := value.(string) - - if !ok { - return errors.New("Expected string type for multiopen") - } - - switch val { - case "tab", "hsplit", "vsplit": - default: - return errors.New(option + " must be 'tab', 'hsplit', or 'vsplit'") - } - - return nil -} - -func validateReload(option string, value interface{}) error { - val, ok := value.(string) - - if !ok { - return errors.New("Expected string type for reload") - } - - switch val { - case "prompt", "auto", "disabled": - default: - return errors.New(option + " must be 'prompt', 'auto' or 'disabled'") - } - - return nil -} - -func validateMatchBraceStyle(option string, value interface{}) error { - val, ok := value.(string) - - if !ok { - errors.New("Expected string type for matchbracestyle") - } - - switch val { - case "underline", "highlight": - default: - return errors.New(option + " must be 'underline' or 'highlight'") - } - - return nil -} From bbc6a1ff71697c1e9b133432d46dd30e7e645cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6ran=20Karl?= <3951388+JoeKar@users.noreply.github.com> Date: Sat, 11 Nov 2023 19:25:48 +0100 Subject: [PATCH 3/3] settings: Autocomplete string options --- internal/action/infocomplete.go | 30 +++++++----------------------- internal/config/settings.go | 4 ++-- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/internal/action/infocomplete.go b/internal/action/infocomplete.go index e093123d96..ee2e27e7e8 100644 --- a/internal/action/infocomplete.go +++ b/internal/action/infocomplete.go @@ -192,13 +192,6 @@ func OptionValueComplete(b *buffer.Buffer) ([]string, []string) { _, suggestions = colorschemeComplete(input) case "filetype": _, suggestions = filetypeComplete(input) - case "fileformat": - if strings.HasPrefix("unix", input) { - suggestions = append(suggestions, "unix") - } - if strings.HasPrefix("dos", input) { - suggestions = append(suggestions, "dos") - } case "sucmd": if strings.HasPrefix("sudo", input) { suggestions = append(suggestions, "sudo") @@ -206,22 +199,13 @@ func OptionValueComplete(b *buffer.Buffer) ([]string, []string) { if strings.HasPrefix("doas", input) { suggestions = append(suggestions, "doas") } - case "clipboard": - if strings.HasPrefix("external", input) { - suggestions = append(suggestions, "external") - } - if strings.HasPrefix("internal", input) { - suggestions = append(suggestions, "internal") - } - if strings.HasPrefix("terminal", input) { - suggestions = append(suggestions, "terminal") - } - case "matchbracestyle": - if strings.HasPrefix("underline", input) { - suggestions = append(suggestions, "underline") - } - if strings.HasPrefix("highlight", input) { - suggestions = append(suggestions, "highlight") + default: + if choices, ok := config.OptionChoices[inputOpt]; ok { + for _, choice := range choices { + if strings.HasPrefix(choice, input) { + suggestions = append(suggestions, choice) + } + } } } } diff --git a/internal/config/settings.go b/internal/config/settings.go index 9c9a9312ce..78874ed667 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -38,7 +38,7 @@ var optionValidators = map[string]optionValidator{ } // a list of settings with pre-defined choices -var optionChoices = map[string][]string{ +var OptionChoices = map[string][]string{ "clipboard": {"internal", "external", "terminal"}, "fileformat": {"unix", "dos"}, "matchbracestyle": {"underline", "highlight"}, @@ -473,7 +473,7 @@ func validateNonNegativeValue(option string, value interface{}) error { } func validateChoice(option string, value interface{}) error { - if choices, ok := optionChoices[option]; ok { + if choices, ok := OptionChoices[option]; ok { val, ok := value.(string) if !ok { return errors.New("Expected string type for " + option)