This one is going to need some real-life testing. Before the appended patch, either "zle push-line-or-edit" had to be last thing done by any user-defined widget, or it had to be special-cased for PREBUFFER because at the PS2 prompt it effectively executed a send-break to force the parser to return to the PS1 prompt. With this patch, the current user-defined widget may continue executing through to either normal return or until another widget that ends the ZLE session (such as accept-line) is called. However, this is not transitive, that is, if user-defined widget X uses "zle Y" and Y is a user-defined widget that calls push-line-or-edit, then X will stop immediately after Y returns. It may be possible to change that, but: one thing at a time. Although push-line-or-edit clears the current BUFFER, the already-parsed PREBUFFER won't be discarded (from the parser state) until ZLE finishes. This means that if a widget such as accept-line is called in this circumstance (e.g., at PS2 prompt) the entire parser state up to that point is accepted. This has the probably-unwanted effect of restarting the parser at the end of "$PREBUFFER$BUFFFER" instead of at PS1, thereby potentially duplicating what was just pushed (with anything new in BUFFER in between). Of course, you can stuff something into BUFFER that finishes the expression represented by PREBUFFER, which will then execute that and restart with the pushed state. The foregoing all applies to "zle push-input" which is implemented by call to pushlineoredit().