Skip to content

Commit 868fff1

Browse files
committed
feat(wrapperModules.xdg): init
1 parent 8ba8703 commit 868fff1

1 file changed

Lines changed: 246 additions & 0 deletions

File tree

wrapperModules/x/xdg/module.nix

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
{
2+
config,
3+
lib,
4+
wlib,
5+
pkgs,
6+
...
7+
}:
8+
let
9+
types = lib.types;
10+
pathAsStr = types.coercedTo types.path builtins.toString types.str;
11+
in
12+
{
13+
imports = [ wlib.modules.default ];
14+
15+
options = {
16+
baseDirs.enable = lib.mkEnableOption "management of XDG base directories";
17+
18+
baseDirs.cacheHome = lib.mkOption {
19+
type = types.nullOr pathAsStr;
20+
default = "$HOME/.cache";
21+
description = ''
22+
Absolute path to directory holding application caches.
23+
24+
Sets `XDG_CACHE_HOME` for the user if `xdg.enable` is set `true`.
25+
'';
26+
};
27+
28+
baseDirs.configHome = lib.mkOption {
29+
type = types.nullOr pathAsStr;
30+
default = "$HOME/.config";
31+
description = ''
32+
Absolute path to directory holding application configurations.
33+
34+
Sets `XDG_CONFIG_HOME` for the user if `xdg.enable` is set `true`.
35+
'';
36+
};
37+
38+
baseDirs.dataHome = lib.mkOption {
39+
type = types.nullOr pathAsStr;
40+
default = "$HOME/.local/share";
41+
description = ''
42+
Absolute path to directory holding application data.
43+
44+
Sets `XDG_DATA_HOME` for the user if `xdg.enable` is set `true`.
45+
'';
46+
};
47+
48+
baseDirs.stateHome = lib.mkOption {
49+
type = types.nullOr pathAsStr;
50+
default = "$HOME/.local/state";
51+
description = ''
52+
Absolute path to directory holding application states.
53+
54+
Sets `XDG_STATE_HOME` for the user if `xdg.enable` is set `true`.
55+
'';
56+
};
57+
58+
userDirs.enable = lib.mkOption {
59+
type = types.bool;
60+
default = false;
61+
description = ''
62+
Whether to manage {file}`$XDG_CONFIG_HOME/user-dirs.dirs`.
63+
64+
The generated file is read-only.
65+
'';
66+
};
67+
68+
userDirs.package = lib.mkPackageOption pkgs "xdg-user-dirs" { nullable = true; };
69+
70+
# Well-known directory list from
71+
# https://gitlab.freedesktop.org/xdg/xdg-user-dirs/blob/master/man/user-dirs.dirs.xml
72+
73+
userDirs.desktop = lib.mkOption {
74+
type = types.nullOr pathAsStr;
75+
default = "$HOME/Desktop";
76+
description = "The Desktop directory.";
77+
};
78+
79+
userDirs.documents = lib.mkOption {
80+
type = types.nullOr pathAsStr;
81+
default = "$HOME/Documents";
82+
description = "The Documents directory.";
83+
};
84+
85+
userDirs.download = lib.mkOption {
86+
type = types.nullOr pathAsStr;
87+
default = "$HOME/Downloads";
88+
description = "The Downloads directory.";
89+
};
90+
91+
userDirs.music = lib.mkOption {
92+
type = types.nullOr pathAsStr;
93+
default = "$HOME/Music";
94+
description = "The Music directory.";
95+
};
96+
97+
userDirs.pictures = lib.mkOption {
98+
type = types.nullOr pathAsStr;
99+
default = "$HOME/Pictures";
100+
description = "The Pictures directory.";
101+
};
102+
103+
userDirs.publicShare = lib.mkOption {
104+
type = types.nullOr pathAsStr;
105+
default = "$HOME/Public";
106+
description = "The Public share directory.";
107+
};
108+
109+
userDirs.templates = lib.mkOption {
110+
type = types.nullOr pathAsStr;
111+
default = "$HOME/Templates";
112+
description = "The Templates directory.";
113+
};
114+
115+
userDirs.videos = lib.mkOption {
116+
type = types.nullOr pathAsStr;
117+
default = "$HOME/Videos";
118+
description = "The Videos directory.";
119+
};
120+
121+
userDirs.extraConfig = lib.mkOption {
122+
type = types.attrsOf (pathAsStr);
123+
default = { };
124+
defaultText = lib.literalExpression "{ }";
125+
example = lib.literalExpression ''
126+
{
127+
MISC = "$HOME/Misc";
128+
}
129+
'';
130+
description = ''
131+
Other user directories.
132+
133+
The key ‘MISC’ corresponds to the user-dirs entry ‘XDG_MISC_DIR’.
134+
'';
135+
};
136+
137+
userDirs.createDirectories = lib.mkEnableOption "automatic creation of the XDG user directories";
138+
139+
userDirs.setSessionVariables = lib.mkOption {
140+
type = types.bool;
141+
default = false;
142+
description = ''
143+
Whether to set the XDG user dir environment variables, like
144+
`XDG_DESKTOP_DIR`.
145+
146+
::: {.note}
147+
The recommended way to get these values is via the `xdg-user-dir`
148+
command or by processing `$XDG_CONFIG_HOME/user-dirs.dirs` directly in
149+
your application.
150+
:::
151+
'';
152+
};
153+
};
154+
155+
config =
156+
let
157+
baseDirs = (
158+
lib.filterAttrs (n: v: !isNull v) {
159+
XDG_CACHE_HOME = config.baseDirs.cacheHome;
160+
XDG_CONFIG_HOME = config.baseDirs.configHome;
161+
XDG_DATA_HOME = config.baseDirs.dataHome;
162+
XDG_STATE_HOME = config.baseDirs.stateHome;
163+
}
164+
);
165+
166+
userDirs =
167+
(lib.filterAttrs (n: v: !isNull v) {
168+
DESKTOP = config.userDirs.desktop;
169+
DOCUMENTS = config.userDirs.documents;
170+
DOWNLOAD = config.userDirs.download;
171+
MUSIC = config.userDirs.music;
172+
PICTURES = config.userDirs.pictures;
173+
PUBLICSHARE = config.userDirs.publicShare;
174+
TEMPLATES = config.userDirs.templates;
175+
VIDEOS = config.userDirs.videos;
176+
})
177+
// config.userDirs.extraConfig;
178+
179+
# Allow runtime env-var expansion
180+
esc-fn = wlib.escapeShellArgWithEnv;
181+
182+
baseDirsSessionVars = lib.mapAttrs (_k: v: {
183+
data = v;
184+
inherit esc-fn;
185+
}) baseDirs;
186+
187+
userDirsSessionVars = lib.mapAttrs' (k: v: {
188+
name = "XDG_${k}_DIR";
189+
value = {
190+
data = v;
191+
inherit esc-fn;
192+
};
193+
}) userDirs;
194+
in
195+
{
196+
env =
197+
let
198+
baseDirsEnabled = config.baseDirs.enable;
199+
userDirsEnabled = config.userDirs.enable && config.userDirs.setSessionVariables;
200+
in
201+
(lib.optionalAttrs baseDirsEnabled baseDirsSessionVars)
202+
// (lib.optionalAttrs userDirsEnabled userDirsSessionVars);
203+
204+
extraPackages = lib.mkIf config.userDirs.enable [
205+
config.userDirs.package
206+
];
207+
208+
runShell =
209+
let
210+
mkdir = (dir: ''[[ -L "${dir}" ]] || mkdir -p "${dir}"'');
211+
createDirs = dirs: (lib.concatMapStringsSep "\n" mkdir (lib.attrValues dirs));
212+
213+
toKeyValue = pkgs.formats.keyValue { };
214+
215+
userDirsConf = pkgs.writeText "user-dirs.conf" "enabled=False";
216+
userDirsDirs =
217+
let
218+
# For some reason, these need to be wrapped with quotes to be valid.
219+
wrapped = lib.mapAttrs' (k: v: {
220+
name = ''"${k}"'';
221+
value = v.data;
222+
}) userDirsSessionVars;
223+
in
224+
toKeyValue.generate "user-dirs.dirs" wrapped;
225+
226+
createBaseDirs = createDirs baseDirs;
227+
createUserDirs = createDirs userDirs;
228+
createUserDirsConf = "cp --no-preserve=all ${userDirsConf} \${XDG_CONFIG_HOME}/user-dirs.conf";
229+
createUserDirsDirs = "cp --no-preserve=all ${userDirsDirs} \${XDG_CONFIG_HOME}/user-dirs.dirs";
230+
in
231+
[
232+
{
233+
name = "XDG_SETUP";
234+
data = builtins.concatStringsSep "\n" [
235+
(lib.optionalString config.baseDirs.enable createBaseDirs)
236+
(lib.optionalString (config.userDirs.enable && config.userDirs.createDirectories) createUserDirs)
237+
(lib.optionalString config.userDirs.enable createUserDirsConf)
238+
(lib.optionalString config.userDirs.enable createUserDirsDirs)
239+
];
240+
}
241+
];
242+
243+
# NOTE: Any shell works here
244+
package = lib.mkDefault pkgs.bashInteractive;
245+
};
246+
}

0 commit comments

Comments
 (0)