@kecan0406/ttheme 1.2.6 → 1.2.8

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.
package/shell/ttheme.zsh CHANGED
@@ -33,6 +33,7 @@ __tt_fresh() {
33
33
  __tt_prompt() {
34
34
  emulate -L zsh ${=${options[xtrace]:#off}:+-o xtrace}
35
35
  (( TTHEME_FRONT < 0 )) || TTHEME_FRONT=0
36
+ [[ -n $TTHEME_SSH_SPEC ]] && __tt_ssh_back
36
37
  __tt_fresh
37
38
  }
38
39
 
@@ -48,7 +49,7 @@ __tt_gone() {
48
49
  __tt_reload
49
50
  __tt_reset_reloaded $bg
50
51
  print -n $'\e[?1004l'
51
- for hook in precmd:__tt_prompt precmd:__tt_precmd precmd:__tt_prompted precmd:__tt_unmux preexec:__tt_preexec preexec:__tt_mux chpwd:__tt_chpwd; do
52
+ for hook in precmd:__tt_prompt precmd:__tt_precmd precmd:__tt_prompted precmd:__tt_unmux preexec:__tt_preexec preexec:__tt_ran chpwd:__tt_chpwd; do
52
53
  add-zsh-hook -d ${hook%%:*} ${hook#*:}
53
54
  done
54
55
  (( $+functions[add-zle-hook-widget] )) && add-zle-hook-widget -d line-init __tt_line_init
@@ -80,9 +81,15 @@ typeset -g TTHEME_PINS_FILE=${TTHEME_CONFIG:h}/pins
80
81
  typeset -g TTHEME_PINS_RAW="" TTHEME_PINS_AT=""
81
82
  typeset -gA TTHEME_PINS=()
82
83
  typeset -g TTHEME_PIN="" TTHEME_PIN_SPEC="" TTHEME_BASE_SPEC=""
84
+ typeset -g TTHEME_SSH_SPEC="" TTHEME_SSH_BACK=""
83
85
 
84
86
  __tt_tilde() { REPLY=${1/#$HOME\//\~/} }
85
87
 
88
+ __tt_ssh_ok() {
89
+ setopt localoptions extendedglob
90
+ [[ $1 == ssh:[[:alnum:]._*?:-]## ]]
91
+ }
92
+
86
93
  __tt_pins_load() {
87
94
  emulate -L zsh ${=${options[xtrace]:#off}:+-o xtrace}
88
95
  setopt localoptions extendedglob
@@ -96,10 +103,16 @@ __tt_pins_load() {
96
103
  TTHEME_PINS=()
97
104
  for line in "${(@f)raw}"; do
98
105
  line=${line%%[[:space:]]##}
99
- [[ $line == [~/]*[[:space:]]* ]] || continue
106
+ [[ $line == ([~/]|ssh:)*[[:space:]]* ]] || continue
100
107
  name=${line##*[[:space:]]} key=${${line%[[:space:]]*}%%[[:space:]]##}
101
- [[ $key == \~ ]] && key=$HOME
102
- TTHEME_PINS[${key/#\~\//$HOME/}]=$name
108
+ if [[ $key == ssh:* ]]; then
109
+ key=ssh:${(L)key#ssh:}
110
+ __tt_ssh_ok $key || continue
111
+ TTHEME_PINS[$key]=$name
112
+ else
113
+ [[ $key == \~ ]] && key=$HOME
114
+ TTHEME_PINS[${key/#\~\//$HOME/}]=$name
115
+ fi
103
116
  [[ -n ${TTHEME_PALETTE[$name]} ]] || print -u2 "ttheme: unknown palette '$name' pinned to $key"
104
117
  done
105
118
  }
@@ -124,7 +137,9 @@ typeset -g TTHEME_STATE_DIR=${XDG_STATE_HOME:-$HOME/.local/state}/ttheme
124
137
 
125
138
  () {
126
139
  emulate -L zsh ${=${options[xtrace]:#off}:+-o xtrace}
127
- if [[ $TERM_PROGRAM == WarpTerminal ]]; then
140
+ if [[ -n $NVIM || -n $VIM_TERMINAL || -n $INSIDE_EMACS || $TERM_PROGRAM == vscode ]]; then
141
+ typeset -g TTHEME_ADAPTER=editor
142
+ elif [[ $TERM_PROGRAM == WarpTerminal ]]; then
128
143
  typeset -g TTHEME_ADAPTER=warp
129
144
  elif [[ -n $GHOSTTY_RESOURCES_DIR || $TERM_PROGRAM == ghostty ]]; then
130
145
  typeset -g TTHEME_ADAPTER=ghostty
@@ -163,7 +178,7 @@ __tt_active() {
163
178
  }
164
179
 
165
180
  typeset -g TTHEME_HEARD=""
166
- typeset -gi TTHEME_RECHECK=0 TTHEME_FOCUS=0 TTHEME_FRONT=-1
181
+ typeset -gi TTHEME_RECHECK=0 TTHEME_FOCUS=0 TTHEME_FRONT=-1 TTHEME_RAN=0
167
182
 
168
183
  __tt_put() {
169
184
  local f=${1:A}
@@ -237,6 +252,18 @@ __tt_recheck() {
237
252
  fi
238
253
  }
239
254
 
255
+ __tt_mend() {
256
+ local REPLY
257
+ local -a p=(${(L)=TTHEME_SPEC})
258
+ local -A got
259
+ TTHEME_RAN=0
260
+ [[ -n $TTHEME_PAINTED ]] && (( ${#p} >= 20 )) && __tt_reverts || return 0
261
+ __tt_ask $'\e]11;?\e\\\e]12;?\e\\' || return 0
262
+ __tt_colors "$REPLY"
263
+ [[ $p[1] == - || ${got[11]:-$p[1]} == $p[1] ]] && [[ ${got[12]:-$p[3]} == $p[3] ]] && return 0
264
+ __tt_apply "$TTHEME_SPEC"
265
+ }
266
+
240
267
  source $TTHEME_HOME/adapters/_osc.zsh
241
268
  source $TTHEME_HOME/adapters/_wired.zsh
242
269
  [[ -r $TTHEME_HOME/adapters/$TTHEME_ADAPTER.zsh ]] &&
@@ -257,25 +284,6 @@ __tt_name_of() { REPLY=${${(k)TTHEME_PALETTE[(re)$1]}:-custom} }
257
284
 
258
285
  __tt_color() { [[ -t 1 && -z $NO_COLOR && $TERM != dumb ]] }
259
286
 
260
- __tt_palette_line() {
261
- local name=$1 width=$2 on=$3 label=${4:-$1} hex cell="" bar=""
262
- local -a p=(${=TTHEME_PALETTE[$name]}) sw=(${=TTHEME_SWATCH[$name]})
263
- (( ${#p} >= 20 )) || return 1
264
- for hex in $sw; do
265
- hex=${hex#\#}
266
- cell+=$'\e[38;2;'$((16#${hex:0:2}))';'$((16#${hex:2:2}))';'$((16#${hex:4:2}))'m■ '
267
- done
268
- if [[ -n $on ]]; then
269
- local cur=${p[3]#\#} sel=${p[4]#\#} fg=${p[2]#\#} ac
270
- printf -v ac '\e[38;2;%d;%d;%dm' $((16#${cur:0:2})) $((16#${cur:2:2})) $((16#${cur:4:2}))
271
- printf -v bar '\e[48;2;%d;%d;%d;38;2;%d;%d;%dm' \
272
- $((16#${sel:0:2})) $((16#${sel:2:2})) $((16#${sel:4:2})) $((16#${fg:0:2})) $((16#${fg:2:2})) $((16#${fg:4:2}))
273
- printf '%s▌\e[39m %s %s■\e[39m \e[1m%-*s\e[22m %s\e[0m\n' "$ac" "$bar" "$ac" "$width" "$label" "$cell"
274
- else
275
- printf ' %-*s %s\e[0m\n' "$width" "$label" "$cell"
276
- fi
277
- }
278
-
279
287
  __tt_announce() {
280
288
  (( TTHEME_ANNOUNCE )) || return 0
281
289
  local -a p=(${=TTHEME_SPEC})
@@ -298,7 +306,7 @@ __tt_announce() {
298
306
  __tt_dir_rule() {
299
307
  local k base best="" bestlen=-1 p=${1:A}
300
308
  for k in ${(k)TTHEME_PINS}; do
301
- [[ -n ${TTHEME_PALETTE[$TTHEME_PINS[$k]]} ]] || continue
309
+ [[ $k == /* && -n ${TTHEME_PALETTE[$TTHEME_PINS[$k]]} ]] || continue
302
310
  base=${${k%/\*\*}:A}
303
311
  if [[ $k == *"/**" ]]; then
304
312
  [[ $p == "$base" || $p == "${base%/}"/* ]] || continue
@@ -381,9 +389,77 @@ __tt_focus() {
381
389
  fi
382
390
  }
383
391
 
384
- __tt_mux() {
392
+ __tt_ssh_host() {
393
+ setopt localoptions extendedglob
394
+ local w o host=""
395
+ local -a words=(${(z)1})
396
+ local -i i=1 tty=0 ended=0
397
+ while [[ ${words[i]} == ([[:alpha:]_][[:alnum:]_]#=*|command|exec|noglob|nocorrect|-) ]]; do (( ++i )); done
398
+ [[ ${${(Q)words[i]}:t} == ssh ]] || return 1
399
+ for (( ++i; i <= ${#words}; i++ )); do
400
+ case ${words[i]} in
401
+ ('&&'|'||'|';'|';;'|';&'|';|') break ;;
402
+ ('2>'|'2>>'|'2>|'|'2>&') (( ++i )); continue ;;
403
+ ('&'|'&!'|'&|'|'|'|'|&'|[0-9]#[\<\>]*|'&>'*) return 1 ;;
404
+ esac
405
+ w=${(Q)words[i]}
406
+ if (( ! ended )) && [[ $w == -?* ]]; then
407
+ [[ $w == -- ]] && { ended=1; continue }
408
+ o=${w#-}
409
+ while [[ -n $o ]]; do
410
+ case ${o[1]} in
411
+ (t) (( ++tty )) ;;
412
+ ([fGNnsTVOQW]) return 1 ;;
413
+ ([BbcDEeFIiJLlmoPpRSw]) [[ -n ${o[2,-1]} ]] || (( ++i )); break ;;
414
+ esac
415
+ o=${o[2,-1]}
416
+ done
417
+ continue
418
+ fi
419
+ if [[ -n $host ]]; then
420
+ (( tty )) || return 1
421
+ break
422
+ fi
423
+ host=$w
424
+ done
425
+ [[ $host == ssh://* ]] && host=${${host#ssh://}%:<->}
426
+ REPLY=${(L)${${host##*@}#\[}%\]}
427
+ [[ -n $REPLY ]]
428
+ }
429
+
430
+ __tt_ssh_rule() {
431
+ local k best=""
432
+ [[ -n ${TTHEME_PALETTE[${TTHEME_PINS[ssh:$1]}]} ]] && { REPLY=ssh:$1; return 0 }
433
+ for k in ${(k)TTHEME_PINS}; do
434
+ [[ $k == ssh:*[*?]* && -n ${TTHEME_PALETTE[$TTHEME_PINS[$k]]} && $1 == ${~k#ssh:} ]] || continue
435
+ (( ${#k} > ${#best} )) && best=$k
436
+ done
437
+ [[ -n $best ]] || return 1
438
+ REPLY=$best
439
+ }
440
+
441
+ __tt_ssh_back() {
442
+ local back=$TTHEME_SSH_BACK worn=$TTHEME_SSH_SPEC
443
+ TTHEME_SSH_BACK="" TTHEME_SSH_SPEC=""
444
+ [[ $TTHEME_SPEC == "$worn" && $back != "$worn" ]] || return 0
445
+ if [[ -n $back ]]; then
446
+ __tt_wear "$back"
447
+ else
448
+ __tt_osc_reset
449
+ TTHEME_SPEC=
450
+ fi
451
+ }
452
+
453
+ __tt_ran() {
385
454
  emulate -L zsh ${=${options[xtrace]:#off}:+-o xtrace}
455
+ local REPLY name
456
+ TTHEME_RAN=1
386
457
  [[ ${${(z)3}[1]:t} == tmux ]] && TTHEME_MUXED=1
458
+ [[ $3 == *ssh* ]] && __tt_ssh_host "$3" && __tt_ssh_rule "$REPLY" || return 0
459
+ name=$TTHEME_PINS[$REPLY]
460
+ TTHEME_SSH_BACK=$TTHEME_SPEC TTHEME_SSH_SPEC=$TTHEME_PALETTE[$name]
461
+ [[ $TTHEME_SSH_SPEC == "$TTHEME_SPEC" ]] || __tt_wear "$TTHEME_SSH_SPEC" "$name"
462
+ return 0
387
463
  }
388
464
 
389
465
  __tt_unmux() {
@@ -402,6 +478,7 @@ __tt_blur() {
402
478
  __tt_line_init() {
403
479
  emulate -L zsh ${=${options[xtrace]:#off}:+-o xtrace}
404
480
  (( TTHEME_RECHECK )) && __tt_recheck
481
+ (( TTHEME_RAN )) && __tt_mend
405
482
  __tt_typed
406
483
  (( TTHEME_FOCUS )) && __tt_focus_on
407
484
  }
@@ -452,13 +529,24 @@ __tt_dir_label() {
452
529
  }
453
530
 
454
531
  __tt_pin_scope() {
455
- if [[ $1 == *"/**" ]]; then
532
+ if [[ $1 == ssh:* ]]; then
533
+ REPLY="while connected"
534
+ elif [[ $1 == *"/**" ]]; then
456
535
  REPLY="and below"
457
536
  else
458
537
  REPLY="this directory"
459
538
  fi
460
539
  }
461
540
 
541
+ __tt_pin_where() {
542
+ if [[ $1 == ssh:* ]]; then
543
+ REPLY="ssh ${1#ssh:}"
544
+ else
545
+ __tt_pin_base "$1"
546
+ __tt_dir_label "$REPLY"
547
+ fi
548
+ }
549
+
462
550
  __tt_repo() {
463
551
  local at=${1:a}
464
552
  while [[ $at != / ]]; do
@@ -485,6 +573,11 @@ __tt_pin_cover() {
485
573
 
486
574
  __tt_pin_scopes() {
487
575
  local d=${1:a} k
576
+ if [[ $1 == ssh:* ]]; then
577
+ plabel=(" This host ") pkeys=("$1") pkdef=1
578
+ [[ $1 == *[*?]* ]] && plabel=(" Every match ")
579
+ return 0
580
+ fi
488
581
  plabel=(" This directory " " And below ") pkeys=("$d" "${d%/}/**") pkdef=2
489
582
  if __tt_repo "$d" && [[ $REPLY != "$d" ]]; then
490
583
  plabel+=(" Repository ") pkeys+=("$REPLY/**")
@@ -498,26 +591,30 @@ __tt_pin_scopes() {
498
591
  }
499
592
 
500
593
  __tt_pin_save() {
501
- local name=$1 key=$2 k base spec REPLY
502
- __tt_pin_base "$key"
503
- base=$REPLY
504
- for k in ${(k)TTHEME_PINS}; do
505
- [[ $k == /* ]] || continue
506
- __tt_pin_base "$k"
507
- [[ $REPLY == "$base" ]] && unset "TTHEME_PINS[$k]"
508
- done
594
+ local name=$1 key=$2 k base spec=$3 REPLY
595
+ if [[ $key == /* ]]; then
596
+ __tt_pin_base "$key"
597
+ base=$REPLY
598
+ for k in ${(k)TTHEME_PINS}; do
599
+ [[ $k == /* ]] || continue
600
+ __tt_pin_base "$k"
601
+ [[ $REPLY == "$base" ]] && unset "TTHEME_PINS[$k]"
602
+ done
603
+ fi
509
604
  TTHEME_PINS[$key]=$name
510
605
  if ! __tt_pins_write; then
511
606
  print -u2 "ttheme pin: could not write $TTHEME_PINS_FILE"
512
607
  return 1
513
608
  fi
514
- [[ -n $TTHEME_PIN ]] || TTHEME_BASE_SPEC=$3
515
- if __tt_dir_rule "$PWD"; then
516
- spec=${TTHEME_PALETTE[$TTHEME_PINS[$REPLY]]}
517
- TTHEME_PIN=$REPLY TTHEME_PIN_SPEC=$spec
518
- else
519
- spec=$TTHEME_BASE_SPEC
520
- TTHEME_PIN="" TTHEME_PIN_SPEC=""
609
+ if [[ $key == /* ]]; then
610
+ [[ -n $TTHEME_PIN ]] || TTHEME_BASE_SPEC=$3
611
+ if __tt_dir_rule "$PWD"; then
612
+ spec=${TTHEME_PALETTE[$TTHEME_PINS[$REPLY]]}
613
+ TTHEME_PIN=$REPLY TTHEME_PIN_SPEC=$spec
614
+ else
615
+ spec=$TTHEME_BASE_SPEC
616
+ TTHEME_PIN="" TTHEME_PIN_SPEC=""
617
+ fi
521
618
  fi
522
619
  if [[ $spec != "$TTHEME_SPEC" ]]; then
523
620
  if [[ -n $spec ]]; then
@@ -527,7 +624,7 @@ __tt_pin_save() {
527
624
  TTHEME_SPEC=
528
625
  fi
529
626
  fi
530
- __tt_dir_label "$base"
627
+ __tt_pin_where "$key"
531
628
  k=$REPLY
532
629
  __tt_pin_scope "$key"
533
630
  if __tt_color; then
@@ -535,7 +632,7 @@ __tt_pin_save() {
535
632
  else
536
633
  print -r -- "Pinned · $name → $k · $REPLY"
537
634
  fi
538
- if [[ $TTHEME_PIN != "$key" ]]; then
635
+ if [[ $key == /* && $TTHEME_PIN != "$key" ]]; then
539
636
  __tt_here_line Here
540
637
  print -r -- "$REPLY"
541
638
  fi
@@ -544,10 +641,11 @@ __tt_pin_save() {
544
641
  __tt_unpin_drop() {
545
642
  local k REPLY where
546
643
  local -a gone=()
644
+ local -i dirs=0
547
645
  for k in "$@"; do
548
646
  [[ -n ${TTHEME_PINS[$k]} ]] || continue
549
- __tt_pin_base "$k"
550
- __tt_dir_label "$REPLY"
647
+ [[ $k == /* ]] && dirs=1
648
+ __tt_pin_where "$k"
551
649
  where=$REPLY
552
650
  __tt_pin_scope "$k"
553
651
  gone+=("Unpinned · ${TTHEME_PINS[$k]} on $where · $REPLY")
@@ -565,6 +663,7 @@ __tt_unpin_drop() {
565
663
  print -r -- "$k"
566
664
  fi
567
665
  done
666
+ (( dirs )) || return 0
568
667
  __tt_here_line Here
569
668
  print -r -- "$REPLY"
570
669
  }
@@ -719,6 +818,15 @@ __tt_unpin() {
719
818
  local -i chosen=0 color=0
720
819
  __tt_color && color=1
721
820
  __tt_pins_load
821
+ if [[ $1 == ssh:* ]]; then
822
+ k=ssh:${(L)1#ssh:}
823
+ if [[ -z ${TTHEME_PINS[$k]} ]]; then
824
+ print -u2 -r -- "ttheme unpin: nothing pinned to ssh ${k#ssh:}"
825
+ return 1
826
+ fi
827
+ __tt_unpin_drop $k
828
+ return
829
+ fi
722
830
  if (( $# )); then
723
831
  d=$1
724
832
  [[ $d == \~ || $d == \~/* ]] && d=$HOME${d#\~}
@@ -1063,12 +1171,22 @@ __tt_map_fit() {
1063
1171
  done
1064
1172
  }
1065
1173
 
1174
+ __tt_map_ssh() {
1175
+ local k name flag
1176
+ for k in ${(oi)${(M)${(k)TTHEME_PINS}:#ssh:*}}; do
1177
+ name=$TTHEME_PINS[$k] flag=""
1178
+ [[ -n ${TTHEME_PALETTE[$name]} ]] || flag="not installed"
1179
+ lp+=("") lpw+=(0) ll+=("ssh ${k#ssh:}") lat+=("$k") lpal+=("$name") lnote+=("while connected") lflag+=("$flag")
1180
+ done
1181
+ }
1182
+
1066
1183
  __tt_map_tree() {
1067
1184
  local home=${HOME:a} here=${PWD:a} htip="" REPLY
1068
1185
  local -A own=() below=() parent=() mark=() tstrip=()
1069
1186
  local -a roots=() lp=() lpw=() ll=() lat=() lpal=() lnote=() lflag=() reply
1070
1187
  local -i width=$(( COLUMNS > 0 ? COLUMNS : 80 ))
1071
1188
  __tt_map_build ""
1189
+ __tt_map_ssh
1072
1190
  __tt_map_fit $width
1073
1191
  print -rl -- "${reply[@]}"
1074
1192
  print
@@ -1127,42 +1245,12 @@ __tt_order() {
1127
1245
  }
1128
1246
 
1129
1247
  __tt_menu() {
1130
- local k cur="" grp last_grp="" shelf last_shelf="" label REPLY
1248
+ local k
1131
1249
  local -a reply
1132
- local -i width=0
1133
1250
  __tt_order
1134
- if ! __tt_color; then
1135
- for k in $reply; do
1136
- printf '%s\t%s\t%s\n' "$k" "${TTHEME_GROUP[$k]:-Other}" "${TTHEME_SRC[$k]:-unknown}"
1137
- done
1138
- return 0
1139
- fi
1140
- [[ -n $TTHEME_SPEC ]] && __tt_name_of "$TTHEME_SPEC" && cur=$REPLY
1141
- for k in $reply; do
1142
- label=${k##*/}
1143
- [[ -n ${TTHEME_CATALOG[$k]} && ${TTHEME_GROUP[$k]} == *@* ]] && label=" $label"
1144
- (( ${#label} > width )) && width=${#label}
1145
- done
1146
1251
  for k in $reply; do
1147
- grp=${TTHEME_GROUP[$k]:-Other}
1148
- if [[ $grp != $last_grp ]]; then
1149
- [[ $grp == *@* && $last_grp != *@* && -n $last_grp ]] && printf ' \033[2m── Markets ──────────\033[0m\n'
1150
- printf ' \033[1m%s\033[0m' "$grp"
1151
- [[ -n ${TTHEME_NATIVE[$k]} ]] && printf ' \033[2m%s\033[0m' "${TTHEME_NATIVE[$k]}"
1152
- printf '\n'
1153
- last_grp=$grp last_shelf=""
1154
- fi
1155
- shelf=""
1156
- [[ $grp == *@* ]] && shelf=${TTHEME_CATALOG[$k]}
1157
- if [[ -n $shelf && $shelf != "$last_shelf" ]]; then
1158
- printf ' \033[1m%s\033[0m\n' "$shelf"
1159
- last_shelf=$shelf
1160
- fi
1161
- label=${k##*/}
1162
- [[ -n $shelf ]] && label=" $label"
1163
- __tt_palette_line "$k" $width "${${(M)k:#$cur}:+1}" "$label"
1252
+ printf '%s\t%s\t%s\n' "$k" "${TTHEME_GROUP[$k]:-Other}" "${TTHEME_SRC[$k]:-unknown}"
1164
1253
  done
1165
- printf '\n \033[2mttheme use <palette> paints this tab · ttheme preview · ttheme help\033[0m\n'
1166
1254
  }
1167
1255
 
1168
1256
  __tt_help() {
@@ -1215,14 +1303,17 @@ __tt_cli() {
1215
1303
  }
1216
1304
 
1217
1305
  __tt_catalog() {
1218
- local was
1306
+ local was="$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}"
1219
1307
  __tt_cli "$@" || return
1220
1308
  [[ $1 == (list|share) ]] && return 0
1309
+ __tt_catalog_done "$was"
1310
+ }
1311
+
1312
+ __tt_catalog_done() {
1221
1313
  [[ -r $TTHEME_HOME/palettes.zsh ]] || return 0
1222
- was="$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}"
1223
1314
  __tt_palettes_load && __tt_reloaded
1224
- [[ "$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}" == "$was" ]] && return 0
1225
- __tt_follow "$was"
1315
+ [[ "$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}" == "$1" ]] && return 0
1316
+ __tt_follow "$1"
1226
1317
  __tt_worn_shown
1227
1318
  __tt_reload
1228
1319
  }
@@ -1453,6 +1544,11 @@ __tt_pv_shows() {
1453
1544
  }
1454
1545
 
1455
1546
  __tt_pv_focus() {
1547
+ if (( te )); then
1548
+ __tt_pv_shows $tename
1549
+ (( resized )) || [[ $REPLY == "$bgname" ]] || __tt_pv_bg_show "$REPLY"
1550
+ return 0
1551
+ fi
1456
1552
  [[ ${rtype[cur]} == thm ]] || return 0
1457
1553
  __tt_pv_shows ${rval[cur]}
1458
1554
  (( resized )) || [[ $REPLY == "$bgname" ]] || __tt_pv_bg_show "$REPLY"
@@ -1537,6 +1633,11 @@ __tt_pv_lw() {
1537
1633
  (( l < 38 )) && l=38
1538
1634
  (( l > 56 )) && l=56
1539
1635
  (( sw > 64 )) && sw=64
1636
+ if (( te && sw < 50 )); then
1637
+ sw=50
1638
+ (( pw - l - 6 < sw )) && l=$(( pw - sw - 6 ))
1639
+ (( l < 30 )) && l=30
1640
+ fi
1540
1641
  (( sw > pw - l - 6 )) && sw=$(( pw - l - 6 ))
1541
1642
  if (( color && sw >= 32 )); then
1542
1643
  lw=$l
@@ -1653,6 +1754,29 @@ __tt_pv_bg_title() {
1653
1754
  return 0
1654
1755
  }
1655
1756
 
1757
+ __tt_pv_bar() {
1758
+ local z=$'\e[0m' d=$'\e[2m' on=$'\e[7;1m'$ac line=" " title hint="tab next"
1759
+ local -i i at=${TTHEME_HUB_TABS[(Ie)preview]} len=${#TTHEME_HUB_TITLES}
1760
+ (( color )) || z= d= on=
1761
+ [[ ${rtype[cur]} == thm ]] && hint="⇧tab switch"
1762
+ for title in $TTHEME_HUB_TITLES; do
1763
+ (( len += ${#title} + 2 ))
1764
+ done
1765
+ for (( i = 1; i <= ${#TTHEME_HUB_TITLES}; i++ )); do
1766
+ title=${TTHEME_HUB_TITLES[i]}
1767
+ (( i > 1 )) && line+=" "
1768
+ if (( i != at )); then
1769
+ line+=$d" $title "$z
1770
+ elif (( color )); then
1771
+ line+=$on" $title "$z
1772
+ else
1773
+ line+="[$title]"
1774
+ fi
1775
+ done
1776
+ (( len + ${#hint} + 2 <= $1 )) && line+=" "$d$hint$z
1777
+ REPLY=$line
1778
+ }
1779
+
1656
1780
  __tt_pv_head() {
1657
1781
  local b=$'\e[1m' d=$'\e[2m' z=$'\e[0m' right=$6
1658
1782
  (( color )) || b= d= z=
@@ -1664,7 +1788,7 @@ __tt_pv_head() {
1664
1788
 
1665
1789
  __tt_pv_foot() {
1666
1790
  setopt localoptions extendedglob
1667
- 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
1791
+ 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 tb=EDIT
1668
1792
  local -a kk=() kl=() seg=()
1669
1793
  local -i end=$1 i lwid rwid room
1670
1794
  (( color )) || b= d= z= y= on=
@@ -1676,6 +1800,7 @@ __tt_pv_foot() {
1676
1800
  badge=HELP right=$b"? esc"$z$d" close"$z
1677
1801
  elif [[ -n $pick ]]; then
1678
1802
  badge='PREVIEW (APPLY)' lead="$pick →"
1803
+ (( te )) && badge="$tb (APPLY)"
1679
1804
  for (( i = 1; i <= ${#plabel}; i++ )); do
1680
1805
  if (( i != pk )); then
1681
1806
  lead+=" "$d${plabel[i]}$z
@@ -1687,34 +1812,58 @@ __tt_pv_foot() {
1687
1812
  done
1688
1813
  if [[ $mode == pin ]]; then
1689
1814
  badge='PREVIEW (PIN)'
1690
- __tt_pin_base "${pkeys[pk]}"
1691
- __tt_dir_label "$REPLY"
1815
+ (( te )) && badge="$tb (PIN)"
1816
+ __tt_pin_where "${pkeys[pk]}"
1692
1817
  note=$REPLY
1693
- elif (( pk == 1 )); then
1818
+ elif (( pk == 2 )); then
1694
1819
  note="Until this tab closes"
1695
1820
  else
1696
1821
  note="New tabs · the default palette"
1697
1822
  fi
1698
1823
  kk=(enter) kl=(confirm)
1699
1824
  right=$b"esc"$z$d" back"$z
1700
- elif [[ -n $tune ]]; then
1701
- badge='IMAGE EDIT' kk=(↑↓ ←→ '=' +) kl=(field step reset "reset all")
1702
- if (( tf == 2 )); then
1703
- kl[2]=move kk+=(1-9) kl+=(place)
1704
- elif (( tf == 4 )); then
1705
- kl[2]=switch kk=(${kk:#'='}) kl=("${(@)kl[1,2]}" "reset all")
1706
- else
1707
- kk+=(⇧←→) kl+=(×10)
1825
+ elif (( te && tfocus == 0 )); then
1826
+ badge=$tb
1827
+ kk=("${(@ps:\x1e:)teframe[6]}") kl=("${(@ps:\x1e:)teframe[7]}")
1828
+ i=${kk[(Ie)esc]}
1829
+ (( i )) && kk[i]=() kl[i]=()
1830
+ right=$b"esc"$z$d" cancel"$z
1831
+ if [[ $temode == list ]]; then
1832
+ kk=("${kk[1]}" s "${(@)kk[2,-1]}" ⇧enter) kl=("${kl[1]}" save "${(@)kl[2,-1]}" apply)
1833
+ elif [[ $temode == tune ]]; then
1834
+ right=$b"esc"$z$d" undo"$z
1835
+ elif [[ $temode == (type|compare) ]]; then
1836
+ right=$b"esc"$z$d" back"$z
1708
1837
  fi
1709
- if (( bgoff[$tpick] )); then
1710
- kk+=(space enter) kl+=(show keep)
1838
+ elif (( te && tfocus == 2 )); then
1839
+ badge=$tb kk=(enter ↑↓ s) kl=(apply move save)
1840
+ right=$b"esc"$z$d" cancel"$z
1841
+ elif (( te )); then
1842
+ badge=$tb
1843
+ kk=(↑↓ ←→ s) kl=(field step save)
1844
+ if [[ -n $tune ]] && (( tf == 5 )); then
1845
+ __tt_pv_bg_images $tune
1846
+ kl[2]="image ×$REPLY"
1847
+ (( REPLY > 1 )) || { kk[2]=() kl[2]=() }
1848
+ __tt_pv_bg_findable $tune && { kk+=(f); kl+=(find) }
1849
+ kk+=(D) kl+=(remove)
1850
+ elif [[ -n $tune ]]; then
1851
+ __tt_pv_bg_findable $tune && { kk+=(f); kl+=(find) }
1852
+ if (( tf == 2 )); then
1853
+ kl[2]=move kk+=(1-9 '=' +) kl+=(place reset "reset all")
1854
+ elif (( tf == 4 )); then
1855
+ kl[2]=switch kk+=(+) kl+=("reset all")
1856
+ else
1857
+ kk+=('=' + ⇧←→) kl+=(reset "reset all" ×10)
1858
+ fi
1859
+ (( bgoff[$tpick] )) && { kk+=(space); kl+=(show) } || { kk+=(c space); kl+=(colors hide) }
1860
+ __tt_pv_bg_images $tune
1861
+ (( REPLY > 1 )) && { kk+=(', .' D); kl+=("image ×$REPLY" remove) }
1711
1862
  else
1712
- kk+=(c space enter) kl+=(colors hide keep)
1863
+ kk=(enter ↑↓ s) kl=(find move save)
1713
1864
  fi
1714
- __tt_pv_bg_images $tune
1715
- (( REPLY > 1 )) && { kk+=(', .' D); kl+=("image ×$REPLY" remove) }
1716
- __tt_pv_bg_findable $tune && { kk+=(f); kl+=(find) }
1717
- right=$b"esc"$z$d" undo"$z
1865
+ kk+=(⇧enter) kl+=(apply)
1866
+ right=$b"esc"$z$d" cancel"$z
1718
1867
  elif (( conf )); then
1719
1868
  badge=CONFIG kk=(↑↓ ←→ enter) kl=(setting value save)
1720
1869
  right=$b"esc"$z$d" undo"$z
@@ -1730,13 +1879,7 @@ __tt_pv_foot() {
1730
1879
  kk=(→) kl=(open)
1731
1880
  fi
1732
1881
  else
1733
- kk=(enter) kl=(apply)
1734
- [[ $mode == pin ]] && kl[1]=pin
1735
- if __tt_pv_bg_state ${rval[cur]}; then
1736
- kk+=(tab) kl+=("tune bg")
1737
- elif __tt_pv_bg_findable ${rval[cur]}; then
1738
- kk+=(tab) kl+=("find bg")
1739
- fi
1882
+ kk=(enter tab) kl=(apply edit)
1740
1883
  (( split )) && { kk+=(⇧←→); kl+=(example) }
1741
1884
  [[ -n $flt ]] && { kk+=(bksp); kl+=(edit) }
1742
1885
  fi
@@ -1797,20 +1940,38 @@ __tt_pv_foot() {
1797
1940
  __tt_pv_help() {
1798
1941
  local back="the tab" z=$'\e[0m' b=$'\e[1m' blank
1799
1942
  [[ -n ${TTHEME_PALETTE[$cn]} ]] && back=$cn
1800
- local -a hk=(Move Series Filter "" Example Apply) hv=(
1801
- "↑↓ home end pgup pgdn"
1802
- "←→ · enter or space on a series"
1803
- "Any text · bksp · ctrl-u clears"
1804
- "Names and titles, in Japanese too"
1805
- "⇧←→ ${(Lj:, :)TTHEME_SCENES}"
1806
- "enter · esc restores $back"
1807
- )
1808
- if (( bgcw )); then
1809
- hk+=("Tune bg" "" "" "" "" "" "")
1810
- hv+=("tab · finds one on the boorus, or takes your own, if none" "↑↓ field ←→ step ⇧←→ ×10 1-9 place" "= resets a field · + resets all" "space hides · enter keeps · esc undoes" "c tone ↔ the picture's own colors" ", . other pictures · D removes one" "f adds one from the boorus or your own")
1943
+ local -a hk=() hv=()
1944
+ if (( te )); then
1945
+ hk=(Move Image "" "" "" Palette "" "" "" Apply Save Cancel)
1946
+ hv=(
1947
+ "↑↓ j k the image, the palette, then Apply · home end"
1948
+ "Images ←→ , . pick one · D removes it · f finds one"
1949
+ "enter on the empty frame · finds the first one"
1950
+ "←→ step ⇧←→ ×10 1-9 place · = resets · + all"
1951
+ "space hides · c colors"
1952
+ "←→ normal or bright · enter tab tune it · # a color"
1953
+ "r resets a slot · R all · space the colors before"
1954
+ "c copies · v pastes · = bright follows normal"
1955
+ "f moves the colors the gate misses · u undo"
1956
+ "enter on Apply, or ⇧enter anywhere · saves, asks where"
1957
+ "s · keeps the picture and the palette"
1958
+ "esc · back to the list, dropping what changed since s"
1959
+ )
1960
+ else
1961
+ hk=(Move Series Filter "" Example Apply Edit)
1962
+ hv=(
1963
+ "↑↓ home end pgup pgdn"
1964
+ "←→ · enter or space on a series"
1965
+ "Any text · bksp · ctrl-u clears"
1966
+ "Names and titles, in Japanese too"
1967
+ "⇧←→ ${(Lj:, :)TTHEME_SCENES}"
1968
+ "enter applies · esc restores $back"
1969
+ "tab → ctrl+e · its colors and picture"
1970
+ )
1971
+ hk+=(Config "")
1972
+ hv+=("alt-c · ↑↓ setting ←→ value" "enter saves · esc undoes")
1973
+ (( hub )) && { hk+=(Screens); hv+=("shift+tab · tab on a series") }
1811
1974
  fi
1812
- hk+=(Config "")
1813
- hv+=("alt-c · ↑↓ setting ←→ value" "enter saves · esc undoes")
1814
1975
  hk+=(Close)
1815
1976
  hv+=("? esc")
1816
1977
  (( color )) || z= b=
@@ -1824,6 +1985,7 @@ __tt_pv_help() {
1824
1985
  return 0
1825
1986
  fi
1826
1987
  w=$(( pw - 2 < 58 ? pw - 2 : 58 )) hh=$(( ${#hk} + 4 ))
1988
+ (( te )) && w=$(( pw - 2 < 76 ? pw - 2 : 76 ))
1827
1989
  x=$(( (pw - w) / 2 + 1 )) y=$(( (ph - hh) / 2 ))
1828
1990
  (( y < 4 )) && y=4
1829
1991
  blank=${(l:w:: :)}
@@ -1945,21 +2107,11 @@ __tt_pv_tune() {
1945
2107
  ',') __tt_pv_bg_pick -1 ;;
1946
2108
  '.') __tt_pv_bg_pick 1 ;;
1947
2109
  D) __tt_pv_bg_drop ;;
1948
- f)
1949
- __tt_pv_bg_findable $tune || return 0
1950
- name=$tune
1951
- __tt_pv_untune
1952
- __tt_pv_bg_find $name
1953
- __tt_pv_tune_open $name
1954
- ;;
1955
- $'\r'|$'\n') __tt_pv_tune_keep ;;
1956
- esc) __tt_pv_untune ;;
1957
- '?') help=1 ;;
1958
2110
  esac
1959
2111
  return 0
1960
2112
  }
1961
2113
 
1962
- __tt_pv_tune_keep() {
2114
+ __tt_pv_tune_stage() {
1963
2115
  local img was=${bgview[$tune]:-$tune}
1964
2116
  local -i changed=0
1965
2117
  for img in ${(k)tsnaps}; do
@@ -1975,10 +2127,14 @@ __tt_pv_tune_keep() {
1975
2127
  fi
1976
2128
  fi
1977
2129
  (( changed )) && msg="Kept · saved when preview closes" msgt=200
1978
- __tt_pv_bg_strip_off
1979
2130
  tune="" tpick="" tsnaps=() bgname=""
1980
2131
  }
1981
2132
 
2133
+ __tt_pv_tune_keep() {
2134
+ __tt_pv_bg_strip_off
2135
+ __tt_pv_tune_stage
2136
+ }
2137
+
1982
2138
  __tt_pv_untune() {
1983
2139
  local img
1984
2140
  local -a s
@@ -2003,8 +2159,8 @@ __tt_pv_regroup() {
2003
2159
  __tt_pv_conf() {
2004
2160
  case $key in
2005
2161
  $'\x03') return 1 ;;
2006
- up) cf=$(( cf > 1 ? cf - 1 : ${#cvars} )) ;;
2007
- down) cf=$(( cf < ${#cvars} ? cf + 1 : 1 )) ;;
2162
+ up|k) cf=$(( cf > 1 ? cf - 1 : ${#cvars} )) ;;
2163
+ down|j) cf=$(( cf < ${#cvars} ? cf + 1 : 1 )) ;;
2008
2164
  left|sleft) __tt_pv_conf_step -1 ;;
2009
2165
  right|sright) __tt_pv_conf_step 1 ;;
2010
2166
  $'\r'|$'\n') __tt_pv_conf_save ;;
@@ -2074,7 +2230,6 @@ __tt_pv_redraw() {
2074
2230
  msg="Drawing the background pictures again" msgt=300
2075
2231
  printf '\e[?2026h'
2076
2232
  __tt_pv_draw
2077
- __tt_pv_bg_close
2078
2233
  out=$(__tt_cli redraw 2>&1)
2079
2234
  bgsrc=() resized=1 bgname="" bgshown="" bgdim=()
2080
2235
  __tt_reload
@@ -2157,27 +2312,36 @@ __tt_pv_reach() {
2157
2312
  local -i room=$2
2158
2313
  (( color )) || d= z=
2159
2314
  (( room < 2 )) && room=2
2160
- __tt_pin_base "$key"
2161
- base=$REPLY
2162
- for k in ${(k)TTHEME_PINS}; do
2163
- [[ $k == /* ]] || continue
2164
- __tt_pin_base "$k"
2165
- [[ $REPLY == "$base" ]] || continue
2166
- if [[ $k != "$key" || $TTHEME_PINS[$k] != "$pick" ]]; then
2167
- __tt_pin_scope "$k"
2168
- was+=("${TTHEME_PINS[$k]} · $REPLY")
2169
- fi
2170
- unset "TTHEME_PINS[$k]"
2171
- done
2172
- TTHEME_PINS[$key]=$pick
2173
- top=$base
2174
- [[ $base != / ]] && __tt_pin_cover "${base:h}" && __tt_pin_base "$REPLY" && top=$REPLY
2175
- mark[$base]=new
2176
- __tt_map_build "$top"
2315
+ if [[ $key == ssh:* ]]; then
2316
+ __tt_pin_scope "$key"
2317
+ [[ -n ${TTHEME_PINS[$key]} && $TTHEME_PINS[$key] != "$pick" ]] && was+=("${TTHEME_PINS[$key]} · $REPLY")
2318
+ TTHEME_PINS[$key]=$pick
2319
+ mark[$key]=new
2320
+ __tt_map_ssh
2321
+ else
2322
+ __tt_pin_base "$key"
2323
+ base=$REPLY
2324
+ for k in ${(k)TTHEME_PINS}; do
2325
+ [[ $k == /* ]] || continue
2326
+ __tt_pin_base "$k"
2327
+ [[ $REPLY == "$base" ]] || continue
2328
+ if [[ $k != "$key" || $TTHEME_PINS[$k] != "$pick" ]]; then
2329
+ __tt_pin_scope "$k"
2330
+ was+=("${TTHEME_PINS[$k]} · $REPLY")
2331
+ fi
2332
+ unset "TTHEME_PINS[$k]"
2333
+ done
2334
+ TTHEME_PINS[$key]=$pick
2335
+ top=$base
2336
+ [[ $base != / ]] && __tt_pin_cover "${base:h}" && __tt_pin_base "$REPLY" && top=$REPLY
2337
+ mark[$base]=new
2338
+ __tt_map_build "$top"
2339
+ fi
2177
2340
  __tt_map_fit $1
2178
2341
  (( ${#reply} > room )) && reply=("${(@)reply[1,room-1]}" " …")
2179
- reach=("${reply[@]}" "")
2180
- __tt_dir_label "$base"
2342
+ reach=("${reply[@]}")
2343
+ [[ $key == /* || ${#was} -gt 0 ]] && reach+=("")
2344
+ __tt_pin_where "$key"
2181
2345
  base=$REPLY
2182
2346
  for k in $was; do
2183
2347
  __tt_clip "${d}Replaces ${k% · *} on $base · ${k##* · }$z" $1
@@ -2186,6 +2350,7 @@ __tt_pv_reach() {
2186
2350
  __tt_pin_scope "$key"
2187
2351
  __tt_clip "→ $base · $REPLY" $(( $1 - ${(m)#pick} - 2 ))
2188
2352
  rsub=$REPLY
2353
+ [[ $key == /* ]] || return 0
2189
2354
  __tt_here_fit "Then here" $1
2190
2355
  reach+=("${reply[@]}")
2191
2356
  }
@@ -2199,11 +2364,14 @@ __tt_pv_draw() {
2199
2364
  __tt_pv_norm "$flt"
2200
2365
  nflt=$REPLY
2201
2366
  fi
2367
+ if (( te )) && [[ -n $tespec && $tespec != "$applied" ]]; then
2368
+ __tt_pv_paint "$tespec"
2369
+ applied=$tespec
2370
+ fi
2202
2371
  __tt_pv_lw
2203
2372
  lw=$reply[1] sw=$reply[2]
2204
2373
  split=$(( sw > 0 )) sc=$(( pw - 1 - sw ))
2205
2374
  h=$(( ph - 5 ))
2206
- [[ -n $tune ]] && (( ! split )) && h=$(( ph - 14 ))
2207
2375
  (( conf && ! split )) && h=$(( ph - 6 - ${#cvars} ))
2208
2376
  reach=()
2209
2377
  if [[ -n $pick && $mode == pin ]]; then
@@ -2253,6 +2421,10 @@ __tt_pv_draw() {
2253
2421
  __tt_pv_flush
2254
2422
  return 0
2255
2423
  fi
2424
+ if (( te && ! split )); then
2425
+ __tt_pv_te_draw
2426
+ return 0
2427
+ fi
2256
2428
  if [[ -n $flt ]]; then
2257
2429
  if (( color )); then
2258
2430
  line=" "$'\e[1m'$flt$zz$ac$'\e[7m \e[0m'
@@ -2284,11 +2456,16 @@ __tt_pv_draw() {
2284
2456
  local tail=$'\e['$(( lw - ${#cnt} ))'G'$dd$cnt$zz
2285
2457
  [[ -n $flt ]] && tail=$'\e['$(( lw - ${#cnt} ))'G'$cnt
2286
2458
  if [[ $1 == hint ]] && (( ! wiped )); then
2287
- print -rn -- $'\e[H\e[0m\e['$lw'X'$line$tail
2288
- printf '\e[1;%dH\e[?2026l' $(( 4 + ${(m)#flt} ))
2459
+ print -rn -- $'\e['$(( 1 + hub ))$'H\e[0m\e['$lw'X'$line$tail
2460
+ printf '\e[%d;%dH\e[?2026l' $(( 1 + hub )) $(( 4 + ${(m)#flt} ))
2289
2461
  return 0
2290
2462
  fi
2291
- out+=$line$'\e[K'$tail$'\n\e[K\n'
2463
+ if (( hub )); then
2464
+ __tt_pv_bar $(( split ? sc - 2 : pw - 1 ))
2465
+ out+=$REPLY$'\e[K\n'$line$'\e[K'$tail$'\n'
2466
+ else
2467
+ out+=$line$'\e[K'$tail$'\n\e[K\n'
2468
+ fi
2292
2469
  (( N > h && top > 1 )) && out+=" "$dd"…"$zz
2293
2470
  out+=$'\e[K\n'
2294
2471
  for (( k = 0; k < ph - 4; k++ )); do
@@ -2316,17 +2493,15 @@ __tt_pv_draw() {
2316
2493
  for (( k = 1; k <= ${#reach} && k + 2 < ph; k++ )); do
2317
2494
  out+=$'\e['$(( k + 2 ))';'$sc'H'${reach[k]}
2318
2495
  done
2319
- elif [[ -n $tune ]]; then
2320
- (( bgoff[$tpick] )) && state=off
2321
- __tt_pv_bg_title $(( sw - ${#tune} - 6 ))
2322
- __tt_pv_head 1 $sc $se $tune "$REPLY" $state
2323
- __tt_pv_bg_panel $tpick 4 $sc $se
2324
2496
  elif (( conf )); then
2325
2497
  __tt_tilde "$TTHEME_CONFIG"
2326
2498
  src=$REPLY
2327
2499
  (( 8 + ${#src} > sw )) && src=""
2328
2500
  __tt_pv_head 1 $sc $se Config "" "$src"
2329
2501
  __tt_pv_conf_panel 4 $sc $se
2502
+ elif (( te )); then
2503
+ __tt_pv_te_head $sc $se
2504
+ __tt_pv_te_panel $sc $se 3 $(( ph - 1 ))
2330
2505
  else
2331
2506
  [[ -n $an ]] && src=${TTHEME_SRC[$an]}
2332
2507
  (( ${#an} + 2 + ${#src} > sw )) && src=""
@@ -2340,18 +2515,6 @@ __tt_pv_draw() {
2340
2515
  for (( k = 1; k <= ${#reach}; k++ )); do
2341
2516
  out+=$'\e['$(( ph - 1 - ${#reach} + k ))';1H'${reach[k]}
2342
2517
  done
2343
- elif [[ -n $tune ]]; then
2344
- (( bgoff[$tpick] )) && state=off
2345
- held=(${=bgpics[$tune]})
2346
- src=""
2347
- if (( ${#held} > 1 )); then
2348
- k=${held[(Ie)${${tpick#$tune}#:}]}
2349
- (( k )) || k=${held[(Ie)${bgact[$tune]}]}
2350
- src=" · $k/${#held}"
2351
- fi
2352
- __tt_pv_bg_title $(( lw - ${#tune} - 6 )) "$src"
2353
- __tt_pv_head $(( ph - 10 )) 1 $lw $tune "$REPLY" $state
2354
- __tt_pv_bg_panel $tpick $(( ph - 9 )) 1 $lw
2355
2518
  elif (( conf )); then
2356
2519
  __tt_pv_head $(( ph - 2 - ${#cvars} )) 1 $lw Config
2357
2520
  __tt_pv_conf_panel $(( ph - 1 - ${#cvars} )) 1 $lw
@@ -2431,9 +2594,17 @@ __tt_pv_getch() {
2431
2594
  read -sk 1 -t $1 2>/dev/null
2432
2595
  return
2433
2596
  fi
2434
- local t=0.2
2597
+ local -F t=0.2 at
2598
+ local -i quick=0
2435
2599
  (( gstep )) && t=0.06
2436
- while ! read -sk 1 -t $t 2>/dev/null; do
2600
+ while :; do
2601
+ at=$EPOCHREALTIME
2602
+ read -sk 1 -t $t 2>/dev/null && return 0
2603
+ if (( EPOCHREALTIME - at < t / 4 )); then
2604
+ (( ++quick >= 5 )) && { pvgone=1; return 1 }
2605
+ else
2606
+ quick=0
2607
+ fi
2437
2608
  [[ -t 0 ]] || return 1
2438
2609
  __tt_pv_size && return 1
2439
2610
  if (( osdt > 0 )); then
@@ -2445,9 +2616,8 @@ __tt_pv_getch() {
2445
2616
  (( msgt > 0 )) || return 1
2446
2617
  fi
2447
2618
  (( gstep )) && { gstep=$(( gstep - 1 )); tick=1; return 1 }
2448
- (( SECONDS >= exnext )) && { __tt_pv_roll; gstep=8; tick=1; return 1 }
2619
+ (( ! te && SECONDS >= exnext )) && { __tt_pv_roll; gstep=8; tick=1; return 1 }
2449
2620
  done
2450
- return 0
2451
2621
  }
2452
2622
 
2453
2623
  __tt_pv_read() {
@@ -2485,6 +2655,7 @@ __tt_pv_read() {
2485
2655
  "6~") key=pgdn ;;
2486
2656
  "1;2C") key=sright ;;
2487
2657
  "1;2D") key=sleft ;;
2658
+ "27;2;13~"|"13;2u") key=senter ;;
2488
2659
  Z) key=stab ;;
2489
2660
  *) key=nop ;;
2490
2661
  esac
@@ -2496,7 +2667,7 @@ __tt_pv_pick() {
2496
2667
  esc) pick="" ;;
2497
2668
  left|stab) pk=$(( (pk + ${#plabel} - 2) % ${#plabel} + 1 )) ;;
2498
2669
  right|$'\t') pk=$(( pk % ${#plabel} + 1 )) ;;
2499
- $'\r'|$'\n')
2670
+ $'\r'|$'\n'|senter)
2500
2671
  sel=$pick picked=$pk
2501
2672
  return 1
2502
2673
  ;;
@@ -2504,6 +2675,457 @@ __tt_pv_pick() {
2504
2675
  return 0
2505
2676
  }
2506
2677
 
2678
+ __tt_pv_screen() {
2679
+ local err
2680
+ local -i at=${TTHEME_HUB_TABS[(Ie)preview]} n=${#TTHEME_HUB_TABS} rc
2681
+ local -i to=$(( (at - 1 + $1 + n) % n + 1 ))
2682
+ __tt_pv_bg_close
2683
+ while (( to != at )); do
2684
+ hubwas="$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}"
2685
+ err=$(TTHEME_HUB=${TTHEME_HUB_TABS[to]} __tt_cli ${TTHEME_HUB_TABS[to]} 2>&1 >/dev/tty)
2686
+ rc=$?
2687
+ if (( rc == TTHEME_HUB_CLOSED )); then
2688
+ hubleft=1
2689
+ return 1
2690
+ elif (( rc > TTHEME_HUB_SWITCH && rc <= TTHEME_HUB_SWITCH + n )); then
2691
+ to=$(( rc - TTHEME_HUB_SWITCH ))
2692
+ else
2693
+ err=${${err//$'\n'/ }## #}
2694
+ msg=${err:-"${TTHEME_HUB_TITLES[to]} failed"} msgt=300
2695
+ to=$at
2696
+ fi
2697
+ done
2698
+ printf '\e[?2026h\e[?25l'
2699
+ if [[ -n $applied ]]; then
2700
+ __tt_pv_paint "$applied"
2701
+ else
2702
+ __tt_osc_reset
2703
+ painted=""
2704
+ fi
2705
+ resized=1 bgname="" bgshown="" bgdim=()
2706
+ return 0
2707
+ }
2708
+
2709
+ __tt_te_stop() {
2710
+ setopt localoptions nomonitor nonotify
2711
+ (( TE_IN )) && { print -r -u $TE_IN -- quit 2>/dev/null; exec {TE_IN}>&- }
2712
+ (( TE_OUT )) && exec {TE_OUT}<&-
2713
+ TE_IN=0 TE_OUT=0
2714
+ (( TE_PID )) && { kill $TE_PID 2>/dev/null; wait $TE_PID 2>/dev/null }
2715
+ TE_PID=0
2716
+ return 0
2717
+ }
2718
+
2719
+ __tt_te_ask() {
2720
+ local line
2721
+ (( TE_IN && TE_OUT )) || return 1
2722
+ print -r -u $TE_IN -- "$1" 2>/dev/null || { __tt_te_stop; return 1 }
2723
+ if ! IFS= read -r -u $TE_OUT -t 5 line 2>/dev/null; then
2724
+ __tt_te_stop
2725
+ msg="The palette panel stopped" msgt=300
2726
+ return 1
2727
+ fi
2728
+ teframe=("${(@ps:\x1f:)line}")
2729
+ temode=${teframe[3]:-list}
2730
+ tedirty=${teframe[4]:-0}
2731
+ [[ ${teframe[1]} == error ]] && { msg=${teframe[8]:-"Could not save the tone"} msgt=300 }
2732
+ [[ -n ${teframe[5]} ]] && tespec=${teframe[5]}
2733
+ return 0
2734
+ }
2735
+
2736
+ __tt_te_unsaved_image() {
2737
+ local img
2738
+ for img in ${(k)tsnaps}; do
2739
+ [[ "${bgsize[$img]} ${bgpos[$img]} ${bgop[$img]} ${bgoff[$img]}" == "${tsnaps[$img]}" ]] || return 0
2740
+ done
2741
+ [[ -n $tune && $tpick != "${bgview[$tune]:-$tune}" ]] && return 0
2742
+ return 1
2743
+ }
2744
+
2745
+ __tt_te_unsaved() {
2746
+ (( tedirty )) && return 0
2747
+ __tt_te_unsaved_image
2748
+ }
2749
+
2750
+ __tt_te_save_image() {
2751
+ __tt_te_unsaved_image || return 0
2752
+ __tt_pv_tune_keep
2753
+ __tt_pv_bg_save > /dev/null 2>&1
2754
+ bgedit=() bgswap=() bgview=()
2755
+ __tt_pv_bg_reset $tename
2756
+ bgload[$tename]=""
2757
+ __tt_pv_tune_open $tename
2758
+ }
2759
+
2760
+ __tt_te_open() {
2761
+ local name=$1
2762
+ local -i rfd wfd
2763
+ setopt localoptions nomonitor nonotify
2764
+ coproc __tt_cli tone $name 2>/dev/null
2765
+ exec {rfd}<&p {wfd}>&p
2766
+ TE_OUT=$rfd TE_IN=$wfd TE_PID=$!
2767
+ tename=$name tfocus=0 tespec="" tesz="" teframe=() tedirty=0 temode=list tetop=0 msgt=0
2768
+ if ! __tt_te_ask "focus 1"; then
2769
+ msg="Could not start the palette panel for $name" msgt=300
2770
+ __tt_te_stop
2771
+ return 0
2772
+ fi
2773
+ te=1
2774
+ (( bgcw )) && __tt_pv_bg_state $name && __tt_pv_tune_open $name
2775
+ __tt_te_image && __tt_te_to_image 1
2776
+ resized=1
2777
+ return 0
2778
+ }
2779
+
2780
+ __tt_te_close() {
2781
+ [[ -n $tune ]] && __tt_pv_untune
2782
+ __tt_te_stop
2783
+ te=0 tfocus=0 tename="" tespec="" tesz="" teframe=() tetop=0 help=0 pick=""
2784
+ resized=1 bgname=""
2785
+ return 0
2786
+ }
2787
+
2788
+ __tt_te_save() {
2789
+ __tt_te_save_image
2790
+ if (( tedirty )); then
2791
+ __tt_te_ask save || return 1
2792
+ if [[ ${teframe[1]} == saved ]]; then
2793
+ __tt_palettes_load && __tt_reloaded
2794
+ __tt_reload
2795
+ applied=${TTHEME_PALETTE[$tename]:-$applied}
2796
+ tespec=$applied
2797
+ else
2798
+ return 1
2799
+ fi
2800
+ fi
2801
+ msg="Saved" msgt=200
2802
+ return 0
2803
+ }
2804
+
2805
+ __tt_te_apply() {
2806
+ if __tt_te_unsaved; then
2807
+ __tt_te_save || return 0
2808
+ fi
2809
+ if (( canpick )); then
2810
+ pick=$tename pk=$pkdef
2811
+ return 0
2812
+ fi
2813
+ sel=$tename
2814
+ return 1
2815
+ }
2816
+
2817
+ __tt_te_image() {
2818
+ [[ -n $tune ]] || __tt_pv_bg_findable $tename
2819
+ }
2820
+
2821
+ __tt_te_to_image() {
2822
+ tfocus=1 tf=5
2823
+ [[ $1 == last && -n $tune ]] && tf=3
2824
+ __tt_te_ask "focus 0"
2825
+ }
2826
+
2827
+ __tt_te_to_palette() {
2828
+ tfocus=0
2829
+ __tt_te_ask "focus 1" && __tt_te_ask "key $1"
2830
+ }
2831
+
2832
+ __tt_te_to_apply() {
2833
+ tfocus=2
2834
+ __tt_te_ask "focus 0"
2835
+ }
2836
+
2837
+ __tt_te_to_top() {
2838
+ if __tt_te_image; then
2839
+ __tt_te_to_image first
2840
+ else
2841
+ __tt_te_to_palette home
2842
+ fi
2843
+ }
2844
+
2845
+ __tt_te_find() {
2846
+ local name=$tename
2847
+ __tt_pv_bg_findable $name || return 0
2848
+ __tt_te_save_image
2849
+ __tt_pv_untune
2850
+ __tt_pv_bg_find $name
2851
+ __tt_pv_bg_state $name && __tt_pv_tune_open $name
2852
+ tf=5
2853
+ return 0
2854
+ }
2855
+
2856
+ __tt_te_key() {
2857
+ local m
2858
+ if [[ $temode == list ]]; then
2859
+ case $key in
2860
+ home) __tt_te_to_top; return 0 ;;
2861
+ end) __tt_te_to_apply; return 0 ;;
2862
+ esac
2863
+ fi
2864
+ case $key in
2865
+ up|down|left|right|home|end|pgup|pgdn|esc) m="key $key" ;;
2866
+ sleft) m="key shift-left" ;;
2867
+ sright) m="key shift-right" ;;
2868
+ stab) m="key shift-tab" ;;
2869
+ $'\t') m="key tab" ;;
2870
+ $'\r'|$'\n') m="key enter" ;;
2871
+ $'\x7f'|$'\x08') m="key backspace" ;;
2872
+ $'\x03') m="key ctrl-c" ;;
2873
+ nop|altc) return 0 ;;
2874
+ *)
2875
+ (( ${#key} == 1 )) || return 0
2876
+ m="ch $(( #key ))"
2877
+ ;;
2878
+ esac
2879
+ __tt_te_ask "$m" || { __tt_te_close; return 0 }
2880
+ case ${teframe[2]} in
2881
+ save) __tt_te_save ;;
2882
+ cancel) __tt_te_close ;;
2883
+ below) __tt_te_to_apply ;;
2884
+ above)
2885
+ if __tt_te_image; then
2886
+ __tt_te_to_image last
2887
+ else
2888
+ __tt_te_to_apply
2889
+ fi
2890
+ ;;
2891
+ esac
2892
+ return 0
2893
+ }
2894
+
2895
+ __tt_pv_te_image() {
2896
+ local -a order=(5)
2897
+ local -i i
2898
+ [[ -n $tune ]] && order=(5 4 1 2 3)
2899
+ i=${order[(Ie)$tf]}
2900
+ (( i )) || { tf=5; i=1 }
2901
+ case $key in
2902
+ s) __tt_te_save ;;
2903
+ esc) __tt_te_close ;;
2904
+ up|k)
2905
+ if (( i > 1 )); then
2906
+ tf=${order[i-1]}
2907
+ else
2908
+ __tt_te_to_apply
2909
+ fi
2910
+ ;;
2911
+ down|j)
2912
+ if (( i < ${#order} )); then
2913
+ tf=${order[i+1]}
2914
+ else
2915
+ __tt_te_to_palette home
2916
+ fi
2917
+ ;;
2918
+ home) tf=5 ;;
2919
+ end) __tt_te_to_apply ;;
2920
+ $'\r'|$'\n') [[ -n $tune ]] || __tt_te_find ;;
2921
+ f) __tt_te_find ;;
2922
+ left|right|sleft|sright)
2923
+ if (( tf == 5 )); then
2924
+ if [[ -z $tune ]]; then
2925
+ :
2926
+ elif [[ $key == *left ]]; then
2927
+ __tt_pv_bg_pick -1
2928
+ else
2929
+ __tt_pv_bg_pick 1
2930
+ fi
2931
+ elif [[ -n $tune ]]; then
2932
+ __tt_pv_tune
2933
+ fi
2934
+ ;;
2935
+ '=') [[ -n $tune ]] && (( tf != 5 )) && __tt_pv_tune ;;
2936
+ *) [[ -n $tune ]] && __tt_pv_tune ;;
2937
+ esac
2938
+ [[ -n $tune ]] || tf=5
2939
+ return 0
2940
+ }
2941
+
2942
+ __tt_te_button() {
2943
+ case $key in
2944
+ $'\r'|$'\n') __tt_te_apply; return $? ;;
2945
+ s) __tt_te_save ;;
2946
+ esc) __tt_te_close ;;
2947
+ up|k) __tt_te_to_palette end ;;
2948
+ down|j|home) __tt_te_to_top ;;
2949
+ esac
2950
+ return 0
2951
+ }
2952
+
2953
+ __tt_pv_te() {
2954
+ case $key in
2955
+ $'\x03') return 1 ;;
2956
+ $'\x05') return 0 ;;
2957
+ senter) __tt_te_apply; return $? ;;
2958
+ '?') help=1; return 0 ;;
2959
+ esac
2960
+ case $tfocus in
2961
+ 0) __tt_te_key ;;
2962
+ 1) __tt_pv_te_image ;;
2963
+ *) __tt_te_button ;;
2964
+ esac
2965
+ return $?
2966
+ }
2967
+
2968
+ __tt_pv_te_head() {
2969
+ local z=$'\e[0m' d=$'\e[2m' b=$'\e[1m' y=$'\e[33m' line REPLY
2970
+ local -i col=$1 end=$2 room=$(( $2 - $1 + 1 ))
2971
+ (( color )) || z= d= b= y=
2972
+ __tt_te_unsaved && (( room -= 11 ))
2973
+ line=$b$ac"◆"$z" "$b$tename$z
2974
+ [[ -n ${TTHEME_GROUP[$tename]} ]] && line+=" "$d"· ${TTHEME_GROUP[$tename]}"$z
2975
+ __tt_clip "$line" $room
2976
+ out+=$'\e[1;'$col'H'$REPLY$z
2977
+ __tt_te_unsaved && out+=$'\e[1;'$(( end - 8 ))'H'$y"●"$z" "$d"unsaved"$z
2978
+ return 0
2979
+ }
2980
+
2981
+ __tt_pv_te_tile() {
2982
+ local z=$'\e[0m' d=$'\e[2m' b=$'\e[1m' sty top side bot
2983
+ local -i y=$1 col=$2 r tc=10
2984
+ (( color )) || z= d= b=
2985
+ if (( tfocus == 1 && tf == 5 )); then
2986
+ sty=$b$ac top="┏${(l:tc::━:)}┓" side="┃" bot="┗${(l:tc::━:)}┛"
2987
+ else
2988
+ sty=$d top="╭${(l:tc::─:)}╮" side="│" bot="╰${(l:tc::─:)}╯"
2989
+ fi
2990
+ out+=$'\e['$y';'$col'H'$sty$top$z
2991
+ for (( r = 1; r <= 3; r++ )); do
2992
+ out+=$'\e['$(( y + r ))';'$col'H'$sty$side${(l:tc::░:)}$side$z
2993
+ done
2994
+ out+=$'\e['$(( y + 4 ))';'$col'H'$sty$bot$z$'\e['$(( y + 2 ))';'$(( col + tc + 4 ))'H'
2995
+ if (( tfocus == 1 && tf == 5 )); then
2996
+ out+=$b"enter"$z$d" finds one"$z
2997
+ else
2998
+ out+=$d"enter finds one"$z
2999
+ fi
3000
+ return 0
3001
+ }
3002
+
3003
+ __tt_pv_te_ghost() {
3004
+ local z=$'\e[0m' d=$'\e[2m'
3005
+ local -i r0=$1 col=$2 T=$(( $3 - $2 - 21 )) i
3006
+ (( color )) || z= d=
3007
+ (( T < 8 )) && T=8
3008
+ out+=$'\e['$r0';'$col'H '$d"Colors"$'\e['$r0';'$(( col + 12 ))'H'" tone original "$z
3009
+ out+=$'\e['$(( r0 + 1 ))';'$col'H '$d"Size"$'\e['$(( r0 + 1 ))';'$(( col + 12 ))'H'${(l:T::─:)}$z
3010
+ for (( i = 1; i <= 9; i++ )); do
3011
+ out+=$'\e['$(( r0 + 3 + (i - 1) / 3 ))';'$(( col + 12 + (i - 1) % 3 * 3 ))'H'$d"·"$z
3012
+ done
3013
+ out+=$'\e['$(( r0 + 4 ))';'$col'H '$d"Position"$z
3014
+ out+=$'\e['$(( r0 + 7 ))';'$col'H '$d"Opacity"$'\e['$(( r0 + 7 ))';'$(( col + 12 ))'H'${(l:T::─:)}$z
3015
+ return 0
3016
+ }
3017
+
3018
+ __tt_pv_te_panel() {
3019
+ local z=$'\e[0m' d=$'\e[2m' b=$'\e[1m' tt st note REPLY
3020
+ local -a held
3021
+ local -i col=$1 end=$2 r0=$3 r1=$4 R W T I=3 V at i n y tfs=$tf lo=15
3022
+ (( color )) || z= d= b=
3023
+ R=$(( r1 - r0 + 1 )) W=$(( end - col + 1 ))
3024
+ [[ $temode == list ]] || lo=21
3025
+ [[ -n $tune ]] || __tt_pv_bg_findable $tename && I=17
3026
+ T=$(( R - I - 3 ))
3027
+ (( T > 26 )) && T=26
3028
+ (( T < 21 )) && T=$lo
3029
+ if [[ "$W $T" != "$tesz" ]]; then
3030
+ tesz="$W $T"
3031
+ __tt_te_ask "size $W $T"
3032
+ fi
3033
+ V=$(( I + T + 3 ))
3034
+ if (( V <= R || tfocus == 1 )); then
3035
+ tetop=0
3036
+ elif (( tfocus == 2 )); then
3037
+ tetop=$(( V - R ))
3038
+ else
3039
+ at=$(( I + 1 + ${teframe[9]:-2} ))
3040
+ (( at - 2 < tetop )) && tetop=$(( at > 2 ? at - 2 : 0 ))
3041
+ (( at > tetop + R )) && tetop=$(( at - R ))
3042
+ (( tetop > V - R )) && tetop=$(( V - R ))
3043
+ fi
3044
+ if (( tetop == 0 && I <= R )); then
3045
+ y=$r0
3046
+ tt=$d
3047
+ (( tfocus == 1 )) && tt=$b$ac
3048
+ out+=$'\e['$y';'$(( col + 2 ))'H'$tt"Image"$z
3049
+ if [[ -n $tune ]]; then
3050
+ (( bgoff[$tpick] )) && st=off || st=on
3051
+ __tt_pv_bg_title $(( W - 14 ))
3052
+ out+=" "$d$REPLY$z$'\e['$y';'$(( end - ${#st} + 1 ))'H'$d$st$z
3053
+ fi
3054
+ if (( I == 17 )); then
3055
+ held=() n=0 note="0/0"
3056
+ if [[ -n $tune ]]; then
3057
+ held=(${=bgpics[$tune]})
3058
+ n=${held[(Ie)${${tpick#$tune}#:}]}
3059
+ (( n )) || n=${held[(Ie)${bgact[$tune]}]}
3060
+ (( n )) || n=1
3061
+ note="$n/$(( ${#held} ? ${#held} : 1 ))"
3062
+ fi
3063
+ st=" " tt=$d
3064
+ (( tfocus == 1 && tf == 5 )) && st=$ac"▶"$z" " tt=$b
3065
+ out+=$'\e['$(( y + 2 ))';'$col'H'$st$tt"Images"$z$'\e['$(( y + 2 ))';'$(( end - ${#note} + 1 ))'H'$d$note$z
3066
+ if [[ -n $tune ]]; then
3067
+ bgstrip="$(( y + 2 )) $col $end"
3068
+ (( tfocus == 1 )) || tf=0
3069
+ __tt_pv_bg_panel $tpick $(( y + 9 )) $col $end
3070
+ tf=$tfs
3071
+ else
3072
+ __tt_pv_te_tile $(( y + 3 )) $col
3073
+ __tt_pv_te_ghost $(( y + 9 )) $col $end
3074
+ fi
3075
+ elif (( bgcw )); then
3076
+ out+=$'\e['$(( y + 2 ))';'$(( col + 2 ))'H'$d"No picture yet"$z
3077
+ else
3078
+ out+=$'\e['$(( y + 2 ))';'$(( col + 2 ))'H'$d"This terminal shows no pictures"$z
3079
+ fi
3080
+ fi
3081
+ for (( i = 1; i <= T; i++ )); do
3082
+ y=$(( r0 + I + i - tetop ))
3083
+ (( y >= r0 && y <= r1 )) || continue
3084
+ out+=$'\e['$y';'$col'H'${teframe[9 + i]}$z
3085
+ done
3086
+ y=$(( r0 + V - 1 - tetop ))
3087
+ (( y >= r0 && y <= r1 )) || return 0
3088
+ if [[ $mode == pin ]]; then
3089
+ note="saves, then asks how far it reaches"
3090
+ elif (( canpick )); then
3091
+ note="saves, then asks where"
3092
+ else
3093
+ note="saves and wears it in this tab"
3094
+ fi
3095
+ out+=$'\e['$y';'$col'H'
3096
+ if (( tfocus == 2 )); then
3097
+ (( color )) && out+=$ac"▶"$z" "$'\e[7;1m'$ac" Apply "$z || out+="▶ [Apply]"
3098
+ else
3099
+ (( color )) && out+=" "$b" Apply "$z || out+=" Apply "
3100
+ fi
3101
+ out+=" "$d$note$z
3102
+ return 0
3103
+ }
3104
+
3105
+ __tt_pv_te_draw() {
3106
+ local -i i end=$(( pw - 2 < 66 ? pw - 2 : 66 ))
3107
+ for (( i = 1; i < ph; i++ )); do
3108
+ out+=$'\e['$i$';1H\e[K'
3109
+ done
3110
+ __tt_pv_te_head 2 $end
3111
+ __tt_pv_te_panel 2 $end 3 $(( ph - 1 ))
3112
+ reach=()
3113
+ if [[ -n $pick && $mode == pin ]]; then
3114
+ __tt_pv_reach $se $(( ph - 13 ))
3115
+ if (( ${#reach} )); then
3116
+ __tt_pv_head $(( ph - 1 - ${#reach} )) 1 $se "$pick" "$rsub"
3117
+ for (( i = 1; i <= ${#reach}; i++ )); do
3118
+ out+=$'\e['$(( ph - 1 - ${#reach} + i ))$';1H\e[K'${reach[i]}
3119
+ done
3120
+ fi
3121
+ fi
3122
+ (( help )) && __tt_pv_help
3123
+ out+=$'\e['$ph';1H'
3124
+ __tt_pv_foot $pw
3125
+ (( osdt > 0 )) && __tt_pv_osd
3126
+ __tt_pv_flush
3127
+ }
3128
+
2507
3129
  __tt_pv_handle() {
2508
3130
  local name
2509
3131
  if (( help )); then
@@ -2517,6 +3139,10 @@ __tt_pv_handle() {
2517
3139
  __tt_pv_pick
2518
3140
  return
2519
3141
  fi
3142
+ if (( te )); then
3143
+ __tt_pv_te
3144
+ return
3145
+ fi
2520
3146
  if [[ -n $tune ]]; then
2521
3147
  __tt_pv_tune
2522
3148
  return
@@ -2543,7 +3169,7 @@ __tt_pv_handle() {
2543
3169
  fi
2544
3170
  fi
2545
3171
  ;;
2546
- $'\r'|$'\n')
3172
+ $'\r'|$'\n'|senter)
2547
3173
  if [[ ${rtype[cur]} == thm ]]; then
2548
3174
  if (( canpick )); then
2549
3175
  pick=${rval[cur]} pk=$pkdef
@@ -2571,7 +3197,14 @@ __tt_pv_handle() {
2571
3197
  cur=1
2572
3198
  fi
2573
3199
  ;;
2574
- right) [[ ${rtype[cur]} == (hdr|cat) && -z ${exp[${rval[cur]}]} ]] && __tt_pv_toggle ;;
3200
+ right)
3201
+ if [[ ${rtype[cur]} == thm ]]; then
3202
+ __tt_te_open ${rval[cur]}
3203
+ elif [[ ${rtype[cur]} == (hdr|cat) && -z ${exp[${rval[cur]}]} ]]; then
3204
+ __tt_pv_toggle
3205
+ fi
3206
+ ;;
3207
+ $'\x05') [[ ${rtype[cur]} == thm ]] && __tt_te_open ${rval[cur]} ;;
2575
3208
  left) __tt_pv_left ;;
2576
3209
  home) cur=1 ;;
2577
3210
  end) (( ${#rval} )) && cur=${#rval} ;;
@@ -2595,16 +3228,13 @@ __tt_pv_handle() {
2595
3228
  ;;
2596
3229
  ' ') [[ ${rtype[cur]} == (hdr|cat) ]] && __tt_pv_toggle ;;
2597
3230
  $'\t')
2598
- [[ ${rtype[cur]} == thm ]] || return 0
2599
- name=${rval[cur]}
2600
- if __tt_pv_bg_state $name || { __tt_pv_bg_findable $name && __tt_pv_bg_find $name }; then
2601
- __tt_pv_tune_open $name
2602
- elif __tt_pv_bg_findable $name; then
2603
- :
2604
- elif (( bgcw )); then
2605
- msg="No background image for $name" msgt=200
3231
+ if [[ ${rtype[cur]} == thm ]]; then
3232
+ __tt_te_open ${rval[cur]}
3233
+ elif (( hub )); then
3234
+ __tt_pv_screen 1 || return 1
2606
3235
  fi
2607
3236
  ;;
3237
+ stab) (( hub )) && { __tt_pv_screen -1 || return 1 } ;;
2608
3238
  altc)
2609
3239
  conf=1 cf=1 csnap=()
2610
3240
  for name in $cvars; do
@@ -2638,7 +3268,10 @@ __tt_pv_handle() {
2638
3268
 
2639
3269
  __tt_preview() {
2640
3270
  emulate -L zsh ${=${options[xtrace]:#off}:+-o xtrace}
2641
- local mode=$1 pdir=${2:-$PWD}
3271
+ zmodload -F zsh/datetime p:EPOCHREALTIME 2>/dev/null
3272
+ local mode=$1 pdir=${2:-$PWD} hubwas=""
3273
+ local -i hub=0 hubleft=0
3274
+ [[ $mode == hub ]] && hub=1
2642
3275
  if [[ ! -t 0 || ! -t 1 ]]; then
2643
3276
  print -u2 "ttheme ${mode:-preview}: needs a terminal"
2644
3277
  return 1
@@ -2649,9 +3282,11 @@ __tt_preview() {
2649
3282
  local -i scene=0
2650
3283
  local -a bgorder=()
2651
3284
  local -A bgfrom=() bgurl=() bgby=() bgsent=() bgcost=() bgdim=() bgsrc=() bgfill=() bgfocus=() bgsize=() bgpos=() bgop=() bgdef=() bgoff=() bgbase=() bgload=() bgshot=() bgshotkey=() bgedit=() bgtunef=() bgofff=() bgimages=()
2652
- local -A bgpic=() bgpics=() bgact=() bgview=() bgswap=() bgthumb=() tsnaps=() pvseek=() bgcolors=()
3285
+ local -A bgpic=() bgpics=() bgact=() bgview=() bgswap=() bgthumb=() tsnaps=() pvseek=() bgcolors=() bgprep=()
2653
3286
  local conf=0 cf=1
2654
- local -a plabel=(" This tab " " Default ") pkeys=() reach=() csnap=()
3287
+ local -a plabel=(" Default " " This tab ") pkeys=() reach=() csnap=() teframe=()
3288
+ local te=0 tfocus=0 tetop=0 tename="" tedirty=0 temode=list tespec="" tesz=""
3289
+ local -i TE_IN=0 TE_OUT=0 TE_PID=0 pvgone=0 bgprepid=0
2655
3290
  local -a cvars=(TTHEME_TAB_PALETTE TTHEME_ANNOUNCE TTHEME_FX TTHEME_SORT TTHEME_BG_BLUR TTHEME_BG_COLORS) clabel=("New tabs" Announce "Search fx" Sort Blur Colors)
2656
3291
  local -a cchoice=("off seq" "1 0" "typewriter decode glitch" "abc series" "0 1 2 3 4" "tone original") cshow=("off seq" "on off" "typewriter decode glitch" "abc series" "off 1px 2px 3px 4px" "tone original")
2657
3292
  local -A cnote=(
@@ -2667,7 +3302,6 @@ __tt_preview() {
2667
3302
  )
2668
3303
  __tt_pv_conf_rows
2669
3304
  [[ $mode == pin ]] && __tt_pin_scopes "$pdir"
2670
- [[ $mode == init ]] && pkdef=2
2671
3305
  __tt_pv_canpick
2672
3306
  __tt_pv_size
2673
3307
  local -a groups=() rtype=() rval=() rcnt=() reply=()
@@ -2686,7 +3320,7 @@ __tt_preview() {
2686
3320
  printf '\e[?2026h\e[?1049h\e[?7l\e[?25l'
2687
3321
  while :; do
2688
3322
  printf '\e[?2026h'
2689
- if (( tick )); then
3323
+ if (( tick && ! te )); then
2690
3324
  __tt_pv_draw hint
2691
3325
  else
2692
3326
  __tt_pv_focus
@@ -2695,6 +3329,7 @@ __tt_preview() {
2695
3329
  fi
2696
3330
  tick=0
2697
3331
  if ! __tt_pv_read; then
3332
+ (( pvgone )) && break
2698
3333
  [[ -t 0 ]] && continue
2699
3334
  break
2700
3335
  fi
@@ -2719,10 +3354,13 @@ __tt_preview() {
2719
3354
  elif [[ $applied != "$orig" ]]; then
2720
3355
  __tt_pv_paint "${TTHEME_PAINTED:+$orig}"
2721
3356
  fi
2722
- printf '\e[?7h\e[?1049l\e[?25h\e[?2026l'
3357
+ printf '\e[?7h'
3358
+ (( hubleft )) || printf '\e[?1049l'
3359
+ printf '\e[?25h\e[?2026l'
2723
3360
  [[ -n $tty ]] && stty "$tty" 2>/dev/null
2724
3361
  TTHEME_RAW=0
2725
3362
  [[ -n $tune ]] && __tt_pv_untune
3363
+ (( TE_IN )) && __tt_te_stop
2726
3364
  (( conf )) && __tt_pv_unconf
2727
3365
  __tt_pv_bg_save
2728
3366
  if [[ -n $spec ]]; then
@@ -2731,7 +3369,7 @@ __tt_preview() {
2731
3369
  __tt_pin_save "$sel" "${pkeys[picked]}" "$orig"
2732
3370
  [[ $TTHEME_SPEC == "$orig" ]] || __tt_announce
2733
3371
  __tt_sync
2734
- elif (( picked == 2 )); then
3372
+ elif (( picked == 1 )); then
2735
3373
  __tt_announce
2736
3374
  __tt_keep "$sel" force
2737
3375
  else
@@ -2741,6 +3379,7 @@ __tt_preview() {
2741
3379
  else
2742
3380
  (( ${#bgedit} + ${#bgswap} )) && [[ -n ${TTHEME_PALETTE[$cn]} ]] && { __tt_shown "$cn" && __tt_reload }
2743
3381
  fi
3382
+ (( hubleft )) && __tt_catalog_done "$hubwas"
2744
3383
  }
2745
3384
  return 0
2746
3385
  }
@@ -2769,7 +3408,11 @@ ttheme() {
2769
3408
  fi
2770
3409
  if (( ! $# )); then
2771
3410
  (( ${#TTHEME_PALETTE} )) || { __tt_empty; return }
2772
- __tt_menu
3411
+ if [[ -t 0 && -t 1 ]]; then
3412
+ __tt_preview hub
3413
+ else
3414
+ __tt_menu
3415
+ fi
2773
3416
  return 0
2774
3417
  fi
2775
3418
 
@@ -2794,12 +3437,18 @@ ttheme() {
2794
3437
  __tt_keep "$REPLY" ;;
2795
3438
  preview) __tt_preview ;;
2796
3439
  pin)
2797
- if [[ -n $2 ]]; then
3440
+ if [[ $2 == ssh:* ]]; then
3441
+ REPLY=ssh:${(L)2#ssh:}
3442
+ [[ $REPLY != ssh: ]] || { __tt_misuse pin "missing the host after ssh:"; return }
3443
+ [[ $REPLY != *@* ]] || { print -u2 -r -- "ttheme pin: an ssh pin names the host alone — ssh:${REPLY##*@}"; return 1 }
3444
+ __tt_ssh_ok $REPLY || { print -u2 -r -- "ttheme pin: not a host: ${2#ssh:} — letters, digits, . - : and the wildcards * ?"; return 1 }
3445
+ elif [[ -n $2 ]]; then
2798
3446
  REPLY=$2
2799
3447
  [[ $REPLY == \~ || $REPLY == \~/* ]] && REPLY=$HOME${REPLY#\~}
2800
3448
  [[ -d $REPLY ]] || { print -u2 -r -- "ttheme pin: no such directory: $2"; return 1 }
3449
+ REPLY=${REPLY:a}
2801
3450
  fi
2802
- __tt_preview pin ${REPLY:+${REPLY:a}} ;;
3451
+ __tt_preview pin ${REPLY:+$REPLY} ;;
2803
3452
  unpin) __tt_unpin "${@:2}" ;;
2804
3453
  pins) __tt_pins_map ;;
2805
3454
  esac
@@ -2824,7 +3473,17 @@ if (( ${+functions[compdef]} )); then
2824
3473
  elif [[ $words[2] == market && $words[3] == (add|init) && $CURRENT == 4 ]]; then
2825
3474
  _files -/
2826
3475
  elif [[ $words[2] == (pin|unpin) && $CURRENT == 3 ]]; then
2827
- _files -/
3476
+ reply=(${${(M)${(k)TTHEME_PINS}:#ssh:*}#ssh:})
3477
+ if compset -P 'ssh:'; then
3478
+ if [[ $words[2] == unpin ]]; then
3479
+ compadd -- $reply
3480
+ elif (( $+functions[_ssh_hosts] )); then
3481
+ _ssh_hosts
3482
+ fi
3483
+ else
3484
+ _files -/
3485
+ [[ $words[2] == pin || ${#reply} -gt 0 ]] && compadd -S '' -- ssh:
3486
+ fi
2828
3487
  elif [[ $words[2] == add && $words[CURRENT-1] == --market ]]; then
2829
3488
  _files -/
2830
3489
  elif [[ $words[2] == add ]]; then
@@ -2859,7 +3518,7 @@ fi
2859
3518
  add-zsh-hook chpwd __tt_chpwd
2860
3519
  add-zsh-hook precmd __tt_prompt
2861
3520
  if (( ! TTHEME_TMUX )); then
2862
- add-zsh-hook preexec __tt_mux
3521
+ add-zsh-hook preexec __tt_ran
2863
3522
  add-zsh-hook precmd __tt_unmux
2864
3523
  fi
2865
3524
  if __tt_follows_focus || (( TTHEME_TMUX )); then