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
154 inherit (inputs.nixCats) utils;
155
156 luaPath = "${./.}";
157
158 extra_pkg_config = {
159
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
177
178
179
180
181
182
183
184
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 mkPlugin = name: src: as an argument. mkPlugin takes a name,
225 and then a src which is any flake input or fetched drv,
226 and it returns a nvim plugin that can be further 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 It also recieves a mkNvimPlugin = src: name: which does the same thing, but
231 with the arguments the wrong way around.
232 It is still present for backwards compatibility.
233
234 These are the things you can return:
235
236 categoryDefinitions = { pkgs, settings, categories, extra, name, mkPlugin, mkNvimPlugin, ... }@packageDef: {
237
238 <startupPlugins>
239 a flexible set of categories, each containing startup plugins.
240 Startup plugins are loaded and can be required.
241 In addition, this can also recieve a superset of the home manager syntax for
242 plugins. see :help nixCats.flake.outputs.categoryDefinitions.schemas below
243 for info
244
245 <optionalPlugins>
246 a flexible set of categories, each containing optional plugins.
247 Optional plugins need to be added with packadd before being required.
248 Use :NixCats pawsible to see the names to use for packadd
249 In addition, this can also recieve a superset of the home manager syntax for
250 plugins. see :help nixCats.flake.outputs.categoryDefinitions.schemas below
251 for info
252
253 <lspsAndRuntimeDeps>
254 a flexible set of categories, each containing LSPs or
255 other internal runtime dependencies such as ctags or debuggers
256 these are available to the PATH while within the Neovim program.
257 this includes the Neovim terminal.
258 lspsAndRuntimeDeps = {
259
260 general = with pkgs; [
261 universal-ctags
262 ripgrep
263 fd
264 ];
265 go = with pkgs; [
266 gopls
267 gotools
268 go-tools
269 gccgo
270 ];
271 };
272
273 <sharedLibraries>
274 a flexible set of categories, each containing a derivation for
275 a runtime shared library. Will be prepended to the LD_LIBRARY_PATH variable.
276 sharedLibraries = {
277 general = {
278 myGitStuff = with pkgs; [
279 libgit2
280 ];
281 };
282 };
283
284 <environmentVariables>
285 a flexible set of categories, each containing an ATTRIBUTE SET of
286 EnvironmentVariableName = "EnvironmentVariableValue";
287 environmentVariables = {
288 general = {
289 CATTESTVARDEFAULT = "It worked!";
290 };
291 };
292
293 <wrapperArgs>
294 a flexible set of categories, each containing escaped lists of wrapper arguments.
295 wrapperArgs = {
296 yourCategory = [
297 [ "--set" "MYVAR" "test value" ]
298 {
299 value = [ "--set" "MYVAR2" "test value 2" ];
300 priority = 150;
301 }
302 ];
303 another = [
304 "--suffix"
305 "PATH"
306 "${pkgs.lib.makeBinPath [ pkgs.something ]}"
307 ];
308 };
309 If you don't know what that is, see here:
310 https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/setup-hooks/make-wrapper.sh
311
312 <extraWrapperArgs>
313 a flexible set of categories, each containing unescaped wrapper arguments.
314 extraWrapperArgs = {
315 yourCategory = [
316 "--set MYVAR 'test value'"
317 {
318 value = "--set MYVAR2 'test value 2'";
319 priority = 150;
320 }
321 ];
322 };
323
324 <extraLuaPackages>
325 a flexible set of categories, each containing FUNCTIONS
326 that return lists of extra Lua packages.
327 These functions are the same thing that you would pass to lua.withPackages.
328 Is used to populate $LUA_PATH and $LUA_CPATH
329 extraLuaPackages = {
330 general = [ (lp: [ lp.magick ]) ];
331 };
332
333 <optionalLuaPreInit>
334 a flexible set of categories, each containing a list of lua strings,
335 or a LIST of sets containing a priority and a string of the format:
336 catname = [ "require('athing')" { config = "require('something')"; priority = 150; } ];
337 (150 is default priority)
338 These will be ran before sourcing your init.lua
339 It is not the recommended way to create Lua for this flake,
340 but it may be useful in editing flake imports
341 of other already configured setups following the nixCats format.
342
343 <optionalLuaAdditions>
344 a flexible set of categories, each containing a list of lua strings,
345 or a LIST of sets containing a priority and a string of the format:
346 catname = [ "require('athing')" { config = "require('something')"; priority = 150; } ];
347 (150 is default priority)
348 These will be ran after sourcing your init.lua
349 It is not the recommended way to create Lua for this flake,
350 but it may be useful in editing flake imports
351 of other already configured setups following the nixCats format.
352
353 <bashBeforeWrapper>
354 a flexible set of categories, each containing arbitrary Bash code
355 to run before the wrapper starts within the wrapper's Bash environment.
356 # WARNING: only use this if you know what you are doing and why you need
357 to do it. Whenever possible, use wrapperArgs or extraWrapperArgs instead.
358 This section works the same as extraWrapperArgs but for bash.
359
360 <extraCats>
361 a flexible set of categories, each containing a list of attribute paths,
362 specified as lists of strings. Thus each category would contain a list of
363 lists of strings.
364 Allows inclusion of extra categories contingent on each lists inclusion in the package,
365 and is useful for creating default values for subcategories.
366 For more info, see below at
367 :h nixCats.flake.outputs.categoryDefinitions.default_values
368 # WARNING: use of categories argument in this set will cause infinite recursion
369 # The categories argument of this function is the FINAL value.
370 # You may use it in any of the other sets.
371
372 <propagatedBuildInputs>
373 a flexible set of categories, each containing internal BUILD dependencies.
374 Will not be available to the PATH unless in a devShell.
375 # WARNING: USING THIS SECTION WILL CAUSE NVIM TO BUILD FROM SOURCE.
376 }
377
378 In essence, the contents of each set listed here are filtered
379 based on the packageDefinitions set you provide,
380 whereby including categoryname = true; you enable that category.
381 :help nixCats.flake.outputs.packageDefinitions
382
383 It will remove duplicate items, so feel free to include the same thing in
384 multiple categories if it suits your purposes.
385
386 It does this recursively. (explained below)
387
388 If, inside one of these main sets, you had another set,
389 it would consider that a subcategory, and you could enable it
390 just like you do with a normal category, by setting a value with the
391 corresponding attribute path to true in the category
392 set of nixCats.flake.outputs.packageDefinitions.
393 You can nest them as much as you like, or just have a category that is a
394 single derivation.
395
396 nixCats.flake.outputs.categoryDefinitions.schemas
397
398 You may also use the variables passed to your categoryDefinitions function
399 to get access to the set of categories and settings that are being
400 used to define the current package being built!
401
402 themer = with pkgs.vimPlugins;
403 (builtins.getAttr packageDef.categories.colorscheme {
404
405 "onedark" = onedark-vim;
406 "catppuccin" = catppuccin-nvim;
407 }
408 );
409
410 In addition to all this, if a plugin is defined within a list, it may
411 instead be defined within an attribute set that also contains config
412 to be ran after sourcing init.lua and optionalLuaAdditions
413 to do this, you may use the following syntax in opt or start sections:
414 [
415
416 { plugin = derivation; config.lua = ""; config.vim = "";}
417 { plugin = derivation; config = ""; type = "<viml or lua>"; }
418 { plugin = derivation; config = ""; }
419 { plugin = derivation; }
420
421
422
423
424
425
426
427
428
429
430
431
432 derivation
433
434
435
436 ]
437
438 nixCats.flake.outputs.categoryDefinitions.default_values
439
440 There are 2 ways of creating default values in nixCats.
441
442 #1 Implicit: when value is in another section of categoryDefinitions
443
444 If in your categoryDefinitions you had the following:
445
446 environmentVariables = {
447 test = {
448 subtest1 = {
449 CATTESTVAR = "It worked!";
450 };
451 subtest2 = {
452 CATTESTVAR3 = "It didn't work!";
453 };
454 };
455 };
456 extraWrapperArgs = {
457 test = [
458 '' --set CATTESTVAR2 "It worked again!"''
459 ];
460 };
461
462 And in your packageDefinitions set, under categories, you had the following:
463
464 test = {
465 subtest1 = true;
466 };
467
468 you could echo $CATTESTVAR and $CATTESTVAR2 in your terminal to see them.
469 However you could not echo $CATTESTVAR3.
470
471 All items that are not attributes of the parent set will be included
472 when you enable a subcategory. This includes lists, strings, functions, etc...
473
474 However, attributes will not and you must explicitly enable all attributes of
475 a subcategory if you set even 1 explicitly.
476
477 Thus to include CATTESTVAR3, you would have to enable it like so:
478 test = {
479 subtest1 = true;
480 subtest2 = true;
481 };
482 However, those are all the items in the test category.
483 So instead we can do this to enable all the subcategories in test.
484 test = true;
485
486 This applies in many situations. Take this one for example.
487
488 lspsAndRuntimeDeps = {
489 neonixdev = {
490 inherit (pkgs)
491 nix-doc nil lua-language-server nixd;
492 };
493 };
494 startupPlugins = {
495 neonixdev = with pkgs.vimPlugins; [
496 neodev-nvim
497 neoconf-nvim
498 ];
499 };
500
501 If you were to put the following in your packageDefinitions:
502 neonixdev.nix-doc = true;
503
504 neodev-nvim and neoconf-nvim would still be included.
505 However, nil, lua-language-server, and nixd would not be!
506 You would need to pick which of those you wanted separately.
507 Sometimes this is the desired behavior.
508 Sometimes it is not and a list of packages would be better suited.
509
510 This leads us to our second way to make a default value:
511
512 #2 Explicit: using extraCats section of categoryDefinitions.
513
514 The extraCats section of categoryDefinitions contains categories of attribute
515 paths. If that category is defined, the categories specified by the attribute
516 paths will also be enabled. This means you could make it so that if you
517 included the go category, it could then enable debug.go and lsp.go for you.
518 But in addition to that, it can be combined with the implicit form of creating
519 default values above in an interesting way.
520
521 categoryDefinitions = { pkgs, settings, categories, extra, name, ... }@packageDef: {
522 lspsAndRuntimeDeps = {
523 debug = with pkgs; {
524 go = [ delve ];
525 };
526 go = with pkgs; [
527 gopls
528 gotools
529 go-tools
530 gccgo
531 ];
532 };
533 startupPlugins = {
534 debug = with pkgs.vimPlugins; {
535 default = [
536 nvim-dap
537 nvim-dap-ui
538 nvim-dap-virtual-text
539 ];
540 go = [ nvim-dap-go ];
541 };
542 };
543
544
545
546 extraCats = {
547
548
549
550
551 debug = [
552 [ "debug" "default" ]
553 ];
554
555
556 go = [
557 [ "debug" "go" ]
558 ];
559 };
560 };
561
562 If you wish to only enable a value via extraCats if multiple other categories
563 are enabled, the categories in extraCats also accept a set form!
564
565 extraCats = {
566
567 target.cat = [
568
569 [ "to" "enable" ]
570
571 {
572 cat = [ "other" "toenable" ];
573
574
575
576 when = [
577 [ "another" "cat" ]
578 ];
579
580 cond = [
581 [ "other" "category" ]
582 ];
583 }
584 ];
585 };
586
587 ---------------------------------------------------------------------------------------
588 Package Generation: nixCats.flake.outputs.packageDefinitions
589
590 generate packages by calling that builder function we just created.
591 Place them in the packageDefinitions set.
592
593 First, pick the set of settings you wish to include.
594
595 Then, pass it a set of named boolean values like this:
596 { categoryname1 = true; categoryname2 = false; etc... }
597 False may be omitted. True may not.
598 Only true matters for what plugins will be added.
599
600 These categories are defined in the Builder function above
601 by placing named lists of plugins in the flexible sets provided.
602 The category names are the names of those lists.
603 Add a new list, then enable the category here.
604
605 If you have categories with the same name in
606 multiple different sets outlined above in the builder,
607 all plugins in those categories will be
608 included when you set "thatname = true;" here.
609 hence, general = true; will include the general lspsAndDeps category,
610 as well as the general startupPlugins category.
611
612 an example package definition:
613
614 packageDefinitions = {
615 nixCats = { pkgs, name, ... }: {
616 setting = {
617 wrapRc = true;
618
619 aliases = [ "viCat" ];
620 };
621 categories = {
622 custom = true;
623 gitPlugins = true;
624 general = true;
625 neonixdev = true;
626
627
628
629 lspDebugMode = false;
630
631
632
633 theBestCat = "says meow!!!";
634
635
636
637
638 };
639 extra = {
640 there_is = "also";
641 an_extra = "table";
642 for = ''if you dont want the main subcategory get function
643 to apply to something, or think it all being in categories is too
644 messy
645 '';
646 you_can = ''nixCats.extra("path.to.val")'';
647 for_safer = ''table access via vim.tbl_get'';
648 };
649 };
650 };
651
652 You can use the nixCats plugin for the set you define here in your Lua
653 It returns a Lua table of the same format.
654
655 see :help nixCats
656
657 For more nuances on enabling categories and subcategories, see above at
658 :help nixCats.flake.outputs.categoryDefinitions.default_values
659 and
660 :help nixCats.flake.outputs.categoryDefinitions.schemas
661
662 ----------------------------------------------------------------------------------------
663 Settings nixCats.flake.outputs.settings
664
665 These are the defaults:
666
667 default_settings = {
668
669
670
671 aliases = null;
672
673
674 extraName = "";
675
676
677 hosts = {};
678
679
680
681
682
683
684
685 wrapRc = true;
686
687
688
689
690
691
692
693
694
695
696
697
698 configDirName = "nvim";
699
700
701
702
703
704
705 unwrappedCfgPath = null;
706
707
708
709
710
711 neovim-unwrapped = null;
712
713
714
715 nvimSRC = null;
716
717
718
719
720 suffix-path = true;
721
722
723 suffix-LD = true;
724
725
726
727
728
729
730
731
732 autowrapRuntimeDeps = "suffix";
733
734
735
736
737
738
739
740 autoconfigure = "prefix";
741
742
743
744
745
746
747
748
749 collate_grammars = true;
750
751
752
753
754 autoPluginDeps = true;
755
756
757
758
759 moduleNamespace = [ <packagename> ];
760 };
761
762 QUICK TIP: wrapRc
763
764 The wrapRc option is very useful for testing Lua changes.
765 It removes the need to stage and rebuild to see your Lua changes reflected.
766 You will still need to rebuild when making changes to Nix regardless of the
767 value of wrapRc.
768
769 However it also means that the Lua isn't going run if it isn't in the right
770 folder, i.e. when installed and run from GitHub with nix run.
771
772 If the Lua is not in vim.fn.stdpath('config'), wrapRc = false will not work.
773 By default this is ~/.config/nvim on Linux systems, although we can
774 change nvim to whatever we wish via the configDirName setting.
775
776 Alternatively, you can set the unwrappedCfgPath option to allow the
777 configuration to be set to an absolute path. You still may want to set
778 the configDirName option anyway to change the data directories,
779 or explicitly keep it the same on both so that they share stuff like auths.
780
781 The most convenient way to use this is the following:
782 Make a second identical packageDefinition, but with wrapRc disabled.
783 Then install both the wrapped one and unwrapped one with different aliases.
784 When you want to hack in Lua, use unwrapped! When you're done, just rebuild
785 and go back to the wrapped one.
786
787 The templates/example/flake.nix file from the example config template
788 has an example of this with nixCats and regularCats.
789
790 Then, when testing Lua changes, you run the other package and have a vanilla
791 Neovim experience, only rebuilding when you install new packages.
792
793 When you are satisfied, simply rebuild and go back to using the main package,
794 as it was the same except for the single option!
795
796 --------------------------------------------------------------------------------------
797 Remote Host Providers: nixCats.flake.outputs.settings.hosts
798
799 You can bundle anything with nixCats as a host/provider!
800 Each "host" defined in the hosts set will
801 create a new section in categoryDefinitions,
802 and a global variable of your choosing will be set to the path of the host.
803
804 Each defined host will also be added to your path as ${nvimname}-${hostname}
805
806 So if your package was named mynvim,
807 enabling the python3 host will add mynvim-python3 to your path.
808
809 There are some with builtin defaults.
810 For those, unless you wish to redefine them, you only need to enable them.
811 hosts.python3.enable = true
812 hosts.node.enable = true
813 hosts.ruby.enable = true
814 hosts.perl.enable = true
815
816 Lets use python3, as an example of a host definition.
817
818 It will create a section in categoryDefinitions called python3 you can use.
819 The things defined within it will wrap only that host.
820
821 categoryDefinitions = { pkgs, settings, categories, name, ... }@packageDef: {
822 python3 = {
823 wrapperArgs = {
824 somecatname = [
825 [ "--unset" "PYTHONSAFEPATH" ]
826 ];
827 };
828 extraWrapperArgs = {
829 somecatname = [
830 "--prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.vulkan-loader ]}"
831 ];
832 };
833 envVars = {
834 somecatname = {
835 MY_VAR = "somevalue";
836 };
837 };
838
839
840
841
842 libraries = {
843 somecatname = [
844 (p: [p.pytest])
845 ];
846 };
847 };
848 }
849
850 The definition for the python3 host would look like this when fully spelled out:
851
852 packageDefinitions = {
853 somename = {pkgs, name, ...}: {
854 settings = {
855 hosts = {
856 python3 = {
857 enable = true;
858
859
860
861
862
863
864
865 path = depfn: {
866 value = (pkgs.python3.withPackages (p: depfn p ++ [p.pynvim])).interpreter;
867 args = [ "--unset" "PYTHONPATH" ];
868 };
869
870
871
872
873 global = "python3_host_prog";
874
875
876
877
878
879
880
881 pluginAttr = "python3Dependencies";
882
883
884
885
886
887
888
889
890 disabled = "loaded_python3_provider";
891
892
893
894 };
895 };
896 };
897 };
898 };
899
900 You can bundle and wrap anything this way!
901
902 packageDefinitions = {
903 packagename = { pkgs, name, mkPlugin, ... }: {
904 categories = {
905 };
906 settings = {
907 hosts = {
908 neovide = {
909
910
911 enable = true;
912 path = {
913 value = "${pkgs.neovide}/bin/neovide";
914 args = [ "--add-flags" "--neovim-bin ${name}" ];
915 };
916 };
917 };
918 };
919 extra = {};
920 };
921 };
922
923 Defaults:
924
925 defaults = {
926 python3 = {
927 path = depfn: {
928 value = (pkgs.python3.withPackages (p: depfn p ++ [p.pynvim])).interpreter;
929 args = [ "--unset" "PYTHONPATH" ];
930 };
931 pluginAttr = "python3Dependencies";
932 };
933 node = {
934 path = {
935 value = "${pkgs.neovim-node-client or pkgs.nodePackages.neovim}/bin/neovim-node-host";
936 nvimArgs = [ "--suffix" "PATH" ":" "${pkgs.nodejs}/bin" ];
937 };
938 };
939 perl = {
940 path = depfn: "${pkgs.perl.withPackages (p: depfn p ++ [ p.NeovimExt p.Appcpanminus ])}/bin/perl";
941 };
942 ruby = {
943 path = let
944 rubyEnv = pkgs.bundlerEnv {
945 name = "neovim-ruby-env";
946 postBuild = "ln -sf ${pkgs.ruby}/bin/* $out/bin";
947 gemdir = "${pkgs.path}/pkgs/applications/editors/neovim/ruby_provider";
948 };
949 in {
950 value = "${rubyEnv}/bin/neovim-ruby-host";
951 nvimArgs = [
952 "--set" "GEM_HOME" "${rubyEnv}/${rubyEnv.ruby.gemPath}"
953 "--suffix" "PATH" ":" "${rubyEnv}/bin"
954 ];
955 };
956 };
957 };
958
959 --------------------------------------------------------------------------------------
960 Neovim Builder Creation: nixCats.flake.outputs.builder
961
962 Now we define our builder function.
963 We inherit utils.baseBuilder which is
964 a function that takes five arguments. It is defined in ./builder.
965 Right now we are going to call it with just the first four arguments. This will
966 leave us with a function that takes 1 argument.
967 That argument is the name of the Neovim package to be packaged.
968
969 1. The path to the Lua to include (in the flake, we use the self variable to get
970 this path and wrap the Lua when wrapRc = true)
971
972 2. A set containing parameters for the pkgs to be used:
973 It takes 2 forms. You can either pass it a nixpkgs and a system and it
974 will resolve the pkgs for you and pass it to your categoryDefinitions and
975 packageDefinitions,
976 or you can pass it a pkgs instead to inherit the values and do the same.
977
978 You may also provide a dependencyOverlays list to add overlays for nvim only,
979 extra_pkg_config (maps to the config argument to import nixpkgs { ... }),
980 nixCats_passthru (extra items to put into passthru in the final drv),
981 and extra_pkg_params (contains any fields in import nixpkgs { ... } not mentioned).
982
983 3. our function that takes an individual package definition
984 and returns a set of categoryDefinitions.
985
986 4. our set of packageDefinitions see: nixCats.flake.outputs.packageDefinitions
987
988 It is now a function that takes a name, and returns your chosen Neovim package.
989
990 packages = nixpkgs.lib.genAttrs nixpkgs.lib.platforms.all (system: let
991
992 nixCatsBuilder = utils.baseBuilder luaPath {
993 inherit nixpkgs system dependencyOverlays extra_pkg_config;
994 } categoryDefinitions packageDefinitions;
995 in {
996
997
998 default = nixCatsBuilder defaultPackageName;
999 });
1000
1001
1002 packages = nixpkgs.lib.genAttrs nixpkgs.lib.platforms.all (system: let
1003
1004 pkgs = import nixpkgs {
1005 inherit system;
1006 overlays = dependencyOverlays;
1007 config = extra_pkg_config;
1008 };
1009
1010 nixCatsBuilder = utils.baseBuilder luaPath {
1011
1012 inherit pkgs;
1013 } categoryDefinitions packageDefinitions;
1014 in {
1015
1016
1017 default = nixCatsBuilder defaultPackageName;
1018 });
1019
1020 ---------------------------------------------------------------------------------------
1021 Flake Exports and Export options nixCats.flake.outputs.exports
1022
1023 They look something like this:
1024
1025
1026
1027 utils.eachSystem nixpkgs.lib.platforms.all (system: let
1028
1029 nixCatsBuilder = utils.baseBuilder luaPath {
1030 inherit nixpkgs system dependencyOverlays extra_pkg_config;
1031 } categoryDefinitions packageDefinitions;
1032
1033
1034
1035 defaultPackage = nixCatsBuilder defaultPackageName;
1036
1037
1038
1039
1040 pkgs = import nixpkgs { inherit system; };
1041
1042
1043
1044
1045
1046 in
1047 {
1048
1049
1050
1051
1052 packages = utils.mkAllWithDefault defaultPackage;
1053
1054
1055
1056 devShells = {
1057 default = pkgs.mkShell {
1058 name = defaultPackageName;
1059 packages = [ defaultPackage ];
1060 inputsFrom = [ ];
1061 shellHook = ''
1062 '';
1063 };
1064 };
1065
1066 }) // {
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077 overlays = utils.makeOverlays luaPath {
1078
1079 inherit nixpkgs dependencyOverlays extra_pkg_config;
1080
1081 } categoryDefinitions packageDefinitions defaultPackageName;
1082
1083
1084
1085
1086 nixosModules.default = utils.mkNixosModules {
1087 inherit dependencyOverlays luaPath defaultPackageName
1088 categoryDefinitions packageDefinitions nixpkgs;
1089 };
1090
1091 homeModule = utils.mkHomeModules {
1092 inherit dependencyOverlays luaPath defaultPackageName
1093 categoryDefinitions packageDefinitions nixpkgs;
1094 };
1095
1096 inherit utils;
1097 inherit (utils) templates;
1098 };
1099
1100 nixCats.flake.outputs.utils
1101
1102 The <utils> set exports all the functions used in creating the format in the
1103 templates, including the main builder!
1104 (see :h nixCats.flake.outputs.builder for builder explanation)
1105
1106 In the interests of not repeating ourselves,
1107 a list of most functions exported in the <utils> set
1108 can be found here:
1109 https://nixcats.org/nixCats_utils.html
1110
1111 Missing from that list however,
1112 is an explanation of the internal <n2l> library
1113 nixCats uses to create the nixCats Lua plugin!
1114
1115 The library fully escapes all items passed to it,
1116 so usually you can't execute lua code in them.
1117 But you may still explicitly pass it lua code to execute at runtime
1118 by declaring them as inline lua types!
1119
1120 An intricate explanation of the full set
1121 of features the <n2l> library contains are below.
1122
1123 All other functions made available by
1124 the <utils> set are explained in the documentation
1125 at https://nixcats.org/nixCats_utils.html
1126
1127 nixCats.flake.outputs.utils.n2l
1128 <n2l> This is the Nix to Lua library nixCats
1129 uses to create the nixCats Lua plugin
1130 You may wish to use some functions from it.
1131
1132 The library is exported from the <utils> set as utils.n2l
1133
1134 It contains <toLua> and <prettyLua> and <uglyLua> which convert Nix to Lua.
1135
1136 it contains a <member> function to determine if a value is a special "inline lua" type
1137 it contains a <typeof> function to determine which special "inline lua" type it is
1138 it contains a <resolve> function which knows how to resolve the types to a string of code
1139 it contains the <default_subtype> name as well.
1140
1141 But of much more interest to you is the types you may declare.
1142
1143 Everything being passed through settings, categories, and extra in packageDefinitions
1144 will be properly escaped. But this also means that
1145 you cannot write any Lua code there.
1146
1147 Luckily, we have some types we can declare that will allow you to do this.
1148
1149 To declare that an item is a Lua value rather than a hard coded one,
1150 you may choose one of these types. To do this, call its constructor!
1151
1152 for example, types.inline-unsafe has 1 field, body.
1153
1154 To declare one in our settings, categories, and extra sets, it would look
1155 something like this:
1156
1157 categories = {
1158 somecat = utils.n2l.types.inline-unsafe.mk {body = "vim.fn.stdpath('data')"; }`
1159 }
1160
1161 inline-safe is the default type, and it gets to define a shorthand form.
1162
1163 categories = {
1164 somecat = utils.n2l.types.inline-safe.mk "vim.fn.stdpath('data')";`
1165 }
1166
1167 These are all the types, each one has an associated mk
1168 function to create a value of that type,
1169 which accepts the fields listed here, defined with default values.
1170
1171
1172 inline-safe = {
1173 default = (v: if v ? body then v else { body = v; });
1174 fields = { body = "nil"; };
1175 format = LI: "assert(loadstring(${luaEnclose "return ${LI.expr.body or LI.expr or "nil"}"}))()";
1176 };
1177
1178 inline-unsafe = {
1179 fields = { body = "nil"; };
1180 format = LI: "${LI.expr.body or "nil"}";
1181 };
1182
1183
1184 function-safe = {
1185 fields = { body = "return nil"; args = []; };
1186 format = LI:
1187 ''assert(loadstring(${luaEnclose ''return (function(${fixargs (LI.expr.args or [])}) ${LI.expr.body or "return nil"} end)''}))()'';
1188 };
1189
1190
1191 function-unsafe = {
1192 fields = { body = "return nil"; args = []; };
1193 format = LI: ''(function(${fixargs (LI.expr.args or [])}) ${LI.expr.body or "return nil"} end)'';
1194 };
1195 with-meta = {
1196 fields = {
1197 table = {};
1198 meta = {};
1199 newtable = null;
1200 tablevar = "tbl_in";
1201 };
1202 format = LI: opts: let
1203 metaarg1 = if LI.expr.newtable or null == null then LI.expr.tablevar or "{}" else toLuaFull opts LI.expr.newtable;
1204 result = inline.types.function-unsafe.mk {
1205 args = [ (LI.expr.tablevar or "tbl_in") ];
1206 body = ''return setmetatable(${metaarg1}, ${toLuaFull opts LI.expr.meta})'';
1207 };
1208 in "${toLuaFull opts result}(${toLuaFull opts LI.expr.table})";
1209 };
1210
1211
1212 Some more useage examples:
1213
1214 exampleSafeFunc = utils.n2l.types.function-safe.mk {
1215 args = [ "hello" ];
1216 body = ''
1217 print(hello)
1218 return hi
1219 '';
1220 };
1221 exampleUnsafeFunc = utils.n2l.types.function-unsafe.mk {
1222 args = [ "hi" "hello" ];
1223 body = ''
1224 print(hi)
1225 print(hello)
1226 return hi .. hello
1227 '';
1228 };
1229 };
1230 funcResults = {
1231 test1 = utils.n2l.types.inline-safe.mk ''${utils.n2l.resolve exampleSafeFunc}("Hello World!")'';
1232 };
1233 lua_table_with_meta = utils.n2l.types.with-meta.mk (let
1234 tablevar = "tbl_in";
1235 in {
1236 table = {
1237 this = "is a test table";
1238 inatesttable = "that will be translated to a Lua table with a metatable";
1239 };
1240
1241
1242 inherit tablevar;
1243 meta = {
1244
1245 __call = utils.n2l.types.function-unsafe.mk {
1246 args = [ "self" "..." ];
1247 body = ''
1248 print("This table is named ${tablevar}")
1249 return ${tablevar}.this
1250 '';
1251 };
1252 };
1253
1254
1255
1256 newtable = null;
1257 });
1258
1259 ---------------------------------------------------------------------------------------
1260 vim:tw=78:ts=8:ft=help:norl: