grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / programs / tmux.nix
bloba157bedc8aae681ac8f3701f4343b5989069116d
1 { config, pkgs, lib, ... }:
3 let
4   inherit (lib) mkOption mkIf types optionalString;
6   cfg = config.programs.tmux;
8   defaultKeyMode  = "emacs";
9   defaultResize   = 5;
10   defaultShortcut = "b";
11   defaultTerminal = "screen";
13   boolToStr = value: if value then "on" else "off";
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     set  -g history-limit   ${toString cfg.historyLimit}
21     ${optionalString cfg.newSession "new-session"}
23     ${optionalString cfg.reverseSplit ''
24     bind v split-window -h
25     bind s split-window -v
26     ''}
28     set -g status-keys ${cfg.keyMode}
29     set -g mode-keys   ${cfg.keyMode}
31     ${optionalString (cfg.keyMode == "vi" && cfg.customPaneNavigationAndResize) ''
32     bind h select-pane -L
33     bind j select-pane -D
34     bind k select-pane -U
35     bind l select-pane -R
37     bind -r H resize-pane -L ${toString cfg.resizeAmount}
38     bind -r J resize-pane -D ${toString cfg.resizeAmount}
39     bind -r K resize-pane -U ${toString cfg.resizeAmount}
40     bind -r L resize-pane -R ${toString cfg.resizeAmount}
41     ''}
43     ${optionalString (cfg.shortcut != defaultShortcut) ''
44     # rebind main key: C-${cfg.shortcut}
45     unbind C-${defaultShortcut}
46     set -g prefix C-${cfg.shortcut}
47     bind ${cfg.shortcut} send-prefix
48     bind C-${cfg.shortcut} last-window
49     ''}
51     setw -g aggressive-resize ${boolToStr cfg.aggressiveResize}
52     setw -g clock-mode-style  ${if cfg.clock24 then "24" else "12"}
53     set  -s escape-time       ${toString cfg.escapeTime}
55     ${cfg.extraConfigBeforePlugins}
57     ${lib.optionalString (cfg.plugins != []) ''
58     # Run plugins
59     ${lib.concatMapStringsSep "\n" (x: "run-shell ${x.rtp}") cfg.plugins}
61     ''}
63     ${cfg.extraConfig}
64   '';
66 in {
67   ###### interface
69   options = {
70     programs.tmux = {
72       enable = mkOption {
73         type = types.bool;
74         default = false;
75         description = "Whenever to configure {command}`tmux` system-wide.";
76         relatedPackages = [ "tmux" ];
77       };
79       aggressiveResize = mkOption {
80         default = false;
81         type = types.bool;
82         description = ''
83           Resize the window to the size of the smallest session for which it is the current window.
84         '';
85       };
87       baseIndex = mkOption {
88         default = 0;
89         example = 1;
90         type = types.int;
91         description = "Base index for windows and panes.";
92       };
94       clock24 = mkOption {
95         default = false;
96         type = types.bool;
97         description = "Use 24 hour clock.";
98       };
100       customPaneNavigationAndResize = mkOption {
101         default = false;
102         type = types.bool;
103         description = "Override the hjkl and HJKL bindings for pane navigation and resizing in VI mode.";
104       };
106       escapeTime = mkOption {
107         default = 500;
108         example = 0;
109         type = types.int;
110         description = "Time in milliseconds for which tmux waits after an escape is input.";
111       };
113       extraConfigBeforePlugins = mkOption {
114         default = "";
115         description = ''
116           Additional contents of /etc/tmux.conf, to be run before sourcing plugins.
117         '';
118         type = types.lines;
119       };
121       extraConfig = mkOption {
122         default = "";
123         description = ''
124           Additional contents of /etc/tmux.conf, to be run after sourcing plugins.
125         '';
126         type = types.lines;
127       };
129       historyLimit = mkOption {
130         default = 2000;
131         example = 5000;
132         type = types.int;
133         description = "Maximum number of lines held in window history.";
134       };
136       keyMode = mkOption {
137         default = defaultKeyMode;
138         example = "vi";
139         type = types.enum [ "emacs" "vi" ];
140         description = "VI or Emacs style shortcuts.";
141       };
143       newSession = mkOption {
144         default = false;
145         type = types.bool;
146         description = "Automatically spawn a session if trying to attach and none are running.";
147       };
149       reverseSplit = mkOption {
150         default = false;
151         type = types.bool;
152         description = "Reverse the window split shortcuts.";
153       };
155       resizeAmount = mkOption {
156         default = defaultResize;
157         example = 10;
158         type = types.int;
159         description = "Number of lines/columns when resizing.";
160       };
162       shortcut = mkOption {
163         default = defaultShortcut;
164         example = "a";
165         type = types.str;
166         description = "Ctrl following by this key is used as the main shortcut.";
167       };
169       terminal = mkOption {
170         default = defaultTerminal;
171         example = "screen-256color";
172         type = types.str;
173         description = ''
174           Set the $TERM variable. Use tmux-direct if italics or 24bit true color
175           support is needed.
176         '';
177       };
179       secureSocket = mkOption {
180         default = true;
181         type = types.bool;
182         description = ''
183           Store tmux socket under /run, which is more secure than /tmp, but as a
184           downside it doesn't survive user logout.
185         '';
186       };
188       plugins = mkOption {
189         default = [];
190         type = types.listOf types.package;
191         description = "List of plugins to install.";
192         example = lib.literalExpression "[ pkgs.tmuxPlugins.nord ]";
193       };
195       withUtempter = mkOption {
196         description = ''
197           Whether to enable libutempter for tmux.
198           This is required so that tmux can write to /var/run/utmp (which can be queried with `who` to display currently connected user sessions).
199           Note, this will add a guid wrapper for the group utmp!
200         '';
201         default = true;
202         type = types.bool;
203       };
204     };
205   };
207   ###### implementation
209   config = mkIf cfg.enable {
210     environment = {
211       etc."tmux.conf".text = tmuxConf;
213       systemPackages = [ pkgs.tmux ] ++ cfg.plugins;
215       variables = {
216         TMUX_TMPDIR = lib.optional cfg.secureSocket ''''${XDG_RUNTIME_DIR:-"/run/user/$(id -u)"}'';
217       };
218     };
219     security.wrappers = mkIf cfg.withUtempter {
220       utempter = {
221         source = "${pkgs.libutempter}/lib/utempter/utempter";
222         owner = "root";
223         group = "utmp";
224         setuid = false;
225         setgid = true;
226       };
227     };
228   };
230   imports = [
231     (lib.mkRenamedOptionModule [ "programs" "tmux" "extraTmuxConf" ] [ "programs" "tmux" "extraConfig" ])
232   ];
234   meta.maintainers = with lib.maintainers; [ hxtmdev ];