diff --git a/flake.lock b/flake.lock index 81df676..3c5a887 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nix2lua": { "locked": { - "lastModified": 1716204167, - "narHash": "sha256-Jo1bjYIMy0Zj4zrkcMrcG0N2Qnhc75OnxL6fnqBG+mg=", + "lastModified": 1716215210, + "narHash": "sha256-GjwpjhNGdrGH0dElAvcKSFY3nbRw4JYOKtKMmhMsEWw=", "ref": "refs/heads/main", - "rev": "654eda07372a9a2a03e746d9758f6b39de396a83", - "revCount": 51, + "rev": "4d3ae67617c2c1301a1a90601e20e15614d20319", + "revCount": 52, "type": "git", "url": "https://git.pleshevski.ru/mynix/nix2lua" }, diff --git a/modules/plugins/snippet/luasnip.nix b/modules/plugins/snippet/luasnip.nix index 6ce6389..1997dcd 100644 --- a/modules/plugins/snippet/luasnip.nix +++ b/modules/plugins/snippet/luasnip.nix @@ -1,7 +1,177 @@ { config, lib, pkgs, ... }: let + inherit (lib.nix2lua) LuaNil scope lset pipe1 call call1; cfg = config.plugins.snippet.luasnip; + + + jump = lib.mkOption { + type = with lib.types; nullOr number; + default = null; + description = '' + This determines when this node will be jumped to. + + `:help luasnip-insertnode` + `:help luasnip-basics-jump-index` + ''; + }; + unwrapJump = index: if index == null then LuaNil else index; + + nodes = lib.mkOption { + type = with lib.types; listOf (submodule snippetNodeOpts); + }; + unwrapNodes = map (n: n.genConfig); + + genConfig = lib.mkOption { + type = lib.types.attrs; + internal = true; + }; + + snippetNodeOpts = { config, ... }: { + options = with lib; with types; { + text = mkOption { + type = nullOr (either str (listOf str)); + default = null; + }; + + insert = mkOption { + type = nullOr (either number (submodule ({ ... }: { + options = { + inherit jump; + text = mkOption { + type = nullOr (either str (listOf str)); + default = null; + description = '' + A single string for just one line, a list with entries for multiple lines. + This text will be SELECTed when the `insertNode` is jumped into. + + `:help luasnip-insertnode` + ''; + }; + }; + }))); + default = null; + }; + + choice = mkOption { + type = nullOr (submodule ({ ... }: { + options = { inherit jump nodes; }; + })); + default = null; + }; + + snippet = mkOption { + type = nullOr (submodule ({ ... }: { + options = { + inherit jump nodes; + indent = mkOption { + type = types.str; + default = ""; + }; + }; + })); + default = null; + }; + + inherit genConfig; + }; + + config = { + genConfig = + let + ins = config.insert; + ch = config.choice; + sn = config.snippet; + in + if config.text != null then call1 "t" config.text + else if ins != null then + if builtins.isInt ins then call "i" [ ins ] + else call "i" [ (unwrapJump ins.jump) ins.text ] + else if ch != null then + call "c" [ (unwrapJump ch.jump) (unwrapNodes ch.nodes) ] + else if sn != null then + if sn.indent != "" then + call "isn" [ (unwrapJump sn.jump) (unwrapNodes sn.nodes) sn.indent ] + else call "sn" [ (unwrapJump sn.jump) (unwrapNodes sn.nodes) ] + else null; + }; + }; + + snippetOpts = { name, ... } @ sub: { + options = with lib; with types; { + context = mkOption { + type = either str attrs; + description = '' + `:help luasnip-snippets'; + ''; + }; + + nodes = nodes // { default = [ ]; }; + + inherit genConfig; + }; + + config = { + context = lib.mkDefault name; + + genConfig = call "s" [ sub.config.context (unwrapNodes sub.config.nodes) ]; + }; + }; + + snippetGroupOpts = { ... } @ sub: { + options = with lib; { + filetype = mkOption { + type = types.str; + }; + + opts = { + type = mkOption { + type = types.nullOr (types.enum [ "snippets" "autosnippets" ]); + default = null; + }; + key = mkOption { + type = types.nullOr types.str; + default = null; + }; + override_priority = mkOption { + type = types.nullOr types.number; + default = null; + description = '' + Set priority for all snippets. + + `:help luasnip-api` + ''; + }; + default_priority = mkOption { + type = types.nullOr types.number; + default = null; + description = '' + Set priority only for snippets without snippet priority. + + `:help luasnip-api` + ''; + }; + }; + + snippets = mkOption { + type = types.attrsOf (types.submodule snippetOpts); + default = { }; + }; + + inherit genConfig; + }; + + config = { + genConfig = + let plugin = config.plugin.luasnip; in + let inherit (sub.config) filetype snippets opts; in + pipe1 plugin.var (call "add_snippets" [ + filetype + (map (s: s.genConfig) (builtins.attrValues snippets)) + opts + ]); + }; + }; in { options.plugins.snippet.luasnip = with lib; { @@ -13,12 +183,34 @@ in type = types.attrs; default = { }; }; + + snippetGroups = mkOption { + type = types.listOf (types.submodule snippetGroupOpts); + default = [ ]; + }; }; config = lib.mkIf cfg.enable { - plugin.luasnip = { + plugin.luasnip = rec { inherit (cfg) package; + varName = "luasnip"; setupSettings = cfg.settings; + afterSetup = lib.mkIf (cfg.snippetGroups != [ ]) [ + (scope (lib.flatten [ + (lib.mapAttrsToList (k: v: lset k (pipe1 varName v)) { + s = "snippet"; + sn = "snippet_node"; + isn = "indent_snippet_node"; + t = "text_node"; + i = "insert_node"; + f = "function_node"; + c = "choice_node"; + d = "dynamic_node"; + r = "restore_node"; + }) + (map (sg: sg.genConfig) cfg.snippetGroups) + ])) + ]; }; }; }