aboutsummaryrefslogtreecommitdiffstats
path: root/config/hypr/scripts/ToggleWaybarTime.sh
blob: 09ae94332ef8f0bbd4a5351df3ac14b4018619a7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/usr/bin/env bash
# ==================================================
#  KoolDots (2026)
#  Project URL: https://github.com/LinuxBeginnings
#  License: GNU GPLv3
#  SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
# Toggle Waybar clock format between 12H and 24H

WAYBAR_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/waybar"

# Files that hold toggleable clock formats
MODULES_FILES=(
  "$WAYBAR_DIR/Modules"         # clock, clock#2, clock#3, clock#4, clock#5
  "$WAYBAR_DIR/ModulesVertical" # clock#vertical
)

# Nerd Font clock glyph (U+F017) used by the "clock" and "clock#2" formats.
# Spelled out as a codepoint on purpose: a literal glyph here is easy to
# replace with a look-alike from a different Private Use range, which would
# make the patterns below stop matching without any visible difference.
CLOCK_GLYPH=$'\uf017'
# Nerd Font calendar glyph (U+F073), used by the clock#vertical formats
CAL_GLYPH=$'\uf073'

# Clock format pairs. FORMATS_12H[n] and FORMATS_24H[n] belong to the same
# module: toggling comments out the one and uncomments the other.
#
# The strings must match the "format" values in MODULES_FILES *verbatim*,
# including the {:L...} locale prefix and every space. A format that is not
# listed here, or listed with a typo, is silently left on whatever it is
# currently set to - so keep this list in sync when adding or editing a clock
# module.
FORMATS_12H=(
  "$CLOCK_GLYPH {:%I:%M %p}"           # clock
  "$CLOCK_GLYPH {:%I:%M %p}"           # clock#2
  '{:L%I:%M %p - %d/%b}'               # clock#3
  '{:L%B | %a %d, %Y | %I:%M %p}'      # clock#4
  '{:%A, %I:%M %P}'                    # clock#5
  "$CLOCK_GLYPH\n{:%I\n%M\n%p\n\n$CAL_GLYPH \n%d\n%m\n%y}"   # clock#vertical
)

FORMATS_24H=(
  "$CLOCK_GLYPH {:%H:%M:%S}"           # clock
  "$CLOCK_GLYPH  {:%H:%M}"             # clock#2
  '{:L%H:%M - %d/%b}'                  # clock#3
  '{:L%B | %a %d, %Y | %H:%M}'         # clock#4
  '{:%a %d | %H:%M}'                   # clock#5
  "$CLOCK_GLYPH\n{:%H\n%M\n%S\n\n$CAL_GLYPH \n%d\n%m\n%y}"   # clock#vertical
)

notify_swaync() {
  command -v notify-send >/dev/null 2>&1 || return 0
  export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
  local icon="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/note.png"
  if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
    local bus_path="${XDG_RUNTIME_DIR}/bus"
    if [ -S "$bus_path" ]; then
      export DBUS_SESSION_BUS_ADDRESS="unix:path=$bus_path"
    fi
  fi
  DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR" \
    notify-send -a "Waybar Time" -u low -t 2000 -i "$icon" "$@" >/dev/null 2>&1 || true
}

# Only work on the files that are actually present
FILES=()
for f in "${MODULES_FILES[@]}"; do
  [ -f "$f" ] && FILES+=("$f")
done

if [ "${#FILES[@]}" -eq 0 ]; then
  notify_swaync "No Waybar modules file found in: $WAYBAR_DIR"
  exit 1
fi

# Escape the characters that are special inside a sed BRE, plus the '#' we use
# as the s/// delimiter. Needed because the formats contain '.', '*' and the
# literal backslashes of clock#vertical.
escape_bre() {
  printf '%s' "$1" | sed 's/[][\\.*^$#]/\\&/g'
}

# Comment out / re-enable the "format" line carrying the given format string
comment_out() {
  local file="$1" esc
  esc=$(escape_bre "$2")
  sed -i "s#^\([[:space:]]*\)\(\"format\":[[:space:]]*\"${esc}\".*\)#\1//\2#" "$file"
}

