@kecan0406/ttheme 1.2.7 → 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
 
@@ -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
  }
@@ -271,25 +284,6 @@ __tt_name_of() { REPLY=${${(k)TTHEME_PALETTE[(re)$1]}:-custom} }
271
284
 
272
285
  __tt_color() { [[ -t 1 && -z $NO_COLOR && $TERM != dumb ]] }
273
286
 
274
- __tt_palette_line() {
275
- local name=$1 width=$2 on=$3 label=${4:-$1} hex cell="" bar=""
276
- local -a p=(${=TTHEME_PALETTE[$name]}) sw=(${=TTHEME_SWATCH[$name]})
277
- (( ${#p} >= 20 )) || return 1
278
- for hex in $sw; do
279
- hex=${hex#\#}
280
- cell+=$'\e[38;2;'$((16#${hex:0:2}))';'$((16#${hex:2:2}))';'$((16#${hex:4:2}))'m■ '
281
- done
282
- if [[ -n $on ]]; then
283
- local cur=${p[3]#\#} sel=${p[4]#\#} fg=${p[2]#\#} ac
284
- printf -v ac '\e[38;2;%d;%d;%dm' $((16#${cur:0:2})) $((16#${cur:2:2})) $((16#${cur:4:2}))
285
- printf -v bar '\e[48;2;%d;%d;%d;38;2;%d;%d;%dm' \
286
- $((16#${sel:0:2})) $((16#${sel:2:2})) $((16#${sel:4:2})) $((16#${fg:0:2})) $((16#${fg:2:2})) $((16#${fg:4:2}))
287
- printf '%s▌\e[39m %s %s■\e[39m \e[1m%-*s\e[22m %s\e[0m\n' "$ac" "$bar" "$ac" "$width" "$label" "$cell"
288
- else
289
- printf ' %-*s %s\e[0m\n' "$width" "$label" "$cell"
290
- fi
291
- }
292
-
293
287
  __tt_announce() {
294
288
  (( TTHEME_ANNOUNCE )) || return 0
295
289
  local -a p=(${=TTHEME_SPEC})
@@ -312,7 +306,7 @@ __tt_announce() {
312
306
  __tt_dir_rule() {
313
307
  local k base best="" bestlen=-1 p=${1:A}
314
308
  for k in ${(k)TTHEME_PINS}; do
315
- [[ -n ${TTHEME_PALETTE[$TTHEME_PINS[$k]]} ]] || continue
309
+ [[ $k == /* && -n ${TTHEME_PALETTE[$TTHEME_PINS[$k]]} ]] || continue
316
310
  base=${${k%/\*\*}:A}
317
311
  if [[ $k == *"/**" ]]; then
318
312
  [[ $p == "$base" || $p == "${base%/}"/* ]] || continue
@@ -395,10 +389,77 @@ __tt_focus() {
395
389
  fi
396
390
  }
397
391
 
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
+
398
453
  __tt_ran() {
399
454
  emulate -L zsh ${=${options[xtrace]:#off}:+-o xtrace}
455
+ local REPLY name
400
456
  TTHEME_RAN=1
401
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
402
463
  }
403
464
 
404
465
  __tt_unmux() {
@@ -468,13 +529,24 @@ __tt_dir_label() {
468
529
  }
469
530
 
470
531
  __tt_pin_scope() {
471
- if [[ $1 == *"/**" ]]; then
532
+ if [[ $1 == ssh:* ]]; then
533
+ REPLY="while connected"
534
+ elif [[ $1 == *"/**" ]]; then
472
535
  REPLY="and below"
473
536
  else
474
537
  REPLY="this directory"
475
538
  fi
476
539
  }
477
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
+
478
550
  __tt_repo() {
479
551
  local at=${1:a}
480
552
  while [[ $at != / ]]; do
@@ -501,6 +573,11 @@ __tt_pin_cover() {
501
573
 
502
574
  __tt_pin_scopes() {
503
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
504
581
  plabel=(" This directory " " And below ") pkeys=("$d" "${d%/}/**") pkdef=2
505
582
  if __tt_repo "$d" && [[ $REPLY != "$d" ]]; then
506
583
  plabel+=(" Repository ") pkeys+=("$REPLY/**")
@@ -514,26 +591,30 @@ __tt_pin_scopes() {
514
591
  }
515
592
 
516
593
  __tt_pin_save() {
517
- local name=$1 key=$2 k base spec REPLY
518
- __tt_pin_base "$key"
519
- base=$REPLY
520
- for k in ${(k)TTHEME_PINS}; do
521
- [[ $k == /* ]] || continue
522
- __tt_pin_base "$k"
523
- [[ $REPLY == "$base" ]] && unset "TTHEME_PINS[$k]"
524
- 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
525
604
  TTHEME_PINS[$key]=$name
526
605
  if ! __tt_pins_write; then
527
606
  print -u2 "ttheme pin: could not write $TTHEME_PINS_FILE"
528
607
  return 1
529
608
  fi
530
- [[ -n $TTHEME_PIN ]] || TTHEME_BASE_SPEC=$3
531
- if __tt_dir_rule "$PWD"; then
532
- spec=${TTHEME_PALETTE[$TTHEME_PINS[$REPLY]]}
533
- TTHEME_PIN=$REPLY TTHEME_PIN_SPEC=$spec
534
- else
535
- spec=$TTHEME_BASE_SPEC
536
- 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
537
618
  fi
538
619
  if [[ $spec != "$TTHEME_SPEC" ]]; then
539
620
  if [[ -n $spec ]]; then
@@ -543,7 +624,7 @@ __tt_pin_save() {
543
624
  TTHEME_SPEC=
544
625
  fi
545
626
  fi
546
- __tt_dir_label "$base"
627
+ __tt_pin_where "$key"
547
628
  k=$REPLY
548
629
  __tt_pin_scope "$key"
549
630
  if __tt_color; then
@@ -551,7 +632,7 @@ __tt_pin_save() {
551
632
  else
552
633
  print -r -- "Pinned · $name → $k · $REPLY"
553
634
  fi
554
- if [[ $TTHEME_PIN != "$key" ]]; then
635
+ if [[ $key == /* && $TTHEME_PIN != "$key" ]]; then
555
636
  __tt_here_line Here
556
637
  print -r -- "$REPLY"
557
638
  fi
@@ -560,10 +641,11 @@ __tt_pin_save() {
560
641
  __tt_unpin_drop() {
561
642
  local k REPLY where
562
643
  local -a gone=()
644
+ local -i dirs=0
563
645
  for k in "$@"; do
564
646
  [[ -n ${TTHEME_PINS[$k]} ]] || continue
565
- __tt_pin_base "$k"
566
- __tt_dir_label "$REPLY"
647
+ [[ $k == /* ]] && dirs=1
648
+ __tt_pin_where "$k"
567
649
  where=$REPLY
568
650
  __tt_pin_scope "$k"
569
651
  gone+=("Unpinned · ${TTHEME_PINS[$k]} on $where · $REPLY")
@@ -581,6 +663,7 @@ __tt_unpin_drop() {
581
663
  print -r -- "$k"
582
664
  fi
583
665
  done
666
+ (( dirs )) || return 0
584
667
  __tt_here_line Here
585
668
  print -r -- "$REPLY"
586
669
  }
@@ -735,6 +818,15 @@ __tt_unpin() {
735
818
  local -i chosen=0 color=0
736
819
  __tt_color && color=1
737
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
738
830
  if (( $# )); then
739
831
  d=$1
740
832
  [[ $d == \~ || $d == \~/* ]] && d=$HOME${d#\~}
@@ -1079,12 +1171,22 @@ __tt_map_fit() {
1079
1171
  done
1080
1172
  }
1081
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
+
1082
1183
  __tt_map_tree() {
1083
1184
  local home=${HOME:a} here=${PWD:a} htip="" REPLY
1084
1185
  local -A own=() below=() parent=() mark=() tstrip=()
1085
1186
  local -a roots=() lp=() lpw=() ll=() lat=() lpal=() lnote=() lflag=() reply
1086
1187
  local -i width=$(( COLUMNS > 0 ? COLUMNS : 80 ))
1087
1188
  __tt_map_build ""
1189
+ __tt_map_ssh
1088
1190
  __tt_map_fit $width
1089
1191
  print -rl -- "${reply[@]}"
1090
1192
  print
@@ -1143,42 +1245,12 @@ __tt_order() {
1143
1245
  }
1144
1246
 
1145
1247
  __tt_menu() {
1146
- local k cur="" grp last_grp="" shelf last_shelf="" label REPLY
1248
+ local k
1147
1249
  local -a reply
1148
- local -i width=0
1149
1250
  __tt_order
1150
- if ! __tt_color; then
1151
- for k in $reply; do
1152
- printf '%s\t%s\t%s\n' "$k" "${TTHEME_GROUP[$k]:-Other}" "${TTHEME_SRC[$k]:-unknown}"
1153
- done
1154
- return 0
1155
- fi
1156
- [[ -n $TTHEME_SPEC ]] && __tt_name_of "$TTHEME_SPEC" && cur=$REPLY
1157
1251
  for k in $reply; do
1158
- label=${k##*/}
1159
- [[ -n ${TTHEME_CATALOG[$k]} && ${TTHEME_GROUP[$k]} == *@* ]] && label=" $label"
1160
- (( ${#label} > width )) && width=${#label}
1161
- done
1162
- for k in $reply; do
1163
- grp=${TTHEME_GROUP[$k]:-Other}
1164
- if [[ $grp != $last_grp ]]; then
1165
- [[ $grp == *@* && $last_grp != *@* && -n $last_grp ]] && printf ' \033[2m── Markets ──────────\033[0m\n'
1166
- printf ' \033[1m%s\033[0m' "$grp"
1167
- [[ -n ${TTHEME_NATIVE[$k]} ]] && printf ' \033[2m%s\033[0m' "${TTHEME_NATIVE[$k]}"
1168
- printf '\n'
1169
- last_grp=$grp last_shelf=""
1170
- fi
1171
- shelf=""
1172
- [[ $grp == *@* ]] && shelf=${TTHEME_CATALOG[$k]}
1173
- if [[ -n $shelf && $shelf != "$last_shelf" ]]; then
1174
- printf ' \033[1m%s\033[0m\n' "$shelf"
1175
- last_shelf=$shelf
1176
- fi
1177
- label=${k##*/}
1178
- [[ -n $shelf ]] && label=" $label"
1179
- __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}"
1180
1253
  done
1181
- printf '\n \033[2mttheme use <palette> paints this tab · ttheme preview · ttheme help\033[0m\n'
1182
1254
  }
1183
1255
 
1184
1256
  __tt_help() {
@@ -1231,14 +1303,17 @@ __tt_cli() {
1231
1303
  }
1232
1304
 
1233
1305
  __tt_catalog() {
1234
- local was
1306
+ local was="$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}"
1235
1307
  __tt_cli "$@" || return
1236
1308
  [[ $1 == (list|share) ]] && return 0
1309
+ __tt_catalog_done "$was"
1310
+ }
1311
+
1312
+ __tt_catalog_done() {
1237
1313
  [[ -r $TTHEME_HOME/palettes.zsh ]] || return 0
1238
- was="$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}"
1239
1314
  __tt_palettes_load && __tt_reloaded
1240
- [[ "$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}" == "$was" ]] && return 0
1241
- __tt_follow "$was"
1315
+ [[ "$TTHEME_STARTUP ${TTHEME_PALETTE[$TTHEME_STARTUP]}" == "$1" ]] && return 0
1316
+ __tt_follow "$1"
1242
1317
  __tt_worn_shown
1243
1318
  __tt_reload
1244
1319
  }
@@ -1469,6 +1544,11 @@ __tt_pv_shows() {
1469
1544
  }
1470
1545
 
1471
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
1472
1552
  [[ ${rtype[cur]} == thm ]] || return 0
1473
1553
  __tt_pv_shows ${rval[cur]}
1474
1554
  (( resized )) || [[ $REPLY == "$bgname" ]] || __tt_pv_bg_show "$REPLY"
@@ -1553,6 +1633,11 @@ __tt_pv_lw() {
1553
1633
  (( l < 38 )) && l=38
1554
1634
  (( l > 56 )) && l=56
1555
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
1556
1641
  (( sw > pw - l - 6 )) && sw=$(( pw - l - 6 ))
1557
1642
  if (( color && sw >= 32 )); then
1558
1643
  lw=$l
@@ -1669,6 +1754,29 @@ __tt_pv_bg_title() {
1669
1754
  return 0
1670
1755
  }
1671
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
+
1672
1780
  __tt_pv_head() {
1673
1781
  local b=$'\e[1m' d=$'\e[2m' z=$'\e[0m' right=$6
1674
1782
  (( color )) || b= d= z=
@@ -1680,7 +1788,7 @@ __tt_pv_head() {
1680
1788
 
1681
1789
  __tt_pv_foot() {
1682
1790
  setopt localoptions extendedglob
1683
- 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
1684
1792
  local -a kk=() kl=() seg=()
1685
1793
  local -i end=$1 i lwid rwid room
1686
1794
  (( color )) || b= d= z= y= on=
@@ -1692,6 +1800,7 @@ __tt_pv_foot() {
1692
1800
  badge=HELP right=$b"? esc"$z$d" close"$z
1693
1801
  elif [[ -n $pick ]]; then
1694
1802
  badge='PREVIEW (APPLY)' lead="$pick →"
1803
+ (( te )) && badge="$tb (APPLY)"
1695
1804
  for (( i = 1; i <= ${#plabel}; i++ )); do
1696
1805
  if (( i != pk )); then
1697
1806
  lead+=" "$d${plabel[i]}$z
@@ -1703,34 +1812,58 @@ __tt_pv_foot() {
1703
1812
  done
1704
1813
  if [[ $mode == pin ]]; then
1705
1814
  badge='PREVIEW (PIN)'
1706
- __tt_pin_base "${pkeys[pk]}"
1707
- __tt_dir_label "$REPLY"
1815
+ (( te )) && badge="$tb (PIN)"
1816
+ __tt_pin_where "${pkeys[pk]}"
1708
1817
  note=$REPLY
1709
- elif (( pk == 1 )); then
1818
+ elif (( pk == 2 )); then
1710
1819
  note="Until this tab closes"
1711
1820
  else
1712
1821
  note="New tabs · the default palette"
1713
1822
  fi
1714
1823
  kk=(enter) kl=(confirm)
1715
1824
  right=$b"esc"$z$d" back"$z
1716
- elif [[ -n $tune ]]; then
1717
- badge='IMAGE EDIT' kk=(↑↓ ←→ '=' +) kl=(field step reset "reset all")
1718
- if (( tf == 2 )); then
1719
- kl[2]=move kk+=(1-9) kl+=(place)
1720
- elif (( tf == 4 )); then
1721
- kl[2]=switch kk=(${kk:#'='}) kl=("${(@)kl[1,2]}" "reset all")
1722
- else
1723
- 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
1724
1837
  fi
1725
- if (( bgoff[$tpick] )); then
1726
- 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) }
1727
1862
  else
1728
- kk+=(c space enter) kl+=(colors hide keep)
1863
+ kk=(enter ↑↓ s) kl=(find move save)
1729
1864
  fi
1730
- __tt_pv_bg_images $tune
1731
- (( REPLY > 1 )) && { kk+=(', .' D); kl+=("image ×$REPLY" remove) }
1732
- __tt_pv_bg_findable $tune && { kk+=(f); kl+=(find) }
1733
- right=$b"esc"$z$d" undo"$z
1865
+ kk+=(⇧enter) kl+=(apply)
1866
+ right=$b"esc"$z$d" cancel"$z
1734
1867
  elif (( conf )); then
1735
1868
  badge=CONFIG kk=(↑↓ ←→ enter) kl=(setting value save)
1736
1869
  right=$b"esc"$z$d" undo"$z
@@ -1746,13 +1879,7 @@ __tt_pv_foot() {
1746
1879
  kk=(→) kl=(open)
1747
1880
  fi
1748
1881
  else
1749
- kk=(enter) kl=(apply)
1750
- [[ $mode == pin ]] && kl[1]=pin
1751
- if __tt_pv_bg_state ${rval[cur]}; then
1752
- kk+=(tab) kl+=("tune bg")
1753
- elif __tt_pv_bg_findable ${rval[cur]}; then
1754
- kk+=(tab) kl+=("find bg")
1755
- fi
1882
+ kk=(enter tab) kl=(apply edit)
1756
1883
  (( split )) && { kk+=(⇧←→); kl+=(example) }
1757
1884
  [[ -n $flt ]] && { kk+=(bksp); kl+=(edit) }
1758
1885
  fi
@@ -1813,20 +1940,38 @@ __tt_pv_foot() {
1813
1940
  __tt_pv_help() {
1814
1941
  local back="the tab" z=$'\e[0m' b=$'\e[1m' blank
1815
1942
  [[ -n ${TTHEME_PALETTE[$cn]} ]] && back=$cn
1816
- local -a hk=(Move Series Filter "" Example Apply) hv=(
1817
- "↑↓ home end pgup pgdn"
1818
- "←→ · enter or space on a series"
1819
- "Any text · bksp · ctrl-u clears"
1820
- "Names and titles, in Japanese too"
1821
- "⇧←→ ${(Lj:, :)TTHEME_SCENES}"
1822
- "enter · esc restores $back"
1823
- )
1824
- if (( bgcw )); then
1825
- hk+=("Tune bg" "" "" "" "" "" "")
1826
- 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") }
1827
1974
  fi
1828
- hk+=(Config "")
1829
- hv+=("alt-c · ↑↓ setting ←→ value" "enter saves · esc undoes")
1830
1975
  hk+=(Close)
1831
1976
  hv+=("? esc")
1832
1977
  (( color )) || z= b=
@@ -1840,6 +1985,7 @@ __tt_pv_help() {
1840
1985
  return 0
1841
1986
  fi
1842
1987
  w=$(( pw - 2 < 58 ? pw - 2 : 58 )) hh=$(( ${#hk} + 4 ))
1988
+ (( te )) && w=$(( pw - 2 < 76 ? pw - 2 : 76 ))
1843
1989
  x=$(( (pw - w) / 2 + 1 )) y=$(( (ph - hh) / 2 ))
1844
1990
  (( y < 4 )) && y=4
1845
1991
  blank=${(l:w:: :)}
@@ -1961,21 +2107,11 @@ __tt_pv_tune() {
1961
2107
  ',') __tt_pv_bg_pick -1 ;;
1962
2108
  '.') __tt_pv_bg_pick 1 ;;
1963
2109
  D) __tt_pv_bg_drop ;;
1964
- f)
1965
- __tt_pv_bg_findable $tune || return 0
1966
- name=$tune
1967
- __tt_pv_untune
1968
- __tt_pv_bg_find $name
1969
- __tt_pv_tune_open $name
1970
- ;;
1971
- $'\r'|$'\n') __tt_pv_tune_keep ;;
1972
- esc) __tt_pv_untune ;;
1973
- '?') help=1 ;;
1974
2110
  esac
1975
2111
  return 0
1976
2112
  }
1977
2113
 
1978
- __tt_pv_tune_keep() {
2114
+ __tt_pv_tune_stage() {
1979
2115
  local img was=${bgview[$tune]:-$tune}
1980
2116
  local -i changed=0
1981
2117
  for img in ${(k)tsnaps}; do
@@ -1991,10 +2127,14 @@ __tt_pv_tune_keep() {
1991
2127
  fi
1992
2128
  fi
1993
2129
  (( changed )) && msg="Kept · saved when preview closes" msgt=200
1994
- __tt_pv_bg_strip_off
1995
2130
  tune="" tpick="" tsnaps=() bgname=""
1996
2131
  }
1997
2132
 
2133
+ __tt_pv_tune_keep() {
2134
+ __tt_pv_bg_strip_off
2135
+ __tt_pv_tune_stage
2136
+ }
2137
+
1998
2138
  __tt_pv_untune() {
1999
2139
  local img
2000
2140
  local -a s
@@ -2019,8 +2159,8 @@ __tt_pv_regroup() {
2019
2159
  __tt_pv_conf() {
2020
2160
  case $key in
2021
2161
  $'\x03') return 1 ;;
2022
- up) cf=$(( cf > 1 ? cf - 1 : ${#cvars} )) ;;
2023
- 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 )) ;;
2024
2164
  left|sleft) __tt_pv_conf_step -1 ;;
2025
2165
  right|sright) __tt_pv_conf_step 1 ;;
2026
2166
  $'\r'|$'\n') __tt_pv_conf_save ;;
@@ -2090,7 +2230,6 @@ __tt_pv_redraw() {
2090
2230
  msg="Drawing the background pictures again" msgt=300
2091
2231
  printf '\e[?2026h'
2092
2232
  __tt_pv_draw
2093
- __tt_pv_bg_close
2094
2233
  out=$(__tt_cli redraw 2>&1)
2095
2234
  bgsrc=() resized=1 bgname="" bgshown="" bgdim=()
2096
2235
  __tt_reload
@@ -2173,27 +2312,36 @@ __tt_pv_reach() {
2173
2312
  local -i room=$2
2174
2313
  (( color )) || d= z=
2175
2314
  (( room < 2 )) && room=2
2176
- __tt_pin_base "$key"
2177
- base=$REPLY
2178
- for k in ${(k)TTHEME_PINS}; do
2179
- [[ $k == /* ]] || continue
2180
- __tt_pin_base "$k"
2181
- [[ $REPLY == "$base" ]] || continue
2182
- if [[ $k != "$key" || $TTHEME_PINS[$k] != "$pick" ]]; then
2183
- __tt_pin_scope "$k"
2184
- was+=("${TTHEME_PINS[$k]} · $REPLY")
2185
- fi
2186
- unset "TTHEME_PINS[$k]"
2187
- done
2188
- TTHEME_PINS[$key]=$pick
2189
- top=$base
2190
- [[ $base != / ]] && __tt_pin_cover "${base:h}" && __tt_pin_base "$REPLY" && top=$REPLY
2191
- mark[$base]=new
2192
- __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
2193
2340
  __tt_map_fit $1
2194
2341
  (( ${#reply} > room )) && reply=("${(@)reply[1,room-1]}" " …")
2195
- reach=("${reply[@]}" "")
2196
- __tt_dir_label "$base"
2342
+ reach=("${reply[@]}")
2343
+ [[ $key == /* || ${#was} -gt 0 ]] && reach+=("")
2344
+ __tt_pin_where "$key"
2197
2345
  base=$REPLY
2198
2346
  for k in $was; do
2199
2347
  __tt_clip "${d}Replaces ${k% · *} on $base · ${k##* · }$z" $1
@@ -2202,6 +2350,7 @@ __tt_pv_reach() {
2202
2350
  __tt_pin_scope "$key"
2203
2351
  __tt_clip "→ $base · $REPLY" $(( $1 - ${(m)#pick} - 2 ))
2204
2352
  rsub=$REPLY
2353
+ [[ $key == /* ]] || return 0
2205
2354
  __tt_here_fit "Then here" $1
2206
2355
  reach+=("${reply[@]}")
2207
2356
  }
@@ -2215,11 +2364,14 @@ __tt_pv_draw() {
2215
2364
  __tt_pv_norm "$flt"
2216
2365
  nflt=$REPLY
2217
2366
  fi
2367
+ if (( te )) && [[ -n $tespec && $tespec != "$applied" ]]; then
2368
+ __tt_pv_paint "$tespec"
2369
+ applied=$tespec
2370
+ fi
2218
2371
  __tt_pv_lw
2219
2372
  lw=$reply[1] sw=$reply[2]
2220
2373
  split=$(( sw > 0 )) sc=$(( pw - 1 - sw ))
2221
2374
  h=$(( ph - 5 ))
2222
- [[ -n $tune ]] && (( ! split )) && h=$(( ph - 14 ))
2223
2375
  (( conf && ! split )) && h=$(( ph - 6 - ${#cvars} ))
2224
2376
  reach=()
2225
2377
  if [[ -n $pick && $mode == pin ]]; then
@@ -2269,6 +2421,10 @@ __tt_pv_draw() {
2269
2421
  __tt_pv_flush
2270
2422
  return 0
2271
2423
  fi
2424
+ if (( te && ! split )); then
2425
+ __tt_pv_te_draw
2426
+ return 0
2427
+ fi
2272
2428
  if [[ -n $flt ]]; then
2273
2429
  if (( color )); then
2274
2430
  line=" "$'\e[1m'$flt$zz$ac$'\e[7m \e[0m'
@@ -2300,11 +2456,16 @@ __tt_pv_draw() {
2300
2456
  local tail=$'\e['$(( lw - ${#cnt} ))'G'$dd$cnt$zz
2301
2457
  [[ -n $flt ]] && tail=$'\e['$(( lw - ${#cnt} ))'G'$cnt
2302
2458
  if [[ $1 == hint ]] && (( ! wiped )); then
2303
- print -rn -- $'\e[H\e[0m\e['$lw'X'$line$tail
2304
- 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} ))
2305
2461
  return 0
2306
2462
  fi
2307
- 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
2308
2469
  (( N > h && top > 1 )) && out+=" "$dd"…"$zz
2309
2470
  out+=$'\e[K\n'
2310
2471
  for (( k = 0; k < ph - 4; k++ )); do
@@ -2332,17 +2493,15 @@ __tt_pv_draw() {
2332
2493
  for (( k = 1; k <= ${#reach} && k + 2 < ph; k++ )); do
2333
2494
  out+=$'\e['$(( k + 2 ))';'$sc'H'${reach[k]}
2334
2495
  done
2335
- elif [[ -n $tune ]]; then
2336
- (( bgoff[$tpick] )) && state=off
2337
- __tt_pv_bg_title $(( sw - ${#tune} - 6 ))
2338
- __tt_pv_head 1 $sc $se $tune "$REPLY" $state
2339
- __tt_pv_bg_panel $tpick 4 $sc $se
2340
2496
  elif (( conf )); then
2341
2497
  __tt_tilde "$TTHEME_CONFIG"
2342
2498
  src=$REPLY
2343
2499
  (( 8 + ${#src} > sw )) && src=""
2344
2500
  __tt_pv_head 1 $sc $se Config "" "$src"
2345
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 ))
2346
2505
  else
2347
2506
  [[ -n $an ]] && src=${TTHEME_SRC[$an]}
2348
2507
  (( ${#an} + 2 + ${#src} > sw )) && src=""
@@ -2356,18 +2515,6 @@ __tt_pv_draw() {
2356
2515
  for (( k = 1; k <= ${#reach}; k++ )); do
2357
2516
  out+=$'\e['$(( ph - 1 - ${#reach} + k ))';1H'${reach[k]}
2358
2517
  done
2359
- elif [[ -n $tune ]]; then
2360
- (( bgoff[$tpick] )) && state=off
2361
- held=(${=bgpics[$tune]})
2362
- src=""
2363
- if (( ${#held} > 1 )); then
2364
- k=${held[(Ie)${${tpick#$tune}#:}]}
2365
- (( k )) || k=${held[(Ie)${bgact[$tune]}]}
2366
- src=" · $k/${#held}"
2367
- fi
2368
- __tt_pv_bg_title $(( lw - ${#tune} - 6 )) "$src"
2369
- __tt_pv_head $(( ph - 10 )) 1 $lw $tune "$REPLY" $state
2370
- __tt_pv_bg_panel $tpick $(( ph - 9 )) 1 $lw
2371
2518
  elif (( conf )); then
2372
2519
  __tt_pv_head $(( ph - 2 - ${#cvars} )) 1 $lw Config
2373
2520
  __tt_pv_conf_panel $(( ph - 1 - ${#cvars} )) 1 $lw
@@ -2447,9 +2594,17 @@ __tt_pv_getch() {
2447
2594
  read -sk 1 -t $1 2>/dev/null
2448
2595
  return
2449
2596
  fi
2450
- local t=0.2
2597
+ local -F t=0.2 at
2598
+ local -i quick=0
2451
2599
  (( gstep )) && t=0.06
2452
- 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
2453
2608
  [[ -t 0 ]] || return 1
2454
2609
  __tt_pv_size && return 1
2455
2610
  if (( osdt > 0 )); then
@@ -2461,9 +2616,8 @@ __tt_pv_getch() {
2461
2616
  (( msgt > 0 )) || return 1
2462
2617
  fi
2463
2618
  (( gstep )) && { gstep=$(( gstep - 1 )); tick=1; return 1 }
2464
- (( SECONDS >= exnext )) && { __tt_pv_roll; gstep=8; tick=1; return 1 }
2619
+ (( ! te && SECONDS >= exnext )) && { __tt_pv_roll; gstep=8; tick=1; return 1 }
2465
2620
  done
2466
- return 0
2467
2621
  }
2468
2622
 
2469
2623
  __tt_pv_read() {
@@ -2501,6 +2655,7 @@ __tt_pv_read() {
2501
2655
  "6~") key=pgdn ;;
2502
2656
  "1;2C") key=sright ;;
2503
2657
  "1;2D") key=sleft ;;
2658
+ "27;2;13~"|"13;2u") key=senter ;;
2504
2659
  Z) key=stab ;;
2505
2660
  *) key=nop ;;
2506
2661
  esac
@@ -2512,7 +2667,7 @@ __tt_pv_pick() {
2512
2667
  esc) pick="" ;;
2513
2668
  left|stab) pk=$(( (pk + ${#plabel} - 2) % ${#plabel} + 1 )) ;;
2514
2669
  right|$'\t') pk=$(( pk % ${#plabel} + 1 )) ;;
2515
- $'\r'|$'\n')
2670
+ $'\r'|$'\n'|senter)
2516
2671
  sel=$pick picked=$pk
2517
2672
  return 1
2518
2673
  ;;
@@ -2520,6 +2675,457 @@ __tt_pv_pick() {
2520
2675
  return 0
2521
2676
  }
2522
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
+
2523
3129
  __tt_pv_handle() {
2524
3130
  local name
2525
3131
  if (( help )); then
@@ -2533,6 +3139,10 @@ __tt_pv_handle() {
2533
3139
  __tt_pv_pick
2534
3140
  return
2535
3141
  fi
3142
+ if (( te )); then
3143
+ __tt_pv_te
3144
+ return
3145
+ fi
2536
3146
  if [[ -n $tune ]]; then
2537
3147
  __tt_pv_tune
2538
3148
  return
@@ -2559,7 +3169,7 @@ __tt_pv_handle() {
2559
3169
  fi
2560
3170
  fi
2561
3171
  ;;
2562
- $'\r'|$'\n')
3172
+ $'\r'|$'\n'|senter)
2563
3173
  if [[ ${rtype[cur]} == thm ]]; then
2564
3174
  if (( canpick )); then
2565
3175
  pick=${rval[cur]} pk=$pkdef
@@ -2587,7 +3197,14 @@ __tt_pv_handle() {
2587
3197
  cur=1
2588
3198
  fi
2589
3199
  ;;
2590
- 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]} ;;
2591
3208
  left) __tt_pv_left ;;
2592
3209
  home) cur=1 ;;
2593
3210
  end) (( ${#rval} )) && cur=${#rval} ;;
@@ -2611,16 +3228,13 @@ __tt_pv_handle() {
2611
3228
  ;;
2612
3229
  ' ') [[ ${rtype[cur]} == (hdr|cat) ]] && __tt_pv_toggle ;;
2613
3230
  $'\t')
2614
- [[ ${rtype[cur]} == thm ]] || return 0
2615
- name=${rval[cur]}
2616
- if __tt_pv_bg_state $name || { __tt_pv_bg_findable $name && __tt_pv_bg_find $name }; then
2617
- __tt_pv_tune_open $name
2618
- elif __tt_pv_bg_findable $name; then
2619
- :
2620
- elif (( bgcw )); then
2621
- 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
2622
3235
  fi
2623
3236
  ;;
3237
+ stab) (( hub )) && { __tt_pv_screen -1 || return 1 } ;;
2624
3238
  altc)
2625
3239
  conf=1 cf=1 csnap=()
2626
3240
  for name in $cvars; do
@@ -2654,7 +3268,10 @@ __tt_pv_handle() {
2654
3268
 
2655
3269
  __tt_preview() {
2656
3270
  emulate -L zsh ${=${options[xtrace]:#off}:+-o xtrace}
2657
- 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
2658
3275
  if [[ ! -t 0 || ! -t 1 ]]; then
2659
3276
  print -u2 "ttheme ${mode:-preview}: needs a terminal"
2660
3277
  return 1
@@ -2665,9 +3282,11 @@ __tt_preview() {
2665
3282
  local -i scene=0
2666
3283
  local -a bgorder=()
2667
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=()
2668
- local -A bgpic=() bgpics=() bgact=() bgview=() bgswap=() bgthumb=() tsnaps=() pvseek=() bgcolors=()
3285
+ local -A bgpic=() bgpics=() bgact=() bgview=() bgswap=() bgthumb=() tsnaps=() pvseek=() bgcolors=() bgprep=()
2669
3286
  local conf=0 cf=1
2670
- 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
2671
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)
2672
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")
2673
3292
  local -A cnote=(
@@ -2683,7 +3302,6 @@ __tt_preview() {
2683
3302
  )
2684
3303
  __tt_pv_conf_rows
2685
3304
  [[ $mode == pin ]] && __tt_pin_scopes "$pdir"
2686
- [[ $mode == init ]] && pkdef=2
2687
3305
  __tt_pv_canpick
2688
3306
  __tt_pv_size
2689
3307
  local -a groups=() rtype=() rval=() rcnt=() reply=()
@@ -2702,7 +3320,7 @@ __tt_preview() {
2702
3320
  printf '\e[?2026h\e[?1049h\e[?7l\e[?25l'
2703
3321
  while :; do
2704
3322
  printf '\e[?2026h'
2705
- if (( tick )); then
3323
+ if (( tick && ! te )); then
2706
3324
  __tt_pv_draw hint
2707
3325
  else
2708
3326
  __tt_pv_focus
@@ -2711,6 +3329,7 @@ __tt_preview() {
2711
3329
  fi
2712
3330
  tick=0
2713
3331
  if ! __tt_pv_read; then
3332
+ (( pvgone )) && break
2714
3333
  [[ -t 0 ]] && continue
2715
3334
  break
2716
3335
  fi
@@ -2735,10 +3354,13 @@ __tt_preview() {
2735
3354
  elif [[ $applied != "$orig" ]]; then
2736
3355
  __tt_pv_paint "${TTHEME_PAINTED:+$orig}"
2737
3356
  fi
2738
- printf '\e[?7h\e[?1049l\e[?25h\e[?2026l'
3357
+ printf '\e[?7h'
3358
+ (( hubleft )) || printf '\e[?1049l'
3359
+ printf '\e[?25h\e[?2026l'
2739
3360
  [[ -n $tty ]] && stty "$tty" 2>/dev/null
2740
3361
  TTHEME_RAW=0
2741
3362
  [[ -n $tune ]] && __tt_pv_untune
3363
+ (( TE_IN )) && __tt_te_stop
2742
3364
  (( conf )) && __tt_pv_unconf
2743
3365
  __tt_pv_bg_save
2744
3366
  if [[ -n $spec ]]; then
@@ -2747,7 +3369,7 @@ __tt_preview() {
2747
3369
  __tt_pin_save "$sel" "${pkeys[picked]}" "$orig"
2748
3370
  [[ $TTHEME_SPEC == "$orig" ]] || __tt_announce
2749
3371
  __tt_sync
2750
- elif (( picked == 2 )); then
3372
+ elif (( picked == 1 )); then
2751
3373
  __tt_announce
2752
3374
  __tt_keep "$sel" force
2753
3375
  else
@@ -2757,6 +3379,7 @@ __tt_preview() {
2757
3379
  else
2758
3380
  (( ${#bgedit} + ${#bgswap} )) && [[ -n ${TTHEME_PALETTE[$cn]} ]] && { __tt_shown "$cn" && __tt_reload }
2759
3381
  fi
3382
+ (( hubleft )) && __tt_catalog_done "$hubwas"
2760
3383
  }
2761
3384
  return 0
2762
3385
  }
@@ -2785,7 +3408,11 @@ ttheme() {
2785
3408
  fi
2786
3409
  if (( ! $# )); then
2787
3410
  (( ${#TTHEME_PALETTE} )) || { __tt_empty; return }
2788
- __tt_menu
3411
+ if [[ -t 0 && -t 1 ]]; then
3412
+ __tt_preview hub
3413
+ else
3414
+ __tt_menu
3415
+ fi
2789
3416
  return 0
2790
3417
  fi
2791
3418
 
@@ -2810,12 +3437,18 @@ ttheme() {
2810
3437
  __tt_keep "$REPLY" ;;
2811
3438
  preview) __tt_preview ;;
2812
3439
  pin)
2813
- 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
2814
3446
  REPLY=$2
2815
3447
  [[ $REPLY == \~ || $REPLY == \~/* ]] && REPLY=$HOME${REPLY#\~}
2816
3448
  [[ -d $REPLY ]] || { print -u2 -r -- "ttheme pin: no such directory: $2"; return 1 }
3449
+ REPLY=${REPLY:a}
2817
3450
  fi
2818
- __tt_preview pin ${REPLY:+${REPLY:a}} ;;
3451
+ __tt_preview pin ${REPLY:+$REPLY} ;;
2819
3452
  unpin) __tt_unpin "${@:2}" ;;
2820
3453
  pins) __tt_pins_map ;;
2821
3454
  esac
@@ -2840,7 +3473,17 @@ if (( ${+functions[compdef]} )); then
2840
3473
  elif [[ $words[2] == market && $words[3] == (add|init) && $CURRENT == 4 ]]; then
2841
3474
  _files -/
2842
3475
  elif [[ $words[2] == (pin|unpin) && $CURRENT == 3 ]]; then
2843
- _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
2844
3487
  elif [[ $words[2] == add && $words[CURRENT-1] == --market ]]; then
2845
3488
  _files -/
2846
3489
  elif [[ $words[2] == add ]]; then