1
0
mirror of https://github.com/nix-community/home-manager synced 2024-07-04 20:33:27 +02:00
home-manager/modules/services/window-managers/i3-sway/i3.nix
Emily 9f9e277b60 treewide: remove now-redundant lib.mdDoc calls
These (and the `*MD` functions apart from `literalMD`) are now no-ops
in nixpkgs and serve no purpose other than to add additional noise and
potentially mislead people into thinking unmarked DocBook documentation
will still be accepted.

Note that if backporting changes including documentation to 23.05,
the `mdDoc` calls will need to be re-added.

To reproduce this commit, run:

    $ NIX_PATH=nixpkgs=flake:nixpkgs/e7e69199f0372364a6106a1e735f68604f4c5a25 \
      nix shell nixpkgs#coreutils \
      -c find . -name '*.nix' \
      -exec nix run -- github:emilazy/nix-doc-munge/98dadf1f77351c2ba5dcb709a2a171d655f15099 \
      --strip {} +
    $ ./format
2023-07-17 18:49:09 +01:00

271 lines
10 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.xsession.windowManager.i3;
commonOptions = import ./lib/options.nix {
inherit config lib cfg pkgs;
moduleName = "i3";
};
configModule = types.submodule {
options = {
inherit (commonOptions)
fonts window floating focus assigns modifier workspaceLayout
workspaceAutoBackAndForth keycodebindings colors bars startup gaps menu
terminal defaultWorkspace workspaceOutputAssign;
keybindings = mkOption {
type = types.attrsOf (types.nullOr types.str);
default = mapAttrs (n: mkOptionDefault) {
"${cfg.config.modifier}+Return" = "exec ${cfg.config.terminal}";
"${cfg.config.modifier}+Shift+q" = "kill";
"${cfg.config.modifier}+d" = "exec ${cfg.config.menu}";
"${cfg.config.modifier}+Left" = "focus left";
"${cfg.config.modifier}+Down" = "focus down";
"${cfg.config.modifier}+Up" = "focus up";
"${cfg.config.modifier}+Right" = "focus right";
"${cfg.config.modifier}+Shift+Left" = "move left";
"${cfg.config.modifier}+Shift+Down" = "move down";
"${cfg.config.modifier}+Shift+Up" = "move up";
"${cfg.config.modifier}+Shift+Right" = "move right";
"${cfg.config.modifier}+h" = "split h";
"${cfg.config.modifier}+v" = "split v";
"${cfg.config.modifier}+f" = "fullscreen toggle";
"${cfg.config.modifier}+s" = "layout stacking";
"${cfg.config.modifier}+w" = "layout tabbed";
"${cfg.config.modifier}+e" = "layout toggle split";
"${cfg.config.modifier}+Shift+space" = "floating toggle";
"${cfg.config.modifier}+space" = "focus mode_toggle";
"${cfg.config.modifier}+a" = "focus parent";
"${cfg.config.modifier}+Shift+minus" = "move scratchpad";
"${cfg.config.modifier}+minus" = "scratchpad show";
"${cfg.config.modifier}+1" = "workspace number 1";
"${cfg.config.modifier}+2" = "workspace number 2";
"${cfg.config.modifier}+3" = "workspace number 3";
"${cfg.config.modifier}+4" = "workspace number 4";
"${cfg.config.modifier}+5" = "workspace number 5";
"${cfg.config.modifier}+6" = "workspace number 6";
"${cfg.config.modifier}+7" = "workspace number 7";
"${cfg.config.modifier}+8" = "workspace number 8";
"${cfg.config.modifier}+9" = "workspace number 9";
"${cfg.config.modifier}+0" = "workspace number 10";
"${cfg.config.modifier}+Shift+1" =
"move container to workspace number 1";
"${cfg.config.modifier}+Shift+2" =
"move container to workspace number 2";
"${cfg.config.modifier}+Shift+3" =
"move container to workspace number 3";
"${cfg.config.modifier}+Shift+4" =
"move container to workspace number 4";
"${cfg.config.modifier}+Shift+5" =
"move container to workspace number 5";
"${cfg.config.modifier}+Shift+6" =
"move container to workspace number 6";
"${cfg.config.modifier}+Shift+7" =
"move container to workspace number 7";
"${cfg.config.modifier}+Shift+8" =
"move container to workspace number 8";
"${cfg.config.modifier}+Shift+9" =
"move container to workspace number 9";
"${cfg.config.modifier}+Shift+0" =
"move container to workspace number 10";
"${cfg.config.modifier}+Shift+c" = "reload";
"${cfg.config.modifier}+Shift+r" = "restart";
"${cfg.config.modifier}+Shift+e" =
"exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'";
"${cfg.config.modifier}+r" = "mode resize";
};
defaultText = "Default i3 keybindings.";
description = ''
An attribute set that assigns a key press to an action using a key symbol.
See <https://i3wm.org/docs/userguide.html#keybindings>.
Consider to use `lib.mkOptionDefault` function to extend or override
default keybindings instead of specifying all of them from scratch.
'';
example = literalExpression ''
let
modifier = config.xsession.windowManager.i3.config.modifier;
in lib.mkOptionDefault {
"''${modifier}+Return" = "exec i3-sensible-terminal";
"''${modifier}+Shift+q" = "kill";
"''${modifier}+d" = "exec ''${pkgs.dmenu}/bin/dmenu_run";
}
'';
};
modes = mkOption {
type = types.attrsOf (types.attrsOf types.str);
default = {
resize = {
"Left" = "resize shrink width 10 px or 10 ppt";
"Down" = "resize grow height 10 px or 10 ppt";
"Up" = "resize shrink height 10 px or 10 ppt";
"Right" = "resize grow width 10 px or 10 ppt";
"Escape" = "mode default";
"Return" = "mode default";
};
};
description = ''
An attribute set that defines binding modes and keybindings
inside them
Only basic keybinding is supported (bindsym keycomb action),
for more advanced setup use 'i3.extraConfig'.
'';
};
};
};
commonFunctions = import ./lib/functions.nix {
inherit config cfg lib;
moduleName = "i3";
};
inherit (commonFunctions)
keybindingsStr keycodebindingsStr modeStr assignStr barStr gapsStr
floatingCriteriaStr windowCommandsStr colorSetStr windowBorderString
fontConfigStr keybindingDefaultWorkspace keybindingsRest workspaceOutputStr;
startupEntryStr = { command, always, notification, workspace, ... }:
concatStringsSep " " [
(if always then "exec_always" else "exec")
(if (notification && workspace == null) then "" else "--no-startup-id")
(if (workspace == null) then
command
else
"i3-msg 'workspace ${workspace}; exec ${command}'")
];
configFile = pkgs.writeText "i3.conf" (concatStringsSep "\n"
((if cfg.config != null then
with cfg.config;
([
(fontConfigStr fonts)
"floating_modifier ${floating.modifier}"
(windowBorderString window floating)
"hide_edge_borders ${window.hideEdgeBorders}"
"focus_wrapping ${focus.wrapping}"
"focus_follows_mouse ${lib.hm.booleans.yesNo focus.followMouse}"
"focus_on_window_activation ${focus.newWindow}"
"mouse_warping ${if focus.mouseWarping then "output" else "none"}"
"workspace_layout ${workspaceLayout}"
"workspace_auto_back_and_forth ${
lib.hm.booleans.yesNo workspaceAutoBackAndForth
}"
"client.focused ${colorSetStr colors.focused}"
"client.focused_inactive ${colorSetStr colors.focusedInactive}"
"client.unfocused ${colorSetStr colors.unfocused}"
"client.urgent ${colorSetStr colors.urgent}"
"client.placeholder ${colorSetStr colors.placeholder}"
"client.background ${colors.background}"
(keybindingsStr { keybindings = keybindingDefaultWorkspace; })
(keybindingsStr { keybindings = keybindingsRest; })
(keycodebindingsStr keycodebindings)
] ++ mapAttrsToList (modeStr false) modes
++ mapAttrsToList assignStr assigns ++ map barStr bars
++ optional (gaps != null) gapsStr
++ map floatingCriteriaStr floating.criteria
++ map windowCommandsStr window.commands ++ map startupEntryStr startup
++ map workspaceOutputStr workspaceOutputAssign)
else
[ ]) ++ [ cfg.extraConfig ]));
# Validates the i3 configuration
checkI3Config =
pkgs.runCommandLocal "i3-config" { buildInputs = [ cfg.package ]; } ''
# We have to make sure the wrapper does not start a dbus session
export DBUS_SESSION_BUS_ADDRESS=1
# A zero exit code means i3 successfully validated the configuration
i3 -c ${configFile} -C -d all || {
echo "i3 configuration validation failed"
echo "For a verbose log of the failure, run 'i3 -c ${configFile} -C -d all'"
exit 1
};
cp ${configFile} $out
'';
in {
meta.maintainers = with maintainers; [ sumnerevans sebtm ];
options = {
xsession.windowManager.i3 = {
enable = mkEnableOption "i3 window manager";
package = mkPackageOption pkgs "i3" { };
config = mkOption {
type = types.nullOr configModule;
default = { };
description = "i3 configuration options.";
};
extraConfig = mkOption {
type = types.lines;
default = "";
description =
"Extra configuration lines to add to ~/.config/i3/config.";
};
};
};
config = mkIf cfg.enable (mkMerge [
{
assertions = [
(hm.assertions.assertPlatform "xsession.windowManager.i3" pkgs
platforms.linux)
];
home.packages = [ cfg.package ];
xsession.windowManager.command = "${cfg.package}/bin/i3";
xdg.configFile."i3/config" = {
source = checkI3Config;
onChange = ''
# There may be several sockets after log out/log in, but the old ones
# will fail with "Connection refused".
for i3Socket in ''${XDG_RUNTIME_DIR:-/run/user/$UID}/i3/ipc-socket.*; do
if [[ -S $i3Socket ]]; then
${cfg.package}/bin/i3-msg -s $i3Socket reload >/dev/null |& grep -v "Connection refused" || true
fi
done
'';
};
}
(mkIf (cfg.config != null) {
warnings = (optional (isList cfg.config.fonts)
"Specifying i3.config.fonts as a list is deprecated. Use the attrset version instead.")
++ flatten (map (b:
optional (isList b.fonts)
"Specifying i3.config.bars[].fonts as a list is deprecated. Use the attrset version instead.")
cfg.config.bars) ++ [
(mkIf (any (s: s.workspace != null) cfg.config.startup)
("'xsession.windowManager.i3.config.startup.*.workspace' is deprecated, "
+ "use 'xsession.windowManager.i3.config.assigns' instead."
+ "See https://github.com/nix-community/home-manager/issues/265."))
(mkIf cfg.config.focus.forceWrapping
("'xsession.windowManager.i3.config.focus.forceWrapping' is deprecated, "
+ "use 'xsession.windowManager.i3.config.focus.wrapping' instead."))
];
})
]);
}