diff options
Diffstat (limited to 'accounts/gkleen@sif/niri/default.nix')
-rw-r--r-- | accounts/gkleen@sif/niri/default.nix | 101 |
1 files changed, 89 insertions, 12 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix index af1af07a..8752f3e3 100644 --- a/accounts/gkleen@sif/niri/default.nix +++ b/accounts/gkleen@sif/niri/default.nix | |||
@@ -35,7 +35,11 @@ let | |||
35 | if jq -e '.is_focused' <<<"$window_json" >/dev/null; then | 35 | if jq -e '.is_focused' <<<"$window_json" >/dev/null; then |
36 | niri msg action focus-workspace-previous | 36 | niri msg action focus-workspace-previous |
37 | else | 37 | else |
38 | niri msg action focus-window --id "$(jq -r '.id' <<<"$window_json")" | 38 | if [[ $(jq -r --arg workspace_name "$workspace_name" 'map(select(.name == $workspace_name)) | .[0].is_focused' <<<"$workspaces_json") != "true" ]] && [[ $(jq -r --arg workspace_name "$workspace_name" 'map(select(.name == $workspace_name)) | .[0].id' <<<"$workspaces_json") = $(jq -r '.workspace_id' <<<"$window_json") ]]; then |
39 | niri msg action focus-workspace "$workspace_name" | ||
40 | else | ||
41 | niri msg action focus-window --id "$(jq -r '.id' <<<"$window_json")" | ||
42 | fi | ||
39 | fi | 43 | fi |
40 | exit 0 | 44 | exit 0 |
41 | fi | 45 | fi |
@@ -45,7 +49,6 @@ let | |||
45 | ''; | 49 | ''; |
46 | }; | 50 | }; |
47 | focus-or-spawn-action = config.lib.niri.actions.spawn (lib.getExe focus_or_spawn); | 51 | focus-or-spawn-action = config.lib.niri.actions.spawn (lib.getExe focus_or_spawn); |
48 | focus-or-spawn-action-app_id = app_id: focus-or-spawn-action ''select(.app_id == "${app_id}")''; | ||
49 | 52 | ||
50 | with_adjacent_workspace = pkgs.writeShellApplication { | 53 | with_adjacent_workspace = pkgs.writeShellApplication { |
51 | name = "with-adjacent-workspace"; | 54 | name = "with-adjacent-workspace"; |
@@ -84,7 +87,7 @@ let | |||
84 | }; | 87 | }; |
85 | with-adjacent-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_adjacent_workspace) "^${lib.concatMapStringsSep "|" ({ name, ...}: name) cfg.scratchspaces}$"; | 88 | with-adjacent-workspace-action = config.lib.niri.actions.spawn (lib.getExe with_adjacent_workspace) "^${lib.concatMapStringsSep "|" ({ name, ...}: name) cfg.scratchspaces}$"; |
86 | focus-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}''; | 89 | focus-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}''; |
87 | move-column-to-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}}}}''; | 90 | move-column-to-adjacent-workspace = direction: with-adjacent-workspace-action direction ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}, "focus": true}}}''; |
88 | 91 | ||
89 | with_unnamed_workspace = pkgs.writeShellApplication { | 92 | with_unnamed_workspace = pkgs.writeShellApplication { |
90 | name = "with-unnamed-workspace"; | 93 | name = "with-unnamed-workspace"; |
@@ -131,7 +134,7 @@ let | |||
131 | 134 | ||
132 | windows_json="$(niri msg -j windows)" | 135 | windows_json="$(niri msg -j windows)" |
133 | active_workspace="$(jq -r '.[] | select(.is_focused) | .workspace_id' <<<"$windows_json")" | 136 | active_workspace="$(jq -r '.[] | select(.is_focused) | .workspace_id' <<<"$windows_json")" |
134 | window_ix="$(gojq -r --arg active_workspace "$active_workspace" '.[] | select('"$window_select"') | "\(.title)\u0000icon\u001f\(.app_id)"' <<<"$windows_json" | fuzzel --log-level=warning --dmenu --index)" | 137 | window_ix="$(gojq -r --arg active_workspace "$active_workspace" '.[] | select('"$window_select"') | "\(.title)\u0000icon\u001f\(.app_id)"' <<<"$windows_json" | fuzzel --width=60 --log-level=warning --dmenu --index)" |
135 | # shellcheck disable=SC2016 | 138 | # shellcheck disable=SC2016 |
136 | window_json="$(gojq -rc --arg active_workspace "$active_workspace" --arg window_ix "$window_ix" 'map(select('"$window_select"')) | .[($window_ix | tonumber)]' <<<"$windows_json")" | 139 | window_json="$(gojq -rc --arg active_workspace "$active_workspace" --arg window_ix "$window_ix" 'map(select('"$window_select"')) | .[($window_ix | tonumber)]' <<<"$windows_json")" |
137 | 140 | ||
@@ -141,6 +144,25 @@ let | |||
141 | ''; | 144 | ''; |
142 | }; | 145 | }; |
143 | with-select-window-action = config.lib.niri.actions.spawn (lib.getExe with_select_window); | 146 | with-select-window-action = config.lib.niri.actions.spawn (lib.getExe with_select_window); |
147 | |||
148 | with_predicate_window = pred: pkgs.writeShellApplication { | ||
149 | name = "with-predicate-window"; | ||
150 | runtimeInputs = [ niri pkgs.gojq pkgs.socat ]; | ||
151 | text = '' | ||
152 | action="$1" | ||
153 | shift | ||
154 | |||
155 | windows_json="$(niri msg -j windows)" | ||
156 | window_json="$(gojq -rc 'map(select(${pred})) | .[0]' <<<"$windows_json")" | ||
157 | |||
158 | [[ -z "$window_json" || $window_json = "null" ]] && exit 1 | ||
159 | |||
160 | jq -c "$action" <<<"$window_json" | socat STDIO "$NIRI_SOCKET" | ||
161 | ''; | ||
162 | }; | ||
163 | |||
164 | with-urgent-window-action = config.lib.niri.actions.spawn (lib.getExe (with_predicate_window ".is_urgent")); | ||
165 | with-focused-window-action = config.lib.niri.actions.spawn (lib.getExe (with_predicate_window ".is_focused")); | ||
144 | in { | 166 | in { |
145 | imports = [ | 167 | imports = [ |
146 | ./waybar.nix | 168 | ./waybar.nix |
@@ -171,6 +193,17 @@ in { | |||
171 | type = lib.types.nullOr lib.types.str; | 193 | type = lib.types.nullOr lib.types.str; |
172 | default = null; | 194 | default = null; |
173 | }; | 195 | }; |
196 | moveKey = lib.mkOption { | ||
197 | type = lib.types.nullOr lib.types.str; | ||
198 | default = let | ||
199 | keys = lib.splitString "+" config.key; | ||
200 | defMoveKey = lib.concatStringsSep "+" (lib.flatten [ | ||
201 | (lib.take (lib.length keys - 1) keys) | ||
202 | ["Shift"] | ||
203 | (lib.takeEnd 1 keys) | ||
204 | ]); | ||
205 | in if config.key == null then null else defMoveKey; | ||
206 | }; | ||
174 | spawn = lib.mkOption { | 207 | spawn = lib.mkOption { |
175 | type = lib.types.nullOr (lib.types.listOf lib.types.str); | 208 | type = lib.types.nullOr (lib.types.listOf lib.types.str); |
176 | default = null; | 209 | default = null; |
@@ -416,7 +449,7 @@ in { | |||
416 | { title = "^Access Request.*"; } | 449 | { title = "^Access Request.*"; } |
417 | { title = ".*Passkey credentials$"; } | 450 | { title = ".*Passkey credentials$"; } |
418 | ]; | 451 | ]; |
419 | windowRuleExtra = [ | 452 | windowRuleExtra = with kdl; [ |
420 | (kdl.leaf "open-focused" false) | 453 | (kdl.leaf "open-focused" false) |
421 | ]; | 454 | ]; |
422 | key = "Mod+Control+P"; | 455 | key = "Mod+Control+P"; |
@@ -444,6 +477,20 @@ in { | |||
444 | app-id = "com.github.wwmm.easyeffects"; | 477 | app-id = "com.github.wwmm.easyeffects"; |
445 | spawn = [ "easyeffects" ]; | 478 | spawn = [ "easyeffects" ]; |
446 | } | 479 | } |
480 | { name = "time"; | ||
481 | key = "Mod+Control+K"; | ||
482 | app-id = "chrome-kimai.yggdrasil.li__-Default"; | ||
483 | spawn = [ (toString (pkgs.resholve.writeScript "kimai" { | ||
484 | interpreter = pkgs.runtimeShell; | ||
485 | inputs = [ pkgs.dex ]; | ||
486 | execer = [ "cannot:${lib.getExe pkgs.dex}" ]; | ||
487 | } '' | ||
488 | exec dex $HOME/.local/state/nix/profile/share/applications/kimai.desktop | ||
489 | '')) ]; | ||
490 | windowRuleExtra = with kdl; [ | ||
491 | (leaf "block-out-from" "screencast") | ||
492 | ]; | ||
493 | } | ||
447 | ]; | 494 | ]; |
448 | programs.niri.config = | 495 | programs.niri.config = |
449 | let | 496 | let |
@@ -500,6 +547,9 @@ in { | |||
500 | SDL_VIDEODRIVER = "wayland"; | 547 | SDL_VIDEODRIVER = "wayland"; |
501 | DISPLAY = ":0"; | 548 | DISPLAY = ":0"; |
502 | ELECTRON_OZONE_PLATFORM_HINT = "auto"; | 549 | ELECTRON_OZONE_PLATFORM_HINT = "auto"; |
550 | SSH_ASKPASS_REQUIRE = "prefer"; | ||
551 | SSH_ASKPASS = lib.getExe pkgs.kdePackages.ksshaskpass; | ||
552 | SUDO_ASKPASS = lib.getExe pkgs.kdePackages.ksshaskpass; | ||
503 | })) | 553 | })) |
504 | 554 | ||
505 | (node "output" "eDP-1" [ | 555 | (node "output" "eDP-1" [ |
@@ -614,7 +664,7 @@ in { | |||
614 | (plain "window-rule" [ | 664 | (plain "window-rule" [ |
615 | (map (title: | 665 | (map (title: |
616 | (leaf "match" { app-id = "^org\\.keepassxc\\.KeePassXC$"; inherit title; }) | 666 | (leaf "match" { app-id = "^org\\.keepassxc\\.KeePassXC$"; inherit title; }) |
617 | ) ["^Unlock Database.*" "^Access Request.*" ".*Passkey credentials$"]) | 667 | ) ["^Unlock Database.*" "^Access Request.*" ".*Passkey credentials$" "Browser Access Request$"]) |
618 | (leaf "open-focused" true) | 668 | (leaf "open-focused" true) |
619 | (leaf "open-floating" true) | 669 | (leaf "open-floating" true) |
620 | ]) | 670 | ]) |
@@ -643,7 +693,7 @@ in { | |||
643 | (plain "window-rule" [ | 693 | (plain "window-rule" [ |
644 | (leaf "match" { app-id = "^thunderbird$"; }) | 694 | (leaf "match" { app-id = "^thunderbird$"; }) |
645 | (leaf "match" { app-id = "^Element$"; }) | 695 | (leaf "match" { app-id = "^Element$"; }) |
646 | (leaf "match" { app-id = "^Rainbow$"; }) | 696 | (leaf "match" { app-id = "^chrome-web\.openrainbow\.com__-Default$"; }) |
647 | (leaf "open-on-workspace" "comm") | 697 | (leaf "open-on-workspace" "comm") |
648 | ]) | 698 | ]) |
649 | (plain "window-rule" [ | 699 | (plain "window-rule" [ |
@@ -662,6 +712,11 @@ in { | |||
662 | (leaf "open-focused" false) | 712 | (leaf "open-focused" false) |
663 | ]) | 713 | ]) |
664 | (plain "window-rule" [ | 714 | (plain "window-rule" [ |
715 | (leaf "match" { app-id = "^chrome-audiobookshelf\.yggdrasil\.li__-Default$"; }) | ||
716 | (leaf "match" { app-id = "^YouTube Music Desktop App$"; }) | ||
717 | (leaf "open-on-workspace" "vid") | ||
718 | ]) | ||
719 | (plain "window-rule" [ | ||
665 | (leaf "match" { app-id = "^pdfpc$"; }) | 720 | (leaf "match" { app-id = "^pdfpc$"; }) |
666 | (plain "default-column-width" [(leaf "proportion" 1.)]) | 721 | (plain "default-column-width" [(leaf "proportion" 1.)]) |
667 | ]) | 722 | ]) |
@@ -761,12 +816,12 @@ in { | |||
761 | done < <(export LC_ALL=C.UTF-8; echo; find "$RESULTS_DIR" -type f -printf $'%T@ %p\n' | sort -n | cut -d' ' -f2- | xargs -r cat) | 816 | done < <(export LC_ALL=C.UTF-8; echo; find "$RESULTS_DIR" -type f -printf $'%T@ %p\n' | sort -n | cut -d' ' -f2- | xargs -r cat) |
762 | $FOUND || echo | 817 | $FOUND || echo |
763 | } | 818 | } |
764 | FUZZEL_RES=$(prev | fuzzel --dmenu --prompt "qalc> ") || exit $? | 819 | FUZZEL_RES=$(prev | fuzzel --dmenu --prompt "qalc> " --width=60) || exit $? |
765 | if [[ "$FUZZEL_RES" =~ .*\ =\ .* ]]; then | 820 | if [[ "$FUZZEL_RES" =~ .*\ =\ .* ]]; then |
766 | QALC_RES="$FUZZEL_RES" | 821 | QALC_RES="$FUZZEL_RES" |
767 | QALC_RET=0 | 822 | QALC_RET=0 |
768 | else | 823 | else |
769 | QALC_RES=$(qalc "$FUZZEL_RES" 2>&1) | 824 | QALC_RES=$(qalc -set "autocalc off" "$FUZZEL_RES" 2>&1) |
770 | QALC_RET=$? | 825 | QALC_RET=$? |
771 | fi | 826 | fi |
772 | [[ -n "$QALC_RES" ]] || exit 1 | 827 | [[ -n "$QALC_RES" ]] || exit 1 |
@@ -786,11 +841,26 @@ in { | |||
786 | notify-send "$QALC_RES" | 841 | notify-send "$QALC_RES" |
787 | ''; | 842 | ''; |
788 | })); | 843 | })); |
844 | "Mod+Shift+U".action = | ||
845 | let | ||
846 | qalcKitty = pkgs.symlinkJoin { | ||
847 | name = "qalc-kitty"; | ||
848 | paths = [ config.programs.kitty.package ]; | ||
849 | buildInputs = [ pkgs.makeWrapper ]; | ||
850 | postBuild = '' | ||
851 | wrapProgram $out/bin/kitty \ | ||
852 | --add-flags "--config ${pkgs.writeText "kitty.conf" '' | ||
853 | include $HOME/${config.xdg.configFile."kitty/kitty.conf".target} | ||
854 | shell ${lib.getExe pkgs.libqalculate} | ||
855 | ''}" | ||
856 | ''; | ||
857 | }; | ||
858 | in spawn (lib.getExe' qalcKitty "kitty"); | ||
789 | "Mod+E".action = spawn (lib.getExe (pkgs.writeShellApplication { | 859 | "Mod+E".action = spawn (lib.getExe (pkgs.writeShellApplication { |
790 | name = "emoji-fuzzel"; | 860 | name = "emoji-fuzzel"; |
791 | runtimeInputs = with pkgs; [ config.programs.fuzzel.package wtype wl-clipboard-rs ]; | 861 | runtimeInputs = with pkgs; [ config.programs.fuzzel.package wtype wl-clipboard-rs ]; |
792 | text = '' | 862 | text = '' |
793 | FUZZEL_RES=$(fuzzel --dmenu --prompt "emoji> " <"$HOME"/.local/share/emoji-data/list.txt) || exit $? | 863 | FUZZEL_RES=$(fuzzel --dmenu --prompt "emoji> " --cache "$HOME"/.cache/fuzzel-emoji --width=60 <"$HOME"/.local/share/emoji-data/list.txt) || exit $? |
794 | [[ -n "$FUZZEL_RES" ]] || exit 1 | 864 | [[ -n "$FUZZEL_RES" ]] || exit 1 |
795 | wl-copy "$(cut -d ':' -f 1 <<<"$FUZZEL_RES" | tr -d '\n')" && wtype -k XF86Paste | 865 | wl-copy "$(cut -d ':' -f 1 <<<"$FUZZEL_RES" | tr -d '\n')" && wtype -k XF86Paste |
796 | ''; | 866 | ''; |
@@ -851,7 +921,7 @@ in { | |||
851 | "Mod+Shift+Asterisk".action = kdl.magic-leaf "move-column-to-workspace" "vid"; | 921 | "Mod+Shift+Asterisk".action = kdl.magic-leaf "move-column-to-workspace" "vid"; |
852 | 922 | ||
853 | "Mod+Plus".action = with-unnamed-workspace-action ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}''; | 923 | "Mod+Plus".action = with-unnamed-workspace-action ''{"Action":{"FocusWorkspace":{"reference":{"Id": .id}}}}''; |
854 | "Mod+Shift+Plus".action = with-unnamed-workspace-action ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}}}}''; | 924 | "Mod+Shift+Plus".action = with-unnamed-workspace-action ''{"Action":{"MoveColumnToWorkspace":{"reference":{"Id": .id}, "focus": true}}}''; |
855 | 925 | ||
856 | "Mod+M".action = consume-or-expel-window-left; | 926 | "Mod+M".action = consume-or-expel-window-left; |
857 | "Mod+W".action = consume-or-expel-window-right; | 927 | "Mod+W".action = consume-or-expel-window-right; |
@@ -923,13 +993,20 @@ in { | |||
923 | "Mod+Comma".action = spawn makoctl "restore"; | 993 | "Mod+Comma".action = spawn makoctl "restore"; |
924 | 994 | ||
925 | "Mod+Control+W".action = with-empty-unnamed-workspace-action "{\"Action\":{\"FocusWorkspace\":{\"reference\":{\"Id\": $workspace_id}}}}"; | 995 | "Mod+Control+W".action = with-empty-unnamed-workspace-action "{\"Action\":{\"FocusWorkspace\":{\"reference\":{\"Id\": $workspace_id}}}}"; |
926 | "Mod+Control+Shift+W".action = with-empty-unnamed-workspace-action "{\"Action\":{\"MoveColumnToWorkspace\":{\"reference\":{\"Id\": $workspace_id}}}}"; | 996 | "Mod+Control+Shift+W".action = with-empty-unnamed-workspace-action "{\"Action\":{\"MoveColumnToWorkspace\":{\"reference\":{\"Id\": $workspace_id}, \"focus\": true}}}"; |
927 | 997 | ||
928 | "Mod+X".action = set-dynamic-cast-window; | 998 | "Mod+X".action = set-dynamic-cast-window; |
929 | "Mod+Shift+X".action = set-dynamic-cast-monitor; | 999 | "Mod+Shift+X".action = set-dynamic-cast-monitor; |
930 | "Mod+Control+Shift+X".action = clear-dynamic-cast-target; | 1000 | "Mod+Control+Shift+X".action = clear-dynamic-cast-target; |
1001 | |||
1002 | "Mod+D".action = with-urgent-window-action "{\"Action\":{\"FocusWindow\":{\"id\": .id}}}"; | ||
1003 | "Mod+Shift+D".action = with-focused-window-action "{\"Action\":{\"UnsetUrgent\":{\"id\": .id}}}"; | ||
1004 | |||
1005 | "Mod+K".action = spawn (lib.getExe' pkgs.worktime "worktime-ui"); | ||
1006 | "Mod+Shift+K".action = spawn (lib.getExe' pkgs.worktime "worktime-stop"); | ||
931 | })) | 1007 | })) |
932 | (map ({ name, selector, spawn, key, ...}: if key != null && selector != null && spawn != null then bind key { action = focus-or-spawn-action selector name spawn; } else null) cfg.scratchspaces) | 1008 | (map ({ name, selector, spawn, key, ...}: if key != null && selector != null && spawn != null then bind key { action = focus-or-spawn-action selector name spawn; } else null) cfg.scratchspaces) |
1009 | (map ({ name, moveKey, ...}: if moveKey != null then bind moveKey { action = kdl.magic-leaf "move-column-to-workspace" name; } else null) cfg.scratchspaces) | ||
933 | ] | 1010 | ] |
934 | )) | 1011 | )) |
935 | ]; | 1012 | ]; |