1{ config, pkgs, lib, ... }:
2
3let
4 inherit (lib) mkOption mkEnableOption mkIf mkMerge types;
5
6 cfg = config.programs.tmux;
7
8 defaultKeyMode = "emacs";
9 defaultResize = 5;
10 defaultShortcut = "b";
11 defaultTerminal = "screen";
12
13 boolToStr = value: if value then "on" else "off";
14
15 tmuxConf = ''
16 set -g default-terminal "${cfg.terminal}"
17 set -g base-index ${toString cfg.baseIndex}
18 setw -g pane-base-index ${toString cfg.baseIndex}
19
20 ${if cfg.newSession then "new-session" else ""}
21
22 ${if cfg.reverseSplit then ''
23 bind v split-window -h
24 bind s split-window -v
25 '' else ""}
26
27 set -g status-keys ${cfg.keyMode}
28 set -g mode-keys ${cfg.keyMode}
29
30 ${if cfg.keyMode == "vi" && cfg.customPaneNavigationAndResize then ''
31 bind h select-pane -L
32 bind j select-pane -D
33 bind k select-pane -U
34 bind l select-pane -R
35
36 bind -r H resize-pane -L ${toString cfg.resizeAmount}
37 bind -r J resize-pane -D ${toString cfg.resizeAmount}
38 bind -r K resize-pane -U ${toString cfg.resizeAmount}
39 bind -r L resize-pane -R ${toString cfg.resizeAmount}
40 '' else ""}
41
42 ${if (cfg.shortcut != defaultShortcut) then ''
43 # rebind main key: C-${cfg.shortcut}
44 unbind C-${defaultShortcut}
45 set -g prefix C-${cfg.shortcut}
46 bind ${cfg.shortcut} send-prefix
47 bind C-${cfg.shortcut} last-window
48 '' else ""}
49
50 setw -g aggressive-resize ${boolToStr cfg.aggressiveResize}
51 setw -g clock-mode-style ${if cfg.clock24 then "24" else "12"}
52 set -s escape-time ${toString cfg.escapeTime}
53 set -g history-limit ${toString cfg.historyLimit}
54
55 ${cfg.extraTmuxConf}
56 '';
57
58in {
59 ###### interface
60
61 options = {
62 programs.tmux = {
63
64 enable = mkEnableOption "<command>tmux</command> - a <command>screen</command> replacement.";
65
66 aggressiveResize = mkOption {
67 default = false;
68 example = true;
69 type = types.bool;
70 description = ''
71 Resize the window to the size of the smallest session for which it is the current window.
72 '';
73 };
74
75 baseIndex = mkOption {
76 default = 0;
77 example = 1;
78 type = types.int;
79 description = "Base index for windows and panes.";
80 };
81
82 clock24 = mkOption {
83 default = false;
84 example = true;
85 type = types.bool;
86 description = "Use 24 hour clock.";
87 };
88
89 customPaneNavigationAndResize = mkOption {
90 default = false;
91 example = true;
92 type = types.bool;
93 description = "Override the hjkl and HJKL bindings for pane navigation and resizing in VI mode.";
94 };
95
96 escapeTime = mkOption {
97 default = 500;
98 example = 0;
99 type = types.int;
100 description = "Time in milliseconds for which tmux waits after an escape is input.";
101 };
102
103 extraTmuxConf = mkOption {
104 default = "";
105 description = ''
106 Additional contents of /etc/tmux.conf
107 '';
108 type = types.lines;
109 };
110
111 historyLimit = mkOption {
112 default = 2000;
113 example = 5000;
114 type = types.int;
115 description = "Maximum number of lines held in window history.";
116 };
117
118 keyMode = mkOption {
119 default = defaultKeyMode;
120 example = "vi";
121 type = types.enum [ "emacs" "vi" ];
122 description = "VI or Emacs style shortcuts.";
123 };
124
125 newSession = mkOption {
126 default = false;
127 example = true;
128 type = types.bool;
129 description = "Automatically spawn a session if trying to attach and none are running.";
130 };
131
132 reverseSplit = mkOption {
133 default = false;
134 example = true;
135 type = types.bool;
136 description = "Reverse the window split shortcuts.";
137 };
138
139 resizeAmount = mkOption {
140 default = defaultResize;
141 example = 10;
142 type = types.int;
143 description = "Number of lines/columns when resizing.";
144 };
145
146 shortcut = mkOption {
147 default = defaultShortcut;
148 example = "a";
149 type = types.str;
150 description = "Ctrl following by this key is used as the main shortcut.";
151 };
152
153 terminal = mkOption {
154 default = defaultTerminal;
155 example = "screen-256color";
156 type = types.str;
157 description = "Set the $TERM variable.";
158 };
159 };
160 };
161
162 ###### implementation
163
164 config = mkIf cfg.enable {
165 environment = {
166 etc."tmux.conf".text = tmuxConf;
167
168 systemPackages = [ pkgs.tmux ];
169
170 variables = {
171 TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}'';
172 };
173 };
174 };
175}