diff --git a/builder/default.nix b/builder/default.nix index 94bcffd2..3b15a51d 100644 --- a/builder/default.nix +++ b/builder/default.nix @@ -67,6 +67,7 @@ let extraCats = {}; } // (categoryDefinitions { # categories depends on extraCats + extra = extraTableLua; inherit categories settings pkgs name; })); inherit (final_cat_defs_set) @@ -78,6 +79,7 @@ let optionalLuaPreInit bashBeforeWrapper; categories = ncTools.applyExtraCats (thisPackage.categories or {}) final_cat_defs_set.extraCats; + extraTableLua = thisPackage.extra or {}; in let @@ -99,7 +101,7 @@ in isStdCfgPath = settings.wrapRc == false && ! builtins.isString settings.unwrappedCfgPath; nixCats_config_location = if isUnwrappedCfgPath then "${settings.unwrappedCfgPath}" - else if isStdCfgPath then ncTools.mkLuaInline ''vim.fn.stdpath("config")'' + else if isStdCfgPath then ncTools.types.inline-unsafe.mk { body = ''vim.fn.stdpath("config")''; } else "${LuaConfig}"; categoriesPlus = categories // { @@ -117,6 +119,7 @@ in settingsTable = ncTools.mkLuaFileWithMeta "settings" settingsPlus; petShop = ncTools.mkLuaFileWithMeta "petShop" all_def_names; depsTable = ncTools.mkLuaFileWithMeta "pawsible" allPluginDeps; + extraItems = ncTools.mkLuaFileWithMeta "extra" extraTableLua; in { name = "nixCats"; builder = pkgs.writeText "builder.sh" /*bash*/ '' @@ -129,6 +132,7 @@ in cp ${settingsTable} $out/lua/nixCats/settings.lua cp ${depsTable} $out/lua/nixCats/pawsible.lua cp ${petShop} $out/lua/nixCats/petShop.lua + cp ${extraItems} $out/lua/nixCats/extra.lua cp -r ${../nixCatsHelp}/* $out/doc/ ''; }); diff --git a/builder/ncTools.nix b/builder/ncTools.nix index 745fd1a3..f903f8e8 100644 --- a/builder/ncTools.nix +++ b/builder/ncTools.nix @@ -3,107 +3,33 @@ { lib, writeText, ... }: with builtins; rec { # NIX CATS INTERNAL UTILS: - mkLuaFileWithMeta = modname: table: writeText "${modname}.lua" /*lua*/'' - local ${modname} = ${toLua table}; - return setmetatable(${modname}, { - __call = function(self, attrpath) - local strtable = {} - if type(attrpath) == "table" then - strtable = attrpath - elseif type(attrpath) == "string" then - for key in attrpath:gmatch("([^%.]+)") do - table.insert(strtable, key) - end - else - print("function requires a table of strings or a dot separated string") - return - end - if #strtable == 0 then return nil end - local tbl = ${modname}; - for _, key in ipairs(strtable) do - if type(tbl) ~= "table" then return nil end - tbl = tbl[key] - end - return tbl + inherit (import ../utils/n2l.nix) toLua types; + + mkLuaFileWithMeta = modname: table: writeText "${modname}.lua" /*lua*/ '' + local ${modname} = ${toLua table}; + return setmetatable(${modname}, { + __call = function(self, attrpath) + local strtable = {} + if type(attrpath) == "table" then + strtable = attrpath + elseif type(attrpath) == "string" then + for key in attrpath:gmatch("([^%.]+)") do + table.insert(strtable, key) + end + else + print('function requires a { "list", "of", "strings" } or a "dot.separated.string"') + return + end + if #strtable == 0 then return nil end + local tbl = ${modname}; + for _, key in ipairs(strtable) do + if type(tbl) ~= "table" then return nil end + tbl = tbl[key] end - }) + return tbl + end + }) ''; - - mkLuaInline = expr: { __type = "nix-to-lua-inline"; inherit expr; }; - - toLua = toLuaInternal {}; - - toLuaInternal = { - pretty ? true, - indentSize ? 2, - # adds indenting to multiline strings - # and multiline lua expressions - formatstrings ? false, # <-- only active if pretty is true - ... - }: input: let - - genStr = str: num: concatStringsSep "" (genList (_: str) num); - - isLuaInline = toCheck: toCheck.__type or "" == "nix-to-lua-inline" && toCheck ? expr; - - luaToString = LI: "assert(loadstring(${luaEnclose "return ${LI.expr}"}))()"; - - luaEnclose = inString: let - measureLongBois = inString: let - normalize_split = list: filter (x: x != null && x != "") - (concatMap (x: if isList x then x else [ ]) list); - splitter = str: normalize_split (split "(\\[=*\\[)|(]=*])" str); - counter = str: map stringLength (splitter str); - getMax = str: foldl' (max: x: if x > max then x else max) 0 (counter str); - getEqSigns = str: (getMax str) - 2; - longBoiLength = getEqSigns inString; - in - if longBoiLength >= 0 then longBoiLength + 1 else 0; - - eqNum = measureLongBois inString; - eqStr = genStr "=" eqNum; - bL = "[" + eqStr + "["; - bR = "]" + eqStr + "]"; - in - bL + inString + bR; - - nl_spc = level: if pretty == true - then "\n${genStr " " (level * indentSize)}" else " "; - - doSingleLuaValue = level: value: let - replacer = str: if pretty && formatstrings then replaceStrings [ "\n" ] [ "${nl_spc level}" ] str else str; - in - if value == true then "true" - else if value == false then "false" - else if value == null then "nil" - else if isFloat value || isInt value then toString value - else if isList value then "${luaListPrinter level value}" - else if isLuaInline value then replacer (luaToString value) - else if value ? outPath then luaEnclose "${value.outPath}" - else if lib.isDerivation value then luaEnclose "${value}" - else if isAttrs value then "${luaTablePrinter level value}" - else replacer (luaEnclose (toString value)); - - luaTablePrinter = level: attrSet: let - nameandstringmap = mapAttrs (n: value: let - name = "[ " + (luaEnclose "${n}") + " ]"; - in - "${name} = ${doSingleLuaValue (level + 1) value}") attrSet; - resultList = attrValues nameandstringmap; - catset = concatStringsSep ",${nl_spc (level + 1)}" resultList; - LuaTable = "{${nl_spc (level + 1)}" + catset + "${nl_spc level}}"; - in - LuaTable; - - luaListPrinter = level: theList: let - stringlist = map (doSingleLuaValue (level + 1)) theList; - catlist = concatStringsSep ",${nl_spc (level + 1)}" stringlist; - LuaList = "{${nl_spc (level + 1)}" + catlist + "${nl_spc level}}"; - in - LuaList; - - in - doSingleLuaValue 0 input; # returns a flattened list with only those lists # whose name was associated with a true value within the categories set diff --git a/builder/nixCats.lua b/builder/nixCats.lua index bfb8203b..693a9100 100644 --- a/builder/nixCats.lua +++ b/builder/nixCats.lua @@ -6,6 +6,7 @@ M.cats = require('nixCats.cats') M.pawsible = require('nixCats.pawsible') M.settings = require('nixCats.settings') M.petShop = require('nixCats.petShop') +M.extra = require('nixCats.extra') M.configDir = M.settings.nixCats_config_location -- NOTE: nixCats is inside of these and thus they could not be written into nixCats -- due to infinite recursion, so they are variables instead. @@ -22,7 +23,7 @@ function M.get(category) table.insert(strtable, key) end else - print("get function requires a table of strings or a dot separated string") + print([[function requires a { "list", "of", "strings" } or a "dot.separated.string"]]) return end ---@type any @@ -48,6 +49,7 @@ function M.addGlobals() "settings", "pawsible", "petShop", + "extra", "vimPackDir", "configDir", "nixCatsPath", diff --git a/builder/nixCatsMeta.lua b/builder/nixCatsMeta.lua index c87973db..f9786a77 100644 --- a/builder/nixCatsMeta.lua +++ b/builder/nixCatsMeta.lua @@ -10,6 +10,9 @@ error("Cannot import a meta module") ---See :h nixCats.flake.outputs.settings ---Function form will return vim.tbl_get for the attrpath ---@field settings table|fun(attrpath: string|string[]): any +---See :h nixCats.flake.outputs.packageDefinitions +---Function form will return vim.tbl_get for the attrpath +---@field extra table|fun(attrpath: string|string[]): any ---Contains the final set of plugins added for this package ---Function form will return vim.tbl_get for the attrpath ---@field pawsible table|fun(attrpath: string|string[]): any diff --git a/builder/vim-pack-dir.nix b/builder/vim-pack-dir.nix index 7f134ea2..87e90553 100644 --- a/builder/vim-pack-dir.nix +++ b/builder/vim-pack-dir.nix @@ -7,7 +7,6 @@ , python3 , symlinkJoin , linkFarm - , callPackage , collate_grammars ? false }: let # NOTE: define helpers for packDir function here: @@ -36,10 +35,10 @@ , ... }: let - inherit (callPackage ./ncTools.nix { }) mkLuaInline; + inherit (import ../utils/n2l.nix) types; # lazy.nvim wrapper uses this value to add the parsers back. ts_grammar_path = if collate_grammars then ts_grammar_plugin_combined else - mkLuaInline "vim.g[ [[nixCats-special-rtp-entry-vimPackDir]] ] .. [[/pack/${grammarPackName}/start/*]]"; + types.inline-unsafe.mk { body = "vim.g[ [[nixCats-special-rtp-entry-vimPackDir]] ] .. [[/pack/${grammarPackName}/start/*]]"; }; mkEntryFromDrv = drv: { name = "${lib.getName drv}"; value = drv; }; fullDeps = { @@ -61,7 +60,7 @@ destination = "/lua/nixCats/saveTheCats.lua"; }); nixCatsFinal = nixCats fullDeps; - in # we add the plugin with ALL the parsers if its the old way, if its the new way, it will be in our packpath already + in # add fully called nixCats plugin along with another to save its path. [ nixCatsFinal (nixCatsDir nixCatsFinal) ]; # gets plugin.dependencies from diff --git a/nixCatsHelp/nixCats_format.txt b/nixCatsHelp/nixCats_format.txt index 445e5d40..332b8caf 100644 --- a/nixCatsHelp/nixCats_format.txt +++ b/nixCatsHelp/nixCats_format.txt @@ -268,7 +268,7 @@ which allows categoryDefinitions to be much more dynamic. These are the things you can return: >nix - categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: { < a flexible set of categories, each containing LSP's or @@ -485,7 +485,7 @@ included the go category, it could then enable debug.go and lsp.go for you. But in addition to that, it can be combined with the implicit form of creating default values above in an interesting way. >nix - categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: { lspsAndRuntimeDeps = { debug = with pkgs; { go = [ delve ]; @@ -574,7 +574,19 @@ an example package definition: # builtins.toString on it and passes it in as a string theBestCat = "says meow!!!"; # maybe you need to pass a port or path in or something idk. - # you could :lua print(require('nixCats').theBestCat) + # you could :lua =nixCats("theBestCat") + # this nixCats("path.to.val") is the main category check function + # and it is built to mirror the nix category scheme as much as possible + }; + extra = { + there_is = "also"; + an_extra = "table"; + for = ''if you dont want the main subcategory get function + to apply to something, or think it all being in categories is too + messy + ''; + you_can = ''nixCats.extra("path.to.val")''; + for_safer = ''table access via vim.tbl_get''; }; }; }; @@ -872,6 +884,7 @@ They look something like this: inherit (utils) templates; }; < + *nixCats.flake.outputs.utils* We also export the set so we can get it easier later, along with which are inside it. @@ -1024,15 +1037,96 @@ whole outputs section instead of eachSystem, it would add the It is the same thing as `nixpkgs.lib.genAttrs`, renamed so that people know how to use it. - luaCode: -This helper can be used in the `packageDefinitions` set in order to write -unescaped lua code into the nixCats plugin. + *nixCats.flake.outputs.utils.n2l* + This is the nix to lua library nixCats +uses to create the nixCats lua plugin +You may wish to use some functions from it. + +It contains and and which convert nix to lua. + +it contains a function to determine if a value is a special "inline lua" type +it contains a function to determine which special "inline lua" type it is +it contains a function which knows how to resolve the types to a string of code +it contains the name as well. + +But of much more interest to you is the types you may declare. + +Everything being passed through settings, categories, and extra in packageDefinitions +will be properly escaped. But this also means that +you cannot write any lua code there. + +Luckily, we have some types we can declare that will allow you to do this. -For example, if `settings.wrapRc = false;` and `settings.unwrappedCfgPath` -is NOT set, nixCats uses this function to make -your config path default to the value of: -`nixCats_config_location = utils.mkLuaInline "vim.fn.stdpath('config')"` +To declare that an item is a lua value rather than a hard coded one, +you may choose one of these types. To do this, call its constructor! +for example, `types.inline-unsafe` has 1 field, `body`. + +To declare one in our settings, categories, and extra sets, it would look +something like this: +>nix + categories = { + somecat = utils.n2l.types.inline-unsafe.mk {body = "vim.fn.stdpath('data')"; }` + } +< +`inline-safe` is the default type, and it gets to define a shorthand form. +>nix + categories = { + somecat = utils.n2l.types.inline-safe.mk "vim.fn.stdpath('data')";` + } +< +These are all the types, each one has an associated `mk` +function to create a value of that type, +which accepts the fields listed here, defined with default values. +>nix + # creates an inline lua value in a way that cant break the table + inline-safe = { + default = (v: if v ? body then v else { body = v; }); + fields = { body = "nil"; }; + format = LI: "assert(loadstring(${luaEnclose "return ${LI.expr.body or LI.expr or "nil"}"}))()"; + }; + # iterpolates whatever string you provide into the table raw + inline-unsafe = { + fields = { body = "nil"; }; + format = LI: "${LI.expr.body or "nil"}"; + }; + # creates a function with args of the names given in args list + # does so in a way where you cannot accidentally break the table + function-safe = { + fields = { body = "return nil"; args = []; }; + format = LI: + ''assert(loadstring(${luaEnclose ''return (function(${fixargs (LI.expr.args or [])}) ${LI.expr.body or "return nil"} end)''}))()''; + }; + # creates a function with args of the names given in args list + # interpolates the body segment raw, just like inline-unsafe, but in a function + function-unsafe = { + fields = { body = "return nil"; args = []; }; + format = LI: ''(function(${fixargs (LI.expr.args or [])}) ${LI.expr.body or "return nil"} end)''; + }; +< + +Some more useage examples: +>nix + exampleSafeFunc = utils.n2l.types.function-safe.mk { + args = [ "hello" ]; + body = /*lua*/ '' + print(hello) + return hi + ''; + }; + exampleUnsafeFunc = utils.n2l.types.function-unsafe.mk { + args = [ "hi" "hello" ]; + body = /*lua*/ '' + print(hi) + print(hello) + return hi .. hello + ''; + }; + }; + funcResults = { + test1 = utils.n2l.types.inline-safe.mk ''${utils.n2l.resolve exampleSafeFunc}("Hello World!")''; + }; +< --------------------------------------------------------------------------------------- Nix OS Module *nixCats.flake.outputs.exports.mkNixosModules* *nixCats.flake.outputs.exports.mkHomeModules* diff --git a/nixCatsHelp/nixCats_plugin.txt b/nixCatsHelp/nixCats_plugin.txt index 207092cb..9025bbd7 100644 --- a/nixCatsHelp/nixCats_plugin.txt +++ b/nixCatsHelp/nixCats_plugin.txt @@ -225,6 +225,9 @@ has the `cat` subcommand to preview the value from `nixCats("catname")`, ---See :h nixCats.flake.outputs.settings ---Function form will return vim.tbl_get for the attrpath ---@field settings table|fun(attrpath: string|string[]): any + ---See :h nixCats.flake.outputs.packageDefinitions + ---Function form will return vim.tbl_get for the attrpath + ---@field extra table|fun(attrpath: string|string[]): any ---Contains the final set of plugins added for this package ---Function form will return vim.tbl_get for the attrpath ---@field pawsible table|fun(attrpath: string|string[]): any diff --git a/nixCatsHelp/tags b/nixCatsHelp/tags index 3c136467..ab61501e 100644 --- a/nixCatsHelp/tags +++ b/nixCatsHelp/tags @@ -17,6 +17,8 @@ nixCats.flake.outputs.getOverlays nixCats_format.txt /*nixCats.flake.outputs.get nixCats.flake.outputs.overlays nixCats_format.txt /*nixCats.flake.outputs.overlays* nixCats.flake.outputs.packageDefinitions nixCats_format.txt /*nixCats.flake.outputs.packageDefinitions* nixCats.flake.outputs.settings nixCats_format.txt /*nixCats.flake.outputs.settings* +nixCats.flake.outputs.utils nixCats_format.txt /*nixCats.flake.outputs.utils* +nixCats.flake.outputs.utils.n2l nixCats_format.txt /*nixCats.flake.outputs.utils.n2l* nixCats.installation_options nixCats_installation.txt /*nixCats.installation_options* nixCats.luaUtils nixCats_luaUtils.txt /*nixCats.luaUtils* nixCats.luaUtils.intro nixCats_luaUtils.txt /*nixCats.luaUtils.intro* diff --git a/templates/example/flake.nix b/templates/example/flake.nix index 43feed59..c65affe6 100644 --- a/templates/example/flake.nix +++ b/templates/example/flake.nix @@ -96,7 +96,7 @@ # see :help nixCats.flake.outputs.categories # and # :help nixCats.flake.outputs.categoryDefinitions.scheme - categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: { # to define and use a new category, simply add a new list to a set here, # and later, you will include categoryname = true; in the set you # provide when you build the package using this builder function. @@ -383,6 +383,7 @@ nixpkgs = nixpkgs; }; }; + extra = {}; }; regularCats = { pkgs, ... }@misc: { settings = { @@ -419,7 +420,13 @@ nixpkgs = nixpkgs; }; theBestCat = "says meow!!"; + }; + extra = { # yes even tortured inputs work. + # extra is just for extra stuff. It works just like categories + # except it doesnt control what gets included, and + # nixCats.extra("attr.path") behaves like vim.tbl_get + # unlike nixCats('attr.path') theWorstCat = { thing'1 = [ "MEOW" '']]' ]=][=[HISSS]]"[['' ]; thing2 = [ @@ -427,7 +434,7 @@ thing3 = [ "give" "treat" ]; } "I LOVE KEYBOARDS" - (utils.mkLuaInline ''[[I am a]] .. [[ lua ]] .. type("value")'') + (utils.n2l.types.inline-safe.mk ''[[I am a]] .. [[ lua ]] .. type("value")'') ]; thing4 = "couch is for scratching"; }; diff --git a/templates/example/lua/nixCatsUtils/init.lua b/templates/example/lua/nixCatsUtils/init.lua index cec1fbbe..36ff9123 100644 --- a/templates/example/lua/nixCatsUtils/init.lua +++ b/templates/example/lua/nixCatsUtils/init.lua @@ -56,6 +56,7 @@ function M.setup(v) wrapRc = false, }), petShop = mk_with_meta({}), + extra = mk_with_meta({}), pawsible = mk_with_meta({ allPlugins = { start = {}, diff --git a/templates/fresh/flake.nix b/templates/fresh/flake.nix index 8ae7caba..09ac8d4f 100644 --- a/templates/fresh/flake.nix +++ b/templates/fresh/flake.nix @@ -85,7 +85,7 @@ # see :help nixCats.flake.outputs.categories # and # :help nixCats.flake.outputs.categoryDefinitions.scheme - categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: { # to define and use a new category, simply add a new list to a set here, # and later, you will include categoryname = true; in the set you # provide when you build the package using this builder function. diff --git a/templates/kickstart-nvim/flake.nix b/templates/kickstart-nvim/flake.nix index f396b622..47f92dc5 100644 --- a/templates/kickstart-nvim/flake.nix +++ b/templates/kickstart-nvim/flake.nix @@ -85,7 +85,7 @@ # see :help nixCats.flake.outputs.categories # and # :help nixCats.flake.outputs.categoryDefinitions.scheme - categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: { # to define and use a new category, simply add a new list to a set here, # and later, you will include categoryname = true; in the set you # provide when you build the package using this builder function. diff --git a/templates/kickstart-nvim/lua/nixCatsUtils/init.lua b/templates/kickstart-nvim/lua/nixCatsUtils/init.lua index cec1fbbe..36ff9123 100644 --- a/templates/kickstart-nvim/lua/nixCatsUtils/init.lua +++ b/templates/kickstart-nvim/lua/nixCatsUtils/init.lua @@ -56,6 +56,7 @@ function M.setup(v) wrapRc = false, }), petShop = mk_with_meta({}), + extra = mk_with_meta({}), pawsible = mk_with_meta({ allPlugins = { start = {}, diff --git a/templates/luaUtils/lua/nixCatsUtils/init.lua b/templates/luaUtils/lua/nixCatsUtils/init.lua index cec1fbbe..36ff9123 100644 --- a/templates/luaUtils/lua/nixCatsUtils/init.lua +++ b/templates/luaUtils/lua/nixCatsUtils/init.lua @@ -56,6 +56,7 @@ function M.setup(v) wrapRc = false, }), petShop = mk_with_meta({}), + extra = mk_with_meta({}), pawsible = mk_with_meta({ allPlugins = { start = {}, diff --git a/templates/module/homeCat.nix b/templates/module/homeCat.nix index 59a46ae2..23063da5 100644 --- a/templates/module/homeCat.nix +++ b/templates/module/homeCat.nix @@ -26,7 +26,7 @@ in { # you could also import lua from the flake though, by not including this. # categoryDefinitions.replace will replace the whole categoryDefinitions with a new one - categoryDefinitions.replace = ({ pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions.replace = ({ pkgs, settings, categories, extra, name, ... }@packageDef: { lspsAndRuntimeDeps = { general = []; }; diff --git a/templates/module/systemCat.nix b/templates/module/systemCat.nix index fd942a8b..68a6118a 100644 --- a/templates/module/systemCat.nix +++ b/templates/module/systemCat.nix @@ -28,7 +28,7 @@ in { # packageDef is your settings and categories for this package. # categoryDefinitions.replace will replace the whole categoryDefinitions with a new one - categoryDefinitions.replace = ({ pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions.replace = ({ pkgs, settings, categories, extra, name, ... }@packageDef: { lspsAndRuntimeDeps = { general = []; }; @@ -120,7 +120,7 @@ in { users.REPLACE_ME = { enable = true; packageNames = [ "REPLACE_MEs_VIM" ]; - categoryDefinitions.replace = ({ pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions.replace = ({ pkgs, settings, categories, extra, name, ... }@packageDef: { lspsAndRuntimeDeps = { general = []; }; diff --git a/templates/nixExpressionFlakeOutputs/default.nix b/templates/nixExpressionFlakeOutputs/default.nix index 5036b2b1..4e055655 100644 --- a/templates/nixExpressionFlakeOutputs/default.nix +++ b/templates/nixExpressionFlakeOutputs/default.nix @@ -43,7 +43,7 @@ ]; in { inherit dependencyOverlays; })) dependencyOverlays; - categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: { lspsAndRuntimeDeps = { general = with pkgs; [ @@ -124,6 +124,7 @@ ]; }; }; + extra = {}; }; }; # In this section, the main thing you will need to do is change the default package name diff --git a/templates/overriding/flake.nix b/templates/overriding/flake.nix index 604c04b8..560923db 100644 --- a/templates/overriding/flake.nix +++ b/templates/overriding/flake.nix @@ -72,7 +72,7 @@ withExtraCats = withExtraOverlays.override (prev: { # add some new stuff, we update into the old categoryDefinitions our new values # to replace all, just dont call utils.mergeCatDefs - categoryDefinitions = utils.mergeCatDefs prev.categoryDefinitions ({ pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions = utils.mergeCatDefs prev.categoryDefinitions ({ pkgs, settings, categories, extra, name, ... }@packageDef: { # We do this with utils.mergeCatDefs # and now we can add some more stuff. lspsAndRuntimeDeps = with pkgs; { diff --git a/templates/overwrite/flake.nix b/templates/overwrite/flake.nix index 45772f3c..2e33b2d1 100644 --- a/templates/overwrite/flake.nix +++ b/templates/overwrite/flake.nix @@ -56,7 +56,7 @@ ] )); - categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: { + categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: { # NOTE: for all available fields, see: # :help nixCats.flake.outputs.categories startupPlugins = with pkgs.vimPlugins; { diff --git a/tests/nvim/plugin/nixCats_plugin.lua b/tests/nvim/plugin/nixCats_plugin.lua index 592004a0..87d6d09b 100644 --- a/tests/nvim/plugin/nixCats_plugin.lua +++ b/tests/nvim/plugin/nixCats_plugin.lua @@ -4,6 +4,7 @@ make_test("nixCats_fields", function() assert.truthy(nixCats.vimPackDir) assert.truthy(nixCats.get) assert.truthy(nixCats.cats) + assert.truthy(nixCats.extra) assert.truthy(nixCats.petShop) assert.truthy(nixCats.pawsible) assert.truthy(nixCats.settings) diff --git a/utils/default.nix b/utils/default.nix index 446ae2bf..6c098c73 100644 --- a/utils/default.nix +++ b/utils/default.nix @@ -125,9 +125,10 @@ with builtins; rec { # you can use this to make values in the tables generated # for the nixCats plugin using lua literals. - # i.e. cache_location = mkLuaInline "vim.fn.stdpath('cache')", - mkLuaInline = expr: { __type = "nix-to-lua-inline"; inherit expr; }; + # i.e. cache_location = utils.n2l.types.inline-safe.mk "vim.fn.stdpath('cache')", + n2l = import ./n2l.nix; + mkLuaInline = trace "utils.mkLuaInline renamed to utils.n2l.types.inline-safe.mk, due to be removed before 2025" n2l.types.inline-safe.mk; # flake-utils' main function, because its all I used # Builds a map from =value to .=value for each system eachSystem = systems: f: diff --git a/utils/n2l.nix b/utils/n2l.nix new file mode 100644 index 00000000..342dce8b --- /dev/null +++ b/utils/n2l.nix @@ -0,0 +1,134 @@ +# Copyright (c) 2023 BirdeeHub +# Licensed under the MIT license +with builtins; let + genStr = str: num: concatStringsSep "" (genList (_: str) num); + luaEnclose = inString: let + measureLongBois = inString: let + normalize_split = list: filter (x: x != null && x != "") + (concatMap (x: if isList x then x else [ ]) list); + splitter = str: normalize_split (split "(\\[=*\\[)|(]=*])" str); + counter = str: map stringLength (splitter str); + getMax = str: foldl' (max: x: if x > max then x else max) 0 (counter str); + getEqSigns = str: (getMax str) - 2; + longBoiLength = getEqSigns inString; + in + if longBoiLength >= 0 then longBoiLength + 1 else 0; + + eqNum = measureLongBois inString; + eqStr = genStr "=" eqNum; + bL = "[" + eqStr + "["; + bR = "]" + eqStr + "]"; + in + bL + inString + bR; + + mkEnum = id: proto: let + filterAttrs = pred: set: + removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set)); + mkBaseT = expr: { __type = id; inherit expr; }; + mkmk = n: p: default: v: mkBaseT ((p.fields or {}) // { type = n; } // default v); + types = mapAttrs (n: p: p // { name = n; mk = mkmk n p (p.default or (o: o)); }) proto; + default_subtype = let + defvals = attrNames (filterAttrs (n: x: isFunction (x.default or false)) proto); + valdef = if length defvals == 1 then head defvals + else if defvals == [] then throw "no default type specified" + else throw "multiple default types specified"; + in valdef; + member = v: v.__type or null == id && v ? expr + && null != types."${v.expr.type or default_subtype}".name or null; + typeof = v: let + in if ! (member v) then null + else types."${v.expr.type or default_subtype}".name; + resolve = v: let vt = typeof v; in + if vt == null then throw "unable to resolve, not subtype of ${id}" + else (proto."${vt}".format or (o: o.expr)) v; + in { inherit types typeof member resolve mkBaseT id default_subtype; }; + + LIproto = let + fixargs = args: if any (v: ! isString v || builtins.match ''^([A-Za-z_][A-Za-z0-9_]*|\.\.\.)$'' v == null) args + then throw "args must be valid lua identifiers" + else concatStringsSep ", " args; + in { + inline-safe = { + default = (v: if v ? body then v else { body = v; }); + fields = { body = "nil"; }; + format = LI: "assert(loadstring(${luaEnclose "return ${LI.expr.body or LI.expr or "nil"}"}))()"; + }; + inline-unsafe = { + fields = { body = "nil"; }; + format = LI: "${LI.expr.body or "nil"}"; + }; + function-safe = { + fields = { body = "return nil"; args = []; }; + format = LI: + ''assert(loadstring(${luaEnclose ''return (function(${fixargs (LI.expr.args or [])}) ${LI.expr.body or "return nil"} end)''}))()''; + }; + function-unsafe = { + fields = { body = "return nil"; args = []; }; + format = LI: ''(function(${fixargs (LI.expr.args or [])}) ${LI.expr.body or "return nil"} end)''; + }; + }; + + inline = mkEnum "nix-to-lua-inline" LIproto; + +in rec { + + toLua = toLuaFull {}; + + prettyLua = toLuaFull { pretty = true; formatstrings = true; }; + + uglyLua = toLuaFull { pretty = false; formatstrings = false; }; + + inherit mkEnum inline; + inherit (inline) types typeof member resolve default_subtype; + + toLuaFull = { + pretty ? true, + indentSize ? 2, + # adds indenting to multiline strings + # and multiline lua expressions + formatstrings ? false, # <-- only active if pretty is true + _level ? 0, # <- starting indentation level, for internal use when defining inline types + ... + }@opts: input: let + nl_spc = level: if pretty == true + then "\n${genStr " " (level * indentSize)}" else " "; + + doSingleLuaValue = level: value: let + replacer = str: if pretty && formatstrings then replaceStrings [ "\n" ] [ "${nl_spc level}" ] str else str; + isDerivation = value: value.type or null == "derivation"; + in + if value == true then "true" + else if value == false then "false" + else if value == null then "nil" + else if isFloat value || isInt value then toString value + else if isList value then "${luaListPrinter level value}" + else if inline.member value then let + res = inline.resolve value; + in if isFunction res then res (opts // { _level = level; }) else replacer res + else if value ? outPath then luaEnclose "${value.outPath}" + else if isDerivation value then luaEnclose "${value}" + else if isAttrs value then "${luaTablePrinter level value}" + else replacer (luaEnclose (toString value)); + + luaTablePrinter = level: attrSet: let + nameandstringmap = mapAttrs (n: value: let + name = "[ " + (luaEnclose "${n}") + " ]"; + in + "${name} = ${doSingleLuaValue (level + 1) value}") attrSet; + resultList = attrValues nameandstringmap; + catset = concatStringsSep ",${nl_spc (level + 1)}" resultList; + LuaTable = "{${nl_spc (level + 1)}" + catset + "${nl_spc level}}"; + in + LuaTable; + + luaListPrinter = level: theList: let + stringlist = map (doSingleLuaValue (level + 1)) theList; + catlist = concatStringsSep ",${nl_spc (level + 1)}" stringlist; + LuaList = "{${nl_spc (level + 1)}" + catlist + "${nl_spc level}}"; + in + LuaList; + + in + doSingleLuaValue _level input; + +}