From acd20254b58ea689d8046ff127bc320d5fa91cf6 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sat, 15 May 2021 13:37:35 -0700 Subject: 48710: histed + other zed updates --- ChangeLog | 4 +++ Completion/Zsh/Command/_zed | 16 ++++++++---- Doc/Zsh/contrib.yo | 21 +++++++++++++-- Functions/Misc/zed | 62 +++++++++++++++++++++++++++++++++++---------- 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 + * 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 -- cgit 1.4.1