summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/services/aerospace/default.nix105
-rw-r--r--tests/services-aerospace.nix45
2 files changed, 147 insertions, 3 deletions
diff --git a/modules/services/aerospace/default.nix b/modules/services/aerospace/default.nix
index 531e7b2..3080579 100644
--- a/modules/services/aerospace/default.nix
+++ b/modules/services/aerospace/default.nix
@@ -9,7 +9,31 @@ let
cfg = config.services.aerospace;
format = pkgs.formats.toml { };
- configFile = format.generate "aerospace.toml" cfg.settings;
+ 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);
+ configFile = format.generate "aerospace.toml" (filterNulls cfg.settings);
in
{
@@ -72,9 +96,84 @@ in
description = "Default orientation for the root container.";
};
on-window-detected = lib.mkOption {
- type = listOf str;
+ type = listOf (submodule {
+ options = {
+ "if" = lib.mkOption {
+ type = submodule {
+ options = {
+ app-id = lib.mkOption {
+ type = nullOr str;
+ default = null;
+ description = "The application ID to match (optional).";
+ };
+ workspace = lib.mkOption {
+ type = nullOr str;
+ default = null;
+ description = "The workspace name to match (optional).";
+ };
+ window-title-regex-substring = lib.mkOption {
+ type = nullOr str;
+ default = null;
+ description = "Substring to match in the window title (optional).";
+ };
+ app-name-regex-substring = lib.mkOption {
+ type = nullOr str;
+ default = null;
+ description = "Regex substring to match the app name (optional).";
+ };
+ during-aerospace-startup = lib.mkOption {
+ type = nullOr bool;
+ default = null;
+ description = "Whether to match during aerospace startup (optional).";
+ };
+ };
+ };
+ default = { };
+ description = "Conditions for detecting a window.";
+ };
+ check-further-callbacks = lib.mkOption {
+ type = nullOr bool;
+ default = null;
+ description = "Whether to check further callbacks after this rule (optional).";
+ };
+ run = lib.mkOption {
+ type = oneOf [str (listOf str)];
+ example = ["move-node-to-workspace m" "resize-node"];
+ description = "Commands to execute when the conditions match (required).";
+ };
+ };
+ });
default = [ ];
- description = "Commands to run every time a new window is detected.";
+ 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 = lib.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 = lib.mkOption {
type = listOf str;
diff --git a/tests/services-aerospace.nix b/tests/services-aerospace.nix
index 28688c4..088c92d 100644
--- a/tests/services-aerospace.nix
+++ b/tests/services-aerospace.nix
@@ -21,6 +21,32 @@ in
alt-k = "focus up";
alt-l = "focus right";
};
+ on-window-detected = [
+ {
+ "if" = {
+ app-id = "Another.Cool.App";
+ during-aerospace-startup = false;
+ };
+ check-further-callbacks = false;
+ run = "move-node-to-workspace m";
+ }
+ {
+ "if".app-name-regex-substring = "finder|calendar";
+ run = "layout floating";
+ }
+ {
+ "if".workspace = "1";
+ run = "layout h_accordion";
+ }
+ ];
+ workspace-to-monitor-force-assignment = {
+ "1" = 1;
+ "2" = "main";
+ "3" = "secondary";
+ "4" = "built-in";
+ "5" = "^built-in retina display$";
+ "6" = [ "secondary" "dell" ];
+ };
};
test = ''
@@ -43,5 +69,24 @@ in
grep 'alt-j = "focus down"' $conf
grep 'alt-k = "focus up"' $conf
grep 'alt-l = "focus right"' $conf
+
+ grep 'check-further-callbacks = false' $conf
+ grep 'run = "move-node-to-workspace m"' $conf
+ grep 'app-id = "Another.Cool.App"' $conf
+ grep 'during-aerospace-startup = false' $conf
+
+ grep 'run = "layout floating"' $conf
+ grep 'app-name-regex-substring = "finder|calendar"' $conf
+ (! grep 'window-title-regex-substring' $conf)
+
+ grep 'workspace = "1"' $conf
+ grep 'run = "layout h_accordion"' $conf
+
+ grep '1 = 1' $conf
+ grep '2 = "main"' $conf
+ grep '3 = "secondary"' $conf
+ grep '4 = "built-in"' $conf
+ grep '5 = "^built-in retina display$"' $conf
+ grep '6 = \["secondary", "dell"\]' $conf
'';
}