at 25.11-pre 9.9 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 makewhatis = "${lib.getBin cfg.package}/bin/makewhatis"; 10 11 cfg = config.documentation.man.mandoc; 12 13 toMandocOutput = 14 output: 15 (lib.mapAttrsToList ( 16 name: value: 17 if lib.isString value || lib.isPath value then 18 "output ${name} ${value}" 19 else if lib.isInt value then 20 "output ${name} ${builtins.toString value}" 21 else if lib.isBool value then 22 lib.optionalString value "output ${name}" 23 else if value == null then 24 "" 25 else 26 throw "Unrecognized value type ${builtins.typeOf value} of key ${name} in mandoc output settings" 27 ) output); 28 29 makeLeadingSlashes = map (path: if builtins.substring 0 1 path != "/" then "/${path}" else path); 30in 31{ 32 meta.maintainers = [ lib.maintainers.sternenseemann ]; 33 34 options = { 35 documentation.man.mandoc = { 36 enable = lib.mkEnableOption "mandoc as the default man page viewer"; 37 38 manPath = lib.mkOption { 39 type = with lib.types; listOf str; 40 default = [ "share/man" ]; 41 example = lib.literalExpression "[ \"share/man\" \"share/man/fr\" ]"; 42 apply = makeLeadingSlashes; 43 description = '' 44 Change the paths included in the MANPATH environment variable, 45 i. e. the directories where {manpage}`man(1)` 46 looks for section-specific directories of man pages. 47 You only need to change this setting if you want extra man pages 48 (e. g. in non-english languages). All values must be strings that 49 are a valid path from the target prefix (without including it). 50 The first value given takes priority. Note that this will not 51 add manpath directives to {manpage}`man.conf(5)`. 52 ''; 53 }; 54 55 cachePath = lib.mkOption { 56 type = with lib.types; listOf str; 57 default = cfg.manPath; 58 defaultText = lib.literalExpression "config.documentation.man.mandoc.manPath"; 59 example = lib.literalExpression "[ \"share/man\" \"share/man/fr\" ]"; 60 apply = makeLeadingSlashes; 61 description = '' 62 Change the paths where mandoc {manpage}`makewhatis(8)`generates the 63 manual page index caches. {option}`documentation.man.generateCaches` 64 should be enabled to allow cache generation. This list should only 65 include the paths to manpages installed in the system configuration, 66 i. e. /run/current-system/sw/share/man. {manpage}`makewhatis(8)` 67 creates a database in each directory using the files 68 `mansection/[arch/]title.section` and `catsection/[arch/]title.0` 69 in it. If a directory contains no manual pages, no database is 70 created in that directory. 71 This option only needs to be set manually if extra paths should be 72 indexed or {option}`documentation.man.manPath` contains paths that 73 can't be indexed. 74 ''; 75 }; 76 77 package = lib.mkOption { 78 type = lib.types.package; 79 default = pkgs.mandoc; 80 defaultText = lib.literalExpression "pkgs.mandoc"; 81 description = '' 82 The `mandoc` derivation to use. Useful to override 83 configuration options used for the package. 84 ''; 85 }; 86 87 settings = lib.mkOption { 88 description = "Configuration for {manpage}`man.conf(5)`"; 89 default = { }; 90 type = lib.types.submodule { 91 options = { 92 manpath = lib.mkOption { 93 type = with lib.types; listOf str; 94 default = [ ]; 95 example = lib.literalExpression "[ \"/run/current-system/sw/share/man\" ]"; 96 description = '' 97 Override the default search path for {manpage}`man(1)`, 98 {manpage}`apropos(1)`, and {manpage}`makewhatis(8)`. It can be 99 used multiple times to specify multiple paths, with the order 100 determining the manual page search order. 101 This is not recommended in favor of 102 {option}`documentation.man.mandoc.manPath`, but if it's needed to 103 specify the manpath in this way, set 104 {option}`documentation.man.mandoc.manPath` to an empty list (`[]`). 105 ''; 106 }; 107 output.fragment = lib.mkOption { 108 type = lib.types.bool; 109 default = false; 110 example = true; 111 description = '' 112 Whether to omit the <!DOCTYPE> declaration and the <html>, <head>, and <body> 113 elements and only emit the subtree below the <body> element in HTML 114 output of {manpage}`mandoc(1)`. The style argument will be ignored. 115 This is useful when embedding manual content within existing documents. 116 ''; 117 }; 118 output.includes = lib.mkOption { 119 type = with lib.types; nullOr str; 120 default = null; 121 example = lib.literalExpression "../src/%I.html"; 122 description = '' 123 A string of relative path used as a template for the output path of 124 linked header files (usually via the In macro) in HTML output. 125 Instances of `%I` are replaced with the include filename. The 126 default is not to present a hyperlink. 127 ''; 128 }; 129 output.indent = lib.mkOption { 130 type = with lib.types; nullOr int; 131 default = null; 132 description = '' 133 Number of blank characters at the left margin for normal text, 134 default of `5` for {manpage}`mdoc(7)` and `7` for 135 {manpage}`man(7)`. Increasing this is not recommended; it may 136 result in degraded formatting, for example overfull lines or ugly 137 line breaks. When output is to a pager on a terminal that is less 138 than 66 columns wide, the default is reduced to three columns. 139 ''; 140 }; 141 output.man = lib.mkOption { 142 type = with lib.types; nullOr str; 143 default = null; 144 example = lib.literalExpression "../html%S/%N.%S.html"; 145 description = '' 146 A template for linked manuals (usually via the Xr macro) in HTML 147 output. Instances of %N and %S are replaced with the linked 148 manual's name and section, respectively. If no section is included, 149 section 1 is assumed. The default is not to present a hyperlink. 150 If two formats are given and a file %N.%S exists in the current 151 directory, the first format is used; otherwise, the second format is used. 152 ''; 153 }; 154 output.paper = lib.mkOption { 155 type = with lib.types; nullOr str; 156 default = null; 157 description = '' 158 This option is for generating PostScript and PDF output. The paper 159 size name may be one of `a3`, `a4`, `a5`, `legal`, or `letter`. 160 You may also manually specify dimensions as `NNxNN`, width by 161 height in millimetres. If an unknown value is encountered, letter 162 is used. Output pages default to letter sized and are rendered in 163 the Times font family, 11-point. Margins are calculated as 1/9 the 164 page length and width. Line-height is 1.4m. 165 ''; 166 }; 167 output.style = lib.mkOption { 168 type = with lib.types; nullOr path; 169 default = null; 170 description = '' 171 Path to the file used for an external style-sheet. This must be a 172 valid absolute or relative URI. 173 ''; 174 }; 175 output.toc = lib.mkEnableOption '' 176 printing a table of contents near the beginning of the HTML output 177 of {manpage}`mandoc(1)` if an input file contains at least two 178 non-standard sections 179 ''; 180 output.width = lib.mkOption { 181 type = with lib.types; nullOr int; 182 default = null; 183 description = '' 184 The ASCII and UTF-8 output width, default is `78`. When output is a 185 pager on a terminal that is less than 79 columns wide, the 186 default is reduced to one less than the terminal width. In any case, 187 lines that are output in literal mode are never wrapped and may 188 exceed the output width. 189 ''; 190 }; 191 }; 192 }; 193 }; 194 195 extraConfig = lib.mkOption { 196 type = lib.types.lines; 197 default = ""; 198 description = '' 199 Extra configuration to write to {manpage}`man.conf(5)`. 200 ''; 201 }; 202 }; 203 }; 204 205 config = lib.mkIf cfg.enable { 206 environment = { 207 systemPackages = [ cfg.package ]; 208 209 etc."man.conf".text = lib.concatStringsSep "\n" ( 210 (map (path: "manpath ${path}") cfg.settings.manpath) 211 ++ (toMandocOutput cfg.settings.output) 212 ++ [ cfg.extraConfig ] 213 ); 214 215 # create mandoc.db for whatis(1), apropos(1) and man(1) -k 216 # TODO(@sternenseemman): fix symlinked directories not getting indexed, 217 # see: https://inbox.vuxu.org/mandoc-tech/20210906171231.GF83680@athene.usta.de/T/#e85f773c1781e3fef85562b2794f9cad7b2909a3c 218 extraSetup = lib.mkIf config.documentation.man.generateCaches '' 219 for man_path in ${ 220 lib.concatMapStringsSep " " (path: "$out" + lib.escapeShellArg path) cfg.cachePath 221 } 222 do 223 [[ -d "$man_path" ]] && ${makewhatis} -T utf8 $man_path 224 done 225 ''; 226 227 # tell mandoc the paths containing man pages 228 profileRelativeSessionVariables."MANPATH" = lib.mkIf (cfg.manPath != [ ]) cfg.manPath; 229 }; 230 }; 231}