diff --git a/modules/misc/news.nix b/modules/misc/news.nix
index bc0fbca7..ff668cab 100644
--- a/modules/misc/news.nix
+++ b/modules/misc/news.nix
@@ -809,6 +809,13 @@ in
A new module is available: 'programs.urxvt'.
'';
}
+
+ {
+ time = "2018-11-13T23:08:03+00:00";
+ message = ''
+ A new module is available: 'programs.tmux'.
+ '';
+ }
];
};
}
diff --git a/modules/modules.nix b/modules/modules.nix
index 374edb62..6a508553 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -61,6 +61,7 @@ let
./programs/taskwarrior.nix
./programs/termite.nix
./programs/texlive.nix
+ ./programs/tmux.nix
./programs/urxvt.nix
./programs/vim.nix
./programs/zathura.nix
diff --git a/modules/programs/tmux.nix b/modules/programs/tmux.nix
new file mode 100644
index 00000000..050168be
--- /dev/null
+++ b/modules/programs/tmux.nix
@@ -0,0 +1,148 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.programs.tmux;
+
+ pluginName = p: if types.package.check p then p.name else p.plugin.name;
+
+ pluginModule = types.submodule {
+ options = {
+ plugin = mkOption {
+ type = types.package;
+ description = "Path of the configuration file to include.";
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ description = "Additional configuration for the associated plugin.";
+ default = "";
+ };
+ };
+ };
+
+in
+
+{
+ options = {
+ programs.tmux = {
+ enable = mkEnableOption "tmux";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.tmux;
+ defaultText = "pkgs.tmux";
+ example = literalExample "pkgs.tmux";
+ description = "The tmux package to install";
+ };
+
+ sensibleOnTop = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Run the sensible plugin at the top of the configuration. It
+ is possible to override the sensible settings using the
+ option.
+ '';
+ };
+
+ tmuxp.enable = mkEnableOption "tmuxp";
+
+ tmuxinator.enable = mkEnableOption "tmuxinator";
+
+ plugins = mkOption {
+ type = with types;
+ listOf (either package pluginModule)
+ // { description = "list of plugin packages or submodules"; };
+ description = ''
+ List of tmux plugins to be included at the end of your tmux
+ configuration. The sensible plugin, however, is defaulted to
+ run at the top of your configuration.
+ '';
+ default = [ ];
+ example = literalExample ''
+ with pkgs; [
+ tmuxPlugins.cpu
+ {
+ plugin = tmuxPlugins.resurrect;
+ extraConfig = "set -g @resurrect-strategy-nvim 'session'";
+ }
+ {
+ plugin = tmuxPlugins.continuum;
+ extraConfig = '''
+ set -g @continuum-restore 'on'
+ set -g @continuum-save-interval '60' # minutes
+ ''';
+ }
+ ]
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Additional configuration to add to
+ tmux.conf.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable (
+ mkMerge [
+ {
+ home.packages = [ cfg.package ]
+ ++ optional cfg.tmuxinator.enable pkgs.tmuxinator
+ ++ optional cfg.tmuxp.enable pkgs.tmuxp;
+
+ home.file.".tmux.conf".text = cfg.extraConfig;
+ }
+
+ (mkIf cfg.sensibleOnTop {
+ home.file.".tmux.conf".text = mkBefore ''
+ # ============================================= #
+ # Start with defaults from the Sensible plugin #
+ # --------------------------------------------- #
+ run-shell ${pkgs.tmuxPlugins.sensible.rtp}
+ # ============================================= #
+ '';
+ })
+
+ (mkIf (cfg.plugins != []) {
+ assertions = [(
+ let
+ hasBadPluginName = p: !(hasPrefix "tmuxplugin" (pluginName p));
+ badPlugins = filter hasBadPluginName cfg.plugins;
+ in
+ {
+ assertion = badPlugins == [];
+ message =
+ "Invalid tmux plugin (not prefixed with \"tmuxplugins\"): "
+ + concatMapStringsSep ", " pluginName badPlugins;
+ }
+ )];
+
+ home.file.".tmux.conf".text = mkAfter ''
+ # ============================================= #
+ # Load plugins with Home Manager #
+ # --------------------------------------------- #
+
+ ${(concatMapStringsSep "\n\n" (p: ''
+ # ${pluginName p}
+ # ---------------------
+ ${p.extraConfig or ""}
+ run-shell ${
+ if types.package.check p
+ then p.rtp
+ else p.plugin.rtp
+ }
+ '') cfg.plugins)}
+ # ============================================= #
+ '';
+ })
+ ]
+ );
+}