chiark / gitweb /
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 9e872f58e0246a01ae40873949152e95ff4b8c61..18a2d7df897d113c8302fe0638e51d3db6de6fbe 100644 (file)
@@ -10,6 +10,30 @@ case ${__mdw_bashrc+t} in
   t) ;;
   *) __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.
 
@@ -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 940f91bf915625c2333ea498c6950b78488fb4ae..582b94df4d85017709054c2e7fa632e976b9489e 100644 (file)
@@ -14,6 +14,50 @@ __mdw_source_if_exists () {
   done
 }
 
+###--------------------------------------------------------------------------
+### 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.
 
@@ -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 c6cfa9960e1c96ef7761bd9bf4095a69ad9efc61..62766c09ed985809eb16e1c305bf2b5de0de8d7b 100644 (file)
--- a/dot/zshrc
+++ b/dot/zshrc
@@ -14,11 +14,33 @@ HISTFILE=~/.zsh-history
 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
 
 ###--------------------------------------------------------------------------