From 933c87c282b83f2f850145491665f91e4ebcce42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=A9tan=20Lepage?= <33058747+GaetanLepage@users.noreply.github.com> Date: Sun, 12 Mar 2023 11:49:41 +0100 Subject: [PATCH] plugins/todo-comments: refactoring + tests (#239) --- plugins/utils/todo-comments.nix | 299 +++++++++++++++++++++----------- tests/plugins/todo-comments.nix | 112 ++++++++++++ 2 files changed, 305 insertions(+), 106 deletions(-) create mode 100644 tests/plugins/todo-comments.nix diff --git a/plugins/utils/todo-comments.nix b/plugins/utils/todo-comments.nix index 151a71b6..62362959 100644 --- a/plugins/utils/todo-comments.nix +++ b/plugins/utils/todo-comments.nix @@ -7,6 +7,13 @@ with lib; let cfg = config.plugins.todo-comments; helpers = import ../helpers.nix {inherit lib;}; + + commands = { + todoQuickFix = "TodoQuickFix"; + todoLocList = "TodoLocList"; + todoTrouble = "TodoTrouble"; + todoTelescope = "TodoTelescope"; + }; in { options = { plugins.todo-comments = @@ -19,103 +26,109 @@ in { "todo-comments" pkgs.vimPlugins.todo-comments-nvim; - signs = helpers.defaultNullOpts.mkBool true '' - Show icons in the signs column. - ''; + signs = helpers.defaultNullOpts.mkBool true "Show icons in the signs column."; signPriority = helpers.defaultNullOpts.mkInt 8 "Sign priority."; - keywords = helpers.mkNullOrOption (types.nullOr types.attrs) '' - Configurations for keywords to be recognized as todo comments. - - Default: - ``` - { - FIX = { - icon = " "; # Icon used for the sign, and in search results. - color = "error"; # Can be a hex color, or a named color. - alt = [ "FIXME" "BUG" "FIXIT" "ISSUE" ]; # A set of other keywords that all map to this FIX keywords. - }; - TODO = { icon = " "; color = "info"; }; - HACK = { icon = " "; color = "warning"; }; - WARN = { icon = " "; color = "warning"; alt = [ "WARNING" "XXX" ]; }; - PERF = { icon = " "; alt = [ "OPTIM" "PERFORMANCE" "OPTIMIZE" ]; }; - NOTE = { icon = " "; color = "hint"; alt = [ "INFO" ]; }; - TEST = { icon = "⏲ "; color = "test"; alt = [ "TESTING" "PASSED" "FAILED" ]; }; - }; - ``` - ''; - - guiStyle = mkOption { - description = "The gui style for highlight groups."; - default = null; - type = types.nullOr (types.submodule ({...}: { + keywords = + helpers.mkNullOrOption + (types.attrsOf (types.submodule { options = { - fg = helpers.defaultNullOpts.mkStr "NONE" '' - The gui style to use for the fg highlight group. + icon = helpers.mkNullOrOption types.str '' + Icon used for the sign, and in search results. ''; - bg = helpers.defaultNullOpts.mkStr "BOLD" '' - The gui style to use for the bg highlight group. + + color = helpers.mkNullOrOption types.str '' + Can be a hex color, or a named color. + ''; + + alt = helpers.mkNullOrOption (types.listOf types.str) '' + A set of other keywords that all map to this FIX keywords. + ''; + + signs = helpers.mkNullOrOption types.bool '' + Configure signs for some keywords individually. ''; }; - })); + })) + '' + Configurations for keywords to be recognized as todo comments. + + Default: + ``` + { + FIX = { + icon = " "; # Icon used for the sign, and in search results. + color = "error"; # Can be a hex color, or a named color. + alt = [ "FIXME" "BUG" "FIXIT" "ISSUE" ]; # A set of other keywords that all map to this FIX keywords. + }; + TODO = { icon = " "; color = "info"; }; + HACK = { icon = " "; color = "warning"; }; + WARN = { icon = " "; color = "warning"; alt = [ "WARNING" "XXX" ]; }; + PERF = { icon = " "; alt = [ "OPTIM" "PERFORMANCE" "OPTIMIZE" ]; }; + NOTE = { icon = " "; color = "hint"; alt = [ "INFO" ]; }; + TEST = { icon = "⏲ "; color = "test"; alt = [ "TESTING" "PASSED" "FAILED" ]; }; + }; + ``` + ''; + + guiStyle = helpers.mkCompositeOption "The gui style for highlight groups." { + fg = helpers.defaultNullOpts.mkStr "NONE" '' + The gui style to use for the fg highlight group. + ''; + + bg = helpers.defaultNullOpts.mkStr "BOLD" '' + The gui style to use for the bg highlight group. + ''; }; mergeKeywords = helpers.defaultNullOpts.mkBool true '' When true, custom keywords will be merged with the default ''; - highlight = mkOption { - description = "Highlight options"; - default = null; - type = types.nullOr (types.submodule ({...}: { - options = { - multiline = helpers.defaultNullOpts.mkBool true '' - Enable multiline todo comments. - ''; + highlight = helpers.mkCompositeOption "Highlight options." { + multiline = helpers.defaultNullOpts.mkBool true '' + Enable multiline todo comments. + ''; - multilinePattern = helpers.defaultNullOpts.mkStr "^." '' - Lua pattern to match the next multiline from the start of the - matched keyword. - ''; + multilinePattern = helpers.defaultNullOpts.mkStr "^." '' + Lua pattern to match the next multiline from the start of the + matched keyword. + ''; - multilineContext = helpers.defaultNullOpts.mkInt 10 '' - Extra lines that will be re-evaluated when changing a line. - ''; + multilineContext = helpers.defaultNullOpts.mkInt 10 '' + Extra lines that will be re-evaluated when changing a line. + ''; - before = helpers.defaultNullOpts.mkStr "" '' - "fg" or "bg" or empty. - ''; + before = helpers.defaultNullOpts.mkStr "" '' + "fg" or "bg" or empty. + ''; - keyword = helpers.defaultNullOpts.mkStr "wide" '' - "fg", "bg", "wide", "wide_bg", "wide_fg" or empty. - (wide and wide_bg is the same as bg, but will also highlight - surrounding characters, wide_fg acts accordingly but with fg). - ''; + keyword = helpers.defaultNullOpts.mkStr "wide" '' + "fg", "bg", "wide", "wide_bg", "wide_fg" or empty. + (wide and wide_bg is the same as bg, but will also highlight + surrounding characters, wide_fg acts accordingly but with fg). + ''; - after = helpers.defaultNullOpts.mkStr "fg" '' - "fg" or "bg" or empty. - ''; + after = helpers.defaultNullOpts.mkStr "fg" '' + "fg" or "bg" or empty. + ''; - pattern = - helpers.mkNullOrOption - (types.oneOf [types.str (types.listOf types.str)]) '' - Pattern or list of patterns, used for highlighting (vim regex) - ''; + pattern = helpers.mkNullOrOption (with types; either str (listOf str)) '' + Pattern or list of patterns, used for highlighting (vim regex) + ''; - commentsOnly = helpers.defaultNullOpts.mkBool true '' - Uses treesitter to match keywords in comments only. - ''; + commentsOnly = helpers.defaultNullOpts.mkBool true '' + Uses treesitter to match keywords in comments only. + ''; - maxLineLen = helpers.defaultNullOpts.mkInt 400 '' - Ignore lines longer than this. - ''; + maxLineLen = helpers.defaultNullOpts.mkInt 400 '' + Ignore lines longer than this. + ''; - exclude = helpers.mkNullOrOption (types.listOf types.str) '' - List of file types to exclude highlighting. - ''; - }; - })); + exclude = helpers.mkNullOrOption (types.listOf types.str) '' + List of file types to exclude highlighting. + ''; }; colors = @@ -137,35 +150,64 @@ in { ``` ''; - search = mkOption { - description = "Search options."; - default = null; - type = types.nullOr (types.submodule ({...}: { - options = { - command = helpers.defaultNullOpts.mkStr "rg" '' - Command to use for searching for keywords. - ''; - args = helpers.mkNullOrOption (types.listOf types.str) '' - Arguments to use for the search command in list form. + search = helpers.mkCompositeOption "Search options." { + command = helpers.defaultNullOpts.mkStr "rg" "Command to use for searching for keywords."; - Default: - ``` - [ - "--color=never" - "--no-heading" - "--with-filename" - "--line-number" - "--column" - ]; - ``` - ''; - pattern = helpers.defaultNullOpts.mkStr "[[\b(KEYWORDS):]]" '' - Regex that will be used to match keywords. - Don't replace the (KEYWORDS) placeholder. - ''; - }; - })); + args = helpers.mkNullOrOption (types.listOf types.str) '' + Arguments to use for the search command in list form. + + Default: + ``` + [ + "--color=never" + "--no-heading" + "--with-filename" + "--line-number" + "--column" + ]; + ``` + ''; + + pattern = helpers.defaultNullOpts.mkStr "[[\b(KEYWORDS):]]" '' + Regex that will be used to match keywords. + Don't replace the (KEYWORDS) placeholder. + ''; }; + + # Keyboard shortcuts for :Todo* commands + keymapsSilent = mkOption { + type = types.bool; + description = "Whether todo-comments keymaps should be silent."; + default = false; + }; + + keymaps = let + mkKeymapOption = optionName: funcName: + helpers.mkCompositeOption "Keymap settings for the `:${funcName}` function." { + key = mkOption { + type = types.str; + description = "Key for the `${funcName}` function."; + }; + + cwd = mkOption { + type = types.nullOr types.str; + description = "Specify the directory to search for comments"; + default = null; + example = "~/projects/foobar"; + }; + + keywords = mkOption { + type = types.nullOr types.str; + description = '' + Comma separated list of keywords to filter results by. + Keywords are case-sensitive. + ''; + default = null; + example = "TODO,FIX"; + }; + }; + in + mapAttrs mkKeymapOption commands; }; }; @@ -173,11 +215,25 @@ in { setupOptions = { signs = cfg.signs; - signPriority = cfg.signPriority; + sign_priority = cfg.signPriority; keywords = cfg.keywords; - guiStyle = cfg.guiStyle; - mergeKeywords = cfg.mergeKeywords; - highlight = cfg.highlight; + gui_style = cfg.guiStyle; + merge_keywords = cfg.mergeKeywords; + highlight = helpers.ifNonNull' cfg.highlight { + inherit + (cfg.highlight) + multiline + before + keyword + after + pattern + exclude + ; + multiline_pattern = cfg.highlight.multilinePattern; + multiline_context = cfg.highlight.multilineContext; + comments_only = cfg.highlight.commentsOnly; + max_line_len = cfg.highlight.maxLineLen; + }; colors = cfg.colors; search = cfg.search; } @@ -188,5 +244,36 @@ in { extraConfigLua = '' require("todo-comments").setup${helpers.toLuaObject setupOptions} ''; + + maps.normal = let + silent = cfg.keymapsSilent; + keymaps = cfg.keymaps; + in + mkMerge ( + mapAttrsToList + ( + optionName: funcName: let + keymap = keymaps.${optionName}; + + key = keymap.key; + + cwd = optionalString (!isNull keymap.cwd) " cwd=${keymap.cwd}"; + keywords = optionalString (!isNull keymap.keywords) " keywords=${keymap.keywords}"; + + action = ":${funcName}${cwd}${keywords}"; + in (mkIf (keymap != null) { + ${key} = { + inherit silent action; + }; + }) + ) + commands + ); + + # Automatically enable plugins if keymaps have been set + plugins = mkMerge [ + (mkIf (!isNull cfg.keymaps.todoTrouble) {trouble.enable = true;}) + (mkIf (!isNull cfg.keymaps.todoTelescope) {telescope.enable = true;}) + ]; }; } diff --git a/tests/plugins/todo-comments.nix b/tests/plugins/todo-comments.nix new file mode 100644 index 00000000..f8e1030c --- /dev/null +++ b/tests/plugins/todo-comments.nix @@ -0,0 +1,112 @@ +{ + # Empty configuration + empty = { + plugins.todo-comments.enable = true; + }; + + # All the upstream default options of todo-comments + defaults = { + plugins.todo-comments = { + enable = true; + + signs = true; + signPriority = 8; + + keywords = { + FIX = { + icon = " "; + color = "error"; + alt = ["FIXME" "BUG" "FIXIT" "ISSUE"]; + signs = false; + }; + TODO = { + icon = " "; + color = "info"; + }; + HACK = { + icon = " "; + color = "warning"; + }; + WARN = { + icon = " "; + color = "warning"; + alt = ["WARNING" "XXX"]; + }; + PERF = { + icon = " "; + alt = ["OPTIM" "PERFORMANCE" "OPTIMIZE"]; + }; + NOTE = { + icon = " "; + color = "hint"; + alt = ["INFO"]; + }; + TEST = { + icon = "⏲ "; + color = "test"; + alt = ["TESTING" "PASSED" "FAILED"]; + }; + }; + + guiStyle = { + fg = "NONE"; + bg = "BOLD"; + }; + + mergeKeywords = true; + + highlight = { + multiline = true; + multilinePattern = "^."; + multilineContext = 10; + before = ""; + keyword = "wide"; + after = "fg"; + pattern = "[[.*<(KEYWORDS)\s*:]]"; + commentsOnly = true; + maxLineLen = 400; + exclude = []; + }; + + colors = { + error = ["DiagnosticError" "ErrorMsg" "#DC2626"]; + warning = ["DiagnosticWarn" "WarningMsg" "#FBBF24"]; + info = ["DiagnosticInfo" "#2563EB"]; + hint = ["DiagnosticHint" "#10B981"]; + default = ["Identifier" "#7C3AED"]; + test = ["Identifier" "#FF00FF"]; + }; + + search = { + command = "rg"; + args = [ + "--color=never" + "--no-heading" + "--with-filename" + "--line-number" + "--column" + ]; + pattern = "[[\b(KEYWORDS):]]"; + }; + + keymapsSilent = true; + + keymaps = { + todoQuickFix.key = ""; + todoLocList = { + key = ""; + cwd = "~/projects/foobar"; + keywords = "TODO,FIX"; + }; + todoTrouble = { + key = ""; + keywords = "TODO,FIX"; + }; + todoTelescope = { + key = ""; + cwd = "~/projects/foobar"; + }; + }; + }; + }; +}