about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--Completion/Zsh/Command/_zed16
-rw-r--r--Doc/Zsh/contrib.yo21
-rw-r--r--Functions/Misc/zed62
4 files changed, 83 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 52fd4be27..973455232 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2021-05-15  Bart Schaefer  <schaefer@zsh.org>
 
+	* 48710: Completion/Zsh/Command/_zed, Doc/Zsh/contrib.yo,
+	Functions/Misc/zed: add "zed -h" aka "histed", update doc and
+	completion; improve compatibility with SH_WORD_SPLIT
+
 	* 48709: Completion/Base/Widget/_complete_help: suppress error
 	messages from comptry
 
diff --git a/Completion/Zsh/Command/_zed b/Completion/Zsh/Command/_zed
index 6b68fadf0..f84993d73 100644
--- a/Completion/Zsh/Command/_zed
+++ b/Completion/Zsh/Command/_zed
@@ -1,10 +1,16 @@
-#compdef zed fned
+#compdef zed fned histed
 
 case $service in
 (fned) _arguments -S : ':shell function:_functions';;
+(histed) _arguments -S : \
+	'1:history file:_files' \
+	'2:history size: ';;
 (zed) _arguments -S : \
-	'(- 2):file:_files' \
-	'(1):shell function:_functions' \
-	'(1)-x+[specify spaces to use for indentation in function expansion]:spaces' \
-	'(1)-f[edit function]';;
+        '(-h 1 3 4)-f[edit function]' \
+        '(-h 1 3 4)-x+[specify spaces to use for indentation in function expansion]:spaces' \
+        '(-f -x 1 2)-h[edit history]' \
+        '(- 2 3 4)1:file:_files' \
+        '(3 4)2:shell function:_functions' \
+        '3:history file:_files -g "*(D)"' \
+        '4:history size';;
 esac
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index da7ab2a7c..b777703b3 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -4295,6 +4295,12 @@ Same as tt(zed -f).  This function does not appear in the zsh
 distribution, but can be created by linking tt(zed) to the name tt(fned)
 in some directory in your tt(fpath).
 )
+findex(histed)
+item(tt(histed) [ [ var(name) ] var(size) ])(
+Same as tt(zed -h).  This function does not appear in the zsh
+distribution, but can be created by linking tt(zed) to the name tt(histed)
+in some directory in your tt(fpath).
+)
 findex(is-at-least)
 item(tt(is-at-least) var(needed) [ var(present) ])(
 Perform a greater-than-or-equal-to comparison of two strings having the
@@ -4504,6 +4510,7 @@ tt(zargs) with the tt(-)tt(-help) option.
 )
 findex(zed)
 xitem(tt(zed) [ tt(-f) [ tt(-x) var(num) ] ] var(name))
