summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMinijackson <minijackson@riseup.net>2021-11-08 16:26:42 +0100
committerMinijackson <minijackson@riseup.net>2021-11-08 16:26:42 +0100
commitc7026a993c4b837dcee39f669e1cc4123f4eb53d (patch)
tree8cfea3898b391a3c2ab8e48a7b1dd2b711456739
downloadnix-module-doc-c7026a993c4b837dcee39f669e1cc4123f4eb53d.tar.gz
nix-module-doc-c7026a993c4b837dcee39f669e1cc4123f4eb53d.zip
initial commit
-rw-r--r--.gitignore2
-rw-r--r--checks/simple-mdbook/.gitignore1
-rw-r--r--checks/simple-mdbook/book.toml6
-rw-r--r--checks/simple-mdbook/src/SUMMARY.md5
-rw-r--r--checks/simple-mdbook/src/chapter_1.md1
-rw-r--r--checks/simple-mdbook/src/chapter_2-1.md1
-rw-r--r--checks/simple-mdbook/src/chapter_2.md1
-rw-r--r--doc-options-md.nix52
-rw-r--r--flake.lock27
-rw-r--r--flake.nix104
-rw-r--r--manpage.nix136
-rw-r--r--mdbook.nix45
12 files changed, 381 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..750baeb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
1result
2result-*
diff --git a/checks/simple-mdbook/.gitignore b/checks/simple-mdbook/.gitignore
new file mode 100644
index 0000000..7585238
--- /dev/null
+++ b/checks/simple-mdbook/.gitignore
@@ -0,0 +1 @@
book
diff --git a/checks/simple-mdbook/book.toml b/checks/simple-mdbook/book.toml
new file mode 100644
index 0000000..425d511
--- /dev/null
+++ b/checks/simple-mdbook/book.toml
@@ -0,0 +1,6 @@
1[book]
2authors = ["Minijackson"]
3language = "en"
4multilingual = false
5src = "src"
6title = "Simple MdBook"
diff --git a/checks/simple-mdbook/src/SUMMARY.md b/checks/simple-mdbook/src/SUMMARY.md
new file mode 100644
index 0000000..9cebd5b
--- /dev/null
+++ b/checks/simple-mdbook/src/SUMMARY.md
@@ -0,0 +1,5 @@
1# Summary
2
3- [Chapter 1](./chapter_1.md)
4- [Chapter 2](./chapter_2.md)
5 - [Chapter 2.2](./chapter_2-1.md)
diff --git a/checks/simple-mdbook/src/chapter_1.md b/checks/simple-mdbook/src/chapter_1.md
new file mode 100644
index 0000000..b743fda
--- /dev/null
+++ b/checks/simple-mdbook/src/chapter_1.md
@@ -0,0 +1 @@
# Chapter 1
diff --git a/checks/simple-mdbook/src/chapter_2-1.md b/checks/simple-mdbook/src/chapter_2-1.md
new file mode 100644
index 0000000..b5cb2dc
--- /dev/null
+++ b/checks/simple-mdbook/src/chapter_2-1.md
@@ -0,0 +1 @@
# Chapter 2.2
diff --git a/checks/simple-mdbook/src/chapter_2.md b/checks/simple-mdbook/src/chapter_2.md
new file mode 100644
index 0000000..7ebb596
--- /dev/null
+++ b/checks/simple-mdbook/src/chapter_2.md
@@ -0,0 +1 @@
# Chapter 2
diff --git a/doc-options-md.nix b/doc-options-md.nix
new file mode 100644
index 0000000..ea21746
--- /dev/null
+++ b/doc-options-md.nix
@@ -0,0 +1,52 @@
1{ outputAttrPath, optionsAttrPath, optionsInternal ? true, }:
2
3{ lib, options, pkgs, ... }:
4
5with lib;
6
7let
8 visibleOptionDocs = filter (opt: opt.visible && !opt.internal) (optionAttrSetToDocList options);
9
10 toValue = value:
11 if value ? _type && value._type == "literalExpression" then value.text
12 else generators.toPretty { } value;
13
14 toMarkdown = option:
15 ''
16 ## `${option.name}`
17
18 ${option.description}
19
20 ${optionalString (option ? default) ''
21 **Default value**:
22
23 ```nix
24 ${toValue option.default}
25 ```
26 ''}
27
28 **Type**: ${option.type}${optionalString option.readOnly " (read only)"}
29
30 ${optionalString (option ? example) ''
31 **Example**:
32
33 ```nix
34 ${toValue option.example}
35 ```
36 ''}
37
38 Declared in:
39
40 ${concatStringsSep "\n" (map (decl: "- ${decl}") option.declarations)}
41
42 '';
43
44 # TODO: rewrite "Declared in" so that it points to GitHub repository
45
46 options-md = concatStringsSep "\n" (map toMarkdown visibleOptionDocs);
47in
48{
49 config = setAttrByPath outputAttrPath {
50 doc-options-md = pkgs.writeText "options.md" options-md;
51 };
52}
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..842821c
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,27 @@
1{
2 "nodes": {
3 "nixpkgs": {
4 "locked": {
5 "lastModified": 1636196544,
6 "narHash": "sha256-15s56Yu3vF8Na4yx4HkNc3997WZltOIB2CT1sOiCKKM=",
7 "owner": "NixOS",
8 "repo": "nixpkgs",
9 "rev": "ce48bcdde86eef5780a60bea55b9bc9dbd8248cd",
10 "type": "github"
11 },
12 "original": {
13 "owner": "NixOS",
14 "ref": "nixos-21.05",
15 "repo": "nixpkgs",
16 "type": "github"
17 }
18 },
19 "root": {
20 "inputs": {
21 "nixpkgs": "nixpkgs"
22 }
23 }
24 },
25 "root": "root",
26 "version": 7
27}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..2826989
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,104 @@
1{
2 description = "Generate documentation for your own projects using the NixOS module system";
3
4 inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.05";
5
6 outputs = { self, nixpkgs }:
7 let pkgs = nixpkgs.legacyPackages.x86_64-linux;
8 in
9 {
10
11 lib.modules = {
12 doc-options-md = import ./doc-options-md.nix;
13 mdbook = import ./mdbook.nix;
14 manpage = import ./manpage.nix;
15 };
16
17 checks.x86_64-linux =
18 let
19 evalModules = modules: pkgs.lib.evalModules {
20 modules = [
21 ({ config._module.args = { inherit pkgs; }; })
22 ] ++ modules;
23 };
24 simpleModule = with pkgs.lib; {
25 options.my.simple.module.outputs = mkOption {
26 type = with types; attrsOf package;
27 default = { };
28 description = ''
29 Output products of my simple module system.
30 '';
31 };
32 };
33 params = {
34 outputAttrPath = [ "my" "simple" "module" "outputs" ];
35 optionsAttrPath = [ "my" "simple" "module" "doc" ];
36 optionsInternal = false;
37 };
38
39 simple-manpage = {
40 name = "my simple module system";
41 shortDescription = "A sample module system";
42 };
43
44 advanced-manpage = {
45 name = "my simple module system";
46 section = 5;
47 shortDescription = "A sample module system";
48 description = ''
49 This is a very advanced module system, for advanced people.
50 '';
51
52 textBefore = ''
53 # A SECTION BEFORE
54
55 This is a section before the options.
56 '';
57
58 textAfter = ''
59 # A SECTION AFTER
60
61 This is a section after the options.
62 '';
63 };
64 in
65 {
66 simple-doc-options-md = (evalModules [
67 simpleModule
68 (self.lib.modules.doc-options-md params)
69 ]).config.my.simple.module.outputs.doc-options-md;
70
71 simple-manpage = (evalModules [
72 simpleModule
73 (self.lib.modules.doc-options-md params)
74 (self.lib.modules.manpage params)
75 {
76 my.simple.module.doc.manpage = simple-manpage;
77 }
78 ]).config.my.simple.module.outputs.manpage;
79
80 advanced-manpage = (evalModules [
81 simpleModule
82 (self.lib.modules.doc-options-md params)
83 (self.lib.modules.manpage params)
84 {
85 my.simple.module.doc.manpage = advanced-manpage;
86 }
87 ]).config.my.simple.module.outputs.manpage;
88
89 simple-mdbook = (evalModules [
90 simpleModule
91 (self.lib.modules.doc-options-md params)
92 (self.lib.modules.mdbook params)
93 {
94 my.simple.module.doc.mdbook.src = ./checks/simple-mdbook;
95 }
96 ]).config.my.simple.module.outputs.mdbook;
97
98 };
99
100 devShell.x86_64-linux = pkgs.mkShell {
101 nativeBuildInputs = with pkgs; [ mdbook pandoc ];
102 };
103 };
104}
diff --git a/manpage.nix b/manpage.nix
new file mode 100644
index 0000000..bea6b25
--- /dev/null
+++ b/manpage.nix
@@ -0,0 +1,136 @@
1{ outputAttrPath, optionsAttrPath, optionsInternal ? true, }:
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8 cfg = getAttrFromPath (optionsAttrPath ++ [ "manpage" ]) config;
9in
10{
11 options = setAttrByPath optionsAttrPath {
12 manpage = {
13 name = mkOption {
14 type = types.str;
15 description = ''
16 Name of the generated manpage.
17 '';
18 internal = optionsInternal;
19 };
20
21 shortDescription = mkOption {
22 type = types.str;
23 description = ''
24 A short description of the generated manpage.
25 '';
26 internal = optionsInternal;
27 };
28
29 description = mkOption {
30 type = with types; nullOr lines;
31 description = ''
32 A long description of the generated manpage.
33 '';
34 default = null;
35 internal = optionsInternal;
36 };
37
38 section = mkOption {
39 type = types.int;
40 default = 5;
41 description = ''
42 The section number for the generated manpage.
43
44 The table below shows the section numbers of the manual followed by the types of pages they contain.
45
46 1. Executable programs or shell commands
47 2. System calls (functions provided by the kernel)
48 3. Library calls (functions within program libraries)
49 4. Special files (usually found in /dev)
50 5. File formats and conventions, e.g. /etc/passwd
51 6. Games
52 7. Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)
53 8. System administration commands (usually only for root)
54 9. Kernel routines [Non standard]
55 '';
56 internal = optionsInternal;
57 };
58
59 file = mkOption {
60 type = types.str;
61 description = ''
62 The file containing the generated manpage.
63 '';
64 default = "${strings.sanitizeDerivationName cfg.name}.${toString cfg.section}";
65 defaultText = "\${lib.strings.sanitizeDerivationName cfg.name}.\${toString cfg.section}";
66 internal = optionsInternal;
67 };
68
69 title = mkOption {
70 type = types.str;
71 default = "${toUpper (strings.sanitizeDerivationName cfg.name)}(${toString cfg.section})";
72 defaultText = "\${toUpper cfg.name}(\${toString cfg.section})";
73 description = ''
74 Title of the generated manpage.
75 '';
76 internal = optionsInternal;
77 };
78
79 textBefore = mkOption {
80 type = types.lines;
81 description = ''
82 Some text to insert before the list of options.
83 '';
84 default = "";
85 internal = optionsInternal;
86 };
87
88 textAfter = mkOption {
89 type = types.lines;
90 description = ''
91 Some text to insert after the list of options.
92 '';
93 default = "";
94 internal = optionsInternal;
95 };
96
97 };
98 };
99
100 config = setAttrByPath outputAttrPath {
101 manpage = pkgs.runCommand cfg.file
102 {
103 src = pkgs.writeText "${cfg.file}.md" ''
104 % ${cfg.title}
105
106 # NAME
107
108 ${cfg.name} - ${cfg.shortDescription}
109
110
111 ${optionalString (cfg.description != null) ''
112 # DESCRIPTION
113
114 ${cfg.description}
115 ''}
116
117
118 ${cfg.textBefore}
119
120
121 # OPTIONS
122
123 You can use the following options:
124
125 ${readFile (getAttrFromPath (outputAttrPath ++ ["doc-options-md"]) config)}
126
127
128 ${cfg.textAfter}
129 '';
130
131 nativeBuildInputs = [ pkgs.pandoc ];
132 } ''
133 pandoc "$src" --from=markdown --to=man --standalone --output="$out"
134 '';
135 };
136}
diff --git a/mdbook.nix b/mdbook.nix
new file mode 100644
index 0000000..d336042
--- /dev/null
+++ b/mdbook.nix
@@ -0,0 +1,45 @@
1{ outputAttrPath, optionsAttrPath, optionsInternal ? true, }:
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8 cfg = getAttrFromPath (optionsAttrPath ++ [ "mdbook" ]) config;
9in
10{
11 options = setAttrByPath optionsAttrPath {
12 mdbook = {
13 src = mkOption {
14 type = with types; either path package;
15 description = ''
16 Root directory of mdbook sources to compile.
17 '';
18 internal = optionsInternal;
19 };
20 };
21 };
22
23 config = setAttrByPath outputAttrPath {
24 # TODO: make pandoc pre-processor
25 mdbook = pkgs.runCommand "mdbook"
26 {
27 src = cfg.src;
28 nativeBuildInputs = with pkgs; [ mdbook ];
29 } ''
30 unpackFile "$src"
31 chmod -R u+w .
32 cd */
33
34 mkdir theme
35 cp ${pkgs.documentation-highlighter}/highlight.pack.js theme/highlight.js
36 cp ${pkgs.documentation-highlighter}/mono-blue.css theme/highlight.css
37
38 cp "${getAttrFromPath (outputAttrPath ++ ["doc-options-md"]) config}" src/options.md
39
40 mdbook build
41
42 cp -r book "$out"
43 '';
44 };
45}