dot/shell-rc, dot/bashrc, dot/zshrc: Introduce a formal notion of hooks.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 21 Apr 2020 11:54:55 +0000 (12:54 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 21 Apr 2020 11:54:55 +0000 (12:54 +0100)
Replace the `__mdw_precmd' and `__mdw_preexec' functions with hooks.
Each shell implementation is responsible for calling the hooks at the
right time, but the common core is responsible for maintaining the hooks
and doing the job of invoking the hook functions.

Use this machinery for the prompt setting and `screen' status things.

dot/bashrc
dot/shell-rc
dot/zshrc

index 9e872f5..18a2d7d 100644 (file)
@@ -11,6 +11,30 @@ case ${__mdw_bashrc+t} in
   *) __mdw_bashrc=t
 
 ###--------------------------------------------------------------------------
+### Hook implementation.
+
+__mdw_precmd_hook= __mdw_preexec_hook=
+__mdw_running=t
+
+__mdw_run_precmd_hook () {
+  __mdw_running=nil
+  __mdw_runhook __mdw_precmd_hook "$@"
+}
+__mdw_run_preexec_hook () {
+  case $__mdw_running in
+    t) ;;
+    nil)
+      __mdw_running=t;
+      set -- $(history 1); shift
+      __mdw_runhook __mdw_preexec_hook "$*"
+      ;;
+  esac
+}
+
+PROMPT_COMMAND=__mdw_run_precmd_hook
+trap __mdw_run_preexec_hook DEBUG
+
+###--------------------------------------------------------------------------
 ### Common shell configuration.
 
 . "$HOME/.shell-rc"
@@ -46,18 +70,11 @@ __mdw_set_prompt_hacks () {
   host='\h' dir=' \w'
 }
 
-__mdw_before_cmd_hack () {
-  set -- $(history 1); shift
-  __mdw_preexec "$*"
-}
-
 ## Only bother if the shell is interactive.
 if [ -t 0 ]; then
   PROMPT_DIRTRIM=5
   __mdw_source_if_exists /usr/lib/git-core/git-sh-prompt
   __mdw_set_prompt_pieces
-  PROMPT_COMMAND=__mdw_precmd
-  PS0="\$(__mdw_before_cmd_hack)"
 fi
 
 ###--------------------------------------------------------------------------
index 940f91b..582b94d 100644 (file)
@@ -15,6 +15,50 @@ __mdw_source_if_exists () {
 }
 
 ###--------------------------------------------------------------------------
+### Hooks.
+
+__mdw_addhook () {
+  local hk=$1 fn=$2 t
+
+  eval t=\${$hk+t}
+  case $t in t) ;; *) echo >&2 "unknown hook \`$hk'"; return 2; esac
+
+  eval t=\$$hk
+  case " $t " in
+    *" $fn "*) ;;
+    *) eval "$hk=\${$hk:+\$$hk }\$fn" ;;
+  esac
+}
+
+__mdw_delhook () {
+  local hk=$1 fn=$2 t l r
+
+  eval t=\${$hk+t}
+  case $t in t) ;; *) echo >&2 "unknown hook \`$hk'"; return 2; esac
+
+  eval t=\" \$$hk \"
+  case $t in
+    *" $fn "*)
+      l=${t%% $fn*} r=${t##*$fn }
+      l=${l# } r=${r% }
+      eval "$hk=\$l\${l:+ }\$r"
+      ;;
+  esac
+}
+
+__mdw_setrc () { return $1; }
+
+__mdw_runhook () {
+  local hk=$1 saverc=$? t i; shift
+
+  eval t=\${$hk+t}
+  case $t in t) ;; *) echo >&2 "unknown hook \`$hk'"; return 2; esac
+
+  eval t=\$$hk
+  for i in $t; do __mdw_setrc $saverc; "$i" "$@"; done
+}
+
+###--------------------------------------------------------------------------
 ### Prompt machinery.
 
 __mdw_set_prompt_hacks () { host=$(hostname); dir=""; }
@@ -101,18 +145,20 @@ __mdw_set_prompt () {
   esac
 }
 
-__mdw_precmd () {
-  __mdw_set_prompt
-  case ${STY+t} in
-    t) printf "\ek%s\e\\" "$__mdw_shell" ;;
-  esac
-}
+__mdw_screen_precmd () { printf "\ek%s\e\\" "$__mdw_shell"; }
+__mdw_screen_preexec () { printf "\ek%s\e\\" "$1"; }
 
-__mdw_preexec () {
-  case ${STY+t} in
-    t) printf "\ek%s\e\\" "$1" ;;
+if [ -t 0 ]; then
+  case ${STY+t},${__mdw_precmd_hook+t},${__mdw_preexec_hook+t} in
+    t,t,t)
+      __mdw_addhook __mdw_precmd_hook __mdw_screen_precmd
+      __mdw_addhook __mdw_preexec_hook __mdw_screen_preexec
+      ;;
   esac
-}
+  case ${__mdw_precmd_hook+t} in
+    t) __mdw_addhook __mdw_precmd_hook __mdw_set_prompt ;;
+  esac
+fi
 
 ###--------------------------------------------------------------------------
 ### Some handy aliases.
index c6cfa99..62766c0 100644 (file)
--- a/dot/zshrc
+++ b/dot/zshrc
@@ -15,10 +15,32 @@ HISTSIZE=1000
 SAVEHIST=1000
 
 ###--------------------------------------------------------------------------
+### Hook implementation.
+
+__mdw_precmd_hook= __mdw_preexec_hook=
+
+__mdw_run_precmd_hook () { __mdw_runhook __mdw_precmd_hook "$@"; }
+__mdw_run_preexec_hook () { __mdw_runhook __mdw_preexec_hook "$@"; }
+
+precmd_functions+=(__mdw_run_precmd_hook)
+preexec_functions+=(__mdw_run_preexec_hook)
+
+###--------------------------------------------------------------------------
 ### Common shell configuration.
 
 . "$HOME/.shell-rc"
 
+## Fixup: `zsh' has sane quoting rules.
+__mdw_runhook () {
+  local hk=$1 saverc=$? t i; shift
+
+  eval t=\${$hk+t}
+  case $t in t) ;; *) echo >&2 "unknown hook \`$hk'"; return 2; esac
+
+  eval t=\$$hk
+  for i in ${=t}; do __mdw_setrc $saverc; "$i" "$@"; done
+}
+
 ###--------------------------------------------------------------------------
 ### Prompt hacking.
 
@@ -36,8 +58,6 @@ __mdw_set_prompt_hacks () {
 if [ -t 0 ]; then
   __mdw_source_if_exists /usr/lib/git-core/git-sh-prompt
   __mdw_set_prompt_pieces
-  precmd_functions+=(__mdw_precmd)
-  preexec_functions+=(__mdw_preexec)
 fi
 
 ###--------------------------------------------------------------------------