about summary refs log tree commit diff
path: root/Functions/Zle
diff options
context:
space:
mode:
Diffstat (limited to 'Functions/Zle')
-rw-r--r--Functions/Zle/.distfiles1
-rw-r--r--Functions/Zle/send-invisible85
2 files changed, 86 insertions, 0 deletions
diff --git a/Functions/Zle/.distfiles b/Functions/Zle/.distfiles
index 2ec4adc22..22eef1e6e 100644
--- a/Functions/Zle/.distfiles
+++ b/Functions/Zle/.distfiles
@@ -33,6 +33,7 @@ read-from-minibuffer
 replace-string
 replace-string-again
 select-word-style
+send-invisible
 smart-insert-last-word
 split-shell-arguments
 transpose-lines
diff --git a/Functions/Zle/send-invisible b/Functions/Zle/send-invisible
new file mode 100644
index 000000000..d31fc76ae
--- /dev/null
+++ b/Functions/Zle/send-invisible
@@ -0,0 +1,85 @@
+#autoload
+
+# send-invisible reads a line from the terminal, displaying an
+# asterisk for each character typed.  It stores the line in the
+# global variable INVISIBLE, and when finished reading, inserts
+# the string ${INVISIBLE} into the original command buffer.
+
+# If one argument is given, it is the prompt.  The default is
+# "Non-echoed text: "
+
+# If two or three arguments are given, they form the prefix and
+# suffix of the inserted INVISIBLE.  Defaults are '${' and '}'
+# but these can be replaced, for example with '"${' and '}"' to
+# enclose the whole word in double quotes, or '${(z)' and '}' to
+# split the value of $INVISIBLE like the shell parser.
+
+# To use:
+#  autoload -Uz send-invisible
+#  zle -N send-invisible
+#  bindkey '^X ' send-invisible
+# Or more elaborately:
+#  hidden-command() { send-invisible '% ' '${(z)' '}' }
+#  zle -N hidden-command
+#  bindkey '^X%' hidden-command
+
+# Shamelessly cribbed from read-from-minibuffer.
+
+emulate -L zsh
+
+# Hide the value of INVISIBLE in any output of set and typeset
+typeset -g -H INVISIBLE=
+
+local pretext="$PREDISPLAY$LBUFFER$RBUFFER$POSTDISPLAY"$'\n'
+
+# Can't directly make these locals because send-invisible is
+# called as a widget, so these special variables are already
+# local at the current level and wouldn't get restored
+local save_lbuffer=$LBUFFER
+local save_rbuffer=$RBUFFER
+local save_predisplay=$PREDISPLAY
+local save_postdisplay=$POSTDISPLAY
+local -a save_region_highlight
+save_region_highlight=("${region_highlight[@]}")
+
+{
+  local lb rb opn=${2:-'${'} cls=${3:-'}'}
+  LBUFFER=
+  RBUFFER=
+  PREDISPLAY="$pretext${1:-Non-echoed text: }"
+  POSTDISPLAY=
+  region_highlight=("P${(m)#pretext} ${(m)#PREDISPLAY} bold")
+
+  while zle -R && zle .read-command
+  do
+    # There are probably more commands that should go into
+    # the first clause here to harmlessly beep, because ...
+    case $REPLY in
+    (send-invisible|run-help|undefined-key|where-is|which-command)
+      zle .beep;;
+    (push-*|send-break) INVISIBLE=;&
+    (accept-*) break;;
+    (*)
+      LBUFFER=$lb
+      RBUFFER=$rb
+      zle $REPLY	# ... this could expose something
+      lb=$LBUFFER
+      rb=$RBUFFER
+      INVISIBLE=$BUFFER
+	LBUFFER=${(l:$#LBUFFER::*:):-}
+	RBUFFER=${(l:$#RBUFFER::*:):-}
+      ;;
+    esac
+  done
+} always {
+  LBUFFER=$save_lbuffer
+  RBUFFER=$save_rbuffer
+  PREDISPLAY=$save_predisplay
+  POSTDISPLAY=$save_postdisplay
+  region_highlight=("${save_region_highlight[@]}")
+  zle -R
+
+  # Now that the highlight has been restored with all the old
+  # text and cursor positioning, insert the new text.
+  LBUFFER+=${INVISIBLE:+${opn}INVISIBLE${cls}}
+}