zsh-workers
 help / color / mirror / code / Atom feed
* Shadowing builtins and functions
@ 2022-06-03  1:36 Bart Schaefer
  2022-06-04 21:22 ` Bart Schaefer
  0 siblings, 1 reply; 2+ messages in thread
From: Bart Schaefer @ 2022-06-03  1:36 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1922 bytes --]

In workers 50316, I wrote:
> That needs some work to avoid conflicting with other helpers that
> redefine compadd

As far as I can tell that now means only _complete_help and
_approximate, and _approximate already avoids redefining compadd when
it is a function instead of a builtin.  I'm not sure if that affects
the results of _complete_help for contexts that use _approximate.

Nevertheless it seems as though a helper for temporarily redefining
builtins and functions as new functions is possible, so an attempt at
it is attached.  The idea here is to create a new unique function name
and link it to the original function, which preserves the function
body, and then unwind that when the redefined function is not needed.
There's no neat way to do this without help from the caller in the
form of an "always" block.

So after a bit of noodling with that idea, the result is _shadow
(attached as _shadow.txt for list server compatibility).  Example of
usage:

diff --git a/Completion/Base/Widget/_complete_help
b/Completion/Base/Widget/_complete_help
index 69855de9d..da5947e7f 100644
--- a/Completion/Base/Widget/_complete_help
+++ b/Completion/Base/Widget/_complete_help
@@ -10,6 +10,7 @@ _complete_help() {
   local -H _help_filter_funcstack="alternative|call_function|describe|dispatch|wanted|requested|all_labels|next_label"

   {
+    _shadow compadd compcall zstyle
     compadd() { return 1 }
     compcall() { _help_sort_tags use-compctl }
     zstyle() {
@@ -43,7 +44,7 @@ _complete_help() {

     ${1:-_main_complete}
   } always {
-    unfunction compadd compcall zstyle
+    _unshadow compadd compcall zstyle
   }

   for i in "${(@ok)help_funcs}"; do

I'm not certain that Completion/Base/Utility is where _shadow would
best be committed, but currently the only places we might want it are
in completion, so it should be loaded along with completions, so
that's where I was thinking to put it.

Remarks?

[-- Attachment #2: _shadow.txt --]
[-- Type: text/plain, Size: 1935 bytes --]

#autoload

## Recommended usage:
#  {
#    _shadow fname
#    function fname {
#      # Do your new thing
#    }
#    # Invoke callers of fname
#  } always {
#    _unshadow fname
#  }
## Alternate usage:
# {
#   _shadow -s suffix fname
#   function fname {
#     # Do other stuff
#     fname@suffix new args for fname
#   }
#   # Invoke callers of fname
# } always {
#   _unshadow -s suffix fname
# }
##

# BUGS:
# * `functions -c` acts like `autoload +X`
# * name collisions are possible in alternate usage
# * functions that examine $0 probably misfire

zmodload zsh/parameter # Or what?

# This probably never comes up, but protect ourself from recursive call
# chains that may duplicate the top elements of $funcstack by creating
# a counter of _shadow calls and using it to make shadow names unique.
typeset -gHi _shadowdepth=0

# Create a copy of each fname so that a caller may redefine
_shadow() {
  local -A fsfx=( -s ${funcstack[2]}:${functrace[2]}:$((_shadowdepth+1)) )
  local fname
  zparseopts -K -A fsfx -D s:
  for fname; do
    local shadowname=${fname}@${fsfx[-s]}
    (( $+functions[$fname] )) &&
      builtin functions -c $fname $shadowname
  done
  ((_shadowdepth++))
}

# Remove the redefined function and shadowing name
_unshadow() {
  local -A fsfx=( -s ${funcstack[2]}:${functrace[2]}:${_shadowdepth} )
  local fname
  zparseopts -K -A fsfx -D s:
  for fname; do
    local shadowname=${fname}@${fsfx[-s]}
    if (( $+functions[$shadowname] )); then
      builtin functions -c $shadowname $fname
      builtin unfunction $shadowname
    elif (( $+functions[$fname] )); then
      builtin unfunction $fname
    fi
  done
  ((_shadowdepth--))
}

# This is tricky.  When we call _shadow recursively from autoload,
# there's an extra level of stack in $functrace that will confuse
# the later call to _unshadow.  Fool ourself into working correctly.
(( ARGC )) && _shadow -s ${funcstack[2]}:${functrace[2]}:1 "$@"

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Shadowing builtins and functions
  2022-06-03  1:36 Shadowing builtins and functions Bart Schaefer
@ 2022-06-04 21:22 ` Bart Schaefer
  0 siblings, 0 replies; 2+ messages in thread
From: Bart Schaefer @ 2022-06-04 21:22 UTC (permalink / raw)
  To: Zsh hackers list

I haven't encountered any problems using this with _complete_help so
I've gone ahead and committed it (along with using it in
Functions/Zle/keeper too).


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-06-04 21:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-03  1:36 Shadowing builtins and functions Bart Schaefer
2022-06-04 21:22 ` Bart Schaefer

Code repositories for project(s) associated with this inbox:

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).