1    =======================================================================================
2    Flake Help                                                      nixCats.flake
3    
4    A Lua-natic's Neovim flake, with extra cats! nixCats!
5    
6    This is the documentation for the flake itself.
7    This flake uses Nix for importing plugins, LSPs, dependencies, and more,
8    in place of usual nvim package managers such as packer, lazy or Mason.
9    
10   Everything else is done in a regular Lua config style.
11   Download in flake.nix and then, simply pretend the root of the flake 
12   is the root of your Lua config. 
13   
14   *******************************************************
15   AN IMPORTANT NOTE:
16   
17   <1> When editing the files within the flake directory,
18   Nix will not package a new file if it isn't staged in git.
19   run git add before rebuilding it whenever adding a new file.
20   Using wrapRc = true would mean this also applies to Lua files.
21   Only tracked files will recieve their updates when
22   rebuilt without git add being ran first. New files need to be added.
23   *******************************************************
24   
25   Related:
26   For detecting what was included by 
27   the flake in your Lua, see:
28   :help nixCats
29   
30   stdpath('config') will still point to ~/.config/<configDirName>.
31   But your Lua config will be in the store.
32   This is okay, because most of the reason for a plugin to use
33   it would be to write to it, and we cant write to store paths anyway. 
34   You could use require('nixCats').configDir,
35   or nixCats('nixCats_config_location')
36   to get current config directory for your uses, if ever necessary.
37   It will be present and correct regardless of settings.
38   
39   However if you did not use Nix at all and did not run the setup
40   function, of course the nixCats plugin wont be there to ask.
41   
42   The setup function from require('nixCatsUtils').setup
43   will provide a mock nixCats plugin with SOME values
44   and empty tables to prevent accidental indexing errors.
45   You could instead do require('nixCatsUtils').isNixCats to default to
46   vim.fn.stdpath('config') if all you wanted was this path though.
47   
48   Keep in mind they will be read-only if in the store!
49   
50   =======================================================================================
51   Flake Inputs:                                            nixCats.flake.inputs
52   
53   If a plugin does not have an extra build step, and are not on nixpkgs,
54   you may use this format to import them, replacing the fields marked with <>
55   
56       "plugins-<pluginName>" = {
57         url = "github:<userName>/<repositoryName>";
58         flake = false;
59       };
60   
61   More info on flake url syntax at:
62   https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#examples
63   You may also use this syntax to pin the version of a plugin regardless of whether
64   you ran nix flake update or not.
65   You may choose the directory, branch, commit, tag, or even directory
66   imported.
67   
68   All inputs named in the plugins-<pluginName> format will be added to pkgs
69   at pkgs.neovimPlugins.<pluginName> for you to add to your configuration.
70   
71   If the plugin has a dot . character in it's name, you should name it something else
72   because . is not a valid character in an identifier in Nix.
73   
74   The name here only affects the filename of the overall plugin, and should
75   only affect things like vim.cmd("packadd <filename>") that refer to
76   the actual filename of the plugin. Usually I would replace it with -
77   You will then add it to categoryDefinitions later with the NEW name.
78   
79   If you use this method to import a plugin, and really dont
80   want to change the filename of the plugin when they have a
81   dot in their name, you may
82   swap the call to (utils.standardPluginOverlay inputs)
83   with (utils.sanitizedPluginOverlay inputs)
84   and then plugins-plugin.name would become pkgs.neovimPlugins.plugin-name
85   but Neovim would see it as vim.cmd("packadd plugin.name") still
86   
87   If they have a build step or are not a plugin, 
88   i.e. an LSP, or if they are a plugin from a flake,
89   dont name them in that format.
90   If they are a plugin from a flake, they can be added directly,
91   or they may be added as an overlay if offered.
92   If they are anything else they arent a plugin at all and obviously
93   should not be added as a plugin via plugins-<pluginName>
94   
95   If they are on nixpkgs, you dont need to put them in inputs,
96   because you will be able to access them through pkgs.vimPlugins variable.
97   Most plugins will not require you to use the inputs section due to being on nixpkgs.
98   But you may still use it to pin the plugin to a specific version.
99   
100  If you decided not to use utils.sanitizedPluginOverlay
101  and wanted to do it with utils.standardPluginOverlay:
102  If in your inputs you had:
103  
104    "plugins-<plugin-name>" = {
105      url = "github:<userName>/<repository.name>";
106      flake = false;
107    };
108  
109  Where you put plugins in your categoryDefinitions, instead of:
110  
111    pkgs.neovimPlugins.<plugin-name>
112  
113  You could put this:
114  
115    { name = "<plugin.name>"; plugin = pkgs.neovimPlugins.<plugin-name>; }
116  
117  You can also override them instead of (or before/during) the above:
118  
119    (pkgs.neovimPlugins.<plugin-name>.overrideAttrs { pname = "<plugin.name>"; })
120  
121  overrideAttrs can be used for a lot more than just fixing the name of the
122  imported plugin. See:
123  https://ryantm.github.io/nixpkgs/using/overrides/
124  
125  If they have a build step and are not on nixpkgs,
126  you will deal with them in overlays/customBuildsOverlay.nix
127  then import them into a category of the builder. 
128  Alternatively you may use overrideAttrs as mentioned above instead of an
129  overlay for these sorts of packages, but this would possibly get messy if the
130  build step were complex.
131  
132  =======================================================================================
133  Flake Outputs Introduction                              nixCats.flake.outputs
134  
135  With our inputs to our flake taken care of:
136  First, we take care of importing our utils set from nixCats.
137  The reason we are doing this now, is so that it can be defined outside of
138  the utils.eachSystem function, and thus we can export it
139  without having to include a system variable when we import it somewhere else.
140  
141  We also define our luaPath, which is the path to be loaded into the store as
142  your new Neovim config directory. (see :help 'rtp' for the directories
143  available for you to use!)
144  
145  We also define our extra_pkg_config, which is used when initializing the
146  nixpkgs instance that will build your Neovim! It's the same one from
147  
148    pkgs = import nixpkgs { inherit system; overlays = []; config = {}; }
149  
150  That is,
151  
152    outputs = { self, nixpkgs, ... }@inputs: let
153      # In the templates, this is inherit (inputs.nixCats) utils;
154      inherit (inputs.nixCats) utils;
155      # path the the store path to be loaded as Neovim config directory
156      luaPath = "${./.}";
157      # used when initializing the nixpkgs instance
158      extra_pkg_config = {
159        # allowUnfree = true;
160      };
161  
162                                             nixCats.flake.outputs.getOverlays
163  
164  Managing the system variable in combination with overlays
165  can be one of the hardest parts of flake usage.
166  This flake resolves our pkgs instance for Neovim itself to help with this,
167  and takes care of passing the correct pkgs instance
168  to the relevant locations later for use in defining your dependencies.
169  
170  
171    dependencyOverlays = (import ./overlays inputs) ++ [
172      (utils.standardPluginOverlay inputs)
173      inputs.neorg-overlay.overlays.default
174      inputs.lz-n.overlays.default
175  
176      # No overlays SHOULD be exported requiring the ${system} variable to access.
177      # However, some are (such as codeium, a free ai plugin)
178  
179      # when other people mess up their overlays
180      # by wrapping them with flake-utils,
181      # you may instead call this function on their overlay.
182      # it will check if it has the system in it.
183      # if so, it will call the function with the system
184      # and return the desired overlay
185      (utils.fixSystemizedOverlay inputs.codeium.overlays
186        (system: inputs.codeium.overlays.${system}.default)
187      )
188    ];
189  
190  
191                                                 nixCats.flake.outputs.overlays
192  utils.standardPluginOverlay
193  Usage of this function to create an overlay is described in:
194  :h nixCats.flake.inputs
195  along with its friend, utils.sanitizedPluginOverlay
196  
197  It takes all the inputs named in the format
198  plugins-somepluginname and makes them into plugins. 
199  Access them to add them to a category of the builder function 
200  with pkgs.neovimPlugins.somepluginname
201  
202  If the plugin doesn't have a build step,
203  and it wasnt on nixpkgs, then use this method.
204  
205  If the plugin does have a build step and isn't on nixpkgs,
206  then you can either make your own overlay from scratch,
207  or you can call overrideAttrs on the generated plugin
208  to add the required items to it.
209  more info at :h nixCats.flake.inputs
210  
211  If you decide you wish to split your customBuildsOverlay up, 
212  see :help nixCats.flake.nixperts.overlays
213  or look at the overlays/default.nix file for advice on how to do that.
214  
215  ---------------------------------------------------------------------------------------
216                                              nixCats.flake.outputs.categories
217  Then we define what is in our categories!
218  This section is a function that takes the package definition for this
219  particular package as an argument.
220  The builder will call it with that argument, you may use it.
221  This allows categoryDefinitions to access their packages categories and settings,
222  which allows categoryDefinitions to be much more dynamic.
223  
224  It also gets mkNvimPlugin = src: name: as an argument. mkNvimPlugin takes a src, either flake input
225  or fetched drv, and then a name, and it returns a nvim plugin that can be further
226  overriden via overrideAttrs if desired.
227  There is an overlay to do this automatically from flake inputs, mentioned
228  above. But sometimes it can be advantageous to do one of them individually.
229  
230  These are the things you can return:
231  
232    categoryDefinitions = { pkgs, settings, categories, extra, name, mkNvimPlugin, ... }@packageDef: {
233  
234  <lspsAndRuntimeDeps>
235    a flexible set of categories, each containing LSPs or
236    other internal runtime dependencies such as ctags or debuggers
237    these are available to the PATH while within the Neovim program.
238    this includes the Neovim terminal.
239  
240  <startupPlugins>
241    a flexible set of categories, each containing startup plugins.
242    Startup plugins are loaded and can be required. 
243  
244  <optionalPlugins>
245    a flexible set of categories, each containing optional plugins.
246    Optional plugins need to be added with packadd before being required.
247    Use :NixCats pawsible to see the names to use for packadd
248  
249  <sharedLibraries>
250    a flexible set of categories, each containing a derivation for
251    a runtime shared library. Will be prepended to the LD_LIBRARY_PATH variable.
252  
253  <environmentVariables>
254    a flexible set of categories, each containing an ATTRIBUTE SET of 
255    EnvironmentVariableName = "EnvironmentVariableValue";
256  
257  <extraWrapperArgs>
258    a flexible set of categories, each containing extra wrapper arguments.
259    If you don't know what that is, see here:
260  github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/setup-hooks/make-wrapper.sh
261  
262  <extraLuaPackages>
263    a flexible set of categories, each containing FUNCTIONS 
264    that return lists of extra Lua packages.
265    These functions are the same thing that you would pass to lua.withPackages.
266    Is used to populate $LUA_PATH and $LUA_CPATH
267  
268  <extraPython3Packages> 
269    a flexible set of categories, each containing FUNCTIONS
270    that return lists of Python packages.
271    These functions are the same thing that you would pass to python.withPackages.
272    You may get the path to this Python environment in your Lua config via
273    vim.g.python3_host_prog
274    or run from nvim terminal via :!<packagename>-python3
275  
276  <extraPython3wrapperArgs>
277    the same as extraWrapperArgs but for bundled python3 executable
278  
279  <propagatedBuildInputs> 
280    a flexible set of categories, each containing internal BUILD dependencies.
281    Will not be available to the PATH unless in a devShell.
282    USING THIS OPTION WILL CAUSE NVIM TO BUILD FROM SOURCE.
283  
284  <optionalLuaPreInit>
285    a flexible set of categories, each containing a Lua string
286    that will be ran before sourcing your init.lua
287    Yes it can access nixCats.
288    It is not the recommended way to create Lua for this flake,
289    but it may be useful in editing flake imports 
290    of other already configured setups following the nixCats format.
291  <optionalLuaAdditions>
292    a flexible set of categories, each containing a Lua string
293    that will be ran after sourcing your init.lua
294    Yes it can access nixCats.
295    It is not the recommended way to create Lua for this flake,
296    but it may be useful in editing flake imports 
297    of other already configured setups following the nixCats format.
298  <bashBeforeWrapper>
299    a flexible set of categories, each containing arbitrary Bash code
300    to run before the wrapper starts within the wrapper's Bash environment.
301    CAUTION: only use this if you know what you are doing and why you need
302    to do it. Whenever possible, use extraWrapperArgs instead.
303  <extraCats>
304    a flexible set of categories, each containing a list of attribute paths,
305    specified as lists of strings. Thus each category would contain a list of
306    lists of strings.
307    Allows inclusion of extra categories contingent on each lists inclusion in the package,
308    and is useful for creating default values for subcategories.
309    For more info, see below at
310    :h nixCats.flake.outputs.categoryDefinitions.default_values
311    # WARNING: use of categories argument in this set will cause infinite recursion
312    # The categories argument of this function is the FINAL value.
313    # You may use it in any of the other sets.
314  }
315  
316  In essence, the contents of each set listed here are filtered
317  based on the packageDefinitions set you provide, 
318  whereby including categoryname = true; you enable that category.
319  :help nixCats.flake.outputs.packageDefinitions
320  
321  It will remove duplicate items, so feel free to include the same thing in
322  multiple categories if it suits your purposes.
323  
324  It does this recursively. (explained below)
325  
326  If, inside one of these main sets, you had another set,
327  it would consider that a subcategory, and you could enable it
328  just like you do with a normal category, by setting a value with the
329  corresponding attribute path to true in the category
330  set of nixCats.flake.outputs.packageDefinitions.
331  You can nest them as much as you like, or just have a category that is a
332  single derivation.
333  
334                              nixCats.flake.outputs.categoryDefinitions.schemas
335  
336   You may also use the variables passed to your categoryDefinitions function
337   to get access to the set of categories and settings that are being
338   used to define the current package being built!
339  
340      themer = with pkgs.vimPlugins;
341        (builtins.getAttr packageDef.categories.colorscheme {
342            # Theme switcher without creating a new category
343            "onedark" = onedark-vim;
344            "catppuccin" = catppuccin-nvim;
345          }
346        );
347  
348    In addition to all this, if a plugin is defined within a list, it may
349    instead be defined within an attribute set that also contains config
350    to be ran after sourcing init.lua and optionalLuaAdditions
351    to do this, you may use the following syntax in opt or start sections: 
352      [
353        # you may add a plugin to a category list in any of these ways
354        { plugin = derivation; config.lua = ""; config.vim = "";}
355        { plugin = derivation; config = ""; type = "<viml or lua>"; }
356        { plugin = derivation; config = ""; } # defaults to viml
357        { plugin = derivation; }
358  
359        # all the above options can also accept an optional = bool;
360        # to override its presence in either startupPlugins or optionalPlugins
361  
362        # they can also accept a name = string; to override its name
363  
364        # they can also accept a priority = integer; with low being first
365        # and default of 150
366        # if they contain a config value, it will be ran in that order.
367  
368        # they also may contain a pre = true in order to be ran BEFORE init.lua
369  
370        derivation
371        # plain derivation does not need to be in a list, but it should be
372        # anyway. It could be on its own though and would act as its own
373        # category.
374      ]
375  
376                              nixCats.flake.outputs.categoryDefinitions.default_values
377  
378  There are 2 ways of creating default values in nixCats.
379  
380  #1 Implicit: when value is in another section of categoryDefinitions
381  
382  If in your categoryDefinitions you had the following:
383  
384      environmentVariables = {
385        test = {
386          subtest1 = {
387            CATTESTVAR = "It worked!";
388          };
389          subtest2 = {
390            CATTESTVAR3 = "It didn't work!";
391          };
392        };
393      };
394      extraWrapperArgs = {
395        test = [
396          '' --set CATTESTVAR2 "It worked again!"''
397        ];
398      };
399  
400  And in your packageDefinitions set, under categories, you had the following:
401  
402      test = {
403        subtest1 = true;
404      };
405  
406  you could echo $CATTESTVAR and $CATTESTVAR2 in your terminal to see them.
407  However you could not echo $CATTESTVAR3.
408  
409  All items that are not attributes of the parent set will be included
410  when you enable a subcategory. This includes lists, strings, functions, etc...
411  
412  However, attributes will not and you must explicitly enable all attributes of
413  a subcategory if you set even 1 explicitly.
414  
415  Thus to include CATTESTVAR3, you would have to enable it like so: 
416      test = {
417        subtest1 = true;
418        subtest2 = true;
419      };
420   However, those are all the items in the test category.
421  So instead we can do this to enable all the subcategories in test. 
422      test = true;
423  
424  This applies in many situations. Take this one for example.
425  
426      lspsAndRuntimeDeps = {
427        neonixdev = {
428          inherit (pkgs)
429            nix-doc nil lua-language-server nixd; 
430        };
431      };
432      startupPlugins = {
433        neonixdev = with pkgs.vimPlugins; [
434          neodev-nvim
435          neoconf-nvim
436        ];
437      };
438  
439   If you were to put the following in your packageDefinitions: 
440      neonixdev.nix-doc = true;
441  
442  neodev-nvim and neoconf-nvim would still be included.
443  However, nil, lua-language-server, and nixd would not be!
444  You would need to pick which of those you wanted separately.
445  Sometimes this is the desired behavior.
446  Sometimes it is not and a list of packages would be better suited.
447  
448  This leads us to our second way to make a default value:
449  
450  #2 Explicit: using extraCats section of categoryDefinitions.
451  
452  The extraCats section of categoryDefinitions contains categories of attribute
453  paths. If that category is defined, the categories specified by the attribute
454  paths will also be enabled. This means you could make it so that if you
455  included the go category, it could then enable debug.go and lsp.go for you.
456  But in addition to that, it can be combined with the implicit form of creating
457  default values above in an interesting way.
458  
459    categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: {
460      lspsAndRuntimeDeps = {
461        debug = with pkgs; {
462          go = [ delve ];
463        };
464        go = with pkgs; [
465          gopls
466          gotools
467          go-tools
468          gccgo
469        ];
470      };
471      startupPlugins = {
472        debug = with pkgs.vimPlugins; {
473          default = [
474            nvim-dap
475            nvim-dap-ui
476            nvim-dap-virtual-text
477          ];
478          go = [ nvim-dap-go ];
479        };
480      };
481      # WARNING: use of categories argument in this set will cause infinite recursion
482      # The categories argument of this function is the FINAL value.
483      # You may use it in any of the other sets.
484      extraCats = {
485        # due to the implicit form of default values in different sections,
486        # this will enable debug.default
487        # if any subcategory of debug is enabled
488        # thus, enabling debug.go would also enable debug.default
489        debug = [
490          [ "debug" "default" ]
491        ];
492        # and if go is enabled, it enables debug.go
493        # which then enables debug.default
494        go = [ # <- must be in a list
495          [ "debug" "go" ]
496        ];
497      };
498    };
499  
500  If you wish to only enable a value via extraCats if multiple other categories
501  are enabled, the categories in extraCats also accept a set form!
502  
503    extraCats = {
504      # if target.cat is enabled, the list of extra cats is active!
505      target.cat = [ # <- must be a list of (sets or list of strings)
506        # list representing attribute path of category to enable.
507        [ "to" "enable" ]
508        # or as a set
509        {
510          cat = [ "other" "toenable" ]; #<- required if providing the set form
511          # all below conditions, if provided, must be true for the `cat` to be included
512  
513          # true if any containing category of the listed cats are enabled
514          when = [ # <- `when` conditions must be a list of list of strings
515            [ "another" "cat" ]
516          ];
517          # true if any containing OR sub category of the listed cats are enabled
518          cond = [ # <- `cond`-itions must be a list of list of strings
519            [ "other" "category" ]
520          ];
521        }
522      ];
523    };
524  
525  ---------------------------------------------------------------------------------------
526  Package Generation:                           nixCats.flake.outputs.packageDefinitions
527  
528  generate packages by calling that builder function we just created.
529  Place them in the packageDefinitions set.
530  
531  First, pick the set of settings you wish to include.
532  
533  Then, pass it a set of named boolean values like this:
534  { categoryname1 = true; categoryname2 = false; etc... }
535  False may be omitted. True may not.
536  Only true matters for what plugins will be added.
537  
538  These categories are defined in the Builder function above 
539  by placing named lists of plugins in the flexible sets provided.
540  The category names are the names of those lists. 
541  Add a new list, then enable the category here.
542  
543  If you have categories with the same name in 
544  multiple different sets outlined above in the builder,
545  all plugins in those categories will be
546  included when you set "thatname = true;" here.
547  hence, general = true; will include the general lspsAndDeps category,
548  as well as the general startupPlugins category.
549  
550  an example package definition:
551  
552    packageDefinitions = {
553      nixCats = { pkgs, ... }: {
554        setting = {
555          wrapRc = true;
556          # nvimSRC = inputs.neovim;
557          aliases = [ "viCat" ];
558        };
559        categories = {
560          custom = true;
561          gitPlugins = true;
562          general = true;
563          neonixdev = true;
564  
565          # this does not have an associated category of plugins, 
566          # but Lua can still check for it
567          lspDebugMode = false;
568  
569          # you could also pass something else and it calls 
570          # builtins.toString on it and passes it in as a string
571          theBestCat = "says meow!!!";
572          # maybe you need to pass a port or path in or something idk.
573          # you could :lua =nixCats("theBestCat")
574          # this nixCats("path.to.val") is the main category check function
575          # and it is built to mirror the Nix category scheme as much as possible
576        };
577        extra = {
578          there_is = "also";
579          an_extra = "table";
580          for = ''if you dont want the main subcategory get function
581            to apply to something, or think it all being in categories is too
582            messy
583          '';
584          you_can = ''nixCats.extra("path.to.val")'';
585          for_safer = ''table access via vim.tbl_get'';
586        };
587      };
588    };
589  
590  You can use the nixCats plugin for the set you define here in your Lua
591  It returns a Lua table of the same format.
592  
593  see :help nixCats
594  
595  For more nuances on enabling categories and subcategories, see above at
596  :help nixCats.flake.outputs.categoryDefinitions.default_values
597  and
598  :help nixCats.flake.outputs.categoryDefinitions.schemas
599  
600  ----------------------------------------------------------------------------------------
601  Settings                                       nixCats.flake.outputs.settings
602  
603  These are the defaults:
604  
605      default_settings = {
606        # YOU ARE IN CHARGE OF MAKING SURE THESE ALIASES DO NOT COLLIDE WITH
607        # ANYTHING ELSE
608        # [ "takes" "a" "list" "of" "strings" "and" "makes" "an" "alias" "for" "each" ];
609        aliases = null;
610        viAlias = false;
611        vimAlias = false;
612  
613        # so that you can see it in the store
614        extraName = "";
615  
616        withRuby = true;
617        withPython3 = true;
618        withNodeJs = false;
619        withPerl = false;
620  
621        # do you want to package the Lua from this flake in the store?
622        # or would you rather it just read it in your .config/<configDirName>?
623        # nixCats and this help will work either way.
624        # packages with wrapRc = false are for quick changes to Lua.
625        # it is not for being ran from anywhere via nix run, because the config
626        # was not wrapped with the program.
627        wrapRc = true;
628  
629        # What should the name of the folder within standard directories
630        # i.e. .config, .local/share, .local/state, .cache, etc... be?
631        # This option is very useful when you want 
632        # to clone an unwrapped config straight to the .config dir.
633        # It is also helpful to prevent other nvim packages sharing data folders.
634        # see :help `$NVIM_APPNAME`
635        configDirName = "nvim";
636  
637        # Only active when wrapRc = false, this option allows you to specify
638        # an absolute path to the unwrapped config directory.
639        # This is not a Nix path. This is the unwrapped config directory.
640        # This means you are going to need to make
641        # sure that it points the right place on the current machine.
642        unwrappedCfgPath = null;
643        # Will not change anything other than config directory, configDirName
644        # is still needed for .local/share or .cache and the like
645  
646        # use this to pin a specific Neovim version.
647        # This one will specify the base Neovim derivation to use.
648        neovim-unwrapped = null;
649        # This one will just override the src value of the Neovim in nixpkgs
650        # import it in flake inputs with flake = false,
651        # It will also obviously cause Neovim to build from source.
652        nvimSRC = null;
653  
654        # These 2 options are useful for when you want to allow your dev shells
655        # to override things such as LSPs and shared libraries that you have
656        # already in your configuration.
657        suffix-path = false;
658        # causes lspsAndDeps to be added to the END of
659        # PATH instead of the start
660        suffix-LD = false;
661        # causes sharedLibraries to be added to the END of
662        # LD_LIBRARY_PATH instead of the start
663  
664        # plugins in nixpkgs sometimes have extra dependencies added to
665        # .runtimeDeps attribute. By default nixCats will append then to the path,
666        # accepts `"suffix"` or `true` to append to the PATH
667        # accepts `"prefix"` to prepend to the PATH
668        # accepts `false` or `null` to not include them.
669        autowrapRuntimeDeps = "suffix";
670  
671        # plugins in nixpkgs sometimes have extra lua config added to
672        # .passthru.initLua attribute for compatibility.
673        # By default nixCats will run them before your configuration.
674        # accepts `"prefix"` or `true` to run before your configuration
675        # accepts `"suffix"` to run afterwards
676        # accepts `false` or `null` to not include them.
677        autoconfigure = "prefix";
678  
679        # whether to group up treesitter grammars into a single directory,
680        # or leave them as separate plugins.
681        # Defaults to true as it results in
682        # a significant startup time performance boost
683        # Works only on grammars that have been passed through
684        # pkgs.neovimUtils.grammarToPlugin
685        # or pkgs.vimPlugins.nvim-treesitter.withPlugins
686        collate_grammars = true;
687  
688        # unsets PYTHONSAFEPATH variable.
689        # Can cause issues with reproducibility,
690        # can fix some stuff
691        disablePythonSafePath = false;
692  
693        # optional, specify custom store path gemdir
694        # must contain a gemset.nix like one generated by bundix
695        # must contain the Neovim gem
696        # for further info, see
697        # https://github.com/NixOS/nixpkgs/tree/74ad6cb1d2b14edb4ad1fffc0791e94910c61453/pkgs/applications/editors/neovim/ruby_provider
698        # https://github.com/BirdeeHub/neovim_ruby_updater
699        gem_path = null;
700        # If you are using neovim-unwrapped from nixpkgs itself,
701        # there is a good chance your Neovim
702        # will not be able to find it regardless of settings.
703        # thus withRuby and gem_path options may not work
704        # It works great using https://github.com/nix-community/neovim-nightly-overlay
705        # so this seems to be an upstream issue, as all the expected variables
706        # are still being set correctly.
707  
708        # each package outputs a module via passthru.
709        # this will set the namespace for the module options
710        # by default will be at config.${packagename}
711        moduleNamespace = [ <packagename> ];
712      };
713  
714  
715  QUICK TIP: wrapRc
716  
717  The wrapRc option is very useful for testing Lua changes.
718  It removes the need to stage and rebuild to see your Lua changes reflected.
719  You will still need to rebuild when making changes to Nix regardless of the
720  value of wrapRc.
721  
722  However it also means that the Lua isn't going run if it isn't in the right
723  folder, i.e. when installed and run from GitHub with nix run.
724  
725  If the Lua is not in vim.fn.stdpath('config'), wrapRc = false will not work.
726  By default this is ~/.config/nvim on Linux systems, although we can
727  change nvim to whatever we wish via the configDirName setting.
728  
729  Alternatively, you can set the unwrappedCfgPath option to allow the
730  configuration to be set to an absolute path. You still may want to set
731  the configDirName option anyway to change the data directories,
732  or explicitly keep it the same on both so that they share stuff like auths.
733  
734  The most convenient way to use this is the following:
735  Make a second identical packageDefinition, but with wrapRc disabled.
736  Then install both the wrapped one and unwrapped one with different aliases.
737  When you want to hack in Lua, use unwrapped! When you're done, just rebuild
738  and go back to the wrapped one.
739  
740  The templates/example/flake.nix file from the example config template
741  has an example of this with nixCats and regularCats.
742  
743  Then, when testing Lua changes, you run the other package and have a vanilla
744  Neovim experience, only rebuilding when you install new packages.
745  
746  When you are satisfied, simply rebuild and go back to using the main package,
747  as it was the same except for the single option!
748  
749  --------------------------------------------------------------------------------------
750  Neovim Builder Creation:                        nixCats.flake.outputs.builder
751  
752  Now we define our builder function.
753  We inherit utils.baseBuilder which is
754  a function that takes five arguments. It is defined in ./builder.
755  Right now we are going to call it with just the first four arguments. This will
756  leave us with a function that takes 1 argument.
757  That argument is the name of the Neovim package to be packaged.
758  
759  1. The path to the Lua to include (in the flake, we use the self variable to get
760       this path and wrap the Lua when wrapRc = true)
761  
762  2. A set containing parameters for the pkgs to be used:
763    It takes 2 forms. You can either pass it a nixpkgs and a system and it
764    will resolve the pkgs for you and pass it to your categoryDefinitions and
765    packageDefinitions,
766    or you can pass it a pkgs instead to inherit the values and do the same.
767  
768    You may also provide a dependencyOverlays list to add overlays for nvim only,
769    extra_pkg_config (maps to the config argument to import nixpkgs { ... }),
770    nixCats_passthru (extra items to put into passthru in the final drv),
771    and extra_pkg_params (contains any fields in import nixpkgs { ... } not mentioned).
772  
773  3. our function that takes an individual package definition
774       and returns a set of categoryDefinitions.
775  
776  4. our set of packageDefinitions see: nixCats.flake.outputs.packageDefinitions
777  
778  It is now a function that takes a name, and returns your chosen Neovim package.
779  
780    packages = nixpkgs.lib.genAttrs nixpkgs.lib.platforms.all (system: let
781      # create our builder for our exports
782      nixCatsBuilder = utils.baseBuilder luaPath {
783        inherit nixpkgs system dependencyOverlays extra_pkg_config;
784      } categoryDefinitions packageDefinitions;
785    in {
786      # it can take a name of a package in packageDefinitions
787      # and return the package!
788      default = nixCatsBuilder defaultPackageName;
789    });
790  
791  
792    packages = nixpkgs.lib.genAttrs nixpkgs.lib.platforms.all (system: let
793      # create our pkgs to pass to builder
794      pkgs = import nixpkgs {
795        inherit system;
796        overlays = dependencyOverlays;
797        config = extra_pkg_config;
798      };
799      # create our builder for our exports
800      nixCatsBuilder = utils.baseBuilder luaPath {
801        /* you can still use dependencyOverlays here and such as well to add */
802        inherit pkgs; # <- but here we are just going to inherit the value.
803      } categoryDefinitions packageDefinitions;
804    in {
805      # it can take a name of a package in packageDefinitions
806      # and return the package!
807      default = nixCatsBuilder defaultPackageName;
808    });
809  
810  ---------------------------------------------------------------------------------------
811  Flake Exports and Export options               nixCats.flake.outputs.exports
812  
813  They look something like this:
814  
815    # this first section is the outputs we
816    # want to wrap with the ${system} variable
817    utils.eachSystem nixpkgs.lib.platforms.all (system: let
818      # this is the builder (see :h nixCats.flake.outputs.builder above):
819      nixCatsBuilder = utils.baseBuilder luaPath {
820        inherit nixpkgs system dependencyOverlays extra_pkg_config;
821      } categoryDefinitions packageDefinitions;
822      # then it takes our categoryDefinitions and packageDefinitions
823  
824      # then we build a package to serve as the default one by providing its name.
825      defaultPackage = nixCatsBuilder defaultPackageName;
826  
827      # this is just for using utils in the following section such as pkgs.mkShell
828      # The one used to build Neovim is resolved inside the builder
829      # and is passed to our categoryDefinitions and packageDefinitions
830      pkgs = import nixpkgs { inherit system; };
831      # as you can see, "resolve pkgs" does not mean anything fancy.
832      # however, with overlays and system variable,
833      # sometimes you can get yourself in a loop when
834      # doing more advanced things. So this flake takes care of that for you.
835      # it will make sure pkgs is passed to the categoryDefinitions and packageDefinitions
836    in
837    {
838      # these outputs will be wrapped with ${system} by utils.eachSystem
839  
840      # this will make a package out of each of the packageDefinitions defined above
841      # and set the default package to the one passed in here.
842      packages = utils.mkAllWithDefault defaultPackage;
843  
844      # choose your package for devShell
845      # and add whatever else you want in it.
846      devShells = {
847        default = pkgs.mkShell {
848          name = defaultPackageName;
849          packages = [ defaultPackage ];
850          inputsFrom = [ ];
851          shellHook = ''
852          '';
853        };
854      };
855  
856    }) // {
857  
858      # these outputs will be NOT wrapped with ${system}
859  
860      # now we can export some things that can be imported in other
861      # flakes, WITHOUT needing to use a system variable to do it.
862      # and update them into the rest of the outputs returned by the
863      # eachSystem function.
864  
865      # this will make an overlay out of each of the packageDefinitions defined
866      # and set the default overlay to the one named here.
867      overlays = utils.makeOverlays luaPath {
868        # we pass in the things to make a pkgs variable to build nvim with later
869        inherit nixpkgs dependencyOverlays extra_pkg_config;
870        # and also our categoryDefinitions
871      } categoryDefinitions packageDefinitions defaultPackageName;
872  
873      # we export a NixOS module to allow configuration from configuration.nix
874      # allows you to either inherit values from your main flake, or start fresh
875      # It requires the system variable to build a package but not to build a module!
876      nixosModules.default = utils.mkNixosModules {
877        inherit dependencyOverlays luaPath defaultPackageName
878          categoryDefinitions packageDefinitions nixpkgs;
879      };
880      # and the same for Home Manager
881      homeModule = utils.mkHomeModules {
882        inherit dependencyOverlays luaPath defaultPackageName
883          categoryDefinitions packageDefinitions nixpkgs;
884      };
885      # and we export these so its super easy to grab them later.
886      inherit utils;
887      inherit (utils) templates;
888    };
889  
890                                    nixCats.flake.outputs.utils
891  
892  The <utils> set exports all the functions used in creating the format in the
893  templates, including the main builder!
894  (see :h nixCats.flake.outputs.builder for builder explanation)
895  
896  In the interests of not repeating ourselves,
897  a list of most functions exported in the <utils> set
898  can be found here:
899  https://nixcats.org/nixCats_utils.html
900  
901  Missing from that list however,
902  is an explanation of the internal <n2l> library
903  nixCats uses to create the nixCats Lua plugin!
904  
905  The library fully escapes all items passed to it,
906  so usually you can't execute lua code in them.
907  But you may still explicitly pass it lua code to execute at runtime
908  by declaring them as inline lua types!
909  
910  An intricate explanation of the full set
911  of features the <n2l> library contains are below.
912  
913  All other functions made available by
914  the <utils> set are explained in the documentation
915  at https://nixcats.org/nixCats_utils.html
916  
917                                    nixCats.flake.outputs.utils.n2l
918  <n2l> This is the Nix to Lua library nixCats
919  uses to create the nixCats Lua plugin
920  You may wish to use some functions from it.
921  
922  The library is exported from the <utils> set as utils.n2l
923  
924  It contains <toLua> and <prettyLua> and <uglyLua> which convert Nix to Lua.
925  
926  it contains a <member> function to determine if a value is a special "inline lua" type
927  it contains a <typeof> function to determine which special "inline lua" type it is
928  it contains a <resolve> function which knows how to resolve the types to a string of code
929  it contains the <default_subtype> name as well.
930  
931  But of much more interest to you is the types you may declare.
932  
933  Everything being passed through settings, categories, and extra in packageDefinitions
934  will be properly escaped. But this also means that
935  you cannot write any Lua code there.
936  
937  Luckily, we have some types we can declare that will allow you to do this.
938  
939  To declare that an item is a Lua value rather than a hard coded one,
940  you may choose one of these types. To do this, call its constructor!
941  
942  for example, types.inline-unsafe has 1 field, body.
943  
944  To declare one in our settings, categories, and extra sets, it would look
945  something like this:
946  
947    categories = {
948      somecat = utils.n2l.types.inline-unsafe.mk {body = "vim.fn.stdpath('data')"; }`
949    }
950  
951  inline-safe is the default type, and it gets to define a shorthand form.
952  
953    categories = {
954      somecat = utils.n2l.types.inline-safe.mk "vim.fn.stdpath('data')";`
955    }
956  
957  These are all the types, each one has an associated mk
958  function to create a value of that type,
959  which accepts the fields listed here, defined with default values.
960  
961    # creates an inline Lua value in a way that cant break the table
962    inline-safe = {
963      default = (v: if v ? body then v else { body = v; });
964      fields = { body = "nil"; };
965      format = LI: "assert(loadstring(${luaEnclose "return ${LI.expr.body or LI.expr or "nil"}"}))()";
966    };
967    # iterpolates whatever string you provide into the table raw
968    inline-unsafe = {
969      fields = { body = "nil"; };
970      format = LI: "${LI.expr.body or "nil"}";
971    };
972    # creates a function with args of the names given in args list
973    # does so in a way where you cannot accidentally break the table
974    function-safe = {
975      fields = { body = "return nil"; args = []; };
976      format = LI: 
977        ''assert(loadstring(${luaEnclose ''return (function(${fixargs (LI.expr.args or [])}) ${LI.expr.body or "return nil"} end)''}))()'';
978    };
979    # creates a function with args of the names given in args list
980    # interpolates the body segment raw, just like inline-unsafe, but in a function
981    function-unsafe = {
982      fields = { body = "return nil"; args = []; };
983      format = LI: ''(function(${fixargs (LI.expr.args or [])}) ${LI.expr.body or "return nil"} end)'';
984    };
985    with-meta = {
986      fields = {
987        table = {}; # <- the table you are adding
988        meta = {}; # <- the metatable you want to add to it (in Nix)
989        newtable = null; # <- if you want to specify a different first arg to setmetatable
990        tablevar = "tbl_in"; # <- varname to refer to the table, to avoid translating multiple times
991      };
992      format = LI: opts: let
993        metaarg1 = if LI.expr.newtable or null == null then LI.expr.tablevar or "{}" else toLuaFull opts LI.expr.newtable;
994        result = inline.types.function-unsafe.mk {
995          args = [ (LI.expr.tablevar or "tbl_in") ];
996          body = ''return setmetatable(${metaarg1}, ${toLuaFull opts LI.expr.meta})'';
997        };
998      in "${toLuaFull opts result}(${toLuaFull opts LI.expr.table})";
999    };
1000 
1001 
1002 Some more useage examples:
1003 
1004   exampleSafeFunc = utils.n2l.types.function-safe.mk {
1005     args = [ "hello" ];
1006     body = /*lua*/ ''
1007       print(hello)
1008       return hi
1009     '';
1010   };
1011   exampleUnsafeFunc = utils.n2l.types.function-unsafe.mk {
1012     args = [ "hi" "hello" ];
1013     body = /*lua*/ ''
1014       print(hi)
1015       print(hello)
1016       return hi .. hello
1017     '';
1018   };
1019   };
1020   funcResults = {
1021     test1 = utils.n2l.types.inline-safe.mk ''${utils.n2l.resolve exampleSafeFunc}("Hello World!")'';
1022   };
1023   lua_table_with_meta = utils.n2l.types.with-meta.mk (let
1024     tablevar = "tbl_in";
1025   in {
1026     table = {
1027       this = "is a test table";
1028       inatesttable = "that will be translated to a Lua table with a metatable";
1029     };
1030     # to avoid translating the table multiple times,
1031     # define a variable name for it in Lua. Defaults to "tbl_in"
1032     inherit tablevar;
1033     meta = {
1034       # __call in Lua lets us also call it like a function
1035       __call = utils.n2l.types.function-unsafe.mk {
1036         args = [ "self" "..." ];
1037         body = ''
1038           print("This table is named ${tablevar}")
1039           return ${tablevar}.this
1040         '';
1041       };
1042     };
1043     # you can change it to set the metatable of
1044     # and return a different table instead.
1045     # sometimes done so that access always uses __index function
1046     newtable = null; # <- default val, sets metatable of tablevar
1047   });
1048 
1049 ---------------------------------------------------------------------------------------
1050 vim:tw=78:ts=8:ft=help:norl: