zsh-workers
 help / color / mirror / code / Atom feed
* [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
@ 2023-12-05  2:12 Vincent Lefevre
  2023-12-05  4:10 ` Bart Schaefer
  0 siblings, 1 reply; 11+ messages in thread
From: Vincent Lefevre @ 2023-12-05  2:12 UTC (permalink / raw)
  To: zsh-workers

Hi,

I was wondering why I got truncated entries in the history
over the past years...

Consider the following with zsh 5.9:

$ zsh -f
zira% touch file
zira% setopt CORRECT_ALL
zira% echo fil && true
zsh: correct 'fil' to 'file' [nyae]?

Here, type Ctrl-C to interrupt.

zira% history
    1  touch file
    2  setopt CORRECT_ALL
    3  echo fil

"echo fil" shouldn't have been put in the history.

Even when I just type "echo fil" instead of "echo fil && true",
this is incorrect. But with data after the word to correct, this
is even worse, as one gets an unexpected entry in the history.

When I type 'a' instead of Ctrl-C, the full command line is put
in the history. This is better, but I'm wondering whether this
behavior is correct. The man page just says (see SPROMPT):

    a (`abort')
        Discard the entire command line without running it.

Nothing about the history. I think that the history shouldn't be
changed. But in this case, a new action (e.g. 'h' for "history")
to discard the entire command line and put it in the history
could be useful in some occasions.

BTW, the behavior in case of several spelling corrections should
be documented.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-05  2:12 [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history Vincent Lefevre
@ 2023-12-05  4:10 ` Bart Schaefer
  2023-12-05 12:57   ` Vincent Lefevre
  0 siblings, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2023-12-05  4:10 UTC (permalink / raw)
  To: zsh-workers

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

On Mon, Dec 4, 2023 at 6:12 PM Vincent Lefevre <vincent@vinc17.net> wrote:
>
> zira% setopt CORRECT_ALL
> zira% echo fil && true
> zsh: correct 'fil' to 'file' [nyae]?
>
> Here, type Ctrl-C to interrupt.
>
> "echo fil" shouldn't have been put in the history.

What's happening here is that the corrections occur in-place as the
parser reads words from the input line, much the same way that aliases
are expanded.

When you hit ctrl-c you cause an interrupt signal which stops the
parser from reading any further input, but because it's interactive
the shell itself doesn't exit, it just forces the parser to return.
The history mechanism then records what the parser read so far.

Conversely when you hit e.g. 'a' the parser is not interrupted,
continues to the end of the line, and then returns.  Again the history
mechanism records what the parser read so far.

Changing this would potentially require changing the way the
lexer+parser handle interrupt signals in general ... or changing both
^C and 'a' to skip the history, I suspect.

> BTW, the behavior in case of several spelling corrections should
> be documented.

Something like this?

[-- Attachment #2: correctall.txt --]
[-- Type: text/plain, Size: 1147 bytes --]

diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index cbd3d0f8e..c3af8dd33 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -1214,6 +1214,9 @@ Note that, when the tt(HASH_LIST_ALL) option is not set or when some
 directories in the path are not readable, this may falsely report spelling
 errors the first time some commands are used.
 
+Refer to the shell variable tt(SPROMPT) for an explanation of the
+`tt([nyae])' (no/yes/abort/edit) prompt that is offered.
+
 The shell variable tt(CORRECT_IGNORE) may be set to a pattern to
 match words that will never be offered as corrections.
 )
@@ -1222,7 +1225,10 @@ pindex(NO_CORRECT_ALL)
 pindex(CORRECTALL)
 pindex(NOCORRECTALL)
 item(tt(CORRECT_ALL) (tt(-O)))(
-Try to correct the spelling of all arguments in a line.
+Try to correct the spelling of all arguments in a line, in order from
+left to right, treating each as a file name.  Answering `tt(a)' or
+`tt(e)' at any prompt stops all corrections, otherwise every correction
+is prompted for.
 
 The shell variable tt(CORRECT_IGNORE_FILE) may be set to a pattern to
 match file names that will never be offered as corrections.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-05  4:10 ` Bart Schaefer
@ 2023-12-05 12:57   ` Vincent Lefevre
  2023-12-05 21:22     ` Bart Schaefer
  2024-01-21  5:06     ` Bart Schaefer
  0 siblings, 2 replies; 11+ messages in thread
From: Vincent Lefevre @ 2023-12-05 12:57 UTC (permalink / raw)
  To: zsh-workers

On 2023-12-04 20:10:10 -0800, Bart Schaefer wrote:
> What's happening here is that the corrections occur in-place as the
> parser reads words from the input line, much the same way that aliases
> are expanded.
> 
> When you hit ctrl-c you cause an interrupt signal which stops the
> parser from reading any further input, but because it's interactive
> the shell itself doesn't exit, it just forces the parser to return.
> The history mechanism then records what the parser read so far.
> 
> Conversely when you hit e.g. 'a' the parser is not interrupted,
> continues to the end of the line, and then returns.  Again the history
> mechanism records what the parser read so far.

I thought that this would have been put in a temporary buffer,
until the (possibly corrected) command is validated.

> Changing this would potentially require changing the way the
> lexer+parser handle interrupt signals in general ... or changing both
> ^C and 'a' to skip the history, I suspect.

I think that ^C and 'a' should just skip the history. Just like when
one types ^C in zle, the command line is discarded and not put in the
history (here, the parser has not been involved).

> > BTW, the behavior in case of several spelling corrections should
> > be documented.
> 
> Something like this?

I was also thinking about the SPROMPT documentation. The following
is inexact:

    n (`no') (default)
        Discard the correction and run the command.
    y (`yes')
        Make the correction and run the command.

One may think that the command will be run immediately after 'n' or 'y'
(i.e. not checking for other corrections). This should be like

    Discard/Make the correction and prompt for the next correction
    or run the command.

In particular, the current 'n' one is very ambiguous, because one may
want to run the command without any additional prompt for corrections.
So perhaps there should be a real

    r (`run`)
        Discard the correction and run the command (without prompting
        for other corrections).

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-05 12:57   ` Vincent Lefevre
@ 2023-12-05 21:22     ` Bart Schaefer
  2023-12-06 15:03       ` Vincent Lefevre
  2024-01-21  5:06     ` Bart Schaefer
  1 sibling, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2023-12-05 21:22 UTC (permalink / raw)
  To: zsh-workers

On Tue, Dec 5, 2023 at 4:57 AM Vincent Lefevre <vincent@vinc17.net> wrote:
>
> I thought that this would have been put in a temporary buffer,
> until the (possibly corrected) command is validated.

I'm not sure what you think "validated" means here.

> I think that ^C and 'a' should just skip the history.

I'm not going to make a decision on that without further feedback.  I
know that when I use 'a' at the "correct" prompt, I often do
eventually want to go back and re-execute the command even if I wasn't
ready to 'e'dit it at the moment of the correction.

I did notice something that seems more like a bug:  If you 'a'bort a
correction at the PS2 prompt, you're returned to PS2, but then never
prompted for further corrections at subsequent PS2 prompts.  Meanwhile
'e'dit at PS2 does not leave the PS2 prompt but then pops the whole
complex command back into the editor after you finally reach the end
of it.  Another side-effect of handling it all during the parse.

> In particular, the current 'n' one is very ambiguous, because one may
> want to run the command without any additional prompt for corrections.
> So perhaps there should be a real
>
>     r (`run`)

Why would you want "discard all and run" but not "accept all and run"?
 Anyway I think that's more typically handled by distinguishing 'n'
/'N' and 'y'/'Y', although (see above) 'a' already discards all.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-05 21:22     ` Bart Schaefer
@ 2023-12-06 15:03       ` Vincent Lefevre
  2023-12-09 21:44         ` Bart Schaefer
  0 siblings, 1 reply; 11+ messages in thread
From: Vincent Lefevre @ 2023-12-06 15:03 UTC (permalink / raw)
  To: zsh-workers

On 2023-12-05 13:22:07 -0800, Bart Schaefer wrote:
> On Tue, Dec 5, 2023 at 4:57 AM Vincent Lefevre <vincent@vinc17.net> wrote:
> >
> > I thought that this would have been put in a temporary buffer,
> > until the (possibly corrected) command is validated.
> 
> I'm not sure what you think "validated" means here.

Once the user has no longer any way to discard the command line,
which will then be really run.

> > I think that ^C and 'a' should just skip the history.
> 
> I'm not going to make a decision on that without further feedback.  I
> know that when I use 'a' at the "correct" prompt, I often do
> eventually want to go back and re-execute the command even if I wasn't
> ready to 'e'dit it at the moment of the correction.

Yes, that's why I had suggested an explicit action for that, in my
first message:

│Nothing about the history. I think that the history shouldn't be
│changed. But in this case, a new action (e.g. 'h' for "history")
│to discard the entire command line and put it in the history
│could be useful in some occasions.

Or just use 'e', then immediately put the command in the history
without running it. Is there a zle widget for that? I would find
this useful even when there are no spelling corrections.

Note that I often recall commands from the history, but sometimes,
this isn't the right context, so that I may get a spelling correction
after hitting [Enter] or ^O (accept-line-and-down-history). Putting
the command in the history again if I abort ('a') is not needed in
such a case and will even conflict with a possible future use of ^O
(because I won't execute the subsequent commands after an abort).

> > In particular, the current 'n' one is very ambiguous, because one may
> > want to run the command without any additional prompt for corrections.
> > So perhaps there should be a real
> >
> >     r (`run`)
> 
> Why would you want "discard all and run" but not "accept all and run"?

IMHO, "accept all and run" is potentially dangerous as one doesn't
know the spelling corrections. Proposed spelling corrections are
useful, but they are often wrong (e.g. for files to be created or
arguments that are not filenames) since the spelling correction
mechanism doesn't know the meaning of the arguments (unlike the
completion mechanism).

With "discard all and run", the user knows what will be executed.
This can be useful when recalling complex commands from the history.
In general, such commands have the correct spelling.

>  Anyway I think that's more typically handled by distinguishing 'n'
> /'N' and 'y'/'Y', although (see above) 'a' already discards all.

but the difference with 'n'/'N'/'y'/'Y' is that 'a' does not run
the command.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-06 15:03       ` Vincent Lefevre
@ 2023-12-09 21:44         ` Bart Schaefer
  2023-12-17 13:54           ` Vincent Lefevre
  0 siblings, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2023-12-09 21:44 UTC (permalink / raw)
  To: zsh-workers

On Wed, Dec 6, 2023 at 7:03 AM Vincent Lefevre <vincent@vinc17.net> wrote:
>
> On 2023-12-05 13:22:07 -0800, Bart Schaefer wrote:
> > On Tue, Dec 5, 2023 at 4:57 AM Vincent Lefevre <vincent@vinc17.net> wrote:
> > >
> > > I thought that this would have been put in a temporary buffer,
> > > until the (possibly corrected) command is validated.
> >
> > I'm not sure what you think "validated" means here.
>
> Once the user has no longer any way to discard the command line,
> which will then be really run.

Ah.  It's in the buffer managed in ZLE as $BUFFER, but corrections
apply left to right as that buffer is converted into a parse tree,
they don't alter the buffer itself.

> > I'm not going to make a decision on that without further feedback.
>
> Yes, that's why I had suggested an explicit action for that

Altering the prompt to add more cases is one of the things I won't do
without feedback.

> Or just use 'e', then immediately put the command in the history
> without running it. Is there a zle widget for that? I would find
> this useful even when there are no spelling corrections.

That would be push-input, which is not bound to anything by default,
but could probably be bound to ESC (shift)Q without disrupting use of
push-line on ESC q.

Correction is not itself a ZLE action -- it happens after ZLE has
returned control to the parser, and works even if ZLE is disabled.  So
there's no widget to fiddle with it.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-09 21:44         ` Bart Schaefer
@ 2023-12-17 13:54           ` Vincent Lefevre
  2023-12-17 19:37             ` Bart Schaefer
  0 siblings, 1 reply; 11+ messages in thread
From: Vincent Lefevre @ 2023-12-17 13:54 UTC (permalink / raw)
  To: zsh-workers

On 2023-12-09 13:44:42 -0800, Bart Schaefer wrote:
> On Wed, Dec 6, 2023 at 7:03 AM Vincent Lefevre <vincent@vinc17.net> wrote:
> >
> > On 2023-12-05 13:22:07 -0800, Bart Schaefer wrote:
> > > On Tue, Dec 5, 2023 at 4:57 AM Vincent Lefevre <vincent@vinc17.net> wrote:
> > > >
> > > > I thought that this would have been put in a temporary buffer,
> > > > until the (possibly corrected) command is validated.
> > >
> > > I'm not sure what you think "validated" means here.
> >
> > Once the user has no longer any way to discard the command line,
> > which will then be really run.
> 
> Ah.  It's in the buffer managed in ZLE as $BUFFER, but corrections
> apply left to right as that buffer is converted into a parse tree,
> they don't alter the buffer itself.

But if one does a first correction, for the second proposed
correction, one types 'e' to edit, one gets the buffer with
the first correction applied.

> > Or just use 'e', then immediately put the command in the history
> > without running it. Is there a zle widget for that? I would find
> > this useful even when there are no spelling corrections.
> 
> That would be push-input, which is not bound to anything by default,
> but could probably be bound to ESC (shift)Q without disrupting use of
> push-line on ESC q.
> 
> Correction is not itself a ZLE action -- it happens after ZLE has
> returned control to the parser, and works even if ZLE is disabled.  So
> there's no widget to fiddle with it.

But what matters to that after 'e', one is in ZLE.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-17 13:54           ` Vincent Lefevre
@ 2023-12-17 19:37             ` Bart Schaefer
  2023-12-18  3:37               ` Vincent Lefevre
  0 siblings, 1 reply; 11+ messages in thread
From: Bart Schaefer @ 2023-12-17 19:37 UTC (permalink / raw)
  To: zsh-workers

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

On Sun, Dec 17, 2023 at 5:54 AM Vincent Lefevre <vincent@vinc17.net> wrote:
>
> On 2023-12-09 13:44:42 -0800, Bart Schaefer wrote:
> > Ah.  It's in the buffer managed in ZLE as $BUFFER, but corrections
> > apply left to right as that buffer is converted into a parse tree,
> > they don't alter the buffer itself.
>
> But if one does a first correction, for the second proposed
> correction, one types 'e' to edit, one gets the buffer with
> the first correction applied.

When you type 'e', correction (and alias expansion!) is temporarily
disabled, the parser is allowed to run to the end, then the parsed
result is reassembled and pushed onto the editor stack (like "print
-z") and zle restarts.

Watch what happens if you type 'e' for a correction at the PS2 prompt.
The parser hasn't reached the end yet, so you get back a PS2 with
empty input, and that will keep happening until a full valid statement
is entered or you interrupt, and then you get back the entire input so
far.

This is another reason 'a' doesn't throw away the history -- you could
lose many lines of typing above the point of canceling the correction.

> > > Or just use 'e', then immediately put the command in the history
> > > without running it. Is there a zle widget for that? I would find
> > > this useful even when there are no spelling corrections.
> >
> > Correction is not itself a ZLE action -- it happens after ZLE has
> > returned control to the parser, and works even if ZLE is disabled.  So
> > there's no widget to fiddle with it.
>
> But what matters to that after 'e', one is in ZLE.

You asked if there was a widget to immediately put the command in the
history after 'e'.  There's not a widget to do all of that, because
there's not a widget triggered on 'e'.

That said ... attached is an actual ZLE implementation of correctall.
I'm not entirely happy with it yet -- problems are:
 * the tricks using "zstyle -e" are rather fragile
 * _path_files alters the leading path and then offers only to correct
the file name at the end ...
 * ... which makes it a pain to prompt correctly for the 'n' action
 * quoted words muddy things.
Features of interest:
 * uses completion, so corrections are context-sensitive rather than
simple file globs
 * offers a menu for multiple corrections (which muddies what 'y'
should do, unfortunately)
 * 'u' (undo) backs out if you TAB too often at that menu
 * 'a' does in fact discard the current line from the history, but at
PS2 it keeps what went before
 * '!' skips all remaining corrections and runs the command

The patch includes a fix for an error I kept encountering in
_approximate ... I think this but happens when the "fake" style is
used, but haven't run it to ground other than working around it.

I will not be pushing this in its current state, use at your own risk
(which would be true even if it were pushed, I suppose).

[-- Attachment #2: correct-all-words.txt --]
[-- Type: text/plain, Size: 6421 bytes --]

diff --git a/Completion/Base/Completer/_approximate b/Completion/Base/Completer/_approximate
index 96860b5a7..3e19621d2 100644
--- a/Completion/Base/Completer/_approximate
+++ b/Completion/Base/Completer/_approximate
@@ -63,7 +63,7 @@ compadd() {
     PREFIX="(#a${_comp_correct})$PREFIX"
   fi
 
-  (( $_correct_group && ${${argv[1,(r)-(|-)]}[(I)-*[JV]]} )) &&
+  (( ${_correct_group:-0} && ${${argv[1,(r)-(|-)]}[(I)-*[JV]]} )) &&
       _correct_expl[_correct_group]=${argv[1,(r)-(-|)][(R)-*[JV]]}
 
   compadd@_approximate "$_correct_expl[@]" "$@"
diff --git a/Functions/Zle/correct-all-words b/Functions/Zle/correct-all-words
new file mode 100644
index 000000000..bef262472
--- /dev/null
+++ b/Functions/Zle/correct-all-words
@@ -0,0 +1,161 @@
+#autoload
+# Intended to be called during accept-line or in zle-line-finish, but can
+# be called by any widget to apply correction to all words in $BUFFER or
+# used as a widget itself
+
+# Compare modify-current-argument
+
+setopt localoptions noksharrays multibyte norecexact
+zmodload zsh/complist || return 1
+
+local -a reply cmdline
+local key REPLY REPLY2 MENUSELECT
+integer pos posword poschar
+unset MENUSELECT	# Bug with no-select plus yes=2 below
+
+local curcontext="${curcontext:-}"
+local widget="correct-${${WIDGET/correct-all-words/}:-all-words}"
+if [[ -z "$curcontext" ]]; then
+  curcontext="${widget}:::"
+else
+  curcontext="${widget}:${curcontext#*:}"
+fi
+local mycontext="${curcontext}"
+
+# This breaks out of read-from-minibuffer if only the original matches
+local shown_original
+zstyle -e ":completion:${widget}:*" original \
+       'if (( compstate[nmatches] == 0 )); \
+       then reply=(false);
+       elif [[ ${compstate[unambiguous]} = ${key} ]]; \
+       then shown_original=unambiguous; zle -U n; reply=(false); \
+       elif [[ -z ${shown_original} ]];
+       then shown_original=original; reply=(true);
+       else reply=(false); fi'
+
+# Would be nice to make these conditional, but it's hard to test for
+# these specifically if a more general context has the style defined
+zstyle ":completion:${widget}:*" menu no-select yes=2
+zstyle ":completion:${widget}:*" group-name ''
+zstyle ":completion:${widget}:*" group-order original corrections
+zstyle ":completion:${widget}:*" show-ambiguity true
+zstyle ":completion:${widget}:*" show-completer true
+zstyle ":completion:${widget}:*" accept-exact false
+
+# Keep completion functions out of the results
+zstyle ":completion:${widget}:*" ignored-patterns '_*'
+
+# This shows earliest the words with the fewest necessary corrections
+zstyle ":completion:${widget}:*" sort false
+
+# Overload fake description to produce a prompt for multiple corrections
+zstyle -e ":completion:${widget}:*:original" fake \
+	 'if (( compstate[nmatches] > 1 )) && \
+	     [[ -z ${shown_original} ]] ; \
+	 then bindkey -M correctall y _correct_word; \
+	 shown_original=fake-original; \
+	 reply=("${key//:/\\:}:TAB to choose, ENTER to accept, n to skip"); \
+	 fi'
+zstyle -e ":completion:${widget}:*:corrections" fake \
+	 'if [[ ${shown_original} = wanted ]] || \
+	     ( (( compstate[nmatches] > 0 )) && \
+	       [[ -z ${shown_original} ]] ); \
+	 then bindkey -M correctall y _correct_word; \
+	 shown_original=fake-corrections; \
+	 reply+=("${key//:/\\:}:TAB to choose, ENTER to accept, n to skip"); \
+	 fi'
+
+# There's no good semantics for 'y' when there are multiple possible
+# corrections.  Left as $'\t\n' it'll skip ahead after a correction is
+# chosen from the list.  Changed to .accept-line it becomes equivalent
+# to 'n' if no choice has been made yet.  The above makes it cycle the
+# menu, but maybe it would be better just to have it do nothing?
+
+autoload -Uz split-shell-arguments read-from-minibuffer mkshadow
+
+split-shell-arguments
+[[ ${#reply} -lt 2 ]] && return 1
+(( posword = REPLY, poschar = REPLY2 ))
+cmdline=("${reply[@]}")		# In case something else uses $reply ...
+
+bindkey -N correctall
+bindkey -M correctall $'\t' _correct_word
+bindkey -M correctall ' ' _correct_word
+for key in n a e \! $'\n' $'\r'
+do
+  bindkey -M correctall $key .accept-line
+done
+bindkey -M correctall u .undo
+bindkey -M correctall '^_' .undo
+bindkey -M correctall -s '^G' e
+bindkey -M correctall -s '^U' a		# Should copy from main XXX
+bindkey -M correctall -s y $'\t\n'
+
+# Work around a bug with recursive-edit from zle-line-finish
+[[ $WIDGET = zle-line-finish ]] && zle recursive-edit	# Fails
+
+local lmini rmini
+{
+  mkshadow -s all-words _original_file _correct_word
+
+  # Force unedited original to precede _path_files additions.
+  # Otherwise the "original" style above handles this.
+  function _original_file {
+    [[ ${key} = */* ]] && shown_original=wanted
+    return 1	# Force call to _correct
+  }
+
+  # This is to avoid having _correct_word stomp on $curcontext,
+  # plus break out of read-from-minibuffer when nothing matches
+  function _correct_word {
+    local shown_original ret REPLY
+    _main_complete _original_file _correct
+    ret=$?
+    [[ ${compstate[nmatches]} -eq 0 ]] && zle -U n
+    return ret
+  }
+
+  # "Real" words from reply[2], reply[4], etc., see split-shell-arguments
+  for pos in {2..${#cmdline}..2}
+  do
+    # Don't try to correct numbers and non-syntax punctuation
+    [[ ${cmdline[pos]} = *[A-Za-z]* ]] || continue
+    
+    {
+      key=${cmdline[pos]}
+      curcontext="${mycontext}"
+
+      # Can't use -K KEYMAP because read-from-minibuffer always resets
+      bindkey -A main llatcerroc
+      bindkey -A correctall main
+
+      # lmini="${PREBUFFER}${(j::)cmdline[1,pos-1]}"	# Too much?
+      lmini=${(j::)cmdline[1,pos-1]}
+      rmini=${(j::)cmdline[pos+1,-1]}
+
+      zle -U $'\t'	# Start minibuffer in completion
+      read-from-minibuffer "Correct $key [nyae!]: " "${lmini}${key}" "${rmini}"
+      REPLY=${${REPLY#${lmini}}%${rmini}}
+    } always { bindkey -A llatcerroc main }
+    case ${KEYS} in
+      (a) zle send-break; break;;
+      (n) continue;;
+      (y|$'\n'|$'\r') cmdline[pos]=${REPLY:-${cmdline[pos]}};;
+      (e) [[ ${WIDGET} = zle-line-finish ]] && {
+	    print -z "${(j::)cmdline}"
+	    cmdline=()
+	    (( posword = 0, poschar = 0 ))
+	  }
+	  ;&
+      (*) break;;
+    esac
+  done
+} always {
+  rmshadow
+  zle -R -c
+}
+
+BUFFER="${(j::)cmdline}"
+CURSOR=$(( ${#${(j::)cmdline[1,posword-1]}} + poschar ))
+
+[[ "${KEYS}" = \! ]] && zle .accept-line

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-17 19:37             ` Bart Schaefer
@ 2023-12-18  3:37               ` Vincent Lefevre
  2023-12-18  6:36                 ` Bart Schaefer
  0 siblings, 1 reply; 11+ messages in thread
From: Vincent Lefevre @ 2023-12-18  3:37 UTC (permalink / raw)
  To: zsh-workers

On 2023-12-17 11:37:12 -0800, Bart Schaefer wrote:
> This is another reason 'a' doesn't throw away the history -- you could
> lose many lines of typing above the point of canceling the correction.

There could have been a special history file for aborts. Or perhaps
the history file could have some flag for commands that are in the
history but have never been run.

Note that in many cases when I want to abort is when the command
already comes from the history. So there's no point saving it again
in general.

> > > > Or just use 'e', then immediately put the command in the history
> > > > without running it. Is there a zle widget for that? I would find
> > > > this useful even when there are no spelling corrections.
> > >
> > > Correction is not itself a ZLE action -- it happens after ZLE has
> > > returned control to the parser, and works even if ZLE is disabled.
> > > So there's no widget to fiddle with it.
> >
> > But what matters is that after 'e', one is in ZLE.
[corrected a typo]

> You asked if there was a widget to immediately put the command in the
> history after 'e'.  There's not a widget to do all of that, because
> there's not a widget triggered on 'e'.

What I intended to mean was just a widget that puts a command in the
history without running it. This is unrelated to corrections (see the
"I would find this useful even when there are no spelling corrections"
sentence above). The point would just be to save what has been typed
and recall this later.

In general, when I type 'e', I just want to edit the command.

> That said ... attached is an actual ZLE implementation of correctall.

I would be much more interested in a "correctnone": there are some
cases where one knows that there is nothing to correct, e.g. because
the arguments do not correspond to existing filenames (they could be
the result of all-matches, for instance).

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-18  3:37               ` Vincent Lefevre
@ 2023-12-18  6:36                 ` Bart Schaefer
  0 siblings, 0 replies; 11+ messages in thread
From: Bart Schaefer @ 2023-12-18  6:36 UTC (permalink / raw)
  To: zsh-workers

On Sun, Dec 17, 2023 at 7:37 PM Vincent Lefevre <vincent@vinc17.net> wrote:
>
> There could have been a special history file for aborts.

Time-travel is not a likely solution ...

> Or perhaps
> the history file could have some flag for commands that are in the
> history but have never been run.

That would get rather messy given the existence of shared history and
of "print -s".

> Note that in many cases when I want to abort is when the command
> already comes from the history. So there's no point saving it again
> in general.

The widget version from my previous message saves only the $PREBUFFER
on abort.  If you've recalled a multi-line construct from history,
PREBUFFER will be empty.

Presently ^C ends up acting like 'e' because I haven't gotten around
to signal handling yet.

> What I intended to mean was just a widget that puts a command in the
> history without running it.

hist-no-exec() {
  print -s "$BUFFER"
  zle send-break
}
zle -N hist-no-exec

Unfortunately this doesn't prevent $PREBUFFER from being saved as its own entry.

> > That said ... attached is an actual ZLE implementation of correctall.
>
> I would be much more interested in a "correctnone"

I gathered that before, which is why the correct-all-words widget adds
the '!' response.

The other typical way to get this is to use the "nocorrect" precommand modifier.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history
  2023-12-05 12:57   ` Vincent Lefevre
  2023-12-05 21:22     ` Bart Schaefer
@ 2024-01-21  5:06     ` Bart Schaefer
  1 sibling, 0 replies; 11+ messages in thread
From: Bart Schaefer @ 2024-01-21  5:06 UTC (permalink / raw)
  To: zsh-workers

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

Coming back to this because of the unfinished documentation patch.

On Tue, Dec 5, 2023 at 4:57 AM Vincent Lefevre <vincent@vinc17.net> wrote:
>
> I was also thinking about the SPROMPT documentation. The following
> is inexact:
>
>     n (`no') (default)
>         Discard the correction and run the command.
>     y (`yes')
>         Make the correction and run the command.

After thinking about this for bit, I realized that the foregoing was
written specifically for the CORRECT option and was never made to
reflect CORRECT_ALL.

> One may think that the command will be run immediately after 'n' or 'y'
> (i.e. not checking for other corrections).

That's exactly what does happen with CORRECT.  So this --

>     Discard/Make the correction and prompt for the next correction
>     or run the command.

-- isn't right either, unless CORRECT_ALL is set.

[-- Attachment #2: sprompt-correctall.txt --]
[-- Type: text/plain, Size: 1048 bytes --]

diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 68df4a16f..a6fbe6723 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -1635,9 +1635,13 @@ All other prompt escapes are also allowed.
 
 The actions available at the prompt are tt([nyae]):
 startsitem()
-sitem(tt(n) +LPAR()`no'+RPAR() +LPAR()default+RPAR())(Discard the correction and run the command.)
-sitem(tt(y) +LPAR()`yes'+RPAR())(Make the correction and run the command.)
-sitem(tt(a) +LPAR()`abort'+RPAR())(Discard the entire command line without running it.)
+sitem(tt(n) +LPAR()`no'+RPAR() +LPAR()default+RPAR())(Discard the correction.
+If there are no more corrections, accept the command line, else (with
+tt(CORRECT_ALL)) prompt for the next.)
+sitem(tt(y) +LPAR()`yes'+RPAR())(Make the correction. If there are no more
+corrections, accept the command line.)
+sitem(tt(a) +LPAR()`abort'+RPAR())(Place the entire command line in the
+history for later edit, but without accepting it.)
 sitem(tt(e) +LPAR()`edit'+RPAR())(Resume editing the command line.)
 endsitem()
 )

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2024-01-21  5:07 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-05  2:12 [BUG] With CORRECT_ALL, an interrupted correct puts a truncated entry in history Vincent Lefevre
2023-12-05  4:10 ` Bart Schaefer
2023-12-05 12:57   ` Vincent Lefevre
2023-12-05 21:22     ` Bart Schaefer
2023-12-06 15:03       ` Vincent Lefevre
2023-12-09 21:44         ` Bart Schaefer
2023-12-17 13:54           ` Vincent Lefevre
2023-12-17 19:37             ` Bart Schaefer
2023-12-18  3:37               ` Vincent Lefevre
2023-12-18  6:36                 ` Bart Schaefer
2024-01-21  5:06     ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).