zsh-workers
 help / color / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: Editing the history in the shell
Date: Sat, 23 May 2020 14:30:36 -0700
Message-ID: <CAH+w=7aWxdY3KuTaYym1GiAowRRHBc=2AJPPgqOmN8G6L0xT2A@mail.gmail.com> (raw)
In-Reply-To: <20200523022807.08f3ba45@tarpaulin.shahaf.local2>


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

Thanks for the review, Daniel.

On Fri, May 22, 2020 at 7:28 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Bart Schaefer wrote on Fri, 22 May 2020 15:24 -0700:
> > 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)
>
> Hmm.  I guess they might be useful as separators?

I did not do this yet.

> Evaluating «$#var» takes O(N) time, which makes this an O(N²) loop.
> Save $#var into an auxiliary variable?

Did that.

> Also, s/print -s/print -s --/.

I went all the way to "print -rs --" although -r may not have been necessary.

I believe the following fixes the last-line-lost problem with "fc -p"
and also a problem that you couldn't save more lines to a history file
than were read from it in the first place.  And I updated the _zed
completer, though not yet the doc.  I'm not entirely sure about some
of the _zed optspecs, but all the desired combinations seem to work
and all the undesired ones seem not to.

Inlined and attached, again.

diff --git a/Completion/Zsh/Command/_zed b/Completion/Zsh/Command/_zed
index 6b68fad..cb90dde 100644
--- a/Completion/Zsh/Command/_zed
+++ b/Completion/Zsh/Command/_zed
@@ -1,10 +1,14 @@
-#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 2)-f[edit function]:shell function:_functions' \
+    '(-h 1 2)-x+[specify spaces to use for indentation in function
expansion]:spaces' \
+    '(-f -x 1)-h[edit history]:history file:_files' \
+    '2:history size: ';;
 esac
diff --git a/Functions/Misc/zed b/Functions/Misc/zed
index 9eb4b2d..21aa94f 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

@@ -133,6 +140,28 @@ if ((fun)) then
 }"
   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
+  var=( "${(@Oav)history:gs/\\/\\\\}" )
+  IFS=$'\n' vared -M zed -m zed-vicmd -i __zed_init var
+  if (( ? )); then
+    [[ -n $1 ]] && unset HISTFILE
+  else
+    local savehist=$#var
+    hist=$HISTSIZE; HISTSIZE=0; fc -R /dev/null
+    if [[ -n $1 ]]; then
+      # Resets on function exit
+      HISTSIZE=$savehist
+      SAVEHIST=$savehist
+    else
+      HISTSIZE=$hist
+    fi
+    for (( hist=1; hist <= savehist; hist++ )) print -rs -- "$var[hist]"
+  fi
 else
   zed_file_name=$1
   [[ -f $1 ]] && var="$(<$1)"

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

diff --git a/Completion/Zsh/Command/_zed b/Completion/Zsh/Command/_zed
index 6b68fad..cb90dde 100644
--- a/Completion/Zsh/Command/_zed
+++ b/Completion/Zsh/Command/_zed
@@ -1,10 +1,14 @@
-#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 2)-f[edit function]:shell function:_functions' \
+	'(-h 1 2)-x+[specify spaces to use for indentation in function expansion]:spaces' \
+	'(-f -x 1)-h[edit history]:history file:_files' \
+	'2:history size: ';;
 esac
diff --git a/Functions/Misc/zed b/Functions/Misc/zed
index 9eb4b2d..21aa94f 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
 
@@ -133,6 +140,28 @@ if ((fun)) then
 }"
   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
+  var=( "${(@Oav)history:gs/\\/\\\\}" )
+  IFS=$'\n' vared -M zed -m zed-vicmd -i __zed_init var
+  if (( ? )); then
+    [[ -n $1 ]] && unset HISTFILE
+  else
+    local savehist=$#var
+    hist=$HISTSIZE; HISTSIZE=0; fc -R /dev/null
+    if [[ -n $1 ]]; then
+      # Resets on function exit
+      HISTSIZE=$savehist
+      SAVEHIST=$savehist
+    else
+      HISTSIZE=$hist
+    fi
+    for (( hist=1; hist <= savehist; hist++ )) print -rs -- "$var[hist]"
+  fi
 else
   zed_file_name=$1
   [[ -f $1 ]] && var="$(<$1)"

  reply index

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

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=7aWxdY3KuTaYym1GiAowRRHBc=2AJPPgqOmN8G6L0xT2A@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