/
default.nix
176 lines (149 loc) · 5.24 KB
/
default.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
# Author: Viacheslav Lotsmanov
# License: Public Domain https://raw.githubusercontent.com/unclechu/tmuxrc/master/LICENSE
let sources = import nix/sources.nix; in
# This module is intended to be called with ‘nixpkgs.callPackage’
{ pkgs ? import sources.nixpkgs {}
, lib ? pkgs.lib
, tmux ? pkgs.tmux
, tmuxPlugins ? pkgs.tmuxPlugins
, dash ? pkgs.dash
, findutils ? pkgs.findutils
, inNixShell ? false
# ↓ Build options ↓
, __srcConfigFile ? ./.tmux.conf
# Make ‘tmuxsh’ available for calling it manually (inside ‘tmux’ session).
# This is not necessary if you add ‘tmuxsh’ to ‘environment.systemPackages’ in
# your NixOS ‘configuration.nix’ for instance. Also this is for executable
# version only, in ‘configuration.nix’ you set just tmux config file
# (to ‘programs.tmux.extraConfig’) and this dependency wouldn’t be provided
# anyway if you don’t add it to ‘environment.systemPackages’.
, with-tmuxsh ? inNixShell
, with-tmux ? inNixShell
}:
let
esc = lib.escapeShellArg;
dash-exe = "${dash}/bin/dash";
tmux-exe = "${tmux}/bin/tmux";
lines = str: builtins.filter builtins.isString (builtins.split "\n" str);
unlines = builtins.concatStringsSep "\n";
# ‘tmuxsh’ for the tmux config itself, without ‘tmux-conf-file’ argument.
# Otherwise it would be a recursive dependency.
# ‘tmuxsh rc’ that tmux config is calling doesn’t depend on that argument.
tmuxsh = pkgs.callPackage nix/apps/tmuxsh.nix {
tmux-conf-file = null;
};
tmuxsh-exe = "${tmuxsh}/bin/tmuxsh";
replace-tmuxsh = builtins.replaceStrings [ "tmuxsh" ] [ tmuxsh-exe ];
pluginsSplit =
let
initial = { place = "pre"; pre = []; plugins = []; post = []; };
result =
builtins.foldl' reducer initial
(lines (replace-tmuxsh (builtins.readFile __srcConfigFile)));
reducer = acc: line: acc // (
if acc.place == "pre"
then if line == "# PLUGINS:BEGIN"
then { place = "plugins"; }
else { pre = acc.pre ++ [line]; }
else
if acc.place == "plugins"
then if line == "# PLUGINS:END"
then { place = "post"; }
else let match = builtins.match "set -g @plugin '.+/(.+)'" line;
in if isNull match
then {}
else { plugins = [ (builtins.elemAt match 0) ]; }
else
if acc.place == "post"
then { post = acc.post ++ [line]; }
else throw "Unexpected ‘place’ during parsing: ‘${acc.place}’"
);
in
assert result.place == "post";
lib.filterAttrs (n: v: n != "place") result;
pluginsLoadingCommandsFile =
let
find = "${findutils}/bin/find";
plugins = builtins.concatStringsSep "\n" (
builtins.map (x: tmuxPlugins.${x}) pluginsSplit.plugins
);
in
pkgs.runCommand "tmux-plugin-imports" {
inherit plugins;
passAsFile = [ "plugins" ];
} ''
set -o errexit || exit
set -o nounset
set -o pipefail
readarray -t PLUGINS < "$pluginsPath"
for plugin in "''${PLUGINS[@]}"; do
if ! [[ -d $plugin ]]; then
>&2 printf 'Plugin path "%s" is not a directory!\n' "$plugin"
exit 1
fi
${esc find} "$plugin" -name '*.tmux' | while read -r file; do
printf "run '%s'\n" "$file" >> "$out"
done
done
'';
config = ''
${unlines pluginsSplit.pre}
# Plugins loading {{{
${builtins.readFile pluginsLoadingCommandsFile}
# Plugins loading }}}
${unlines pluginsSplit.post}
'';
configFile = pkgs.writeTextFile {
name = "tmux.conf";
text = config;
checkPhase = ''(
set -o nounset
set -o xtrace
(f=${esc tmuxsh-exe}; [[ -f $f && -r $f && -x $f ]])
)'';
};
# ‘tmuxsh’ that is provided for the user for manual calls
exported-tmuxsh = pkgs.callPackage nix/apps/tmuxsh.nix {
tmux-conf-file = configFile;
};
wenzels-tmux = pkgs.writeTextFile rec {
name = "wenzels-tmux";
executable = true;
destination = "/bin/tmux";
text = ''
#! ${dash-exe}
${
lib.optionalString
with-tmuxsh
"PATH=${esc (lib.makeBinPath [ exported-tmuxsh ])}\${PATH:+:}\${PATH:-} "
}exec ${esc tmux-exe} -f ${esc configFile} "$@"
'';
checkPhase = ''(
set -o nounset
set -o xtrace
(f=${esc dash-exe}; [[ -f $f && -r $f && -x $f ]])
(f=${esc tmux-exe}; [[ -f $f && -r $f && -x $f ]])
${lib.optionalString with-tmuxsh ''
(f=${esc "${exported-tmuxsh}/bin/tmuxsh"}; [[ -f $f && -r $f && -x $f ]])
''}
(f=${esc configFile}; [[ -f $f && -r $f ]])
)'';
};
shell = pkgs.stdenv.mkDerivation rec {
name = "${lib.getName wenzels-tmux}-shell";
dontUnpack = true; # Make it buildable without “src” attribute
buildInputs =
lib.optional with-tmux wenzels-tmux
++ lib.optional with-tmuxsh exported-tmuxsh;
installPhase = ''(
set -o nounset
touch -- "$out"
printf '%s\n' ${pkgs.lib.escapeShellArgs (map (x: "${x}") buildInputs)} >> "$out"
)'';
};
in
(if inNixShell then shell else {}) // {
inherit config configFile pluginsLoadingCommandsFile shell;
tmux = wenzels-tmux;
tmuxsh = exported-tmuxsh;
}