@kecan0406/ttheme 1.2.4 → 1.2.6

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.2.4",
2
+ "version": "1.2.6",
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.2.4",
3
+ "version": "1.2.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "ttheme": "bin/ttheme.js"
@@ -45,8 +45,19 @@ __tt_repaint() {
45
45
 
46
46
  __tt_apply() { __tt_osc_apply "$@" }
47
47
 
48
+ __tt_wear() {
49
+ local REPLY=$2 name
50
+ [[ -n $REPLY ]] || __tt_name_of "$1"
51
+ name=$REPLY
52
+ TTHEME_SPEC=$1
53
+ __tt_apply "$1"
54
+ [[ -n ${TTHEME_PALETTE[$name]} ]] && __tt_shown "$name" $3 && __tt_reload
55
+ }
56
+
48
57
  __tt_pv_paint() { __tt_apply "$1" && painted=$1 }
49
58
 
59
+ __tt_pv_claim() { : }
60
+
50
61
  __tt_shown() { return 1 }
51
62
 
52
63
  __tt_unshown() { : }
@@ -71,6 +82,8 @@ __tt_follows_prompt() { return 1 }
71
82
 
72
83
  __tt_prompted() { : }
73
84
 
85
+ __tt_pv_conf_rows() { : }
86
+
74
87
  __tt_pv_bg_open() { : }
75
88
 
76
89
  __tt_pv_bg_show() { : }
@@ -1,4 +1,5 @@
1
1
  typeset -g TTHEME_GHOSTTY_PID=""
2
+ typeset -gi TTHEME_GHOSTTY_SENT=0
2
3
 
3
4
  __tt_reload() {
4
5
  local wired
@@ -39,8 +40,8 @@ __tt_reload_ghostty() {
39
40
  __tt_ghostty_owner $PPID
40
41
  owner=$REPLY TTHEME_GHOSTTY_PID=$REPLY
41
42
  fi
42
- (( owner )) && kill -USR2 $owner 2>/dev/null && return
43
- pkill -USR2 -x ghostty 2>/dev/null
43
+ (( owner )) && kill -USR2 $owner 2>/dev/null && { TTHEME_GHOSTTY_SENT=1; return 0 }
44
+ pkill -USR2 -x ghostty 2>/dev/null && TTHEME_GHOSTTY_SENT=1
44
45
  }
45
46
 
46
47
  __tt_ghostty_shown() {
@@ -1,10 +1,11 @@
1
1
  source $TTHEME_HOME/adapters/_bg.zsh
2
2
 
3
- typeset -g TTHEME_GHOSTTY_TABS=$TTHEME_STATE_DIR/ghostty TTHEME_GHOSTTY_FRONT="" TTHEME_GHOSTTY_BLUR=""
4
- typeset -gF TTHEME_GHOSTTY_ASKED=0 TTHEME_GHOSTTY_WANT=0 TTHEME_GHOSTTY_HUSH=0
5
- typeset -gi TTHEME_GHOSTTY_IDLE=1 TTHEME_GHOSTTY_TICK=0 TTHEME_GHOSTTY_NONE=0 TTHEME_GHOSTTY_FOLLOWS=-1
3
+ typeset -g TTHEME_GHOSTTY_TABS=$TTHEME_STATE_DIR/ghostty TTHEME_GHOSTTY_FRONT="" TTHEME_GHOSTTY_BLUR="" TTHEME_GHOSTTY_HEARD="" TTHEME_GHOSTTY_CODE=""
4
+ typeset -gF TTHEME_GHOSTTY_ASKED=0 TTHEME_GHOSTTY_WANT=0 TTHEME_GHOSTTY_HUSH=0 TTHEME_GHOSTTY_TOLD=0 TTHEME_GHOSTTY_NONE_AT=0
5
+ typeset -gi TTHEME_GHOSTTY_IDLE=1 TTHEME_GHOSTTY_TICK=0 TTHEME_GHOSTTY_NONE=0 TTHEME_GHOSTTY_FOLLOWS=-1 TTHEME_GHOSTTY_WFD=0 TTHEME_GHOSTTY_WATCHER=0
6
6
  typeset -gA TTHEME_GHOSTTY_SEEN=() TTHEME_GHOSTTY_RUN=()
7
- typeset -g TTHEME_GHOSTTY_JS='ObjC.import("AppKit");function run(v){var p=+v[0],E=$.NSAppleEventDescriptor,G="com.mitchellh.ghostty",f=function(s){return(s.charCodeAt(0)<<24)|(s.charCodeAt(1)<<16)|(s.charCodeAt(2)<<8)|s.charCodeAt(3)},a=p?$.NSRunningApplication.runningApplicationWithProcessIdentifier(p):$.NSRunningApplication.runningApplicationsWithBundleIdentifier(G).firstObject;if(!a||a.isNil())return"none";var s=$.NSString.stringWithContentsOfFileEncodingError(a.bundleURL.path.js+"/Contents/Resources/Ghostty.sdef",4,null);if(s.isNil()||s.js.indexOf("code=\"Gtty\"")<0)return"blind";var t=E.descriptorWithProcessIdentifier(a.processIdentifier);function q(c,o){var d=E.recordDescriptor;d.setDescriptorForKeyword(E.descriptorWithTypeCode(f("prop")),f("want"));d.setDescriptorForKeyword(o,f("from"));d.setDescriptorForKeyword(E.descriptorWithEnumCode(f("prop")),f("form"));d.setDescriptorForKeyword(E.descriptorWithTypeCode(f(c)),f("seld"));return d.coerceToDescriptorType(f("obj "))}function g(o){var e=E.appleEventWithEventClassEventIDTargetDescriptorReturnIDTransactionID(f("core"),f("getd"),t,-1,0);e.setParamDescriptorForKeyword(o,f("----"));var r=e.sendEventWithOptionsTimeoutError(3,5,null);return!r||r.isNil()||!r.paramDescriptorForKeyword(f("errn")).isNil()?null:r.paramDescriptorForKeyword(f("----"))}var n=E.nullDescriptor,m=q("GTfT",q("GWsT",q("GFWn",n))),w=g(q("pisf",n)),y=g(q("Gtty",m)),i=g(q("Gpid",m));if(!w||!y||!i||w.isNil()||y.isNil()||i.isNil())return"none";return(w.booleanValue?1:0)+" "+y.stringValue.js+" "+i.int32Value}'
7
+ typeset -g TTHEME_GHOSTTY_JS='ObjC.import("AppKit");function run(v){var p=+v[0],E=$.NSAppleEventDescriptor,G="com.mitchellh.ghostty",f=function(s){return(s.charCodeAt(0)<<24)|(s.charCodeAt(1)<<16)|(s.charCodeAt(2)<<8)|s.charCodeAt(3)},a=p?$.NSRunningApplication.runningApplicationWithProcessIdentifier(p):$.NSRunningApplication.runningApplicationsWithBundleIdentifier(G).firstObject;if(!a||a.isNil())return p?"gone":"none";var s=$.NSString.stringWithContentsOfFileEncodingError(a.bundleURL.path.js+"/Contents/Resources/Ghostty.sdef",4,null);if(s.isNil()||s.js.indexOf("code=\"Gtty\"")<0)return"blind";var t=E.descriptorWithProcessIdentifier(a.processIdentifier);function q(c,o){var d=E.recordDescriptor;d.setDescriptorForKeyword(E.descriptorWithTypeCode(f("prop")),f("want"));d.setDescriptorForKeyword(o,f("from"));d.setDescriptorForKeyword(E.descriptorWithEnumCode(f("prop")),f("form"));d.setDescriptorForKeyword(E.descriptorWithTypeCode(f(c)),f("seld"));return d.coerceToDescriptorType(f("obj "))}function g(o){var e=E.appleEventWithEventClassEventIDTargetDescriptorReturnIDTransactionID(f("core"),f("getd"),t,-1,0);e.setParamDescriptorForKeyword(o,f("----"));var r=e.sendEventWithOptionsTimeoutError(3,5,null);return!r||r.isNil()||!r.paramDescriptorForKeyword(f("errn")).isNil()?null:r.paramDescriptorForKeyword(f("----"))}var n=E.nullDescriptor,m=q("GTfT",q("GWsT",q("GFWn",n))),w=g(q("pisf",n)),y=g(q("Gtty",m)),i=g(q("Gpid",m));if(!w||!y||!i||w.isNil()||y.isNil()||i.isNil())return"none";return(w.booleanValue?1:0)+" "+y.stringValue.js+" "+i.int32Value}'
8
+ typeset -g TTHEME_GHOSTTY_WATCH='ObjC.import("AppKit");ObjC.import("CoreGraphics");ObjC.import("unistd");function run(v){var p=+v[0],u=$.getppid(),E=$.NSAppleEventDescriptor,W=$.NSWorkspace.sharedWorkspace,L=$.NSRunLoop.currentRunLoop,o=$.NSFileHandle.fileHandleWithStandardOutput,a=$.NSRunningApplication.runningApplicationWithProcessIdentifier(p),f=function(s){return(s.charCodeAt(0)<<24)|(s.charCodeAt(1)<<16)|(s.charCodeAt(2)<<8)|s.charCodeAt(3)},S=$.kCGWindowListOptionOnScreenOnly|$.kCGWindowListExcludeDesktopElements,A=$.kCGWindowListOptionOnScreenAboveWindow,w=0,b=-1,h=false,z=0,k=0,c={};if(!a||a.isNil())return;var t=E.descriptorWithProcessIdentifier(p);function q(y,x){var d=E.recordDescriptor;d.setDescriptorForKeyword(E.descriptorWithTypeCode(f("prop")),f("want"));d.setDescriptorForKeyword(x,f("from"));d.setDescriptorForKeyword(E.descriptorWithEnumCode(f("prop")),f("form"));d.setDescriptorForKeyword(E.descriptorWithTypeCode(f(y)),f("seld"));return d.coerceToDescriptorType(f("obj "))}function g(x){var e=E.appleEventWithEventClassEventIDTargetDescriptorReturnIDTransactionID(f("core"),f("getd"),t,-1,0);e.setParamDescriptorForKeyword(x,f("----"));var r=e.sendEventWithOptionsTimeoutError(3,5,null);return!r||r.isNil()||!r.paramDescriptorForKeyword(f("errn")).isNil()?null:r.paramDescriptorForKeyword(f("----"))}var m=q("GTfT",q("GWsT",q("GFWn",E.nullDescriptor)));function mine(d){return d.objectForKey("kCGWindowOwnerPID").intValue===p&&d.objectForKey("kCGWindowLayer").intValue===0}function top(){var l=ObjC.castRefToObject($.CGWindowListCopyWindowInfo(S,0));for(var j=0;j<+l.count;j++){var d=l.objectAtIndex(j);if(mine(d))return d.objectForKey("kCGWindowNumber").intValue}return 0}function n(k,x){return+$.CFArrayGetCount($.CGWindowListCreate(k,x))}function idle(){return Math.min($.CGEventSourceSecondsSinceLastEventType(0,1),$.CGEventSourceSecondsSinceLastEventType(0,10),$.CGEventSourceSecondsSinceLastEventType(0,12))}function now(){return $.NSDate.date.timeIntervalSince1970.toFixed(6)}function say(s){o.writeData($(s+"\n").dataUsingEncoding(4))}while(!a.terminated&&$.getppid()===u){var x=w?n(A,w):-2,v=!w||x!==b||!n($.kCGWindowListOptionIncludingWindow,w);if(v||z++%40===0){L.runUntilDate($.NSDate.date);h=W.frontmostApplication.processIdentifier===p;var e=top();w=e;b=e?n(A,e):-1;if(!e){var d=$.NSRunningApplication.runningApplicationWithProcessIdentifier(p);if(!d||d.isNil())break}if(h&&e&&e!==k){k=e;var at=now();if(c[e])say("1 "+c[e]+" "+at);var y=g(q("Gtty",m)),i=g(q("Gpid",m));if(y&&i&&!y.isNil()&&!i.isNil()){var r=y.stringValue.js+" "+i.int32Value;if(r!==c[e])say("1 "+r+" "+now());if(top()===e)c[e]=r}}}if(!h)k=0;delay(!w?1:!h?0.25:idle()<1.5?0.05:0.15)}}'
8
9
 
9
10
  __tt_follows_focus() { return 0 }
10
11
 
@@ -95,8 +96,8 @@ __tt_ghostty_ask() {
95
96
  }
96
97
 
97
98
  __tt_ghostty_check() {
98
- local REPLY shown key pal conf=${TTHEME_CONFIG:h}/backgrounds/shown.conf
99
- local -a at ans rec
99
+ local REPLY shown conf=${TTHEME_CONFIG:h}/backgrounds/shown.conf
100
+ local -a at
100
101
  integer n
101
102
  __tt_ghostty_modules
102
103
  for (( n = 0; n < 3; n++ )); do
@@ -108,17 +109,35 @@ __tt_ghostty_check() {
108
109
  zstat -F %s.%N -A at +mtime -- $conf 2>/dev/null
109
110
  [[ $at[1] == "$shown" ]] && break
110
111
  done
111
- if [[ $REPLY == blind ]] || { [[ $REPLY == none ]] && (( ++TTHEME_GHOSTTY_NONE >= 5 )) }; then
112
+ __tt_ghostty_take "$REPLY"
113
+ }
114
+
115
+ __tt_ghostty_take() {
116
+ local REPLY key pal
117
+ local -a ans rec at
118
+ local -F now=$EPOCHREALTIME
119
+ [[ $1 == gone ]] && return 1
120
+ if [[ $1 == none ]]; then
121
+ (( TTHEME_GHOSTTY_PID )) && ! kill -0 $TTHEME_GHOSTTY_PID 2>/dev/null && return 1
122
+ (( TTHEME_GHOSTTY_NONE )) || TTHEME_GHOSTTY_NONE_AT=$now
123
+ (( ++TTHEME_GHOSTTY_NONE ))
124
+ fi
125
+ if [[ $1 == blind ]] || { [[ $1 == none ]] && (( TTHEME_GHOSTTY_NONE >= 5 && now - TTHEME_GHOSTTY_NONE_AT >= 30 )) }; then
112
126
  __tt_put $TTHEME_GHOSTTY_TABS/.blind "${TERM_PROGRAM_VERSION:--}" 2>/dev/null
113
127
  return 1
114
128
  fi
115
- [[ $REPLY == none ]] && return 0
129
+ [[ $1 == none ]] && return 0
116
130
  TTHEME_GHOSTTY_NONE=0
117
- ans=(${=REPLY})
131
+ ans=(${=1})
118
132
  if [[ $ans[1] != 1 || -z $ans[2] ]]; then
119
133
  TTHEME_GHOSTTY_FRONT=""
120
134
  return 0
121
135
  fi
136
+ if [[ -n $ans[4] ]]; then
137
+ at=("")
138
+ zstat -F %s.%N -A at +mtime -- ${TTHEME_CONFIG:h}/backgrounds/shown.conf 2>/dev/null
139
+ [[ -n $at[1] ]] && (( at[1] > ans[4] )) && return 0
140
+ fi
122
141
  __tt_ghostty_key $ans[2]
123
142
  key=$REPLY
124
143
  TTHEME_GHOSTTY_FRONT=$key TTHEME_GHOSTTY_IDLE=1
@@ -137,9 +156,10 @@ __tt_ghostty_tick() {
137
156
  local -a at rec
138
157
  local -F now=$EPOCHREALTIME
139
158
  integer seen
159
+ [[ -n $TTHEME_GHOSTTY_CODE ]] && zstat -F %s.%N -A at +mtime -- $TTHEME_HOME/adapters/ghostty.zsh 2>/dev/null && [[ $at[1] != "$TTHEME_GHOSTTY_CODE" ]] && return 1
140
160
  zstat -F %s.%N -A at +mtime -- $TTHEME_HOME/palettes.zsh 2>/dev/null && [[ $at[1] != "$TTHEME_PALETTES_AT" ]] && __tt_palettes_load
141
161
  if zstat -F %s.%N -A at +mtime -- $TTHEME_GHOSTTY_TABS/.blur 2>/dev/null && [[ $at[1] != "$TTHEME_GHOSTTY_BLUR" ]]; then
142
- [[ -n $TTHEME_GHOSTTY_BLUR ]] && TTHEME_GHOSTTY_WANT=$now
162
+ [[ -n $TTHEME_GHOSTTY_BLUR ]] && (( now - TTHEME_GHOSTTY_TOLD >= 1 )) && TTHEME_GHOSTTY_WANT=$now
143
163
  TTHEME_GHOSTTY_BLUR=$at[1]
144
164
  fi
145
165
  for f in $TTHEME_GHOSTTY_TABS/[^.]*(N); do
@@ -155,14 +175,14 @@ __tt_ghostty_tick() {
155
175
  (( seen )) || continue
156
176
  if [[ $key == "$TTHEME_GHOSTTY_FRONT" ]]; then
157
177
  TTHEME_GHOSTTY_HUSH=$now
158
- elif (( ++TTHEME_GHOSTTY_RUN[$key] < 5 )); then
178
+ elif (( ++TTHEME_GHOSTTY_RUN[$key] < 5 && now - TTHEME_GHOSTTY_TOLD >= 1 )); then
159
179
  TTHEME_GHOSTTY_WANT=$now
160
180
  fi
161
181
  done
162
- if (( TTHEME_GHOSTTY_HUSH && now - TTHEME_GHOSTTY_HUSH >= 0.3 && now - TTHEME_GHOSTTY_ASKED >= (TTHEME_GHOSTTY_IDLE ? 10 : 2) )); then
182
+ if (( ! TTHEME_GHOSTTY_WFD && TTHEME_GHOSTTY_HUSH && now - TTHEME_GHOSTTY_HUSH >= 0.3 && now - TTHEME_GHOSTTY_ASKED >= (TTHEME_GHOSTTY_IDLE ? 10 : 2) )); then
163
183
  TTHEME_GHOSTTY_HUSH=0 TTHEME_GHOSTTY_WANT=$now
164
184
  fi
165
- (( TTHEME_GHOSTTY_WANT && now - TTHEME_GHOSTTY_ASKED >= 0.2 )) || return 0
185
+ (( TTHEME_GHOSTTY_WANT && now - TTHEME_GHOSTTY_ASKED >= 0.2 && ( ! TTHEME_GHOSTTY_WFD || now - TTHEME_GHOSTTY_WANT >= 0.4 ) )) || return 0
166
186
  TTHEME_GHOSTTY_WANT=0
167
187
  __tt_ghostty_check
168
188
  }
@@ -183,20 +203,56 @@ __tt_ghostty_live() {
183
203
  (( live ))
184
204
  }
185
205
 
206
+ __tt_ghostty_watch() {
207
+ (( TTHEME_GHOSTTY_PID )) || return 0
208
+ coproc osascript -l JavaScript -e $TTHEME_GHOSTTY_WATCH $TTHEME_GHOSTTY_PID 2>/dev/null
209
+ TTHEME_GHOSTTY_WATCHER=$!
210
+ exec {TTHEME_GHOSTTY_WFD}<&p
211
+ }
212
+
213
+ __tt_ghostty_heard() {
214
+ local chunk line
215
+ integer rc
216
+ sysread -t 0 -i $TTHEME_GHOSTTY_WFD chunk 2>/dev/null
217
+ rc=$?
218
+ if (( rc == 2 || rc == 5 )); then
219
+ exec {TTHEME_GHOSTTY_WFD}<&-
220
+ TTHEME_GHOSTTY_WFD=0 TTHEME_GHOSTTY_HEARD=""
221
+ return 0
222
+ fi
223
+ TTHEME_GHOSTTY_HEARD+=$chunk
224
+ while [[ $TTHEME_GHOSTTY_HEARD == *$'\n'* ]]; do
225
+ line=${TTHEME_GHOSTTY_HEARD%%$'\n'*}
226
+ TTHEME_GHOSTTY_HEARD=${TTHEME_GHOSTTY_HEARD#*$'\n'}
227
+ TTHEME_GHOSTTY_TOLD=$EPOCHREALTIME TTHEME_GHOSTTY_WANT=0
228
+ __tt_ghostty_take "$line" || return 1
229
+ done
230
+ return 0
231
+ }
232
+
186
233
  __tt_ghostty_follower() {
187
234
  emulate -L zsh
188
235
  local fd REPLY
236
+ local -a at
189
237
  __tt_ghostty_modules
190
238
  zsystem flock -t 0 -f fd $TTHEME_GHOSTTY_TABS/.follow 2>/dev/null || return 0
191
239
  trap '' HUP
240
+ zstat -F %s.%N -A at +mtime -- $TTHEME_HOME/adapters/ghostty.zsh 2>/dev/null && TTHEME_GHOSTTY_CODE=$at[1]
192
241
  __tt_ghostty_owner $PPID
193
242
  TTHEME_GHOSTTY_PID=$REPLY
194
243
  __tt_ghostty_check || return 0
244
+ __tt_ghostty_watch
195
245
  while [[ -e $TTHEME_HOME/palettes.zsh ]]; do
196
246
  __tt_ghostty_tick || break
197
247
  (( ++TTHEME_GHOSTTY_TICK % 50 )) || __tt_ghostty_live || break
198
- zselect -t 10
248
+ if (( TTHEME_GHOSTTY_WFD )); then
249
+ zselect -t 50 -r $TTHEME_GHOSTTY_WFD && { __tt_ghostty_heard || break }
250
+ else
251
+ zselect -t 10
252
+ fi
199
253
  done
254
+ (( TTHEME_GHOSTTY_WATCHER )) && kill $TTHEME_GHOSTTY_WATCHER 2>/dev/null
255
+ return 0
200
256
  }
201
257
 
202
258
  __tt_reset_reloaded() {
@@ -224,6 +280,41 @@ __tt_shown() {
224
280
  __tt_put $dir/shown.conf "config-file = ?${${1/@/--}/\//--}.conf"
225
281
  }
226
282
 
283
+ __tt_ghostty_took() {
284
+ local f=${TTHEME_CONFIG:h}/backgrounds/shown.conf
285
+ local -A st
286
+ local -F t
287
+ zmodload -F zsh/datetime p:EPOCHREALTIME 2>/dev/null
288
+ t=$EPOCHREALTIME
289
+ while zstat -H st -F %s.%N -- $f 2>/dev/null && [[ ! $st[atime] > $st[mtime] ]]; do
290
+ (( EPOCHREALTIME - t < 0.1 )) || return 0
291
+ done
292
+ t=$EPOCHREALTIME
293
+ while (( EPOCHREALTIME - t < 0.003 )); do :; done
294
+ }
295
+
296
+ __tt_wear() {
297
+ local REPLY=$2 name
298
+ [[ -n $REPLY ]] || __tt_name_of "$1"
299
+ name=$REPLY
300
+ TTHEME_SPEC=$1
301
+ if [[ -n ${TTHEME_PALETTE[$name]} ]] && __tt_shown "$name" $3; then
302
+ TTHEME_GHOSTTY_SENT=0
303
+ __tt_reload
304
+ (( TTHEME_GHOSTTY_SENT )) && __tt_ghostty_took
305
+ __tt_apply "$1"
306
+ return 0
307
+ fi
308
+ __tt_apply "$1"
309
+ return 1
310
+ }
311
+
312
+ __tt_pv_claim() {
313
+ TTHEME_GHOSTTY_SENT=0
314
+ __tt_shown "$1" force && __tt_reload && (( TTHEME_GHOSTTY_SENT )) && __tt_ghostty_took
315
+ return 0
316
+ }
317
+
227
318
  __tt_bg_cells() {
228
319
  local REPLY resp line v f
229
320
  local -i px=2 py=2 fs=0 sc=2
@@ -2,8 +2,9 @@ source $TTHEME_HOME/adapters/_bg.zsh
2
2
 
3
3
  typeset -g TTHEME_WARP_SETTINGS=$HOME/.warp/settings.toml TTHEME_WARP_THEMES=$HOME/.warp/themes TTHEME_WARP_WORN=""
4
4
  typeset -g TTHEME_WARP_TABS=$TTHEME_STATE_DIR/warp TTHEME_WARP_DB="" TTHEME_WARP_ID="" TTHEME_WARP_LAST="" TTHEME_WARP_SEEN=""
5
- typeset -g TTHEME_WARP_SHOWING="" TTHEME_WARP_VIEW=""
6
- typeset -gi TTHEME_WARP_VIEWS=0 TTHEME_WARP_BUSY=0 TTHEME_WARP_FOLLOWS=-1 TTHEME_WARP_TICK=0
5
+ typeset -g TTHEME_WARP_SHOWING="" TTHEME_WARP_VIEW="" TTHEME_WARP_CODE="" TTHEME_WARP_RECORDS=""
6
+ typeset -gi TTHEME_WARP_VIEWS=0 TTHEME_WARP_BUSY=0 TTHEME_WARP_FOLLOWS=-1 TTHEME_WARP_UP=0 TTHEME_WARP_SQLPID=0 TTHEME_WARP_MIXED=0
7
+ typeset -gF TTHEME_WARP_WARM=0 TTHEME_WARP_PRIMED=0 TTHEME_WARP_LIVED=0
7
8
  typeset -ga TTHEME_WARP_LAID=()
8
9
  typeset -g TTHEME_WARP_SQL='with t as (select id, window_id, row_number() over (partition by window_id order by id) - 1 as ix from tabs) select lower(hex(p.uuid)) from app a join windows w on w.id = a.active_window_id join t on t.window_id = w.id and t.ix = w.active_tab_index join pane_nodes n on n.tab_id = t.id and n.is_leaf join pane_leaves l on l.pane_node_id = n.id and l.is_focused join terminal_panes p on p.id = n.id'
9
10
  if [[ $OSTYPE != darwin* ]]; then
@@ -194,8 +195,48 @@ __tt_warp_follow() {
194
195
 
195
196
  __tt_warp_active() {
196
197
  setopt localoptions extendedglob
197
- REPLY=$(sqlite3 -readonly -cmd '.timeout 300' $TTHEME_WARP_DB $TTHEME_WARP_SQL 2>/dev/null)
198
- [[ $REPLY == [0-9a-f](#c32) ]]
198
+ local line
199
+ REPLY=""
200
+ if (( ! TTHEME_WARP_SQLPID )) || ! kill -0 $TTHEME_WARP_SQLPID 2>/dev/null; then
201
+ coproc sqlite3 -readonly -batch -cmd '.timeout 300' $TTHEME_WARP_DB 2>/dev/null
202
+ TTHEME_WARP_SQLPID=$!
203
+ fi
204
+ if print -rp -- "$TTHEME_WARP_SQL; select 'end';" 2>/dev/null; then
205
+ while read -rp -t 1 line; do
206
+ [[ $line == end ]] && { [[ $REPLY == [0-9a-f](#c32) ]]; return }
207
+ REPLY=$line
208
+ done
209
+ fi
210
+ TTHEME_WARP_SQLPID=0 REPLY=""
211
+ return 1
212
+ }
213
+
214
+ __tt_warp_stamp() {
215
+ local -a at
216
+ zstat -F %s.%N -A at +mtime -- $TTHEME_WARP_DB-wal 2>/dev/null || zstat -F %s.%N -A at +mtime -- $TTHEME_WARP_DB 2>/dev/null || return 1
217
+ REPLY=$at[1]
218
+ }
219
+
220
+ __tt_warp_mixed() {
221
+ setopt localoptions extendedglob
222
+ local f pal view
223
+ local -a rec
224
+ local -A looks
225
+ for f in $TTHEME_WARP_TABS/[0-9a-f](#c32)(N); do
226
+ rec=(${=${"$(<$f)"}})
227
+ pal=${rec[3]#-} view=${rec[4]#-}
228
+ [[ $rec[2] != - && -z $TTHEME_STARTUP ]] && pal="" view=""
229
+ pal="${pal:-$TTHEME_STARTUP} $view"
230
+ looks[$pal]=1
231
+ done
232
+ (( ${#looks} > 1 ))
233
+ }
234
+
235
+ __tt_warp_prime() {
236
+ local fd byte
237
+ sysopen -rw -u fd $TTHEME_WARP_SETTINGS 2>/dev/null || return 0
238
+ sysread -s 1 -i $fd byte && sysseek -u $fd 0 && syswrite -o $fd -- $byte
239
+ exec {fd}>&-
199
240
  }
200
241
 
201
242
  __tt_warp_line() {
@@ -207,18 +248,28 @@ __tt_warp_line() {
207
248
  __tt_warp_tick() {
208
249
  local line="" REPLY
209
250
  local -a at
210
- if zstat -F %s.%N -A at +mtime -- $TTHEME_WARP_DB-wal 2>/dev/null || zstat -F %s.%N -A at +mtime -- $TTHEME_WARP_DB 2>/dev/null; then
211
- if [[ $at[1] != "$TTHEME_WARP_SEEN" ]]; then
212
- TTHEME_WARP_SEEN=$at[1]
213
- if __tt_warp_active && [[ $REPLY != "$TTHEME_WARP_ID" ]]; then
214
- TTHEME_WARP_ID=$REPLY
251
+ integer recount=0
252
+ if __tt_warp_stamp && [[ $REPLY != "$TTHEME_WARP_SEEN" ]]; then
253
+ TTHEME_WARP_SEEN=$REPLY
254
+ if __tt_warp_active; then
255
+ TTHEME_WARP_UP=1
256
+ if [[ $REPLY != "$TTHEME_WARP_ID" ]]; then
257
+ TTHEME_WARP_ID=$REPLY recount=1
215
258
  __tt_put $TTHEME_WARP_TABS/.active $REPLY 2>/dev/null
216
259
  fi
260
+ else
261
+ TTHEME_WARP_UP=0
217
262
  fi
218
263
  fi
219
- zstat -F %s.%N -A at +mtime -- $TTHEME_HOME/palettes.zsh 2>/dev/null && [[ $at[1] != "$TTHEME_PALETTES_AT" ]] && __tt_palettes_load
264
+ zstat -F %s.%N -A at +mtime -- $TTHEME_HOME/palettes.zsh 2>/dev/null && [[ $at[1] != "$TTHEME_PALETTES_AT" ]] && __tt_palettes_load && recount=1
265
+ zstat -F %s.%N -A at +mtime -- $TTHEME_WARP_TABS 2>/dev/null && [[ $at[1] != "$TTHEME_WARP_RECORDS" ]] && TTHEME_WARP_RECORDS=$at[1] recount=1
266
+ if (( recount )); then
267
+ __tt_warp_mixed
268
+ TTHEME_WARP_MIXED=$(( ! $? ))
269
+ fi
220
270
  [[ -n $TTHEME_WARP_ID && -r $TTHEME_WARP_TABS/$TTHEME_WARP_ID ]] && line=$(<$TTHEME_WARP_TABS/$TTHEME_WARP_ID)
221
271
  [[ "$TTHEME_WARP_ID $line $TTHEME_PALETTES_AT" == "$TTHEME_WARP_LAST" ]] && return 0
272
+ [[ ${TTHEME_WARP_LAST%% *} == "$TTHEME_WARP_ID" ]] && TTHEME_WARP_WARM=$(( EPOCHREALTIME + 3 ))
222
273
  TTHEME_WARP_LAST="$TTHEME_WARP_ID $line $TTHEME_PALETTES_AT"
223
274
  [[ -n $line ]] && __tt_warp_line ${=line} && __tt_warp_wear "$REPLY"
224
275
  return 0
@@ -239,15 +290,64 @@ __tt_warp_live() {
239
290
  (( live ))
240
291
  }
241
292
 
293
+ __tt_pv_conf_rows() {
294
+ cvars+=(TTHEME_WARP_FAST) clabel+=("Warp tabs") cchoice+=("on off") cshow+=("on off")
295
+ cnote+=(
296
+ TTHEME_WARP_FAST:on "About 0.2 s per switch, for about 8% CPU"
297
+ TTHEME_WARP_FAST:off "About 0.6 s per switch"
298
+ )
299
+ }
300
+
301
+ __tt_warp_warming() {
302
+ [[ $TTHEME_WARP_FAST == on ]] && (( TTHEME_WARP_UP && ( TTHEME_WARP_MIXED || EPOCHREALTIME < TTHEME_WARP_WARM ) ))
303
+ }
304
+
305
+ __tt_warp_wait() {
306
+ local REPLY
307
+ local -F now=$EPOCHREALTIME end=$(( EPOCHREALTIME + 0.1 ))
308
+ if ! __tt_warp_warming; then
309
+ zselect -t 10
310
+ return 0
311
+ fi
312
+ while (( now < end )); do
313
+ if (( now - TTHEME_WARP_PRIMED >= 0.25 )); then
314
+ __tt_warp_prime
315
+ TTHEME_WARP_PRIMED=$now
316
+ fi
317
+ zselect -t 2
318
+ __tt_warp_stamp && [[ $REPLY != "$TTHEME_WARP_SEEN" ]] && return 0
319
+ now=$EPOCHREALTIME
320
+ done
321
+ return 0
322
+ }
323
+
324
+ __tt_warp_code() {
325
+ local -a at conf
326
+ zstat -F %s.%N -A at +mtime -- $TTHEME_HOME/adapters/warp.zsh 2>/dev/null
327
+ zstat -F %s.%N -A conf +mtime -- $TTHEME_CONFIG 2>/dev/null
328
+ REPLY="$at[1] $conf[1]"
329
+ }
330
+
242
331
  __tt_warp_follower() {
243
332
  emulate -L zsh
244
- local fd
333
+ local fd REPLY
245
334
  __tt_warp_db && zsystem flock -t 0 -f fd $TTHEME_WARP_TABS/.follow 2>/dev/null || return 0
246
- trap '' HUP
335
+ trap '' HUP PIPE
336
+ __tt_warp_code
337
+ TTHEME_WARP_CODE=$REPLY TTHEME_WARP_LIVED=$EPOCHREALTIME
247
338
  while [[ -e $TTHEME_HOME/palettes.zsh && -e $TTHEME_WARP_DB ]]; do
248
339
  __tt_warp_tick
249
- (( ++TTHEME_WARP_TICK % 50 )) || __tt_warp_live || break
250
- zselect -t 10
340
+ if (( EPOCHREALTIME - TTHEME_WARP_LIVED >= 5 )); then
341
+ TTHEME_WARP_LIVED=$EPOCHREALTIME
342
+ __tt_warp_live || break
343
+ __tt_warp_code
344
+ if [[ $REPLY != "$TTHEME_WARP_CODE" ]]; then
345
+ coproc :
346
+ zsystem flock -u $fd
347
+ exec zsh -fc 'source $1; __tt_warp_follower' zsh $TTHEME_HOME/ttheme.zsh
348
+ fi
349
+ fi
350
+ __tt_warp_wait
251
351
  done
252
352
  zf_rm -f -- $TTHEME_WARP_TABS/.active 2>/dev/null
253
353
  }
package/shell/ttheme.zsh CHANGED
@@ -118,6 +118,8 @@ __tt_pins_load
118
118
 
119
119
  : ${TTHEME_BG_COLORS:=tone}
120
120
 
121
+ : ${TTHEME_WARP_FAST:=on}
122
+
121
123
  typeset -g TTHEME_STATE_DIR=${XDG_STATE_HOME:-$HOME/.local/state}/ttheme
122
124
 
123
125
  () {
@@ -326,9 +328,8 @@ __tt_dir_sync() {
326
328
  fi
327
329
  TTHEME_PIN=$REPLY TTHEME_PIN_SPEC=$spec
328
330
  [[ -n $spec && $spec != "$TTHEME_SPEC" ]] || return 0
329
- __tt_apply "$spec"
330
- TTHEME_SPEC=$spec
331
- __tt_sync
331
+ __tt_wear "$spec"
332
+ return 0
332
333
  }
333
334
 
334
335
  __tt_chpwd() {
@@ -520,11 +521,11 @@ __tt_pin_save() {
520
521
  fi
521
522
  if [[ $spec != "$TTHEME_SPEC" ]]; then
522
523
  if [[ -n $spec ]]; then
523
- __tt_apply "$spec"
524
+ __tt_wear "$spec"
524
525
  else
525
526
  __tt_osc_reset
527
+ TTHEME_SPEC=
526
528
  fi
527
- TTHEME_SPEC=$spec
528
529
  fi
529
530
  __tt_dir_label "$base"
530
531
  k=$REPLY
@@ -1227,7 +1228,6 @@ __tt_catalog() {
1227
1228
  }
1228
1229
 
1229
1230
  __tt_switch() {
1230
- local spec
1231
1231
  __tt_cli "$@" || return
1232
1232
  [[ -r $TTHEME_HOME/palettes.zsh ]] && __tt_palettes_load && __tt_reloaded
1233
1233
  if ! __tt_active; then
@@ -1237,11 +1237,7 @@ __tt_switch() {
1237
1237
  if [[ $1 == off ]]; then
1238
1238
  __tt_off_here reload
1239
1239
  elif [[ -n $TTHEME_STARTUP ]]; then
1240
- spec=${TTHEME_PALETTE[$TTHEME_STARTUP]}
1241
- __tt_apply "$spec"
1242
- TTHEME_SPEC=$spec
1243
- __tt_shown "$TTHEME_STARTUP" force
1244
- __tt_reload
1240
+ __tt_wear "${TTHEME_PALETTE[$TTHEME_STARTUP]}" "$TTHEME_STARTUP" force || __tt_reload
1245
1241
  fi
1246
1242
  }
1247
1243
 
@@ -1343,9 +1339,7 @@ __tt_next() {
1343
1339
  __tt_rotate() {
1344
1340
  local REPLY
1345
1341
  __tt_next
1346
- __tt_apply "$REPLY"
1347
- TTHEME_SPEC=$REPLY
1348
- __tt_worn_shown force && __tt_reload
1342
+ __tt_wear "$REPLY" "" force
1349
1343
  __tt_announce
1350
1344
  }
1351
1345
 
@@ -2210,7 +2204,7 @@ __tt_pv_draw() {
2210
2204
  split=$(( sw > 0 )) sc=$(( pw - 1 - sw ))
2211
2205
  h=$(( ph - 5 ))
2212
2206
  [[ -n $tune ]] && (( ! split )) && h=$(( ph - 14 ))
2213
- (( conf && ! split )) && h=$(( ph - 12 ))
2207
+ (( conf && ! split )) && h=$(( ph - 6 - ${#cvars} ))
2214
2208
  reach=()
2215
2209
  if [[ -n $pick && $mode == pin ]]; then
2216
2210
  if (( split )); then
@@ -2359,8 +2353,8 @@ __tt_pv_draw() {
2359
2353
  __tt_pv_head $(( ph - 10 )) 1 $lw $tune "$REPLY" $state
2360
2354
  __tt_pv_bg_panel $tpick $(( ph - 9 )) 1 $lw
2361
2355
  elif (( conf )); then
2362
- __tt_pv_head $(( ph - 8 )) 1 $lw Config
2363
- __tt_pv_conf_panel $(( ph - 7 )) 1 $lw
2356
+ __tt_pv_head $(( ph - 2 - ${#cvars} )) 1 $lw Config
2357
+ __tt_pv_conf_panel $(( ph - 1 - ${#cvars} )) 1 $lw
2364
2358
  fi
2365
2359
  (( help )) && __tt_pv_help
2366
2360
  fi
@@ -2671,6 +2665,7 @@ __tt_preview() {
2671
2665
  TTHEME_BG_COLORS:tone "New pictures are tinted in one color of the palette"
2672
2666
  TTHEME_BG_COLORS:original "New pictures keep their own colors"
2673
2667
  )
2668
+ __tt_pv_conf_rows
2674
2669
  [[ $mode == pin ]] && __tt_pin_scopes "$pdir"
2675
2670
  [[ $mode == init ]] && pkdef=2
2676
2671
  __tt_pv_canpick
@@ -2710,6 +2705,7 @@ __tt_preview() {
2710
2705
  done
2711
2706
  } always {
2712
2707
  local spec=${sel:+${TTHEME_PALETTE[$sel]}}
2708
+ [[ -n $spec && $mode != pin ]] && (( ! ${#bgedit} && ! ${#bgswap} )) && __tt_pv_claim "$sel"
2713
2709
  printf '\e[?2026h'
2714
2710
  __tt_pv_bg_close
2715
2711
  if [[ -n $spec ]]; then
@@ -2786,14 +2782,11 @@ ttheme() {
2786
2782
  [[ $1 == config ]] && { __tt_config; return }
2787
2783
  (( ${#TTHEME_PALETTE} )) || { __tt_empty; return }
2788
2784
 
2789
- local REPLY spec
2785
+ local REPLY
2790
2786
  case $1 in
2791
2787
  use)
2792
2788
  __tt_resolve "$2" || return 1
2793
- spec=${TTHEME_PALETTE[$REPLY]}
2794
- __tt_apply "$spec"
2795
- TTHEME_SPEC=$spec
2796
- __tt_shown "$REPLY" force && __tt_reload
2789
+ __tt_wear "${TTHEME_PALETTE[$REPLY]}" "$REPLY" force
2797
2790
  __tt_announce ;;
2798
2791
  next) __tt_rotate ;;
2799
2792
  default)