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 8bf1a208e..0f2d0664d 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 @@ -4543,7 +4557,11 @@ of the return key), or can be bound to a key in either of the tt(zed) or tt(zed-vicmd) keymaps after `tt(zed -b)' has been run. When the widget is called, it prompts for 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 with `tt(zed -f)'. +be left alone. The widget has no effect with `tt(zed -f)'. 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