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 type = types.bool;
69 description = ''
70 Resize the window to the size of the smallest session for which it is the current window.
71 '';
72 };
73
74 baseIndex = mkOption {
75 default = 0;
76 example = 1;
77 type = types.int;
78 description = "Base index for windows and panes.";
79 };
80
81 clock24 = mkOption {
82 default = false;
83 type = types.bool;
84 description = "Use 24 hour clock.";
85 };
86
87 customPaneNavigationAndResize = mkOption {
88 default = false;
89 type = types.bool;
90 description = "Override the hjkl and HJKL bindings for pane navigation and resizing in VI mode.";
91 };
92
93 escapeTime = mkOption {
94 default = 500;
95 example = 0;
96 type = types.int;
97 description = "Time in milliseconds for which tmux waits after an escape is input.";
98 };
99
100 extraTmuxConf = mkOption {
101 default = "";
102 description = ''
103 Additional contents of /etc/tmux.conf
104 '';
105 type = types.lines;
106 };
107
108 historyLimit = mkOption {
109 default = 2000;
110 example = 5000;
111 type = types.int;
112 description = "Maximum number of lines held in window history.";
113 };
114
115 keyMode = mkOption {
116 default = defaultKeyMode;
117 example = "vi";
118 type = types.enum [ "emacs" "vi" ];
119 description = "VI or Emacs style shortcuts.";
120 };
121
122 newSession = mkOption {
123 default = false;
124 type = types.bool;
125 description = "Automatically spawn a session if trying to attach and none are running.";
126 };
127
128 reverseSplit = mkOption {
129 default = false;
130 type = types.bool;
131 description = "Reverse the window split shortcuts.";
132 };
133
134 resizeAmount = mkOption {
135 default = defaultResize;
136 example = 10;
137 type = types.int;
138 description = "Number of lines/columns when resizing.";
139 };
140
141 shortcut = mkOption {
142 default = defaultShortcut;
143 example = "a";
144 type = types.str;
145 description = "Ctrl following by this key is used as the main shortcut.";
146 };
147
148 terminal = mkOption {
149 default = defaultTerminal;
150 example = "screen-256color";
151 type = types.str;
152 description = "Set the $TERM variable.";
153 };
154 };
155 };
156
157 ###### implementation
158
159 config = mkIf cfg.enable {
160 environment = {
161 etc."tmux.conf".text = tmuxConf;
162
163 systemPackages = [ pkgs.tmux ];
164
165 variables = {
166 TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}'';
167 };
168 };
169 };
170}