zsh-workers
 help / color / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Editing the history in the shell
Date: Fri, 22 May 2020 15:24:14 -0700
Message-ID: <CAH+w=7ZFt7jshjv1FCEbmP_PgADvdKwymRutrzwJAvzNpsfOmA@mail.gmail.com> (raw)


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

This is not quite a finished product yet (for one thing, no doc) but
it demonstrates most of the interesting ideas.

The patch implements "zed -h" which loads the history into vared and
arranges to replace the existing history with that before it exits.
This does NOT solve Markus' complaint about the history numbers, they
increase by the number of entries output by the editor. It makes no
attempt to account for various history options, so those may change
the final result if they affect "print -s".

It also handles "zed -h filename" which loads that file and saves it
back again rather than alter the current shell history.  There is a
glitch currently that may lose the most recent line from the file when
it is loaded (not when it is saved), which seems to be the fault of
"fc -p".  There are probably other bugs, I've tested only minimally.

Some unanswered questions:
1) Should it be possible to edit empty events into the history?
Currently empty lines are removed, but changing to IFS=$'\n\n' would
preserve them (thanks Oliver for the idea)
2) Should "vared -h" be used?  I'm inclined to say "no" because the
behavior becomes a bit strange; the entire content of the variable is
treated as one "history event" when navigating, i.e., if you move up
from the top (oldest) history event, the whole history disappears and
is replaced by the single newest event.
3) If the file for "zed -h filename" does not exist, should the editor
be populated from the current shell history?  Currently the editor
starts empty.

Patch both inlined and attached in case gmail garbles the lines.  I
followed the existing coding style of "zed", which is a little quirky.

diff --git a/Functions/Misc/zed b/Functions/Misc/zed
index 9eb4b2d..952e1a9 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,12 +26,15 @@ elif (( $+opts[-x] )); then
 fi

 [[ $0 = fned ]] && fun=1
+[[ $0 = histed ]] && hist=1
 (( bind )) && okargs=0
+(( hist && $# <= 2 )) && okargs=$#

-if (( $# != okargs )); then
+if (( $# != okargs || fun + hist > 1 )); then
     echo 'Usage:
 zed filename
 zed -f [ -x N ] function
+zed -h [ filename [ size ] ]
 zed -b' >&2
     return 1
 fi
@@ -133,6 +138,17 @@ if ((fun)) then
 }"
   fi
   vared -M zed -m zed-vicmd -i __zed_init var && eval function "$var"
+elif ((hist)) then
+  [[ -n $1 ]] && { fc -p -a $1 ${2:-$({ wc -l <$1 } 2>/dev/null)} || return }
+  var=( "${(@Oav)history:gs/\\/\\\\}" )
+  IFS=$'\n' vared -M zed -m zed-vicmd -i __zed_init var
+  if (( ? )); then
+    [[ -n $1 ]] && unset HISTFILE
+  else
+    hist=$HISTSIZE; HISTSIZE=0; fc -R /dev/null; HISTSIZE=$hist
+    for (( hist=1; hist <= $#var; hist++ )) print -s "$var[hist]"
+    [[ -n $1 ]] && SAVEHIST=$#var    # Resets on function exit
+  fi
 else
   zed_file_name=$1
   [[ -f $1 ]] && var="$(<$1)"

[-- Attachment #2: zed-h.txt --]
[-- Type: text/plain, Size: 1768 bytes --]

diff --git a/Functions/Misc/zed b/Functions/Misc/zed
index 9eb4b2d..952e1a9 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,12 +26,15 @@ elif (( $+opts[-x] )); then
 fi
 
 [[ $0 = fned ]] && fun=1
+[[ $0 = histed ]] && hist=1
 (( bind )) && okargs=0
+(( hist && $# <= 2 )) && okargs=$#
 
-if (( $# != okargs )); then
+if (( $# != okargs || fun + hist > 1 )); then
     echo 'Usage:
 zed filename
 zed -f [ -x N ] function
+zed -h [ filename [ size ] ]
 zed -b' >&2
     return 1
 fi
@@ -133,6 +138,17 @@ if ((fun)) then
 }"
   fi
   vared -M zed -m zed-vicmd -i __zed_init var && eval function "$var"
+elif ((hist)) then
+  [[ -n $1 ]] && { fc -p -a $1 ${2:-$({ wc -l <$1 } 2>/dev/null)} || return }
+  var=( "${(@Oav)history:gs/\\/\\\\}" )
+  IFS=$'\n' vared -M zed -m zed-vicmd -i __zed_init var
+  if (( ? )); then
+    [[ -n $1 ]] && unset HISTFILE
+  else
+    hist=$HISTSIZE; HISTSIZE=0; fc -R /dev/null; HISTSIZE=$hist
+    for (( hist=1; hist <= $#var; hist++ )) print -s "$var[hist]"
+    [[ -n $1 ]] && SAVEHIST=$#var	# Resets on function exit
+  fi
 else
   zed_file_name=$1
   [[ -f $1 ]] && var="$(<$1)"

             reply index

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-22 22:24 Bart Schaefer [this message]
2020-05-23  2:28 ` Daniel Shahaf
2020-05-23 21:30   ` Bart Schaefer
2020-05-24 22:02     ` _arguments optspecs (was Re: Editing the history in the shell) Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAH+w=7ZFt7jshjv1FCEbmP_PgADvdKwymRutrzwJAvzNpsfOmA@mail.gmail.com' \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

zsh-workers

Archives are clonable: git clone --mirror http://inbox.vuxu.org/zsh-workers

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.zsh.workers


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git