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