forked from nix-community/home-manager
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhexchat.nix
343 lines (297 loc) · 9.73 KB
/
hexchat.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.programs.hexchat;
channelOptions = with types;
submodule {
options = {
autoconnect = mkOption {
type = nullOr bool;
default = false;
description = "Autoconnect to network.";
};
connectToSelectedServerOnly = mkOption {
type = nullOr bool;
default = true;
description = "Connect to selected server only.";
};
bypassProxy = mkOption {
type = nullOr bool;
default = true;
description = "Bypass proxy.";
};
forceSSL = mkOption {
type = nullOr bool;
default = false;
description = "Use SSL for all servers.";
};
acceptInvalidSSLCertificates = mkOption {
type = nullOr bool;
default = false;
description = "Accept invalid SSL certificates.";
};
useGlobalUserInformation = mkOption {
type = nullOr bool;
default = false;
description = "Use global user information.";
};
};
};
modChannelOption = with types;
submodule {
options = {
autojoin = mkOption {
type = listOf str;
default = [ ];
example = [ "#home-manager" "#linux" "#nix" ];
description = "Channels list to autojoin on connecting to server.";
};
charset = mkOption {
type = nullOr str;
default = null;
example = "UTF-8 (Unicode)";
description = "Character set.";
};
commands = mkOption {
type = listOf str;
default = [ ];
example = literalExpression ''[ "ECHO Greetings fellow Nixer! ]'';
description = "Commands to be executed on connecting to server.";
};
loginMethod = mkOption {
type = nullOr (enum (attrNames loginMethodMap));
default = null;
description = ''
The login method. The allowed options are:
`null`
: Default
`"nickServMsg"`
: NickServ (`/MSG NickServ` + password)
`"nickServ"`
: NickServ (`/NICKSERV` + password)
`"challengeAuth"`
: Challenge Auth (username + password)
`"sasl"`
: SASL (username + password)
`"serverPassword"`
: Server password (`/PASS` password)
`"saslExternal"`
: SASL EXTERNAL (cert)
`"customCommands"`
: Use "commands" field for auth. For example
```nix
commands = [ "/msg NickServ IDENTIFY my_password" ]
```
'';
};
nickname = mkOption {
type = nullOr str;
default = null;
description = "Primary nickname.";
};
nickname2 = mkOption {
type = nullOr str;
default = null;
description = "Secondary nickname.";
};
options = mkOption {
type = nullOr channelOptions;
default = null;
example = {
autoconnect = true;
useGlobalUserInformation = true;
};
description = "Channel options.";
};
password = mkOption {
type = nullOr str;
default = null;
description = ''
Password to use. Note this password will be readable by all user's
in the Nix store.
'';
};
realName = mkOption {
type = nullOr str;
default = null;
description = ''
Real name. Is used to populate the real name field that appears when
someone uses the `WHOIS` command on your nick.
'';
};
userName = mkOption {
type = nullOr str;
default = null;
description = ''
User name. Part of your `user@host` hostmask that
appears to other on IRC.
'';
};
servers = mkOption {
type = listOf str;
default = [ ];
example = [ "irc.oftc.net" ];
description = "IRC Server Address List.";
};
};
};
transformField = k: v: if (v != null) then "${k}=${v}" else null;
listChar = c: l:
if l != [ ] then concatMapStringsSep "\n" (transformField c) l else null;
computeFieldsValue = channel:
let
ifTrue = p: n: if p then n else 0;
result = with channel.options;
foldl' (a: b: a + b) 0 [
(ifTrue (!connectToSelectedServerOnly) 1)
(ifTrue useGlobalUserInformation 2)
(ifTrue forceSSL 4)
(ifTrue autoconnect 8)
(ifTrue (!bypassProxy) 16)
(ifTrue acceptInvalidSSLCertificates 32)
];
in toString (if channel.options == null then 0 else result);
loginMethodMap = {
nickServMsg = 1;
nickServ = 2;
challengeAuth = 4;
sasl = 6;
serverPassword = 7;
customCommands = 9;
saslExternal = 10;
};
loginMethod = channel:
transformField "L" (optionalString (channel.loginMethod != null)
(toString loginMethodMap.${channel.loginMethod}));
# Note: Missing option `D=`.
transformChannel = channelName:
let channel = cfg.channels.${channelName};
in concatStringsSep "\n" (remove null [
"" # leave a space between one server and another
(transformField "N" channelName)
(loginMethod channel)
(transformField "E" channel.charset)
(transformField "F" (computeFieldsValue channel))
(transformField "I" channel.nickname)
(transformField "i" channel.nickname2)
(transformField "R" channel.realName)
(transformField "U" channel.userName)
(transformField "P" channel.password)
(listChar "S" channel.servers)
(listChar "J" channel.autojoin)
(listChar "C" channel.commands)
]);
in {
meta.maintainers = with maintainers; [ thiagokokada ];
options.programs.hexchat = with types; {
enable = mkEnableOption "HexChat, a graphical IRC client";
channels = mkOption {
type = attrsOf modChannelOption;
default = { };
example = literalExpression ''
{
oftc = {
autojoin = [
"#home-manager"
"#linux"
];
charset = "UTF-8 (Unicode)";
commands = [
"ECHO Buzz Lightyear sent you a message: 'To Infinity... and Beyond!'"
];
loginMethod = sasl;
nickname = "my_nickname";
nickname2 = "my_secondchoice";
options = {
acceptInvalidSSLCertificates = false;
autoconnect = true;
bypassProxy = true;
connectToSelectedServerOnly = true;
useGlobalUserInformation = false;
forceSSL = false;
};
password = "my_password";
realName = "my_realname";
servers = [
"irc.oftc.net"
];
userName = "my_username";
};
}'';
description = ''
Configures {file}`$XDG_CONFIG_HOME/hexchat/servlist.conf`.
'';
};
settings = mkOption {
default = null;
type = nullOr (attrsOf str);
example = literalExpression ''
{
irc_nick1 = "mynick";
irc_username = "bob";
irc_realname = "Bart Simpson";
text_font = "Monospace 14";
};
'';
description = ''
Configuration for {file}`$XDG_CONFIG_HOME/hexchat/hexchat.conf`, see
<https://hexchat.readthedocs.io/en/latest/settings.html#list-of-settings>
for supported values.
'';
};
overwriteConfigFiles = mkOption {
type = nullOr bool;
default = false;
description = ''
Enables overwriting HexChat configuration files
({file}`hexchat.conf`, {file}`servlist.conf`).
Any existing HexChat configuration will be lost. Make sure to back up
any previous configuration before enabling this.
Enabling this setting is recommended, because everytime HexChat
application is closed it overwrites Nix/Home Manager provided
configuration files, causing:
1. Nix/Home Manager provided configuration to be out of sync with
actual active HexChat configuration.
2. Nix/Home Manager updates to be blocked until configuration files are
manually removed.
'';
};
theme = mkOption {
type = nullOr package;
default = null;
example = literalExpression ''
source = pkgs.fetchzip {
url = "https://dl.hexchat.net/themes/Monokai.hct#Monokai.zip";
sha256 = "sha256-WCdgEr8PwKSZvBMs0fN7E2gOjNM0c2DscZGSKSmdID0=";
stripRoot = false;
};
'';
description = ''
Theme package for HexChat. Expects a derivation containing decompressed
theme files. Note, `.hct` files are actually ZIP files,
as seen in example.
'';
};
};
config = mkIf cfg.enable {
assertions = [
(hm.assertions.assertPlatform "programs.hexchat" pkgs platforms.linux)
];
home.packages = [ pkgs.hexchat ];
xdg.configFile."hexchat" = mkIf (cfg.theme != null) {
source = cfg.theme;
recursive = true;
};
xdg.configFile."hexchat/hexchat.conf" = mkIf (cfg.settings != null) {
force = cfg.overwriteConfigFiles;
text = concatMapStringsSep "\n" (x: x + " = " + cfg.settings.${x})
(attrNames cfg.settings);
};
xdg.configFile."hexchat/servlist.conf" = mkIf (cfg.channels != { }) {
force = cfg.overwriteConfigFiles;
# Final line breaks is required to avoid cropping last field value.
text = concatMapStringsSep "\n" transformChannel (attrNames cfg.channels)
+ "\n\n";
};
};
}