uncomment() {
  local file="$1" esc
  esc=$(escape_bre "$2")
  sed -i "s#^\([[:space:]]*\)//[[:space:]]*\(\"format\":[[:space:]]*\"${esc}\".*\)#\1\2#" "$file"
}

# $1: 12h | 24h
apply_format() {
  local target="$1" file i
  for file in "${FILES[@]}"; do
    for i in "${!FORMATS_12H[@]}"; do
      if [ "$target" = "24h" ]; then
        comment_out "$file" "${FORMATS_12H[$i]}"
        uncomment "$file" "${FORMATS_24H[$i]}"
      else
        comment_out "$file" "${FORMATS_24H[$i]}"
        uncomment "$file" "${FORMATS_12H[$i]}"
      fi
    done
  done
}

# True when any clock module is currently on a 12H format. %I is the 12-hour
# hour and appears in every 12H format; the anchor skips commented lines.
is_12h_active() {
  grep -qE '^[[:space:]]*"format":.*%I' "${FILES[@]}"
}

snapshot() {
  cat "${FILES[@]}" | cksum
}

# Report formats that are not present in any modules file at all. Catches the
# case where a format above drifts away from the modules files, which would
# otherwise leave that one clock module silently stuck on its old setting.
warn_unknown_formats() {
  local i missing=0
  for i in "${!FORMATS_12H[@]}"; do
    grep -qF "\"${FORMATS_12H[$i]}\"" "${FILES[@]}" ||
      { printf 'Waybar Time: 12H format not found in any modules file: %s\n' "${FORMATS_12H[$i]}" >&2; missing=1; }
    grep -qF "\"${FORMATS_24H[$i]}\"" "${FILES[@]}" ||
      { printf 'Waybar Time: 24H format not found in any modules file: %s\n' "${FORMATS_24H[$i]}" >&2; missing=1; }
  done
  return $missing
}

restart_waybar() {
  local manage_with_systemd=0

  if command -v systemctl >/dev/null 2>&1; then
    if systemctl --user --quiet is-active graphical-session.target 2>/dev/null || systemctl --user --quiet is-active wayland-session@*.target 2>/dev/null; then
      if systemctl --user --quiet is-active waybar.service 2>/dev/null || systemctl --user --quiet is-enabled waybar.service 2>/dev/null; then
        manage_with_systemd=1
      fi
    fi
  fi

  if [ "$manage_with_systemd" -eq 1 ]; then
    systemctl --user stop waybar.service >/dev/null 2>&1 || true
  fi

  pkill -INT -x waybar >/dev/null 2>&1 || true
  pkill -INT -x '.waybar-wrapped' >/dev/null 2>&1 || true
  sleep 0.2
  if pgrep -x waybar >/dev/null 2>&1 || pgrep -x '.waybar-wrapped' >/dev/null 2>&1; then
    pkill -9 -x waybar >/dev/null 2>&1 || true
    pkill -9 -x '.waybar-wrapped' >/dev/null 2>&1 || true
  fi
  sleep 0.2

  if [ "$manage_with_systemd" -eq 1 ]; then
    if ! systemctl --user start waybar.service >/dev/null 2>&1; then
      waybar >/dev/null 2>&1 &
    fi
  else
    waybar >/dev/null 2>&1 &
  fi
}

warn_unknown_formats || true

before=$(snapshot)

if is_12h_active; then
  apply_format 24h
  mode="24H"
else
  apply_format 12h
  mode="12H"
fi

# Nothing replaced means the formats above drifted away from the modules files
if [ "$before" = "$(snapshot)" ]; then
  notify_swaync "Clock format unchanged - no known format matched"
  printf 'Waybar Time: no clock format matched, nothing changed\n' >&2
  exit 1
fi

restart_waybar
sleep 0.3

notify_swaync "Switched to ${mode} format"
printf 'Waybar Time: switched to %s format\n' "$mode"
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage