]> git.sev.monster Git - dotfiles.git/commitdiff
make key handling and logout more robust
authorsev <git@sev.monster>
Mon, 30 Oct 2023 12:14:54 +0000 (07:14 -0500)
committersev <git@sev.monster>
Fri, 5 Apr 2024 21:27:41 +0000 (16:27 -0500)
key setup can know use either terminfo, termcap, or zkbd, and in all cases
appends to the $key array  topreserve existing keys that we do not reset.

the increased knowledge in termcap/terminfo also resulted in .zlogout getting a
facelift to no longer rely on system binaries for terminal reset.

etc/zsh/.zlogout
etc/zsh/.zshrc

index c0054214f1762486b9c16cbcd04a390c26e919c3..1b2b26679a760b26ab5e450b94cda3546d5a28c6 100644 (file)
@@ -10,9 +10,34 @@ _sev_zcleanup
 ## clean up any remaining sockets from gpg forwarding
 [[ -v _GNUPG_SOCK_DEST_BASE ]] && rm -f $_GNUPG_SOCK_DEST_BASE*(=N)
 
+## manually reset terminal for interactive logout
 if [[ -o interactive ]] {
+    # send xterm scrollback clear extension just in case:
+    #  - TERM may not be set correctly
+    #  - terminfo/termcap database entry for reset may be buggy
+    echo -n '\e[3J'
+    # use terminfo/termcap directly instead of relying on system clear/reset:
+    #  - often they are just wrappers for ncurses tput or other tools
+    #  - they may not even exist on lightweight systems
+    #  - provided scripts/binaries may be buggy or broken
+    y=0
+    for x (rs1 rs2 rs3) {
+        [[ -v terminfo[$x] ]] || continue
+        echoti $x
+        y=1
+    }
+    if (( y == 0 )) {
+        for x (rs r1 r2 r3) {
+            [[ -v termcap[$x] ]] || continue
+            echotc $x
+            y=1
+        }
+    }
+    if (( y == 0 )) {
+        # fallback, send ECMA-48 clear
+        echo -n '\e[2J'
+    }
     echo logout
-    clear
 }
 
 ### load site-specific
index 64c7c5e79266d90850b3c6b2289811ec01668278..bfe0d9fe440dd2a80992192738c37ebad2d0aec3 100644 (file)
@@ -62,11 +62,70 @@ compinit -d $cache/.zcompdump
 unset cache
 
 ### keys
