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

Re: monitoring the shell prompt

On Oct 2,  3:03pm, Paolo M. Pumilia wrote:
} Subject: monitoring the shell prompt
} Since i use to switch often between vi-cmd and vi-ins modes, it would 
} be useful to get the current vi mode displayed within the prompt 

Unfortunately the prompt is not recomputed while the editor is active, so
it can't be changed based on the editor state.  You can almost do it by
forcing the editor to be interrupted and restarted, but you may not like
it much.

Here's a sample, using $psvar and the %v escape to track the mode; widgets
require at least 3.1.6, of course, and maybe something later.  I've used
colon-commands instead of comments so you can cut'n'paste to zsh without
setopt interactive_comments.  Oh: Be sure that whatever you stuff into
psvar[1] in each function has the same number of characters as in all the
other functions, or redisplay may be messed up; similarly, try not to have
a prompt that changes width with the time of day and so on.  Put any of
that kind of stuff in RPROMPT.

# --- cut here ---
vi-ins-prompt () {
    zle .$WIDGET		;: For correct cursor placement etc.
    zle .push-input
    bindkey -A viins main
    zle .accept-line		;: The line is empty at this point
    echotc up			;: Draw the new prompt over the old
zle -N vi-ins-prompt
zle -A vi-ins-prompt vi-insert
zle -A vi-ins-prompt vi-insert-bol
zle -A vi-ins-prompt vi-add-next
zle -A vi-ins-prompt vi-add-eol
zle -A vi-ins-prompt vi-change
zle -A vi-ins-prompt vi-change-whole-line
zle -A vi-ins-prompt vi-substitute
: zle -A vi-ins-prompt vi-open-line-above	;: See remarks below
: zle -A vi-ins-prompt vi-open-line-below	;: See remarks below
: I may have missed some widgets that change to insert mode ...

bindkey -N cmdmap vicmd

vi-cmd-prompt () {
    zle .push-input
    bindkey -A cmdmap main
    zle .accept-line		;: The line is empty at this point
    echotc up			;: Draw the new prompt over the old
zle -N vi-cmd-prompt
zle -A vi-cmd-prompt vi-cmd-mode

vi-fix-prompt-and-call () {
    zle .$WIDGET
zle -N vi-fix-prompt-and-call
zle -A vi-fix-prompt-and-call accept-line
zle -A vi-fix-prompt-and-call accept-and-hold
zle -A vi-fix-prompt-and-call accept-infer-next-history
zle -A vi-fix-prompt-and-call accept-line-and-down-history
: I may have missed some of these, too ... which-command, perhaps ...

PROMPT='(@%m) %n %v %% '
# --- cut here ---

I said "almost" for several reasons.  First, the "bindkey -A ..." stuff
is a nasty hack to force the editor to restart in command mode after the
send-break; send-break stops all zle processing (including the current
user-defined widget function) and returns to the prompt with the `main'
keymap active, and you can't "bindkey -A vicmd main" for safety reasons.

Second, if you're not at the PS1 prompt (e.g. you're editing a function
or a control construct like an "if"), executing a send-break will not
have the desired effect.  You'll end up back at a PS1 prompt in command
mode, but the contents of the editor buffer (while not lost) will not
have been yanked back.

Third, and for similar reasons, vi-open-line-{above,below} are sometimes
going to behave strangely.  That's why they're commented out right now,
but you can experiment to see if it's not too confusing for you.

Fourth, I'm not entirely confident that messing with zle's head by moving
the cursor with echotc isn't going to get you into trouble sometimes.

Finally, if the editor ever restarts itself because of an error, the prompt
may not reflect the correct mode.  I think that's pretty unlikely, but I
haven't exhaustively tested this ...

Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

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