Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] Add execute-command() widget function (was Re: [RFC][PATCH] Add change-directory() widget function)

On Tue, Apr 27, 2021 at 3:46 AM Marlon Richert <marlon.richert@xxxxxxxxx> wrote:
> On Tue, Apr 27, 2021 at 12:40 AM Bart Schaefer
> <schaefer@xxxxxxxxxxxxxxxx> wrote:
> > Anyway, no, there's no way to abort the current ZLE without $?
> > becoming nonzero.

I dug around to refresh my memory on this.  The important detail is
that the PS1/PS2 prompts represent ZLE doing a handshake with the
input parser+lexer.  The only way to get back to the PS1 prompt is to
get the parser to abandon its current state, and the only generalized
way to do that is to cause the lexer to return an error, so send-break
simulates the shell having received a keyboard interrupt.  That aborts
the lexer, which aborts the parser, and the top-level state is
restored.  $? represents the interrupt (you can tell a real interrupt
from a simulated one because $? = 130 in the signal case).

BTW, a possible bug with this is that $ZLE_LINE_ABORTED is not
assigned when there is a simulated interrupt.

> In my patch, the last thing done before the widget exits is to set
> $BUFFER and call zle .accept-line. The only return value the user will
> see in that case is that of the executed command; not that of
> .push-line-or-edit. I still prefer that version. Are there drawbacks
> to that approach?

The main drawback is the complexity involved in
creating/installing/disposing a hook function that modifies the zle
startup.  Seeing the exit status of the executed command via %? in the
prompt doesn't "feel" important enough to me to justify the extra

It's also the case that your solution takes two different code paths
in the calling widget depending on $CONTEXT -- the widget continues
past execute-command in the PS1 (or the $? = 75) case, but is aborted
in the PS2 case.  My solution consistently stops the calling widget if
the command is executed.  The documentation will need to account for
whichever approach is chosen.

Perhaps execute-command could set a variable with the exit status of
the command, and then a user for whom it is important to see that
status in the prompt could implement $PS1 in such a way as to show it
in place of %? (and then clear it, perhaps in preexec).

Messages sorted by: Reverse Date, Date, Thread, Author