1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9
10 cfg = config.programs.less;
11
12 configText =
13 if (cfg.configFile != null) then
14 (builtins.readFile cfg.configFile)
15 else
16 ''
17 #command
18 ${builtins.concatStringsSep "\n" (
19 lib.mapAttrsToList (command: action: "${command} ${action}") cfg.commands
20 )}
21 ${lib.optionalString cfg.clearDefaultCommands "#stop"}
22
23 #line-edit
24 ${builtins.concatStringsSep "\n" (
25 lib.mapAttrsToList (command: action: "${command} ${action}") cfg.lineEditingKeys
26 )}
27
28 #env
29 ${builtins.concatStringsSep "\n" (
30 lib.mapAttrsToList (variable: values: "${variable}=${values}") cfg.envVariables
31 )}
32 '';
33
34 lessKey = pkgs.writeText "lessconfig" configText;
35
36in
37
38{
39 options = {
40
41 programs.less = {
42
43 # note that environment.nix sets PAGER=less, and
44 # therefore also enables this module
45 enable = lib.mkEnableOption "less, a file pager";
46
47 package = lib.mkPackageOption pkgs "less" { };
48
49 configFile = lib.mkOption {
50 type = lib.types.nullOr lib.types.path;
51 default = null;
52 example = lib.literalExpression ''"''${pkgs.my-configs}/lesskey"'';
53 description = ''
54 Path to lesskey configuration file.
55
56 {option}`configFile` takes precedence over {option}`commands`,
57 {option}`clearDefaultCommands`, {option}`lineEditingKeys`, and
58 {option}`envVariables`.
59 '';
60 };
61
62 commands = lib.mkOption {
63 type = lib.types.attrsOf lib.types.str;
64 default = { };
65 example = {
66 h = "noaction 5\\e(";
67 l = "noaction 5\\e)";
68 };
69 description = "Defines new command keys.";
70 };
71
72 clearDefaultCommands = lib.mkOption {
73 type = lib.types.bool;
74 default = false;
75 description = ''
76 Clear all default commands.
77 You should remember to set the quit key.
78 Otherwise you will not be able to leave less without killing it.
79 '';
80 };
81
82 lineEditingKeys = lib.mkOption {
83 type = lib.types.attrsOf lib.types.str;
84 default = { };
85 example = {
86 e = "abort";
87 };
88 description = "Defines new line-editing keys.";
89 };
90
91 envVariables = lib.mkOption {
92 type = lib.types.attrsOf lib.types.str;
93 default = {
94 LESS = "-R";
95 };
96 example = {
97 LESS = "--quit-if-one-screen";
98 };
99 description = "Defines environment variables.";
100 };
101
102 lessopen = lib.mkOption {
103 type = lib.types.nullOr lib.types.str;
104 default = null;
105 example = lib.literalExpression ''"|''${pkgs.lesspipe}/bin/lesspipe.sh %s"'';
106 description = ''
107 Before less opens a file, it first gives your input preprocessor a chance to modify the way the contents of the file are displayed.
108 '';
109 };
110
111 lessclose = lib.mkOption {
112 type = lib.types.nullOr lib.types.str;
113 default = null;
114 description = ''
115 When less closes a file opened in such a way, it will call another program, called the input postprocessor,
116 which may perform any desired clean-up action (such as deleting the replacement file created by LESSOPEN).
117 '';
118 };
119 };
120 };
121
122 config = lib.mkIf cfg.enable {
123
124 environment.systemPackages = [ cfg.package ];
125
126 environment.variables = {
127 LESSKEYIN_SYSTEM = builtins.toString lessKey;
128 }
129 // lib.optionalAttrs (cfg.lessopen != null) {
130 LESSOPEN = cfg.lessopen;
131 }
132 // lib.optionalAttrs (cfg.lessclose != null) {
133 LESSCLOSE = cfg.lessclose;
134 };
135
136 warnings =
137 lib.optional
138 (cfg.clearDefaultCommands && (builtins.all (x: x != "quit") (builtins.attrValues cfg.commands)))
139 ''
140 config.programs.less.clearDefaultCommands clears all default commands of less but there is no alternative binding for exiting.
141 Consider adding a binding for 'quit'.
142 '';
143 };
144
145 meta.maintainers = with lib.maintainers; [ johnazoidberg ];
146
147}