+xitem(tt(zed) [ tt(-h) [ var(name) ] var(size) ])
 item(tt(zed -b))(
 This function uses the ZLE editor to edit a file or function.
 
@@ -4518,7 +4525,14 @@ the given number of spaces; `tt(-x 2)' is consistent with the layout
 of functions distributed with the shell.
 
 Without tt(-f), var(name) is the path name of the file to edit, which need
-not exist; it is created on write, if necessary.
+not exist; it is created on write, if necessary.  With tt(-h), the file is
+presumed to contain history events.
+
+When no file name is provided for tt(-h) the current shell history is edited
+in place.  The history is renumbered when zed exits successfully.
+
+When editing history, multi-line events must have a trailing backslash on
+every line before the last.
 
 While editing, the function sets the main keymap to tt(zed) and the
 vi command keymap to tt(zed-vicmd).  These will be copied from the existing
@@ -4544,7 +4558,10 @@ bound to a key in either of the tt(zed) or tt(zed-vicmd) keymaps after
 a new name for the file being edited.  When zed exits the file will be
 written under that name and the original file will be left alone.  The
 widget has no effect when invoked from `tt(zed -f)'.  The completion
-context is changed to `tt(:completion:zed-set-file-name:)'.
+context is changed to `tt(:completion:zed-set-file-name:)'.  When editing
+the current history with `tt(zed -h)', the history is first updated and
+then the file is written, but the global setting of tt(HISTFILE) is not
+altered.
 
 While tt(zed-set-file-name) is running, zed uses the keymap
 tt(zed-normal-keymap), which is linked from the main keymap in effect
diff --git a/Functions/Misc/zed b/Functions/Misc/zed
index 9eb4b2d93..7d0d590db 100644
--- a/Functions/Misc/zed
+++ b/Functions/Misc/zed
@@ -5,16 +5,18 @@
 # Edit small files with the command line editor.
 # Use ^X^W to save (or ZZ in vicmd mode), ^C to abort.
 # Option -f: edit shell functions.  (Also if called as fned.)
+# Option -h: edit shell history.  (Also if called as histed.)
 
 setopt localoptions noksharrays
 
 local var opts zed_file_name
 # We do not want timeout while we are editing a file
-integer TMOUT=0 okargs=1 fun bind
+integer TMOUT=0 okargs=1 fun hist bind
 local -a expand
 
-zparseopts -D -A opts f b x:
+zparseopts -D -A opts f h b x:
 fun=$+opts[-f]
+hist=$+opts[-h]
 bind=$+opts[-b]
 if [[ $opts[-x] == <-> ]]; then
   expand=(-x $opts[-x])
@@ -24,23 +26,28 @@ elif (( $+opts[-x] )); then
 fi
 
 [[ $0 = fned ]] && fun=1
+[[ $0 = histed ]] && hist=1
+(( hist && $# <= 2 )) && okargs=$#
 (( bind )) && okargs=0
 
-if (( $# != okargs )); then
+if (( $# != okargs || bind + fun + hist > 1 )); then
     echo 'Usage:
 zed filename
 zed -f [ -x N ] function
+zed -h [ filename [ size ] ]
 zed -b' >&2
     return 1
 fi
 
 local curcontext=zed:::
 
-# Matching used in zstyle -m: hide result from caller.
-# Variables not used directly here.
-local -a match mbegin mend
-zstyle -m ":completion:zed:*" insert-tab '*' ||
-    zstyle ":completion:zed:*" insert-tab yes
+() {
+    # Matching used in zstyle -m: hide result from caller.
+    # Variables not used directly here.
+    local -a match mbegin mend
+    zstyle -m ":completion:zed:*" insert-tab '*' ||
+	zstyle ":completion:zed:*" insert-tab yes
+}
 
 zmodload zsh/terminfo 2>/dev/null
 
@@ -124,22 +131,51 @@ fi
 setopt localoptions nobanghist
 
 if ((fun)) then
-  var="$(functions $expand -- $1)"
+  var="$(functions $expand -- "$1")"
   # If function is undefined but autoloadable, load it
   if [[ $var = *\#\ undefined* ]] then
-    var="$(autoload +X $1; functions -- $1)"
+    var="$(autoload +X "$1"; functions -- "$1")"
   elif [[ -z $var ]] then
     var="${(q-)1} () {
 }"
   fi
   vared -M zed -m zed-vicmd -i __zed_init var && eval function "$var"
+elif ((hist)) then
+  if [[ -n $1 ]]; then
+    { fc -p -a "$1" ${2:-$({ wc -l <"$1" } 2>/dev/null)} || return }
+    let HISTSIZE++  
+    print -s ""		# Work around fc -p limitation
+  fi
+  # When editing the current shell history, the "zed -h" command is not
+  # itself included because the current event is not added to the ring
+  # until the next prompt is printed.  This means "zed -h" is prepended
+  # to the result of the edit, because of the way "print -s" is defined.
+  var=( "${(@Oav)history}" )
+  IFS=$'\n' vared -M zed -m zed-vicmd -i __zed_init var
+  if (( ? )); then
+    [[ -n $1 ]] && unset HISTFILE
+  else
+    local HISTSIZE=0 savehist=$#var
+    fc -R /dev/null	# Remove entries other than those added here
+    HISTSIZE=$savehist	# Resets on function exit because local
+    [[ -n $1 ]] && SAVEHIST=$savehist	# Resets via foregoing fc -a
+    for (( hist=1; hist <= savehist; hist++ ))
+    do print -rs -- "$var[hist]"
+    done
+    if [[ -n $zed_file_name ]]; then
+      fc -W "$zed_file_name"
+      [[ -n $1 ]] && unset HISTFILE
+    fi
+    # Note prepend effect when global HISTSIZE greater than $savehist.
+    # This does not affect file editing.
+  fi
 else
-  zed_file_name=$1
-  [[ -f $1 ]] && var="$(<$1)"
+  zed_file_name="$1"
+  [[ -f $1 ]] && var="$(<"$1")"
   while vared -M zed -m zed-vicmd -i __zed_init var
   do
     {
-      print -r -- "$var" >| $zed_file_name
+      print -r -- "$var" >| "$zed_file_name"
     } always {
       (( TRY_BLOCK_ERROR = 0 ))
     } && break