From c1ecfb20ba3869f28362786cef43058e92d104fa Mon Sep 17 00:00:00 2001 From: damidoug Date: Wed, 8 Jan 2025 18:51:12 +0100 Subject: [PATCH] aerospace: fix conflit --- modules/lib/maintainers.nix | 6 + modules/misc/news.nix | 12 + modules/modules.nix | 1 + modules/programs/aerospace.nix | 231 ++++++++++++++++++ tests/default.nix | 1 + .../modules/programs/aerospace/aerospace.nix | 27 ++ tests/modules/programs/aerospace/default.nix | 1 + .../programs/aerospace/settings-expected.toml | 29 +++ 8 files changed, 308 insertions(+) create mode 100644 modules/programs/aerospace.nix create mode 100644 tests/modules/programs/aerospace/aerospace.nix create mode 100644 tests/modules/programs/aerospace/default.nix create mode 100644 tests/modules/programs/aerospace/settings-expected.toml diff --git a/modules/lib/maintainers.nix b/modules/lib/maintainers.nix index 7ee9e1df9c1b..d86c3eccfe1b 100644 --- a/modules/lib/maintainers.nix +++ b/modules/lib/maintainers.nix @@ -79,6 +79,12 @@ github = "considerate"; githubId = 217918; }; + damidoug = { + email = "contact@damidoug.dev"; + github = "damidoug"; + githubId = 75175586; + name = "Douglas Damiano"; + }; danjujan = { name = "Jan Schmitz"; email = "44864658+danjujan@users.noreply.github.com"; diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 7a3604be91fe..dd2a844fd598 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1946,6 +1946,7 @@ in { speed, features, or native UIs. Ghostty provides all three. ''; } + { time = "2025-01-04T15:00:00+00:00"; condition = hostPlatform.isLinux; @@ -1960,6 +1961,17 @@ in { as well as wf-shell. ''; } + + { + time = "2025-01-06T19:11:20+00:00"; + condition = hostPlatform.isDarwin; + message = '' + A new module is available: 'programs.aerospace'. + + AeroSpace is an i3-like tiling window manager for macOS. + See https://github.com/nikitabobko/AeroSpace for more. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index 2aae09eb12d6..7bddd163a5bd 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -52,6 +52,7 @@ let ./misc/xfconf.nix ./programs/abook.nix ./programs/aerc.nix + ./programs/aerospace.nix ./programs/afew.nix ./programs/alacritty.nix ./programs/alot.nix diff --git a/modules/programs/aerospace.nix b/modules/programs/aerospace.nix new file mode 100644 index 000000000000..c6da1f8ecbed --- /dev/null +++ b/modules/programs/aerospace.nix @@ -0,0 +1,231 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.programs.aerospace; + + tomlFormat = pkgs.formats.toml { }; + + filterAttrsRecursive = pred: set: + lib.listToAttrs (lib.concatMap (name: + let v = set.${name}; + in if pred v then + [ + (lib.nameValuePair name (if lib.isAttrs v then + filterAttrsRecursive pred v + else if lib.isList v then + (map (i: if lib.isAttrs i then filterAttrsRecursive pred i else i) + (lib.filter pred v)) + else + v)) + ] + else + [ ]) (lib.attrNames set)); + filterNulls = filterAttrsRecursive (v: v != null); +in { + meta.maintainers = with hm.maintainers; [ damidoug ]; + + options.programs.aerospace = with types; { + enable = mkEnableOption "Whether to enable AeroSpace window manager."; + + package = mkPackageOption pkgs "aerospace" { }; + + userSettings = mkOption { + type = submodule { + freeformType = tomlFormat.type; + options = { + start-at-login = lib.mkOption { + type = bool; + default = false; + description = "Start AeroSpace at login."; + }; + after-login-command = mkOption { + type = listOf str; + default = [ ]; + description = '' + You can use it to add commands that run after login to macOS user session. + 'start-at-login' needs to be 'true' for 'after-login-command' to work. + ''; + }; + after-startup-command = mkOption { + type = listOf str; + default = [ ]; + description = '' + You can use it to add commands that run after AeroSpace startup. + 'after-startup-command' is run after 'after-login-command' + ''; + example = [ "layout tiles" ]; + }; + enable-normalization-flatten-containers = mkOption { + type = bool; + default = true; + description = + ''Containers that have only one child are "flattened".''; + }; + enable-normalization-opposite-orientation-for-nested-containers = + mkOption { + type = bool; + default = true; + description = + "Containers that nest into each other must have opposite orientations."; + }; + accordion-padding = mkOption { + type = int; + default = 30; + description = "Padding between windows in an accordion container."; + }; + default-root-container-layout = mkOption { + type = enum [ "tiles" "accordion" ]; + default = "tiles"; + description = "Default layout for the root container."; + }; + default-root-container-orientation = mkOption { + type = enum [ "horizontal" "vertical" "auto" ]; + default = "auto"; + description = "Default orientation for the root container."; + }; + on-window-detected = mkOption { + type = listOf (submodule { + options = { + "if" = mkOption { + type = submodule { + options = { + app-id = mkOption { + type = nullOr str; + default = null; + description = "The application ID to match (optional)."; + }; + workspace = mkOption { + type = nullOr str; + default = null; + description = "The workspace name to match (optional)."; + }; + window-title-regex-substring = mkOption { + type = nullOr str; + default = null; + description = + "Substring to match in the window title (optional)."; + }; + app-name-regex-substring = mkOption { + type = nullOr str; + default = null; + description = + "Regex substring to match the app name (optional)."; + }; + during-aerospace-startup = mkOption { + type = nullOr bool; + default = null; + description = + "Whether to match during aerospace startup (optional)."; + }; + }; + }; + default = { }; + description = "Conditions for detecting a window."; + }; + check-further-callbacks = mkOption { + type = nullOr bool; + default = null; + description = + "Whether to check further callbacks after this rule (optional)."; + }; + run = mkOption { + type = oneOf [ str (listOf str) ]; + example = [ "move-node-to-workspace m" "resize-node" ]; + description = + "Commands to execute when the conditions match (required)."; + }; + }; + }); + default = [ ]; + example = [{ + "if" = { + app-id = "Another.Cool.App"; + workspace = "cool-workspace"; + window-title-regex-substring = "Title"; + app-name-regex-substring = "CoolApp"; + during-aerospace-startup = false; + }; + check-further-callbacks = false; + run = [ "move-node-to-workspace m" "resize-node" ]; + }]; + description = + "Commands to run every time a new window is detected with optional conditions."; + }; + workspace-to-monitor-force-assignment = mkOption { + type = attrsOf (oneOf [ int str (listOf str) ]); + default = { }; + description = '' + Map workspaces to specific monitors. + Left-hand side is the workspace name, and right-hand side is the monitor pattern. + ''; + example = { + "1" = 1; # First monitor from left to right. + "2" = "main"; # Main monitor. + "3" = "secondary"; # Secondary monitor (non-main). + "4" = "built-in"; # Built-in display. + "5" = + "^built-in retina display$"; # Regex for the built-in retina display. + "6" = [ "secondary" "dell" ]; # Match first pattern in the list. + }; + }; + on-focus-changed = mkOption { + type = listOf str; + default = [ ]; + example = [ "move-mouse monitor-lazy-center" ]; + description = + "Commands to run every time focused window or workspace changes."; + }; + on-focused-monitor-changed = mkOption { + type = listOf str; + default = [ "move-mouse monitor-lazy-center" ]; + description = "Commands to run every time focused monitor changes."; + }; + exec-on-workspace-change = mkOption { + type = listOf str; + default = [ ]; + example = [ + "/bin/bash" + "-c" + "sketchybar --trigger aerospace_workspace_change FOCUSED=$AEROSPACE_FOCUSED_WORKSPACE" + ]; + description = "Commands to run every time workspace changes."; + }; + key-mapping.preset = mkOption { + type = enum [ "qwerty" "dvorak" ]; + default = "qwerty"; + description = "Keymapping preset."; + }; + }; + }; + default = { }; + example = literalExpression '' + { + gaps = { + outer.left = 8; + outer.bottom = 8; + outer.top = 8; + outer.right = 8; + }; + mode.main.binding = { + alt-h = "focus left"; + alt-j = "focus down"; + alt-k = "focus up"; + alt-l = "focus right"; + }; + } + ''; + description = '' + AeroSpace configuration, see + + for supported values. + ''; + }; + }; + + config.home = mkIf cfg.enable { + packages = [ cfg.package ]; + file.".config/aerospace/aerospace.toml".source = + tomlFormat.generate "aerospace" (filterNulls cfg.userSettings); + }; + +} diff --git a/tests/default.nix b/tests/default.nix index 638845752269..06c8a09c8c37 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -179,6 +179,7 @@ in import nmtSrc { ./modules/xresources ] ++ lib.optionals isDarwin [ ./modules/launchd + ./modules/programs/aerospace ./modules/services/emacs-darwin ./modules/services/espanso-darwin ./modules/services/git-sync-darwin diff --git a/tests/modules/programs/aerospace/aerospace.nix b/tests/modules/programs/aerospace/aerospace.nix new file mode 100644 index 000000000000..db32c531b527 --- /dev/null +++ b/tests/modules/programs/aerospace/aerospace.nix @@ -0,0 +1,27 @@ +{ + programs.aerospace = { + enable = true; + userSettings = { + gaps = { + outer.left = 8; + outer.bottom = 8; + outer.top = 8; + outer.right = 8; + }; + mode.main.binding = { + alt-h = "focus left"; + alt-j = "focus down"; + alt-k = "focus up"; + alt-l = "focus right"; + }; + }; + }; + + test.stubs.aerospace = { }; + + nmt.script = '' + assertFileContent home-files/.config/aerospace/aerospace.toml ${ + ./settings-expected.toml + } + ''; +} diff --git a/tests/modules/programs/aerospace/default.nix b/tests/modules/programs/aerospace/default.nix new file mode 100644 index 000000000000..d77a32af6379 --- /dev/null +++ b/tests/modules/programs/aerospace/default.nix @@ -0,0 +1 @@ +{ aerospace = ./aerospace.nix; } diff --git a/tests/modules/programs/aerospace/settings-expected.toml b/tests/modules/programs/aerospace/settings-expected.toml new file mode 100644 index 000000000000..d38cba45eb33 --- /dev/null +++ b/tests/modules/programs/aerospace/settings-expected.toml @@ -0,0 +1,29 @@ +accordion-padding = 30 +after-login-command = [] +after-startup-command = [] +default-root-container-layout = "tiles" +default-root-container-orientation = "auto" +enable-normalization-flatten-containers = true +enable-normalization-opposite-orientation-for-nested-containers = true +exec-on-workspace-change = [] +on-focus-changed = [] +on-focused-monitor-changed = ["move-mouse monitor-lazy-center"] +on-window-detected = [] +start-at-login = false + +[gaps.outer] +bottom = 8 +left = 8 +right = 8 +top = 8 + +[key-mapping] +preset = "qwerty" + +[mode.main.binding] +alt-h = "focus left" +alt-j = "focus down" +alt-k = "focus up" +alt-l = "focus right" + +[workspace-to-monitor-force-assignment]