-bindkey -v
-KEYTIMEOUT=10
-## populate key array
-if (( $#terminfo == 0 )) {
-    # terminfo is not set or empty
+## set up zkbd-style key array
+if [[ ! -v _sev_force_zkbd && ( -v terminfo || -v termcap ) ]] {
+    # use application (keypad transmit) mode if the terminal supports it
+    # NOTE: we have to do this because termcap/terminfo keys are usually
+    #       defined in application mode. terminals that do not define these
+    #       capabilities are assumed to always be in application mode.
+    if [[ ( -v terminfo[smkx] && -v terminfo[rmkx] ) ||
+          ( -v termcap[ks]    && -v terminfo[ke] ) ]] {
+        autoload -Uz add-zle-hook-widget
+        function _enter-application-mode {
+            [[ -v terminfo[smkx] ]] && echoti smkx || echotc ks
+        }
+        add-zle-hook-widget line-init _enter-application-mode
+        function _exit-application-mode {
+            [[ -v terminfo[rmkx] ]] && echoti rmkx || echotc ke
+        }
+        add-zle-hook-widget line-finish _exit-application-mode
+        trap _exit-application-mode EXIT
+    }
+    # pull keys from terminfo/termcap
+    # TODO: Menu and more Shift- modifiers
+    typeset -gA key
+    typeset -lA newkey
+    if [[ -v terminfo ]] {
+        src=terminfo
+        newkey=(F1 kf1 F2 kf2 F3 kf3 F4 kf4 F5 kf5 F6 kf6 F7 kf7 F8 kf8 F9 kf9
+                F10 kf10 F11 kf11 F12 kf12
+                Backspace kbs
+                Shift-Tab kcbt
+                Insert    kich1
+                Home      khome
+                PageUp    kpp
+                Delete    kdch1
+                End       kend
+                PageDown  knp
+                Up        kcuu1
+                Down      kcud1
+                Left      kcub1
+                Right     kcuf1
+        )
+    } elif [[ -v termcap ]] {
+        src=termcap
+        newkey=(F1 k1 F2 k2 F3 k3 F4 k4 F5 k5 F6 k6 F7 k7 F8 k8 F9 k9
+                F10 k\; F11 F1 F12 F2
+                Backspace kb
+                Shift-Tab kB
+                Insert    kI
+                Home      kh
+                PageUp    kP
+                Delete    kD
+                End       @7
+                PageDown  kN
+                Up        ku
+                Down      kd
+                Left      kl
+                Right     kr
+        )
+    }
+    for k v (${(kv)newkey}) {
+        key[$k]=${${(P)src}[$v]}
+    }
+    unset k v src newkey
+} else {
+    # use zkbd if termcap/terminfo unavailable
     function find_keymap {
         for f in ${ZDOTDIR:-~}/.zkbd/$TERM{-${DISPLAY:-$VENDOR-$OSTYPE},}
             [[ -f $f ]] && keymap=$f && break
@@ -87,39 +146,6 @@ if (( $#terminfo == 0 )) {
         echo "Failed to source keymap file $keymap" >&2
     }
     unfunction find_keymap; unset keymap
-} else {
-    # activate application mode for zle so terminfo keys work
-    # NOTE: don't do this for zkbd since application mode shouldn't have been
-    #       enabled by zkbd when the keymap file was generated
-    if [[ -v terminfo[smkx] && -v terminfo[rmkx] ]] {
-        autoload -Uz add-zle-hook-widget
-        function _enter-application-mode { echoti smkx }
-        add-zle-hook-widget line-init _enter-application-mode
-        function _exit-application-mode { echoti rmkx }
-        add-zle-hook-widget line-finish _exit-application-mode
-        trap _exit-application-mode EXIT
-    }
-    # match zkbd hash as best we can to terminfo
-    typeset -gA key
-    key=(F1 kf1 F2 kf2 F3 kf3 F4 kf4 F5 kf5 F6 kf6 F7 kf7 F8 kf8 F9 kf9
-         F10 kf10 F11 kf11 F12 kf12
-         Backspace kbs
-         Backtab   kcbt
-         Shift-Tab kcbt
-         Insert    kich1
-         Home      khome
-         PageUp    kpp
-         Delete    kdch1
-         End       kend
-         PageDown  knp
-         Up        kcuu1
-         Down      kcud1
-         Left      kcub1
-         Right     kcuf1
-    )
-    for k v in ${(kv)key}; do
-        key[$k]=$terminfo[$v]
-    done; unset k v
 }
 
 ## load history search
@@ -128,6 +154,9 @@ zle -N up-line-or-beginning-search
 zle -N down-line-or-beginning-search
 
 ## bind keys in both viins and vicmd modes
+# NOTE: cursor keys are bound to normal/raw/nontransmit mode strings by
+#       default, and keys like Home and End are not bound at all, so we rebind
+#       everything to cover all scenarios
 typeset -A a
 a=(
     #key       viins                         vicmd
@@ -143,12 +172,12 @@ a=(
     Left      'backward-char'
     Right     'forward-char'
 )
-for k v in ${(kv)a}; do
+for k v (${(kv)a}) {
     k=$key[$k]
-    if [[ -z "$k" ]] { continue }
+    if [[ -z $k ]] { continue }
     v=($=v)
     bindkey -- $k $v[1]
-    if [[ $v[2] == '-' ]] {
+    if [[ $v[2] == - ]] {
         # copy viins to vicmd verbatim
         bindkey -a -- $k $v[1]
     } elif (( $#v != 1 )) {
@@ -158,7 +187,7 @@ for k v in ${(kv)a}; do
         # copy viins to vicmd and prepend vi- to it
         bindkey -a -- $k vi-$v[1]
     }
-done
+}
 unset a k v
 
 ### aliases
This page took 0.04681 seconds and 4 git commands to generate.