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