@kecan0406/ttheme 1.0.46 → 1.0.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.46",
2
+ "version": "1.0.47",
3
3
  "gate": [
4
4
  {
5
5
  "rule": "foreground",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kecan0406/ttheme",
3
- "version": "1.0.46",
3
+ "version": "1.0.47",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "ttheme": "bin/ttheme.js"
@@ -29,18 +29,6 @@ __tt_bg_refresh() { : }
29
29
 
30
30
  __tt_bg_aligns() { (( ! ${TTHEME_TERMINALS[(Ie)iterm2]} )) }
31
31
 
32
- __tt_b64() {
33
- local t=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ out="" i n
34
- local -a b=("$@")
35
- for (( i = 1; i <= ${#b}; i += 3 )); do
36
- n=$(( (b[i] << 16) | (${b[i+1]:-0} << 8) | ${b[i+2]:-0} ))
37
- out+=${t:$(( (n >> 18) & 63 )):1}${t:$(( (n >> 12) & 63 )):1}
38
- if (( i + 1 <= ${#b} )); then out+=${t:$(( (n >> 6) & 63 )):1}; else out+='='; fi
39
- if (( i + 2 <= ${#b} )); then out+=${t:$(( n & 63 )):1}; else out+='='; fi
40
- done
41
- REPLY=$out
42
- }
43
-
44
32
  __tt_bg_frame() {
45
33
  local -i iw=$1 ih=$2 W=$3 H=$4 s=$5 ax=$(( ($6 - 1) % 3 )) ay=$(( ($6 - 1) / 3 )) f=${8:--1} wide dw dh ox oy
46
34
  wide=$(( W * ih >= H * iw ))
@@ -155,11 +143,22 @@ __tt_bg_label() {
155
143
  }
156
144
 
157
145
  __tt_bg_dim() {
158
- local img=$1
159
- local -a d
146
+ setopt localoptions nomultibyte
147
+ local img=$1 fd hdr="" c
148
+ local -a d=()
149
+ local -i i n
160
150
  [[ -n $img && -r $img ]] || return 1
161
151
  if [[ -z ${bgdim[$img]} ]]; then
162
- d=($(od -An -N24 -tu1 -- $img 2>/dev/null))
152
+ if { exec {fd}<$img } 2>/dev/null; then
153
+ sysread -s 24 -i $fd hdr
154
+ exec {fd}<&-
155
+ fi
156
+ for (( i = 1; i <= ${#hdr}; i++ )); do
157
+ c=${hdr[i]}
158
+ n=$(( #c ))
159
+ (( n < 0 )) && (( n += 256 ))
160
+ d+=($n)
161
+ done
163
162
  if (( ${#d} == 24 && d[1] == 137 && d[2] == 80 && d[3] == 78 && d[4] == 71 )); then
164
163
  bgdim[$img]="$(( (d[17] << 24) | (d[18] << 16) | (d[19] << 8) | d[20] )) $(( (d[21] << 24) | (d[22] << 16) | (d[23] << 8) | d[24] ))"
165
164
  else
@@ -314,7 +313,8 @@ __tt_pv_bg_show() {
314
313
  __tt_bg_send() {
315
314
  if [[ -z ${bgsent[$1]} ]]; then
316
315
  bgsent[$1]=$(( ${#bgsent} + 3 ))
317
- printf '\e_Ga=t,t=f,f=100,i=%d,q=2;%s\e\\' ${bgsent[$1]} "$(print -rn -- $1 | base64 | tr -d '\n')"
316
+ __tt_b64s "$1"
317
+ printf '\e_Ga=t,t=f,f=100,i=%d,q=2;%s\e\\' ${bgsent[$1]} "$REPLY"
318
318
  fi
319
319
  REPLY=${bgsent[$1]}
320
320
  }
@@ -406,6 +406,7 @@ __tt_pv_bg_findable() {
406
406
  __tt_pv_bg_find() {
407
407
  local name=$1 err var
408
408
  local -i rc
409
+ [[ $applied == "$painted" ]] || { __tt_apply "$applied" && painted=$applied }
409
410
  __tt_pv_bg_close
410
411
  err=$(__tt_cli find $name 2>&1 >/dev/tty)
411
412
  rc=$?
@@ -19,6 +19,7 @@ __tt_osc_apply() {
19
19
  out+=$'\e]10;'$p[2]$'\e\\\e]12;'$p[3]$'\e\\\e]17;'$p[4]$'\e\\'
20
20
  for i in {0..15}; do out+=$'\e]4;'$i';'$p[i+5]$'\e\\'; done
21
21
  __tt_out "$out"
22
+ export TTHEME_PAINTED=1
22
23
  (( TTHEME_TMUX )) && tmux set -q @ttheme_bg "$p[1]" 2>/dev/null
23
24
  __tt_worn "$1"
24
25
  return 0
@@ -26,6 +27,7 @@ __tt_osc_apply() {
26
27
 
27
28
  __tt_osc_reset() {
28
29
  __tt_out $'\e]104\e\\\e]110\e\\\e]111\e\\\e]112\e\\\e]117\e\\'
30
+ unset TTHEME_PAINTED
29
31
  (( TTHEME_TMUX )) && tmux set -qu @ttheme_bg 2>/dev/null
30
32
  __tt_worn ""
31
33
  return 0
@@ -43,6 +45,8 @@ __tt_repaint() {
43
45
 
44
46
  __tt_apply() { __tt_osc_apply "$@" }
45
47
 
48
+ __tt_pv_paint() { __tt_apply "$1" && painted=$1 }
49
+
46
50
  __tt_shown() { return 1 }
47
51
 
48
52
  __tt_unshown() { : }
@@ -78,25 +82,54 @@ __tt_pv_bg_save() { : }
78
82
  zmodload zsh/system
79
83
 
80
84
  typeset -g TTHEME_TYPED=""
85
+ typeset -gi TTHEME_RAW=0
86
+
87
+ __tt_b64() {
88
+ local t=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ out="" i n
89
+ local -a b=("$@")
90
+ for (( i = 1; i <= ${#b}; i += 3 )); do
91
+ n=$(( (b[i] << 16) | (${b[i+1]:-0} << 8) | ${b[i+2]:-0} ))
92
+ out+=${t:$(( (n >> 18) & 63 )):1}${t:$(( (n >> 12) & 63 )):1}
93
+ if (( i + 1 <= ${#b} )); then out+=${t:$(( (n >> 6) & 63 )):1}; else out+='='; fi
94
+ if (( i + 2 <= ${#b} )); then out+=${t:$(( n & 63 )):1}; else out+='='; fi
95
+ done
96
+ REPLY=$out
97
+ }
98
+
99
+ __tt_b64s() {
100
+ setopt localoptions nomultibyte
101
+ local s=$1 c
102
+ local -a b=()
103
+ local -i i n
104
+ for (( i = 1; i <= ${#s}; i++ )); do
105
+ c=${s[i]}
106
+ n=$(( #c ))
107
+ (( n < 0 )) && (( n += 256 ))
108
+ b+=($n)
109
+ done
110
+ __tt_b64 $b
111
+ }
81
112
 
82
113
  __tt_ask() {
83
114
  setopt localoptions extendedglob
84
- local fd saved buf="" chunk seqs=$'\e[]_P][^\a\e]#(\a|\e\\\\)|\e\\[[0-?]#[ -/]#[@-~]|\e[^][_P]'
115
+ local fd saved="" buf="" chunk seqs=$'\e[]_P][^\a\e]#(\a|\e\\\\)|\e\\[[0-?]#[ -/]#[@-~]|\e[^][_P]'
85
116
  local -a match mbegin mend
86
117
  REPLY=""
87
118
  { exec {fd}<>/dev/tty } 2>/dev/null || return 1
88
- saved=$(stty -g <&$fd 2>/dev/null && stty raw -echo min 0 time 3 <&$fd 2>/dev/null)
89
- if [[ -z $saved ]]; then
90
- exec {fd}>&-
91
- return 1
119
+ if (( ! TTHEME_RAW )) && ! zle; then
120
+ saved=$(stty -g <&$fd 2>/dev/null && stty raw -echo <&$fd 2>/dev/null)
121
+ if [[ -z $saved ]]; then
122
+ exec {fd}>&-
123
+ return 1
124
+ fi
92
125
  fi
93
126
  printf '%s\e[5n' "$1" >&$fd
94
- while sysread -i $fd -s 4096 chunk 2>/dev/null; do
127
+ while sysread -t 0.3 -i $fd -s 4096 chunk 2>/dev/null; do
95
128
  buf+=$chunk
96
129
  [[ $buf == *$'\e[0n'* ]] && break
97
130
  (( ${#buf} < 16384 )) || break
98
131
  done
99
- stty "$saved" <&$fd 2>/dev/null
132
+ [[ -n $saved ]] && stty "$saved" <&$fd 2>/dev/null
100
133
  exec {fd}>&-
101
134
  while [[ $buf == (#b)([^$'\e']#)(${~seqs})(*) ]]; do
102
135
  TTHEME_TYPED+=$match[1] REPLY+=$match[2] buf=$match[-1]
@@ -111,7 +144,14 @@ __tt_typed() {
111
144
  TTHEME_TYPED=
112
145
  }
113
146
 
114
- __tt_start_bg() { __tt_query_bg }
147
+ __tt_hear() { __tt_query_bg }
148
+
149
+ __tt_heard() { : }
150
+
151
+ __tt_start_bg() {
152
+ REPLY=${TTHEME_HEARD%% *}
153
+ [[ -n $REPLY ]]
154
+ }
115
155
 
116
156
  __tt_query_bg() {
117
157
  local resp
@@ -7,6 +7,17 @@ fi
7
7
 
8
8
  __tt_keepable() { return 0 }
9
9
 
10
+ __tt_pv_paint() {
11
+ local -a p=(${=1})
12
+ if (( ${#p} < 20 )); then
13
+ __tt_out $'\e]110\e\\\e]111\e\\'
14
+ elif [[ $p[1] == - ]]; then
15
+ __tt_out $'\e]111\e\\\e]10;'$p[2]$'\e\\'
16
+ else
17
+ __tt_out $'\e]11;'$p[1]$'\e\\\e]10;'$p[2]$'\e\\'
18
+ fi
19
+ }
20
+
10
21
  __tt_bg_shown() {
11
22
  REPLY=""
12
23
  (( TTHEME_TMUX )) && REPLY=$(tmux show -qv @ttheme_shown 2>/dev/null)
@@ -67,6 +78,6 @@ __tt_bg_crop() {
67
78
  sips -c $h $iw --cropOffset 1 1 $bgcut/pad.png --out $band >/dev/null 2>&1 || return 1
68
79
  fi
69
80
  fi
70
- printf '\e_Ga=t,t=f,f=100,i=999997,q=2;%s\e\\' "$(print -rn -- $band | base64 | tr -d '\n')"
71
- REPLY="999997 0"
81
+ __tt_bg_send $band
82
+ REPLY="$REPLY 0"
72
83
  }
@@ -4,7 +4,11 @@ typeset -g TTHEME_KITTY_SHOWN=""
4
4
 
5
5
  __tt_keepable() { (( ${TTHEME_TERMINALS[(Ie)kitty]} )) }
6
6
 
7
- __tt_kitty_var() { __tt_out $'\e]1337;SetUserVar='$1'='"$(print -rn -- $2 | base64)"$'\a' }
7
+ __tt_kitty_var() {
8
+ local REPLY
9
+ __tt_b64s "$2"
10
+ __tt_out $'\e]1337;SetUserVar='$1'='$REPLY$'\a'
11
+ }
8
12
 
9
13
  __tt_shown() {
10
14
  [[ $2 != force && $TTHEME_KITTY_SHOWN == $1 ]] && return 1
@@ -1,12 +1,13 @@
1
1
  typeset -g TTHEME_TERMINAL_BASE=""
2
2
 
3
- __tt_terminal_base() {
4
- local REPLY resp q=$'\e]11;?\e\\\e]10;?\e\\\e]12;?\e\\\e]17;?\e\\' e v i
3
+ __tt_hear() {
4
+ local resp q=$'\e]11;?\e\\\e]10;?\e\\\e]12;?\e\\\e]17;?\e\\' e v i
5
5
  local -a p
6
6
  local -A got
7
7
  for i in {0..15}; do q+=$'\e]4;'$i$';?\e\\'; done
8
8
  __tt_ask $q || return 1
9
9
  resp=$REPLY
10
+ REPLY=""
10
11
  for e in ${(ps:\e]:)resp}; do
11
12
  [[ $e == *';rgb:'* ]] || continue
12
13
  p=(${(s:/:)${${e#*rgb:}%%[^0-9A-Fa-f/]*}})
@@ -14,17 +15,16 @@ __tt_terminal_base() {
14
15
  done
15
16
  v="$got[11] $got[10] $got[12] ${got[17]:-$got[11]}"
16
17
  for i in {0..15}; do v+=" ${got[4;$i]}"; done
17
- (( ${#${=v}} == 20 )) && TTHEME_TERMINAL_BASE=$v
18
+ (( ${#${=v}} == 20 )) || return 1
19
+ REPLY=$v
18
20
  }
19
21
 
20
- __tt_start_bg() {
21
- REPLY=${TTHEME_TERMINAL_BASE%% *}
22
- [[ -n $REPLY ]]
23
- }
22
+ __tt_heard() { TTHEME_TERMINAL_BASE=$1 }
24
23
 
25
24
  __tt_osc_reset() {
26
25
  [[ -n $TTHEME_TERMINAL_BASE ]] && __tt_osc_apply "$TTHEME_TERMINAL_BASE"
26
+ unset TTHEME_PAINTED
27
27
  return 0
28
28
  }
29
29
 
30
- [[ -o interactive && -t 1 ]] && __tt_terminal_base
30
+ [[ -o interactive && -t 1 ]] && __tt_listen
@@ -2,7 +2,11 @@ typeset -g TTHEME_WEZTERM_SHOWN=""
2
2
 
3
3
  __tt_keepable() { (( ${TTHEME_TERMINALS[(Ie)wezterm]} )) }
4
4
 
5
- __tt_wezterm_show() { printf '\e]1337;SetUserVar=ttheme_shown=%s\a' "$(print -rn -- $1 | base64)" }
5
+ __tt_wezterm_show() {
6
+ local REPLY
7
+ __tt_b64s "$1"
8
+ printf '\e]1337;SetUserVar=ttheme_shown=%s\a' "$REPLY"
9
+ }
6
10
 
7
11
  __tt_shown() {
8
12
  [[ $2 != force && $TTHEME_WEZTERM_SHOWN == $1 ]] && return 1
package/shell/ttheme.zsh CHANGED
@@ -31,10 +31,7 @@ __tt_gone() {
31
31
  for hook in precmd:__tt_fresh precmd:__tt_precmd precmd:__tt_unmux preexec:__tt_preexec preexec:__tt_mux chpwd:__tt_chpwd; do
32
32
  add-zsh-hook -d ${hook%%:*} ${hook#*:}
33
33
  done
34
- if (( $+functions[add-zle-hook-widget] )); then
35
- add-zle-hook-widget -d line-init __tt_focus_on
36
- add-zle-hook-widget -d line-init __tt_typed
37
- fi
34
+ (( $+functions[add-zle-hook-widget] )) && add-zle-hook-widget -d line-init __tt_line_init
38
35
  unfunction ttheme
39
36
  }
40
37
 
@@ -143,16 +140,79 @@ __tt_tmux() {
143
140
  TTHEME_TMUX=1 TTHEME_SPEC=
144
141
  }
145
142
 
146
- source $TTHEME_HOME/adapters/_osc.zsh
147
- [[ -r $TTHEME_HOME/adapters/$TTHEME_ADAPTER.zsh ]] &&
148
- source $TTHEME_HOME/adapters/$TTHEME_ADAPTER.zsh
149
-
150
143
  __tt_active() {
151
144
  [[ -o interactive ]] || return 1
152
145
  (( ${#TTHEME_PALETTE} )) || return 1
153
146
  [[ $TTHEME_ADAPTER != (unknown|warp) || -n $TTHEME_FORCE ]]
154
147
  }
155
148
 
149
+ typeset -g TTHEME_HEARD=""
150
+ typeset -gi TTHEME_RECHECK=0 TTHEME_FOCUS=0
151
+
152
+ __tt_recall() {
153
+ local f=$TTHEME_STATE_DIR/colors.$TTHEME_ADAPTER line
154
+ REPLY=""
155
+ [[ -o zle && -r $f && -z $TTHEME_PAINTED && $TTHEME_TAB_PALETTE == off ]] && (( ! TTHEME_TMUX )) && __tt_active || return 1
156
+ line=$(<$f)
157
+ [[ $line == "${TTHEME_STARTUP:--} "?* ]] || return 1
158
+ REPLY=${line#* }
159
+ }
160
+
161
+ __tt_remember() {
162
+ local f=$TTHEME_STATE_DIR/colors.$TTHEME_ADAPTER line="${TTHEME_STARTUP:--} $1"
163
+ [[ -n $1 && -z $TTHEME_PAINTED ]] && (( ! TTHEME_TMUX )) || return 0
164
+ [[ -r $f && "$(<$f)" == "$line" ]] && return 0
165
+ [[ -d $TTHEME_STATE_DIR ]] || mkdir -p $TTHEME_STATE_DIR 2>/dev/null
166
+ print -r -- "$line" 2>/dev/null > $f
167
+ }
168
+
169
+ __tt_listen() {
170
+ local REPLY
171
+ if __tt_recall; then
172
+ TTHEME_RECHECK=1
173
+ else
174
+ __tt_hear || return 1
175
+ __tt_remember "$REPLY"
176
+ fi
177
+ TTHEME_HEARD=$REPLY
178
+ __tt_heard "$REPLY"
179
+ }
180
+
181
+ __tt_wearing() {
182
+ local k
183
+ [[ -n $1 ]] || return 1
184
+ [[ -n $TTHEME_STARTUP && ${TTHEME_PALETTE[$TTHEME_STARTUP]%% *} == "$1" ]] && { REPLY=$TTHEME_PALETTE[$TTHEME_STARTUP]; return 0 }
185
+ for k in ${(k)TTHEME_PALETTE}; do
186
+ [[ ${TTHEME_PALETTE[$k]%% *} == "$1" ]] && { REPLY=$TTHEME_PALETTE[$k]; return 0 }
187
+ done
188
+ return 1
189
+ }
190
+
191
+ __tt_recheck() {
192
+ local REPLY heard=$TTHEME_HEARD was="" now
193
+ TTHEME_RECHECK=0
194
+ [[ -z $TTHEME_PAINTED ]] && __tt_hear || return 0
195
+ [[ $REPLY == "$heard" ]] && return 0
196
+ now=$REPLY
197
+ __tt_remember "$now"
198
+ TTHEME_HEARD=$now
199
+ __tt_heard "$now"
200
+ [[ $TTHEME_TAB_PALETTE == off ]] || return 0
201
+ __tt_wearing "${heard%% *}" && was=$REPLY
202
+ REPLY=""
203
+ __tt_wearing "${now%% *}"
204
+ if [[ -n $TTHEME_PIN ]]; then
205
+ [[ $TTHEME_BASE_SPEC == "$was" ]] && TTHEME_BASE_SPEC=$REPLY
206
+ elif [[ $TTHEME_SPEC == "$was" ]]; then
207
+ TTHEME_SPEC=$REPLY
208
+ __tt_sync
209
+ fi
210
+ }
211
+
212
+ source $TTHEME_HOME/adapters/_osc.zsh
213
+ [[ -r $TTHEME_HOME/adapters/$TTHEME_ADAPTER.zsh ]] &&
214
+ source $TTHEME_HOME/adapters/$TTHEME_ADAPTER.zsh
215
+
156
216
  __tt_empty() {
157
217
  print -u2 'ttheme: no palettes installed yet — run `ttheme browse` to pick some'
158
218
  return 1
@@ -288,13 +348,17 @@ __tt_unmux() {
288
348
 
289
349
  __tt_blur() { : }
290
350
 
351
+ __tt_line_init() {
352
+ (( TTHEME_RECHECK )) && __tt_recheck
353
+ __tt_typed
354
+ (( TTHEME_FOCUS )) && __tt_focus_on
355
+ }
356
+
291
357
  __tt_bind_focus() {
292
358
  local k
293
359
  zle -N __tt_focus
294
360
  zle -N __tt_blur
295
- zle -N __tt_focus_on
296
- autoload -Uz add-zle-hook-widget
297
- add-zle-hook-widget line-init __tt_focus_on
361
+ TTHEME_FOCUS=1
298
362
  for k in emacs viins vicmd; do
299
363
  bindkey -M $k '^[[I' __tt_focus
300
364
  bindkey -M $k '^[[O' __tt_blur
@@ -461,7 +525,7 @@ __tt_arity() {
461
525
 
462
526
  __tt_cli() {
463
527
  local k
464
- local -a pass=()
528
+ local -a pass=(NODE_COMPILE_CACHE=${XDG_CACHE_HOME:-$HOME/.cache}/ttheme/node)
465
529
  for k in $TTHEME_SETTINGS; do
466
530
  (( $+parameters[$k] )) && pass+=("$k=${(P)k}")
467
531
  done
@@ -642,7 +706,7 @@ __tt_pv_focus() {
642
706
  (( resized )) || [[ ${rval[cur]} == "$bgname" ]] || __tt_pv_bg_show "${rval[cur]}"
643
707
  local spec=${TTHEME_PALETTE[${rval[cur]}]}
644
708
  [[ $spec == "$applied" ]] && return 0
645
- __tt_apply "$spec"
709
+ __tt_pv_paint "$spec"
646
710
  applied=$spec
647
711
  }
648
712
 
@@ -791,10 +855,14 @@ __tt_pv_head() {
791
855
 
792
856
  __tt_pv_foot() {
793
857
  setopt localoptions extendedglob
794
- local b=$'\e[1m' d=$'\e[2m' z=$'\e[0m' y=$'\e[33m' on=$'\e[7;1m'$ac badge="" lead="" note="" right="" text line plain
858
+ local b=$'\e[1m' d=$'\e[2m' z=$'\e[0m' y=$'\e[33m' on=$'\e[7;1m'$ac badge="" lead="" note="" right="" text line plain hex
795
859
  local -a kk=() kl=() seg=()
796
860
  local -i end=$1 i lwid rwid room
797
861
  (( color )) || b= d= z= y= on=
862
+ if (( color )) && [[ -n $applied && $applied != "$painted" ]]; then
863
+ hex=${${=applied}[8]#\#}
864
+ printf -v y '\e[38;2;%d;%d;%dm' $((16#${hex:0:2})) $((16#${hex:2:2})) $((16#${hex:4:2}))
865
+ fi
798
866
  if (( help )); then
799
867
  badge=KEYS right=$b"? esc"$z$d" close"$z
800
868
  elif [[ -n $pick ]]; then
@@ -949,10 +1017,21 @@ __tt_pv_help() {
949
1017
  }
950
1018
 
951
1019
  __tt_pv_specimen() {
952
- local -a sp=(${=applied}) ln=()
1020
+ local -a sp=(${=applied}) ln=() fg=()
953
1021
  (( ${#sp} >= 20 )) || return 0
954
- local z=$'\e[0m' d=$'\e[2m' pr=$'\e[32m❯\e[0m ' sel cu cell line="" lo hi
1022
+ local z=$'\e[0m' d=$'\e[2m' sel cu cell line="" lo hi pr bd
955
1023
  local -i i r cw=4
1024
+ if [[ $applied == "$painted" ]]; then
1025
+ fg=($'\e[31m' $'\e[32m' $'\e[33m' $'\e[34m' $'\e[35m') bd=$'\e[1;34m'
1026
+ else
1027
+ for i in 6 7 8 9 10 17; do
1028
+ lo=${sp[i]#\#}
1029
+ printf -v cell '\e[38;2;%d;%d;%dm' $((16#${lo:0:2})) $((16#${lo:2:2})) $((16#${lo:4:2}))
1030
+ fg+=($cell)
1031
+ done
1032
+ bd=$'\e[1m'$fg[6]
1033
+ fi
1034
+ pr=$fg[2]'❯'$z' '
956
1035
  (( sw < 44 )) && cw=3
957
1036
  (( sw >= 56 )) && cw=$(( (sw + 1) / 8 - 1 ))
958
1037
  (( cw > 7 )) && cw=7
@@ -966,12 +1045,12 @@ __tt_pv_specimen() {
966
1045
  line+=$cell
967
1046
  done
968
1047
  out+=$'\e[4;'$sc'H'$line
969
- ln=($'\e[1;34m~/code/demo\e[0m'$d' on '$z$'\e[35mmain\e[32m +2\e[33m ~1\e[0m' "${pr}git status -sb")
970
- (( sw >= 44 )) && ln+=($'## \e[32mmain\e[0m...\e[31morigin/main\e[33m [ahead 1]\e[0m')
971
- ln+=($'\e[31m M\e[0m src/main.rs' $'\e[31m??\e[0m notes.md' "")
972
- (( sw >= 44 )) && ln+=("${pr}ls" $'\e[1;34mdocs\e[0m \e[1;34msrc\e[0m \e[1;34mtests\e[0m Cargo.toml README.md' "")
973
- ln+=("${pr}cargo test" $'\e[32m ✓\e[0m parses config' $'\e[31m ✗\e[0m renders frame')
974
- (( sw >= 44 )) && ln[-1]+=$d' expected '$z$'\e[32m3\e[0m'$d', received '$z$'\e[31m2\e[0m'
1048
+ ln=($bd'~/code/demo'$z$d' on '$z$fg[5]'main'$fg[2]' +2'$fg[3]' ~1'$z "${pr}git status -sb")
1049
+ (( sw >= 44 )) && ln+=('## '$fg[2]'main'$z'...'$fg[1]'origin/main'$fg[3]' [ahead 1]'$z)
1050
+ ln+=($fg[1]' M'$z' src/main.rs' $fg[1]'??'$z' notes.md' "")
1051
+ (( sw >= 44 )) && ln+=("${pr}ls" $bd'docs'$z' '$bd'src'$z' '$bd'tests'$z' Cargo.toml README.md' "")
1052
+ ln+=("${pr}cargo test" $fg[2]' ✓'$z' parses config' $fg[1]' ✗'$z' renders frame')
1053
+ (( sw >= 44 )) && ln[-1]+=$d' expected '$z$fg[2]'3'$z$d', received '$z$fg[1]'2'$z
975
1054
  ln+=("" "${pr}echo ${sel}selected text${z} ${cu} ${z}")
976
1055
  for (( r = 1; r <= ${#ln}; r++ )); do
977
1056
  (( r + 5 < ph )) || break
@@ -1228,13 +1307,14 @@ __tt_pv_draw() {
1228
1307
  fi
1229
1308
  line=" "$dd"search… e.g. $ex"$zz
1230
1309
  fi
1231
- out+=$line$'\e[K\e['$(( lw - ${#cnt} ))'G'
1232
- if [[ -n $flt ]]; then
1233
- out+=$cnt
1234
- else
1235
- out+=$dd$cnt$zz
1310
+ local tail=$'\e['$(( lw - ${#cnt} ))'G'$dd$cnt$zz
1311
+ [[ -n $flt ]] && tail=$'\e['$(( lw - ${#cnt} ))'G'$cnt
1312
+ if [[ $1 == hint ]] && (( ! wiped )); then
1313
+ print -rn -- $'\e[H\e[0m\e['$lw'X'$line$tail
1314
+ printf '\e[?2026l'
1315
+ return 0
1236
1316
  fi
1237
- out+=$'\n\e[K\n'
1317
+ out+=$line$'\e[K'$tail$'\n\e[K\n'
1238
1318
  (( N > h && top > 1 )) && out+=" "$dd"…"$zz
1239
1319
  out+=$'\e[K\n'
1240
1320
  for (( k = 0; k < ph - 4; k++ )); do
@@ -1377,8 +1457,8 @@ __tt_pv_getch() {
1377
1457
  (( msgt -= gstep ? 6 : 20 ))
1378
1458
  (( msgt > 0 )) || return 1
1379
1459
  fi
1380
- (( gstep )) && { gstep=$(( gstep - 1 )); return 1 }
1381
- (( SECONDS >= exnext )) && { __tt_pv_roll; gstep=8; return 1 }
1460
+ (( gstep )) && { gstep=$(( gstep - 1 )); tick=1; return 1 }
1461
+ (( SECONDS >= exnext )) && { __tt_pv_roll; gstep=8; tick=1; return 1 }
1382
1462
  done
1383
1463
  return 0
1384
1464
  }
@@ -1551,7 +1631,7 @@ __tt_preview() {
1551
1631
  print -u2 "ttheme ${mode:-preview}: needs a terminal"
1552
1632
  return 1
1553
1633
  fi
1554
- local orig=$TTHEME_SPEC applied=$TTHEME_SPEC flt="" sel="" cn="" cdot="" key="" REPLY="" cur=1 top=1 color=0 pw=80 ph=24 resized=1 expal="" exgrp="" exnext=0 gstep=0 gseed=0
1634
+ local orig=$TTHEME_SPEC applied=$TTHEME_SPEC painted=$TTHEME_SPEC flt="" sel="" cn="" cdot="" key="" REPLY="" cur=1 top=1 color=0 pw=80 ph=24 resized=1 expal="" exgrp="" exnext=0 gstep=0 gseed=0 tick=0
1555
1635
  local pick="" pk=1 pkdef=1 picked=0 canpick=0 bgcw=0 bgch=0 bgname="" bgshown="" bginc="" osd="" osdt=0
1556
1636
  local tune="" tsnap="" tf=1 help=0 msg="" msgt=0 an="" bgrel=0 bgmx=0 bgmy=0 bganchor=0 bgcut=""
1557
1637
  local -A bgfrom=() bgsent=() bgdim=() bgsrc=() bgfill=() bgfocus=() bgsize=() bgpos=() bgop=() bgdef=() bgoff=() bgbase=() bgload=() bgshot=() bgshotkey=() bgedit=() bgtunef=() bgofff=() bgimages=()
@@ -1576,14 +1656,23 @@ __tt_preview() {
1576
1656
  __tt_pv_roll
1577
1657
  __tt_pv_rows
1578
1658
  [[ -n ${TTHEME_PALETTE[$cn]} ]] && __tt_pv_goto "$cn"
1579
- printf '\e[?2026h\e[?1049h\e[?7l\e[?25l'
1580
- __tt_pv_bg_open
1659
+ local tty=""
1660
+ local -i TTHEME_RAW=0
1581
1661
  {
1662
+ tty=$(stty -g 2>/dev/null && stty -echo -icanon min 1 time 0 2>/dev/null)
1663
+ TTHEME_RAW=$(( ${#tty} > 0 ))
1664
+ printf '\e[?2026h\e[?1049h\e[?7l\e[?25l'
1665
+ __tt_pv_bg_open
1582
1666
  while :; do
1583
1667
  printf '\e[?2026h'
1584
- __tt_pv_focus
1585
- [[ ${rtype[cur]} == thm ]] && an=${rval[cur]}
1586
- __tt_pv_draw
1668
+ if (( tick )); then
1669
+ __tt_pv_draw hint
1670
+ else
1671
+ __tt_pv_focus
1672
+ [[ ${rtype[cur]} == thm ]] && an=${rval[cur]}
1673
+ __tt_pv_draw
1674
+ fi
1675
+ tick=0
1587
1676
  if ! __tt_pv_read; then
1588
1677
  [[ -t 0 ]] && continue
1589
1678
  break
@@ -1594,15 +1683,27 @@ __tt_preview() {
1594
1683
  done
1595
1684
  done
1596
1685
  } always {
1686
+ local spec=${sel:+${TTHEME_PALETTE[$sel]}}
1597
1687
  printf '\e[?2026h'
1598
1688
  __tt_pv_bg_close
1689
+ if [[ -n $spec ]]; then
1690
+ [[ $spec == "$painted" ]] || __tt_apply "$spec"
1691
+ elif [[ $painted != "$orig" ]]; then
1692
+ if [[ -z $orig ]]; then
1693
+ __tt_osc_reset
1694
+ else
1695
+ __tt_apply "$orig"
1696
+ fi
1697
+ elif [[ $applied != "$orig" ]]; then
1698
+ __tt_pv_paint "${TTHEME_PAINTED:+$orig}"
1699
+ fi
1599
1700
  printf '\e[?7h\e[?1049l\e[?25h\e[?2026l'
1701
+ [[ -n $tty ]] && stty "$tty" 2>/dev/null
1702
+ TTHEME_RAW=0
1600
1703
  [[ -n $tune ]] && __tt_pv_untune
1601
1704
  (( conf )) && __tt_pv_unconf
1602
1705
  __tt_pv_bg_save
1603
- if [[ -n $sel ]]; then
1604
- local spec=${TTHEME_PALETTE[$sel]}
1605
- [[ $spec == "$applied" ]] || __tt_apply "$spec"
1706
+ if [[ -n $spec ]]; then
1606
1707
  TTHEME_SPEC=$spec
1607
1708
  __tt_announce
1608
1709
  if [[ $mode == pin ]]; then
@@ -1614,11 +1715,6 @@ __tt_preview() {
1614
1715
  __tt_shown "$sel" force && __tt_reload
1615
1716
  fi
1616
1717
  else
1617
- if [[ -z $orig && -n $applied ]]; then
1618
- __tt_osc_reset
1619
- elif [[ $orig != "$applied" ]]; then
1620
- __tt_apply "$orig"
1621
- fi
1622
1718
  (( ${#bgedit} )) && [[ -n ${TTHEME_PALETTE[$cn]} ]] && { __tt_shown "$cn" && __tt_reload }
1623
1719
  fi
1624
1720
  }
@@ -1705,15 +1801,12 @@ fi
1705
1801
  if __tt_active; then
1706
1802
  [[ -n $TMUX ]] && __tt_tmux
1707
1803
  () {
1708
- local REPLY k
1804
+ local REPLY
1709
1805
  if [[ -n $TTHEME_SPEC ]]; then
1710
1806
  :
1711
1807
  elif [[ $TTHEME_TAB_PALETTE == off ]]; then
1712
- if __tt_start_bg; then
1713
- for k in ${(k)TTHEME_PALETTE}; do
1714
- [[ ${TTHEME_PALETTE[$k]%% *} == "$REPLY" ]] && { TTHEME_SPEC=$TTHEME_PALETTE[$k]; break }
1715
- done
1716
- fi
1808
+ [[ -n $TTHEME_HEARD ]] || __tt_listen
1809
+ __tt_start_bg && __tt_wearing $REPLY && TTHEME_SPEC=$REPLY
1717
1810
  else
1718
1811
  __tt_next
1719
1812
  TTHEME_SPEC=$REPLY
@@ -1722,8 +1815,8 @@ if __tt_active; then
1722
1815
  __tt_dir_sync
1723
1816
  }
1724
1817
  autoload -Uz add-zsh-hook add-zle-hook-widget
1725
- zle -N __tt_typed
1726
- add-zle-hook-widget line-init __tt_typed
1818
+ zle -N __tt_line_init
1819
+ add-zle-hook-widget line-init __tt_line_init
1727
1820
  add-zsh-hook chpwd __tt_chpwd
1728
1821
  add-zsh-hook precmd __tt_fresh
1729
1822
  if (( ! TTHEME_TMUX )); then