2023-08-07 23:14:58 +02:00
|
|
|
(local yaml (require :lyaml))
|
2023-08-06 23:25:37 +02:00
|
|
|
|
|
|
|
(local { : view } (require :fennel))
|
|
|
|
|
|
|
|
(fn headline [name]
|
2023-08-12 21:49:16 +02:00
|
|
|
(let [(_ _ basename) (string.find name ".*/([^/].*).nix")
|
2023-08-06 23:25:37 +02:00
|
|
|
len (basename:len)]
|
2023-08-12 21:49:16 +02:00
|
|
|
(.. basename "\n" (string.rep "=" len))))
|
2023-08-06 23:25:37 +02:00
|
|
|
|
2023-08-07 23:14:58 +02:00
|
|
|
(fn read-preamble [pathname]
|
|
|
|
(if (= (pathname:sub 1 1) "/")
|
|
|
|
(let [pathname (if (string.match pathname ".nix$")
|
|
|
|
pathname
|
|
|
|
(.. pathname "/default.nix"))]
|
|
|
|
(with-open [f (assert (io.open pathname :r))]
|
2023-08-12 21:49:16 +02:00
|
|
|
(accumulate [lines nil
|
2023-08-07 23:14:58 +02:00
|
|
|
l (f:lines)
|
|
|
|
:until (not (= (string.sub l 1 2) "##"))]
|
2023-08-12 21:49:16 +02:00
|
|
|
(.. (or lines "") (string.gsub l "^## *" "") "\n"))))))
|
2023-08-07 23:14:58 +02:00
|
|
|
|
2023-08-12 22:12:57 +02:00
|
|
|
(fn relative-pathname [pathname]
|
|
|
|
(let [pathname
|
|
|
|
(if (string.match pathname ".nix$")
|
|
|
|
pathname
|
|
|
|
(.. pathname "/default.nix"))]
|
|
|
|
(pick-values 1 (string.gsub pathname "^/nix/store/[^/]+/" "modules/"))))
|
|
|
|
|
2023-08-06 23:25:37 +02:00
|
|
|
(fn strip-newlines [text]
|
2023-08-11 22:12:57 +02:00
|
|
|
(-> text
|
|
|
|
(string.gsub "\n([^\n])" " %1")
|
|
|
|
(string.gsub "\n\n+" "\n")))
|
2023-08-06 23:25:37 +02:00
|
|
|
|
|
|
|
(fn indent [n text]
|
|
|
|
(let [margin (string.rep " " n)]
|
2023-08-11 22:12:57 +02:00
|
|
|
(.. margin (string.gsub (or text "") "\n +" (.. "\n" margin )))))
|
|
|
|
|
|
|
|
(fn indent-literal [n text]
|
|
|
|
(let [margin (string.rep " " n)]
|
|
|
|
(.. margin (string.gsub (or text "") "\n" (.. "\n" margin )))))
|
2023-08-06 23:25:37 +02:00
|
|
|
|
|
|
|
(fn extract-text [description]
|
2023-08-11 22:12:57 +02:00
|
|
|
(match description
|
|
|
|
{ :_type "literalExpression" : text } text
|
|
|
|
(where s (= (type s) "string")) description
|
|
|
|
_ nil))
|
2023-08-06 23:25:37 +02:00
|
|
|
|
2023-08-16 20:43:12 +02:00
|
|
|
(fn escape-backslash [s]
|
|
|
|
(string.gsub s "\\" "\\\\"))
|
|
|
|
|
2023-08-06 23:25:37 +02:00
|
|
|
(fn print-option [o offset]
|
|
|
|
(let [i (or offset 0)]
|
|
|
|
(print (indent i (.. " * option ``" o.name "``")))
|
2023-08-11 22:12:57 +02:00
|
|
|
(case (-?> o.description extract-text strip-newlines)
|
|
|
|
descr (print (indent (+ 4 i) descr)))
|
2023-08-06 23:25:37 +02:00
|
|
|
(print)
|
2023-08-16 20:43:12 +02:00
|
|
|
(print (indent (+ 4 i) (.. "**type** " (escape-backslash o.type) "\n")))
|
2023-08-11 22:12:57 +02:00
|
|
|
(when o.example
|
|
|
|
(print (indent (+ 4 i) "**example**")) (print)
|
|
|
|
(print (indent (+ 4 i) ".. code-block:: nix"))
|
|
|
|
(print)
|
|
|
|
(print (indent-literal (+ 8 i) (extract-text o.example)) "\n")
|
|
|
|
(print))
|
|
|
|
|
|
|
|
(when (extract-text o.default)
|
|
|
|
(print (indent (+ 4 i) "**default**")) (print)
|
|
|
|
(print (indent (+ 4 i) ".. code-block:: nix"))
|
|
|
|
(print)
|
|
|
|
(print (indent-literal (+ 8 i) (extract-text o.default)) "\n")
|
|
|
|
(print))))
|
2023-08-06 23:25:37 +02:00
|
|
|
|
|
|
|
(fn print-service [o]
|
|
|
|
(print (.. " * service ``" o.name "``"))
|
2023-08-12 19:16:20 +02:00
|
|
|
(match (extract-text o.description)
|
|
|
|
descr (print (indent 4 descr)))
|
2023-08-06 23:25:37 +02:00
|
|
|
(print)
|
|
|
|
(print (indent 4 "**Service parameters**\n"))
|
|
|
|
(each [_ param (ipairs o.parameters)]
|
|
|
|
(print-option param 4)))
|
|
|
|
|
2023-08-12 19:16:06 +02:00
|
|
|
(fn output? [option]
|
|
|
|
(match option.loc
|
|
|
|
["system" "outputs" & _] true
|
|
|
|
_ false))
|
|
|
|
|
2023-08-12 21:10:40 +02:00
|
|
|
(fn is-service? [o]
|
|
|
|
(= o.type "parametrisable s6-rc service definition"))
|
|
|
|
|
|
|
|
(fn has-service? [module]
|
|
|
|
(accumulate [found false
|
|
|
|
_ o (ipairs module)]
|
|
|
|
(or found (is-service? o))))
|
|
|
|
|
|
|
|
(fn sort-modules [modules]
|
|
|
|
;; modules containing services should sort _after_ modules
|
|
|
|
;; that contain only options
|
|
|
|
(doto (icollect [n m (pairs modules)]
|
|
|
|
{ :name n :service? (has-service? m) :module m })
|
|
|
|
(table.sort
|
|
|
|
(fn [a b]
|
|
|
|
(if (and a.service? (not b.service?))
|
|
|
|
false
|
|
|
|
(and b.service? (not a.service?))
|
|
|
|
true
|
|
|
|
(< a.name b.name))))))
|
|
|
|
|
2023-08-06 23:25:37 +02:00
|
|
|
(fn sort-options [module]
|
2023-08-12 19:16:06 +02:00
|
|
|
(let [options (icollect [_ o (ipairs module)]
|
|
|
|
(if (not (output? o))
|
|
|
|
o))]
|
2023-08-12 21:10:40 +02:00
|
|
|
(doto options (table.sort (fn [a b] (< a.name b.name))))))
|
2023-08-06 23:25:37 +02:00
|
|
|
|
2023-08-07 23:14:58 +02:00
|
|
|
(let [raw (yaml.load (io.read "*a"))
|
2023-08-06 23:25:37 +02:00
|
|
|
modules {}]
|
|
|
|
(each [_ option (ipairs raw)]
|
2023-08-07 23:14:58 +02:00
|
|
|
(each [_ path (ipairs option.declarations)]
|
|
|
|
(let [e (or (. modules path) [])]
|
|
|
|
(table.insert e option)
|
|
|
|
(tset modules path e))))
|
2023-08-09 23:26:50 +02:00
|
|
|
(tset modules "lib/modules.nix" nil)
|
2023-08-12 21:10:40 +02:00
|
|
|
(let [modules (sort-modules modules)]
|
2023-08-12 22:12:57 +02:00
|
|
|
(each [_ {: name : module : service?} (ipairs modules)]
|
2023-08-12 21:10:40 +02:00
|
|
|
(let [options (sort-options module)]
|
2023-08-12 22:12:57 +02:00
|
|
|
(when (> (# options) 0)
|
|
|
|
(print (or (read-preamble name) (headline name)))
|
|
|
|
(when service?
|
|
|
|
(print "**path** " (.. ":file:`" (relative-pathname name) "`")))
|
|
|
|
(print)
|
|
|
|
(each [_ o (ipairs options)]
|
|
|
|
(if (is-service? o)
|
|
|
|
(print-service o)
|
|
|
|
(print-option o))))))))
|