summaryrefslogtreecommitdiff
path: root/.config/niri
diff options
context:
space:
mode:
Diffstat (limited to '.config/niri')
-rwxr-xr-x.config/niri/apply-colors.sh84
-rw-r--r--.config/niri/config.kdl321
-rwxr-xr-x.config/niri/set-backdrop.sh29
-rwxr-xr-x.config/niri/theme-switcher.sh135
4 files changed, 569 insertions, 0 deletions
diff --git a/.config/niri/apply-colors.sh b/.config/niri/apply-colors.sh
new file mode 100755
index 0000000..505578c
--- /dev/null
+++ b/.config/niri/apply-colors.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+# Apply a wallpaper and generate colors with wallust (16-color palette) + matugen (Material You / M3).
+# Usage: apply-colors.sh <image> [light|dark]
+# Called by theme-switcher.sh and the waybar random-wallpaper click.
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "$(realpath "$0")")" && pwd)"
+IMG="${1:-}"
+MODE="${2:-auto}"
+LOG="${THEME_LOG:-/tmp/theme-switcher.log}"
+
+log() {
+ printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >>"$LOG"
+}
+
+# Record the exact failing command + line on any error.
+trap 'log "apply-colors FAILED (exit $?) in ${BASH_SOURCE[0]}:$LINENO: $BASH_COMMAND"' ERR
+
+if [ -z "$IMG" ] || [ ! -f "$IMG" ]; then
+ echo "usage: $0 <image> [light|dark]" >&2
+ exit 1
+fi
+
+# wait for the awww daemon to be ready (it is spawned next to this script at login)
+log "awww img $IMG"
+for _ in $(seq 1 10); do
+ if awww query >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+done
+
+# set the wallpaper FIRST and unconditionally — this is the critical, must-work
+# step. Color generation below is best-effort: a failure there must never block
+# the wallpaper from changing (that coupling is what froze the wallpaper before).
+awww img "$IMG" || { log "awww img FAILED ($IMG)"; exit 1; }
+
+# blurred copy for the Overview backdrop (sibling or on-the-fly generation)
+"$SCRIPT_DIR/set-backdrop.sh" "$IMG" || log "set-backdrop FAILED ($IMG)"
+
+# wallust: classic 16-color palette (foot, btop, ...)
+# fastresize (the config default) is flaky on some images — always use resized.
+# Best-effort: a wallust failure must not prevent the wallpaper from sticking.
+log "wallust palette=$MODE $IMG"
+case "$MODE" in
+light|dark) WALLUST_PALETTE=("--palette" "$MODE") ;;
+*) WALLUST_PALETTE=() ;;
+esac
+# wallust's `resized` backend is intermittently flaky on some images; retry a
+# few times, but ultimately tolerate failure.
+ok=0
+for attempt in 1 2 3; do
+ if wallust run -b resized "${WALLUST_PALETTE[@]}" "$IMG"; then
+ ok=1
+ break
+ fi
+ log "wallust attempt $attempt FAILED ($IMG, mode=$MODE)"
+ [ "$attempt" -lt 3 ] && sleep 2
+done
+if [ "$ok" -ne 1 ]; then
+ log "wallust FAILED after 3 attempts ($IMG, mode=$MODE) — continuing without wallust colors"
+else
+ # foot needs bare RRGGBB, not #RRGGBB — strip the leading '#'
+ sed -i 's/#\([0-9a-fA-F]\)/\1/g' ~/.cache/wallust/foot-theme.ini 2>/dev/null || true
+fi
+
+# matugen: Material You / M3 colors (niri focus ring, ...)
+# --prefer is required for non-interactive runs (multiple source colors).
+# Best-effort: a matugen failure (e.g. bad config after an upgrade) must not
+# block the wallpaper.
+log "matugen mode=$MODE $IMG"
+case "$MODE" in
+light) matugen image "$IMG" -m "light" --prefer saturation ;;
+dark) matugen image "$IMG" -m "dark" --prefer saturation ;;
+*) matugen image "$IMG" --prefer saturation ;;
+esac || log "matugen FAILED ($IMG, mode=$MODE) — continuing without matugen colors"
+
+# reload consumers
+killall -SIGUSR2 waybar 2>/dev/null || true
+killall -USR1 foot 2>/dev/null || true
+niri msg action load-config-file 2>/dev/null || true
+
+log "apply-colors OK ($IMG, $MODE)"
diff --git a/.config/niri/config.kdl b/.config/niri/config.kdl
new file mode 100644
index 0000000..9d7db14
--- /dev/null
+++ b/.config/niri/config.kdl
@@ -0,0 +1,321 @@
+include optional=true "/home/seraphim/.cache/matugen/theme.kdl"
+spawn-at-startup "mako"
+spawn-at-startup "xrdb" "-merge" "/home/seraphim/.Xresources"
+spawn-at-startup "vicinae" "server"
+spawn-at-startup "gentoo-pipewire-launcher"
+spawn-at-startup "telegram-desktop" "-autostart" "--minimized"
+spawn-at-startup "keepassxc" "--minimized"
+spawn-at-startup "awww-daemon"
+spawn-at-startup "awww-daemon" "--namespace" "backdrop"
+spawn-at-startup "/usr/libexec/hyprpolkitagent"
+spawn-at-startup "dbus-update-activation-environment" "WAYLAND_DISPLAY" "DISPLAY" "XDG_CURRENT_DESKTOP"
+spawn-at-startup "darkman" "run"
+spawn-at-startup "/home/seraphim/dotfiles-gentoo/niri/.config/niri/theme-switcher.sh" "night"
+spawn-at-startup "sh" "-c" "NO_AT_BRIDGE=1 waybar"
+spawn-at-startup "/usr/bin/Throne"
+spawn-at-startup "mpd"
+prefer-no-csd
+screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
+
+environment {
+ OZONE_PLATFORM "wayland"
+ ELECTRON_OZONE_PLATFORM_HINT "auto"
+ XDG_CURRENT_DESKTOP "niri"
+}
+blur {
+ passes 4
+ offset 5.0
+ noise 0.02
+ saturation 1.1
+}
+
+// awww-daemon --namespace backdrop: pre-blurred wallpaper shown in the
+// Overview backdrop. niri cannot blur a backdrop surface itself.
+layer-rule {
+ match namespace="^awww-daemonbackdrop$"
+ place-within-backdrop true
+}
+input {
+ focus-follows-mouse max-scroll-amount="100%"
+
+ keyboard {
+ xkb {
+ layout "us,ru"
+ options "grp:lalt_lshift_toggle,compose:ralt,ctrl:nocaps"
+ }
+ repeat-delay 300
+ repeat-rate 60
+ numlock
+ }
+
+ mouse {
+ accel-speed -0.8
+ accel-profile "flat"
+ }
+}
+
+output "DP-2" {
+ mode "2560x1440"
+ scale 1.5
+ position x=0 y=0
+}
+
+output "HDMI-A-1" {
+ mode "1920x1080@71.910"
+ scale 1
+}
+
+layout {
+ gaps 0.5
+ center-focused-column "never"
+
+ preset-column-widths {
+ proportion 0.33333
+ proportion 0.5
+ proportion 0.66667
+ }
+
+ default-column-width { proportion 0.5; }
+
+ focus-ring {
+ width 2
+ }
+
+ border {
+ off //width 0.5
+ //active-color "#ffc87f"
+ //inactive-color "#505050"
+ //urgent-color "#9b0000"
+ }
+
+ shadow {
+ off
+ //softness 30
+ //spread 5
+ //offset x=0 y=5
+ //color "#0007"
+ }
+}
+
+animations {
+ workspace-switch {
+ duration-ms 275
+ curve "ease-out-cubic"
+ }
+ horizontal-view-movement {
+ spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
+ }
+ window-movement {
+ spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
+ }
+// window-open {
+// duration-ms 150
+// curve "ease-out-expo"
+// }
+// window-close {
+// duration-ms 150
+// curve "ease-out-quad"
+// }
+ window-resize {
+ spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
+ }
+ overview-open-close {
+ duration-ms 150
+ curve "ease-out-quad"
+ }
+}
+
+window-rule {
+ match app-id=r#"^org\.wezfurlong\.wezterm$"#
+ geometry-corner-radius 12
+ clip-to-geometry true
+ background-effect {
+ xray false
+ }
+}
+
+// Helium PiP fix
+window-rule {
+ match app-id=r#"helium$"# title="^Picture-in-Picture$"
+ open-floating true
+ geometry-corner-radius 9000
+ clip-to-geometry true
+ shadow {
+ off
+ }
+}
+
+// Steam notifs fix
+window-rule {
+ match app-id="steam" title=r#"^notificationtoasts_\d+_desktop$"#
+ open-floating true
+ open-focused false
+ default-floating-position x=16 y=16 relative-to="bottom-right"
+}
+
+gestures {
+ hot-corners {
+ off
+ }
+}
+
+cursor {
+ xcursor-theme "Bibata-Modern-Classic"
+ xcursor-size 15
+}
+
+overview {
+ zoom 0.5
+ workspace-shadow {
+ off
+ //softness 15
+ //spread 3
+ //offset x=0 y=6
+ //color "#00000080"
+ }
+}
+debug {
+ honor-xdg-activation-with-invalid-serial
+}
+binds {
+ // Application Launchers
+ Mod+Shift+T { spawn "telegram-desktop"; }
+ Mod+Shift+B { spawn "/opt/helium/helium" "--enable-features=UseOzonePlatform" "--ozone-platform=wayland"; }
+ Mod+D { spawn "vicinae" "toggle"; }
+ Mod+Ctrl+V { spawn "vicinae" "deeplink" "vicinae://launch/clipboard/history"; }
+ Mod+T hotkey-overlay-title="File Manager" { spawn "foot" "-e" "yazi"; }
+ Mod+Alt+R { spawn "foot" "-e" "rmpc"; }
+ Mod+S hotkey-overlay-title="Terminal" { spawn "foot"; }
+ Super+Alt+L hotkey-overlay-title="Lock Screen" { spawn "swaylock"; }
+
+ // Audio & Media Controls
+ XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+ -l 1.0"; }
+ XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; }
+ XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; }
+ XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; }
+
+ XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }
+ XF86AudioStop allow-when-locked=true { spawn-sh "playerctl stop"; }
+ XF86AudioPrev allow-when-locked=true { spawn-sh "playerctl previous"; }
+ XF86AudioNext allow-when-locked=true { spawn-sh "playerctl next"; }
+
+ // universal clipboard hotkeys (super + c / v / x)
+ mod+c { spawn-sh "sleep 0.001 && wtype -M ctrl -k insert -m ctrl"; }
+ mod+v { spawn-sh "sleep 0.001 && wtype -M shift -k insert -m shift"; }
+ mod+x { spawn-sh "sleep 0.001 && wtype -M shift -k delete -m shift"; }
+
+ // Window Management & Views
+ Mod+Tab repeat=false { toggle-overview; }
+ Mod+Grave repeat=false { toggle-overview; }
+ Mod+W repeat=false { close-window; }
+ Mod+F { maximize-column; }
+ Mod+Shift+F { fullscreen-window; }
+ Mod+Ctrl+F { maximize-window-to-edges; }
+ //Mod+Ctrl+F { expand-column-to-available-width; }
+ Mod+Ctrl+C { center-visible-columns; }
+ Mod+Shift+V { toggle-window-floating; }
+ Mod+Q { toggle-column-tabbed-display; }
+
+ // Focus Navigation
+ Mod+Left { focus-column-left; }
+ Mod+Down { focus-window-down; }
+ Mod+Up { focus-window-up; }
+ Mod+Right { focus-column-right; }
+ Mod+H { focus-column-left; }
+ Mod+J { focus-window-down; }
+ Mod+K { focus-window-up; }
+ Mod+L { focus-column-right; }
+ Mod+Shift+WheelScrollUp { focus-monitor-left; }
+ Mod+Shift+WheelScrollDown { focus-monitor-right; }
+
+ // Window Movement
+ Mod+Ctrl+Left { move-column-left; }
+ Mod+Ctrl+Down { move-window-down; }
+ Mod+Ctrl+Up { move-window-up; }
+ Mod+Ctrl+Right { move-column-right; }
+ Mod+Ctrl+H { move-column-left; }
+ Mod+Ctrl+J { move-window-down; }
+ Mod+Ctrl+K { move-window-up; }
+ Mod+Ctrl+L { move-column-right; }
+
+ Mod+Home { focus-column-first; }
+ Mod+End { focus-column-last; }
+ Mod+Ctrl+Home { move-column-to-first; }
+ Mod+Ctrl+End { move-column-to-last; }
+
+ // Monitor Focus & Movement
+ Mod+Shift+1 { focus-monitor-left; }
+ Mod+Shift+2 { focus-monitor-right; }
+ Mod+Shift+Left { focus-monitor-left; }
+ Mod+Shift+Down { focus-monitor-down; }
+ Mod+Shift+Up { focus-monitor-up; }
+ Mod+Shift+Right { focus-monitor-right; }
+ Mod+Shift+H { focus-monitor-left; }
+ Mod+Shift+J { focus-monitor-down; }
+ Mod+Shift+K { focus-monitor-up; }
+ Mod+Shift+L { focus-monitor-right; }
+
+ Mod+Shift+Ctrl+1 { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+2 { move-column-to-monitor-right; }
+ Mod+Shift+Ctrl+Left { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+Down { move-column-to-monitor-down; }
+ Mod+Shift+Ctrl+Up { move-column-to-monitor-up; }
+ Mod+Shift+Ctrl+Right { move-column-to-monitor-right; }
+ Mod+Shift+Ctrl+H { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+J { move-column-to-monitor-down; }
+ Mod+Shift+Ctrl+K { move-column-to-monitor-up; }
+ Mod+Shift+Ctrl+L { move-column-to-monitor-right; }
+
+ // Workspace Navigation
+ Mod+Shift+Page_Down { move-workspace-down; }
+ Mod+Shift+Page_Up { move-workspace-up; }
+ Mod+Shift+U { move-workspace-down; }
+ Mod+Shift+I { move-workspace-up; }
+
+ // Direct Workspace Switching (1-9)
+ Mod+1 { focus-workspace 1; }
+ Mod+2 { focus-workspace 2; }
+ Mod+3 { focus-workspace 3; }
+ Mod+4 { focus-workspace 4; }
+ Mod+5 { focus-workspace 5; }
+ Mod+6 { focus-workspace 6; }
+ Mod+7 { focus-workspace 7; }
+ Mod+8 { focus-workspace 8; }
+ Mod+9 { focus-workspace 9; }
+
+ Mod+Ctrl+1 { move-column-to-workspace 1; }
+ Mod+Ctrl+2 { move-column-to-workspace 2; }
+ Mod+Ctrl+3 { move-column-to-workspace 3; }
+ Mod+Ctrl+4 { move-column-to-workspace 4; }
+ Mod+Ctrl+5 { move-column-to-workspace 5; }
+ Mod+Ctrl+6 { move-column-to-workspace 6; }
+ Mod+Ctrl+7 { move-column-to-workspace 7; }
+ Mod+Ctrl+8 { move-column-to-workspace 8; }
+ Mod+Ctrl+9 { move-column-to-workspace 9; }
+
+ // Column & Window Sizing
+ Mod+BracketLeft { consume-or-expel-window-left; }
+ Mod+BracketRight { consume-or-expel-window-right; }
+
+ Mod+R { switch-preset-column-width; }
+ Mod+Shift+R { switch-preset-column-width-back; }
+ Mod+Ctrl+Shift+R { switch-preset-window-height; }
+ Mod+Ctrl+R { reset-window-height; }
+
+ Mod+Minus { set-column-width "-10%"; }
+ Mod+Equal { set-column-width "+10%"; }
+ Mod+Shift+Minus { set-window-height "-10%"; }
+ Mod+Shift+Equal { set-window-height "+10%"; }
+
+ // Mouse Wheel Bindings
+ Mod+WheelScrollUp { focus-column-left; }
+ Mod+WheelScrollDown { focus-column-right; }
+
+ // Screenshots
+ Print { screenshot; }
+ Ctrl+Print { screenshot-screen; }
+ Alt+Print { screenshot-window; }
+
+ // System Control
+ Mod+Shift+E { quit; }
+}
diff --git a/.config/niri/set-backdrop.sh b/.config/niri/set-backdrop.sh
new file mode 100755
index 0000000..efd02b3
--- /dev/null
+++ b/.config/niri/set-backdrop.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# Push a blurred copy of a wallpaper to the awww-daemon backdrop namespace.
+# Prefers a pre-made <name>-blur.<ext> sibling; otherwise generates one into the cache.
+# Used by theme-switcher.sh and apply-colors.sh for the niri Overview backdrop.
+
+set -euo pipefail
+
+IMG="${1:-}"
+if [ -z "$IMG" ] || [ ! -f "$IMG" ]; then
+ echo "usage: $0 <image>" >&2
+ exit 1
+fi
+
+EXT="${IMG##*.}"
+SIBLING="${IMG%.*}-blur.${EXT}"
+if [ -f "$SIBLING" ]; then
+ BLURRED="$SIBLING"
+else
+ CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/niri-backdrop"
+ mkdir -p "$CACHE_DIR"
+ BASE=$(basename "${IMG%.*}")
+ BLURRED="$CACHE_DIR/${BASE}-blur.jpg"
+ if [ ! -f "$BLURRED" ] || [ "$IMG" -nt "$BLURRED" ]; then
+ magick "$IMG" -blur 0x16 -quality 90 "$BLURRED"
+ fi
+fi
+
+awww img "$BLURRED" -n backdrop
+echo "$BLURRED" >/tmp/current_backdrop_state \ No newline at end of file
diff --git a/.config/niri/theme-switcher.sh b/.config/niri/theme-switcher.sh
new file mode 100755
index 0000000..6d1f548
--- /dev/null
+++ b/.config/niri/theme-switcher.sh
@@ -0,0 +1,135 @@
+#!/bin/bash
+
+# Day/night theme switcher + wallpaper/color applier.
+# Two wallpapers: day.jpg (9:00-18:00) and night.jpg (18:00-9:00).
+#
+# Usage:
+# ./theme-switcher.sh one-shot: apply based on current time, then exit
+# ./theme-switcher.sh day|light force light theme, then exit
+# ./theme-switcher.sh night|dark force dark theme, then exit
+# ./theme-switcher.sh --daemon continuous time-based loop (used at login)
+
+WALLPAPERS="$HOME/Pictures/wallpapers"
+STATE_FILE="/tmp/current_theme_state"
+WALLPAPER_STATE_FILE="/tmp/current_wallpaper_state"
+BACKDROP_STATE_FILE="/tmp/current_backdrop_state"
+PID_FILE="/tmp/theme-switcher.daemon.pid"
+LOG="/tmp/theme-switcher.log"
+SCRIPT_DIR="$(cd "$(dirname "$(realpath "$0")")" && pwd)"
+SET_BACKDROP="$SCRIPT_DIR/set-backdrop.sh"
+
+log() {
+ printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >>"$LOG"
+}
+
+# Resolve TARGET_STATE / MODE / WALLPAPER. Optional $1 forces day|night.
+resolve_target() {
+ local force="${1:-}"
+ if [ "$force" = "day" ] || [ "$force" = "light" ]; then
+ TARGET_STATE="light"
+ MODE="light"
+ WALLPAPER="$WALLPAPERS/day.jpg"
+ elif [ "$force" = "night" ] || [ "$force" = "dark" ]; then
+ TARGET_STATE="dark"
+ MODE="dark"
+ WALLPAPER="$WALLPAPERS/night.jpg"
+ else
+ local HOUR
+ HOUR=$(date +%H)
+ HOUR=$((10#$HOUR))
+ if [ "$HOUR" -ge 9 ] && [ "$HOUR" -lt 18 ]; then
+ TARGET_STATE="light"
+ MODE="light"
+ WALLPAPER="$WALLPAPERS/day.jpg"
+ else
+ TARGET_STATE="dark"
+ MODE="dark"
+ WALLPAPER="$WALLPAPERS/night.jpg"
+ fi
+ fi
+}
+
+# Apply the resolved target once. Returns 0 on success.
+apply_target() {
+ if [ ! -f "$WALLPAPER" ]; then
+ log "wallpaper missing: $WALLPAPER"
+ return 1
+ fi
+
+ local CURRENT_THEME CURRENT_WALLPAPER EXPECTED_BACKDROP ACTUAL_BACKDROP
+
+ CURRENT_THEME=$(cat "$STATE_FILE" 2>/dev/null || true)
+ # Already in the correct theme: don't re-run wallust/matugen every loop tick.
+ # Still self-heal a drifted backdrop below, then bail out.
+ if [ "$CURRENT_THEME" = "$TARGET_STATE" ]; then
+ EXPECTED_BACKDROP=$(cat "$BACKDROP_STATE_FILE" 2>/dev/null || true)
+ ACTUAL_BACKDROP=$(awww query -n backdrop -j 2>/dev/null | jq -r '.["backdrop"][0].displaying.image // empty')
+ if [ -n "$EXPECTED_BACKDROP" ] && [ "$ACTUAL_BACKDROP" != "$EXPECTED_BACKDROP" ]; then
+ "$SET_BACKDROP" "$WALLPAPER"
+ fi
+ return 0
+ fi
+ CURRENT_WALLPAPER=$(cat "$WALLPAPER_STATE_FILE" 2>/dev/null || true)
+
+ # Self-heal the Overview backdrop if it drifted from the expected image.
+ EXPECTED_BACKDROP=$(cat "$BACKDROP_STATE_FILE" 2>/dev/null || true)
+ ACTUAL_BACKDROP=$(awww query -n backdrop -j 2>/dev/null | jq -r '.["backdrop"][0].displaying.image // empty')
+ if [ -n "$EXPECTED_BACKDROP" ] && [ "$ACTUAL_BACKDROP" != "$EXPECTED_BACKDROP" ]; then
+ "$SET_BACKDROP" "$WALLPAPER"
+ fi
+
+ log "switching to $TARGET_STATE ($WALLPAPER)"
+ if sh "$SCRIPT_DIR/apply-colors.sh" "$WALLPAPER" "$MODE"; then
+ if [ "$CURRENT_THEME" != "$TARGET_STATE" ]; then
+ darkman set "$TARGET_STATE"
+ fi
+
+ ln -sf \
+ "theme-${TARGET_STATE}.css" \
+ "$HOME/dotfiles-gentoo/waybar/.config/waybar/theme.css"
+
+ ln -sf \
+ "settings-${TARGET_STATE}.ini" \
+ "$HOME/dotfiles-gentoo/gtk/.config/gtk-3.0/settings.ini"
+
+ echo "$TARGET_STATE" >"$STATE_FILE"
+ echo "$WALLPAPER" >"$WALLPAPER_STATE_FILE"
+ log "switched to $TARGET_STATE ($WALLPAPER)"
+ return 0
+ else
+ log "FAILED to apply $TARGET_STATE ($WALLPAPER)"
+ return 1
+ fi
+}
+
+daemon_loop() {
+ # Refuse to run a second daemon instance (e.g. manual run while one is alive).
+ if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE" 2>/dev/null)" 2>/dev/null; then
+ log "daemon already running (pid $(cat "$PID_FILE")), exiting"
+ exit 0
+ fi
+ echo $$ >"$PID_FILE"
+
+ while true; do
+ resolve_target
+ apply_target || true # failure is retried on the next loop, state is left untouched
+ sleep 60
+ done
+}
+
+case "${1:-}" in
+--daemon | -d) daemon_loop ;;
+"" | day | light | night | dark)
+ resolve_target "${1:-}"
+ apply_target
+ exit $?
+ ;;
+-h | --help)
+ echo "usage: $0 [day|night|--daemon]" >&2
+ exit 0
+ ;;
+*)
+ echo "usage: $0 [day|night|--daemon]" >&2
+ exit 1
+ ;;
+esac