1{ pkgs, lib, ... }:
2let
3 manImplementations = [
4 "mandoc"
5 "man-db"
6 ];
7
8 machineNames = builtins.map machineSafe manImplementations;
9
10 makeConfig = useImpl: {
11 # Note: mandoc currently can't index symlinked section directories.
12 # So if a man section comes from one package exclusively (e. g.
13 # 1p from man-pages-posix and 2 from man-pages), it isn't searchable.
14 environment.systemPackages = [
15 pkgs.man-pages
16 pkgs.openssl
17 pkgs.libunwind
18 ];
19
20 documentation = {
21 enable = true;
22 nixos.enable = lib.mkForce true;
23 dev.enable = true;
24 man =
25 {
26 enable = true;
27 generateCaches = true;
28 }
29 // lib.listToAttrs (
30 builtins.map (impl: {
31 name = impl;
32 value = {
33 enable = useImpl == impl;
34 };
35 }) manImplementations
36 );
37 };
38 };
39
40 machineSafe = builtins.replaceStrings [ "-" ] [ "_" ];
41in
42{
43 name = "man";
44 meta.maintainers = [ lib.maintainers.sternenseemann ];
45
46 nodes = lib.listToAttrs (
47 builtins.map (i: {
48 name = machineSafe i;
49 value = makeConfig i;
50 }) manImplementations
51 );
52
53 testScript =
54 ''
55 import re
56 start_all()
57
58 def match_man_k(page, section, haystack):
59 """
60 Check if the man page {page}({section}) occurs in
61 the output of `man -k` given as haystack. Note:
62 This is not super reliable, e. g. it can't deal
63 with man pages that are in multiple sections.
64 """
65
66 for line in haystack.split("\n"):
67 # man -k can look like this:
68 # page(3) - bla
69 # page (3) - bla
70 # pagea, pageb (3, 3P) - foo
71 # pagea, pageb, pagec(3) - bar
72 pages = line.split("(")[0]
73 sections = re.search("\\([a-zA-Z1-9, ]+\\)", line)
74 if sections is None:
75 continue
76 else:
77 sections = sections.group(0)[1:-1]
78
79 if page in pages and f'{section}' in sections:
80 return True
81
82 return False
83
84 ''
85 + lib.concatMapStrings (machine: ''
86 with subtest("Test direct man page lookups in ${machine}"):
87 # man works
88 ${machine}.succeed("man man > /dev/null")
89 # devman works
90 ${machine}.succeed("man 3 libunwind > /dev/null")
91 # NixOS configuration man page is installed
92 ${machine}.succeed("man configuration.nix > /dev/null")
93
94 with subtest("Test generateCaches via man -k in ${machine}"):
95 expected = [
96 ("openssl", "ssl", 3),
97 ("unwind", "libunwind", 3),
98 ("user", "useradd", 8),
99 ("user", "userdel", 8),
100 ("mem", "free", 3),
101 ("mem", "free", 1),
102 ]
103
104 for (keyword, page, section) in expected:
105 matches = ${machine}.succeed(f"man -k {keyword}")
106 if not match_man_k(page, section, matches):
107 raise Exception(f"{page}({section}) missing in matches: {matches}")
108 '') machineNames;
109}