detached f8cdfba

feat(examples): color the focused window's dot, drop the repeated workspace number and the clock icon

commit
f8cdfbac1b6100c95cc36e9baadd841b9e5904a3
author
brice · · 2026-10-05 17:29 UTC
parent
4bf13d9
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +23 -13
M examples/bundle/left.sh +21 -10
@@ -1,7 +1,8 @@
11 #!/bin/bash
22 # Left: the active workspace as an accent block that fades into the bar, then
3-# the other workspaces with one dot per window. On NeferWL it also shows the
4-# stash. Without NeferWL's state file it shows nothing.
3+# the workspaces with one dot per window. The active workspace shows only its
4+# dots, and the dot of the focused window is in the accent color. On NeferWL it
5+# also shows the stash. Without NeferWL's state file it shows nothing.
56 . "$(dirname "$0")/lib.sh"
67
78 DOT=$ICON_DOT STASH=$ICON_STASH
@@ -12,16 +13,19 @@ DOT=$ICON_DOT STASH=$ICON_STASH
1213
1314 draw() {
1415 # First line: "<active> <count>" of the focused output. Then one line per
15- # workspace: "<n> <windows> <stashed>".
16- local data active count n w s line pips
16+ # workspace: "<n> <windows> <stashed> <focused>", where <focused> is the
17+ # position (from 1) of the focused window among the workspace's windows, or 0.
18+ local data active count n w s f line pips i color
1719 data=$(jq -r '
1820 .output as $o
1921 | (.outputs[] | select(.name == $o)) as $out
2022 | [.windows[] | select(.output == $o)] as $ws
23+ | (if .window.output == $o then .window.id else null end) as $focus
2124 | "\($out.active) \($out.count)",
2225 (range(1; $out.count + 1) as $n
2326 | [$ws[] | select(.workspace == $n)] as $here
24- | "\($n) \($here | length) \([$here[] | select(.stash_count > 0)] | length)")' \
27+ | (if $focus == null then null else ($here | map(.id) | index($focus)) end) as $at
28+ | "\($n) \($here | length) \([$here[] | select(.stash_count > 0)] | length) \(if $at == null then 0 else $at + 1 end)")' \
2529 "$NEFERWL_STATE" 2>/dev/null) || return
2630 read -r active count <<<"$(head -1 <<<"$data")"
2731 # The state file is data, not code: bash arithmetic runs command
@@ -29,16 +33,23 @@ draw() {
2933 [[ $active =~ ^[0-9]+$ && $count =~ ^[0-9]+$ ]] || return
3034
3135 line="$(bg "$ACCENT")$(fg "$(ink "$ACCENT")")$BOLD $active $RESET$(fade "$ACCENT" "$BAR")$(bg "$BAR")"
32- while read -r n w s; do
33- [[ $n =~ ^[0-9]+$ && $w =~ ^[0-9]+$ && $s =~ ^[0-9]+$ ]] || continue
36+ while read -r n w s f; do
37+ [[ $n =~ ^[0-9]+$ && $w =~ ^[0-9]+$ && $s =~ ^[0-9]+$ && $f =~ ^[0-9]+$ ]] || continue
38+ # At most 4 dots; a focused window past the 4th is shown on the 4th.
3439 pips=""
35- ((w > 0)) && printf -v pips "$DOT%.0s" $(seq 1 $((w > 4 ? 4 : w)))
40+ for ((i = 1; i <= (w > 4 ? 4 : w); i++)); do
41+ color=$DIM
42+ ((n == active)) && color=$NEFERBAR_FOREGROUND
43+ ((i == (f > 4 ? 4 : f))) && color=$ACCENT
44+ pips+="$(fg "$color")$DOT"
45+ done
3646 if ((n == active)); then
37- line+="$(fg "$NEFERBAR_FOREGROUND") $n $(fg "$ACCENT")$pips"
47+ # The number is already in the accent block on the left.
48+ line+=" $pips"
3849 ((s > 0)) && line+="$(fg "$NEFERBAR_COLOR2") $STASH$s"
3950 line+=" "
4051 elif ((w > 0)); then
41- line+="$(fg "$NEFERBAR_FOREGROUND") $n $(fg "$DIM")$pips "
52+ line+="$(fg "$NEFERBAR_FOREGROUND") $n $pips "
4253 else
4354 line+="$(fg "$DIM") $n "
4455 fi
@@ -1,7 +1,8 @@
1 #!/bin/bash1 #!/bin/bash
2 # Left: the active workspace as an accent block that fades into the bar, then2 # Left: the active workspace as an accent block that fades into the bar, then
3-# the other workspaces with one dot per window. On NeferWL it also shows the3+# the workspaces with one dot per window. The active workspace shows only its
4-# stash. Without NeferWL's state file it shows nothing.4+# dots, and the dot of the focused window is in the accent color. On NeferWL it
5+# also shows the stash. Without NeferWL's state file it shows nothing.
5 . "$(dirname "$0")/lib.sh"6 . "$(dirname "$0")/lib.sh"
6 7
7 DOT=$ICON_DOT STASH=$ICON_STASH8 DOT=$ICON_DOT STASH=$ICON_STASH
@@ -12,16 +13,19 @@ DOT=$ICON_DOT STASH=$ICON_STASH
12 13
13 draw() {14 draw() {
14 # First line: "<active> <count>" of the focused output. Then one line per15 # First line: "<active> <count>" of the focused output. Then one line per
15- # workspace: "<n> <windows> <stashed>".16+ # workspace: "<n> <windows> <stashed> <focused>", where <focused> is the
16- local data active count n w s line pips17+ # position (from 1) of the focused window among the workspace's windows, or 0.
18+ local data active count n w s f line pips i color
17 data=$(jq -r '19 data=$(jq -r '
18 .output as $o20 .output as $o
19 | (.outputs[] | select(.name == $o)) as $out21 | (.outputs[] | select(.name == $o)) as $out
20 | [.windows[] | select(.output == $o)] as $ws22 | [.windows[] | select(.output == $o)] as $ws
23+ | (if .window.output == $o then .window.id else null end) as $focus
21 | "\($out.active) \($out.count)",24 | "\($out.active) \($out.count)",
22 (range(1; $out.count + 1) as $n25 (range(1; $out.count + 1) as $n
23 | [$ws[] | select(.workspace == $n)] as $here26 | [$ws[] | select(.workspace == $n)] as $here
24- | "\($n) \($here | length) \([$here[] | select(.stash_count > 0)] | length)")' \27+ | (if $focus == null then null else ($here | map(.id) | index($focus)) end) as $at
28+ | "\($n) \($here | length) \([$here[] | select(.stash_count > 0)] | length) \(if $at == null then 0 else $at + 1 end)")' \
25 "$NEFERWL_STATE" 2>/dev/null) || return29 "$NEFERWL_STATE" 2>/dev/null) || return
26 read -r active count <<<"$(head -1 <<<"$data")"30 read -r active count <<<"$(head -1 <<<"$data")"
27 # The state file is data, not code: bash arithmetic runs command31 # The state file is data, not code: bash arithmetic runs command
@@ -29,16 +33,23 @@ draw() {
29 [[ $active =~ ^[0-9]+$ && $count =~ ^[0-9]+$ ]] || return33 [[ $active =~ ^[0-9]+$ && $count =~ ^[0-9]+$ ]] || return
30 34
31 line="$(bg "$ACCENT")$(fg "$(ink "$ACCENT")")$BOLD $active $RESET$(fade "$ACCENT" "$BAR")$(bg "$BAR")"35 line="$(bg "$ACCENT")$(fg "$(ink "$ACCENT")")$BOLD $active $RESET$(fade "$ACCENT" "$BAR")$(bg "$BAR")"
32- while read -r n w s; do36+ while read -r n w s f; do
33- [[ $n =~ ^[0-9]+$ && $w =~ ^[0-9]+$ && $s =~ ^[0-9]+$ ]] || continue37+ [[ $n =~ ^[0-9]+$ && $w =~ ^[0-9]+$ && $s =~ ^[0-9]+$ && $f =~ ^[0-9]+$ ]] || continue
38+ # At most 4 dots; a focused window past the 4th is shown on the 4th.
34 pips=""39 pips=""
35- ((w > 0)) && printf -v pips "$DOT%.0s" $(seq 1 $((w > 4 ? 4 : w)))40+ for ((i = 1; i <= (w > 4 ? 4 : w); i++)); do
41+ color=$DIM
42+ ((n == active)) && color=$NEFERBAR_FOREGROUND
43+ ((i == (f > 4 ? 4 : f))) && color=$ACCENT
44+ pips+="$(fg "$color")$DOT"
45+ done
36 if ((n == active)); then46 if ((n == active)); then
37- line+="$(fg "$NEFERBAR_FOREGROUND") $n $(fg "$ACCENT")$pips"47+ # The number is already in the accent block on the left.
48+ line+=" $pips"
38 ((s > 0)) && line+="$(fg "$NEFERBAR_COLOR2") $STASH$s"49 ((s > 0)) && line+="$(fg "$NEFERBAR_COLOR2") $STASH$s"
39 line+=" "50 line+=" "
40 elif ((w > 0)); then51 elif ((w > 0)); then
41- line+="$(fg "$NEFERBAR_FOREGROUND") $n $(fg "$DIM")$pips "52+ line+="$(fg "$NEFERBAR_FOREGROUND") $n $pips "
42 else53 else
43 line+="$(fg "$DIM") $n "54 line+="$(fg "$DIM") $n "
44 fi55 fi
M examples/bundle/lib.sh +0 -1
@@ -20,7 +20,6 @@ RESET=$'\e[0m' BOLD=$'\e[1m'
2020 ICON_DOT=$'\xef\x84\x91' # U+F111 circle
2121 ICON_STASH=$'\xef\x86\x87' # U+F187 archive
2222 ICON_APP=$'\xef\x8b\x90' # U+F2D0 window
23-ICON_CLOCK=$'\xef\x80\x97' # U+F017 clock
2423
2524 # rgb "#rrggbb" -> "r;g;b"
2625 rgb() {
@@ -20,7 +20,6 @@ RESET=$'\e[0m' BOLD=$'\e[1m'
20 ICON_DOT=$'\xef\x84\x91' # U+F111 circle20 ICON_DOT=$'\xef\x84\x91' # U+F111 circle
21 ICON_STASH=$'\xef\x86\x87' # U+F187 archive21 ICON_STASH=$'\xef\x86\x87' # U+F187 archive
22 ICON_APP=$'\xef\x8b\x90' # U+F2D0 window22 ICON_APP=$'\xef\x8b\x90' # U+F2D0 window
23-ICON_CLOCK=$'\xef\x80\x97' # U+F017 clock
24 23
25 # rgb "#rrggbb" -> "r;g;b"24 # rgb "#rrggbb" -> "r;g;b"
26 rgb() {25 rgb() {
M examples/bundle/right.sh +2 -2
@@ -6,7 +6,7 @@ while true; do
66 # One reading of the clock, for the text and for the sleep, so they cannot
77 # straddle a minute boundary.
88 printf -v now '%(%s)T' -1
9- printf '%s%s%s%s%s %(%H:%M)T %s\f' \
10- "$(fade "$BAR" "$ACCENT")" "$(bg "$ACCENT")" "$(fg "$(ink "$ACCENT")")" "$BOLD" "$ICON_CLOCK" "$now" "$RESET"
9+ printf '%s%s%s%s %(%H:%M)T %s\f' \
10+ "$(fade "$BAR" "$ACCENT")" "$(bg "$ACCENT")" "$(fg "$(ink "$ACCENT")")" "$BOLD" "$now" "$RESET"
1111 sleep $((60 - now % 60))
1212 done
@@ -6,7 +6,7 @@ while true; do
6 # One reading of the clock, for the text and for the sleep, so they cannot6 # One reading of the clock, for the text and for the sleep, so they cannot
7 # straddle a minute boundary.7 # straddle a minute boundary.
8 printf -v now '%(%s)T' -18 printf -v now '%(%s)T' -1
9- printf '%s%s%s%s%s %(%H:%M)T %s\f' \9+ printf '%s%s%s%s %(%H:%M)T %s\f' \
10- "$(fade "$BAR" "$ACCENT")" "$(bg "$ACCENT")" "$(fg "$(ink "$ACCENT")")" "$BOLD" "$ICON_CLOCK" "$now" "$RESET"10+ "$(fade "$BAR" "$ACCENT")" "$(bg "$ACCENT")" "$(fg "$(ink "$ACCENT")")" "$BOLD" "$now" "$RESET"
11 sleep $((60 - now % 60))11 sleep $((60 - now % 60))
12 done12 done

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 5

Tags 4

↑↓ moveenter openesc close