* vim-a-like vi mode status bar
@ 2002-02-16 17:20 Ian Lynagh
2002-02-16 17:48 ` Thomas Köhler
2002-02-20 22:12 ` Steve Talley
0 siblings, 2 replies; 5+ messages in thread
From: Ian Lynagh @ 2002-02-16 17:20 UTC (permalink / raw)
To: zsh-users
[-- Attachment #1: Type: text/plain, Size: 1272 bytes --]
Hi all
I have thought it would be nice to have a vim-a-like indicator of
whether or not you are insert or command mode when using the vi line
editting mode for a long time now. In a burst of enthusiasm I have put
something together over the last couple of days (attached). However it's
not quite as nice as it might have been and I have run into a few
annoyances along the way.
Initially I was planning to have the indicator in the prompt. However
AFAICT once the prompt has been displayed it is cached, so even if you
for zsh to redraw it (I tried various things like "zle redisplay", "zle
push-input; zle get-line", "zle -R") it just redraws the old one. Did I
miss a way to do this?
Is there a reason why it shouldn't be possible to pipe something into
source? Or another way to do it without a temporary file?
With the script attached, if I paste a command in then only the first
character is visible until I press ^R. If I type something else first
then it works fine (even if I first delete what I typed!). Perhaps this
is a bug?
I also couldn't find a way to set the statusbar after accepting a
command. zsh -M complains it's not being called from a widget if I call
it from precmd.
Finally I would welcome any comments/criticisms on the code!
Thanks
Ian
[-- Attachment #2: zsh-vi-mode-status-bar --]
[-- Type: text/plain, Size: 2772 bytes --]
# Provides you with a vim-a-like vi-mode status bar showing what mode
# you are in.
# To be called from .zshrc
# Author: Ian Lynagh <igloo@earth.li>
# Licence: GPL 2
# Copyright: Ian Lynagh <igloo@earth.li> 2002
# Should we show "<insert>" or "" for insert mode?
alias statusbar-show-insert="zstyle :vi-mode-statusbar: show-insert yes"
alias statusbar-no-show-insert="zstyle :vi-mode-statusbar: show-insert no"
alias statusbar-test-show-insert="zstyle -t :vi-mode-statusbar: show-insert"
statusbar-no-show-insert
# What mode are we now in?
alias statusbar-now-insert="zstyle :vi-mode-statusbar: now-insert yes"
alias statusbar-now-command="zstyle :vi-mode-statusbar: now-insert no"
alias statusbar-test-now-insert="zstyle -t :vi-mode-statusbar: now-insert"
# What mode were we in last time?
alias statusbar-last-insert="zstyle :vi-mode-statusbar: last-insert yes"
alias statusbar-last-command="zstyle :vi-mode-statusbar: last-insert no"
alias statusbar-test-last-insert="zstyle -t :vi-mode-statusbar: last-insert"
# Helper function
function stat-statusbar-update {
if statusbar-test-now-insert
then
if statusbar-test-show-insert
then
zle -M "<insert>"
else
if ! statusbar-test-last-insert
then
zle -M ""
fi
fi
statusbar-last-insert
else
zle -M "<command>"
statusbar-last-command
fi
}
# Before each prompt reset
function precmd {
statusbar-now-insert
statusbar-last-command
}
# Wrap each widget
# This makes a new ~/.zshrc.stat.functions
function gen-stat-functions {
local EXTRA CHANGE
rm ~/.zshrc.stat.functions
zle -l -a | grep "^[a-zA-Z]" | while read WIDGET
do
UPDATE="stat-statusbar-update"
CHANGE=""
case "$WIDGET" in
vi-(add-(eol|next)|insert(|-bol)|change-(eol|whole-line) \
|open-line-(above|below)|replace) \
|accept-(and-(hold|infer-next-history)|line(|-and-down-history)) \
|get-line|pound-insert|push-(input|line(|-or-edit)) \
|send-break|run-help|which-command)
CHANGE="statusbar-now-insert"
;;
vi-cmd-mode)
echo foo
CHANGE="statusbar-now-command"
;;
vi-change)
CHANGE="statusbar-now-insert"
UPDATE=""
;;
esac
echo "
function stat-$WIDGET {
zle .$WIDGET
$CHANGE
$UPDATE
}
zle -N stat-$WIDGET stat-$WIDGET
zle -A stat-$WIDGET $WIDGET" >> ~/.zshrc.stat.functions
done
}
# Don't bother updating it automagically - that's just asking for it!
# Just . whatever was last created
. ~/.zshrc.stat.functions
# Use vi mode
bindkey -v
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: vim-a-like vi mode status bar
2002-02-16 17:20 vim-a-like vi mode status bar Ian Lynagh
@ 2002-02-16 17:48 ` Thomas Köhler
2002-02-16 20:05 ` Ian Lynagh
2002-02-20 22:12 ` Steve Talley
1 sibling, 1 reply; 5+ messages in thread
From: Thomas Köhler @ 2002-02-16 17:48 UTC (permalink / raw)
To: zsh-users
[-- Attachment #1.1: Type: text/plain, Size: 988 bytes --]
Hi,
Ian Lynagh wrote [020216 18:28]:
> Hi all
>
> I have thought it would be nice to have a vim-a-like indicator of
> whether or not you are insert or command mode when using the vi line
> editting mode for a long time now. In a burst of enthusiasm I have put
> something together over the last couple of days (attached). However it's
> not quite as nice as it might have been and I have run into a few
> annoyances along the way.
Well, I use something similar. Of course, I have a multiline
prompt, so what I have here might work for you, but it might need
some adjustment - the escape sequences for moving the cursor
might not work for your type of terminal...
Ciao,
Thomas
--
Thomas Köhler Email: jean-luc@picard.franken.de | LCARS - Linux
<>< WWW: http://jeanluc-picard.de | for Computers
IRC: jeanluc | on All Real
PGP public key available from Homepage! | Starships
[-- Attachment #1.2: zshrc.showmode --]
[-- Type: text/plain, Size: 4947 bytes --]
# vi keybindings
bindkey -v
bindkey -M vicmd "^R" redo
bindkey -M vicmd "u" undo
bindkey -M vicmd "ga" what-cursor-position
unsetopt promptcr
redisplay() {
builtin zle .redisplay
( true ; show_mode "INSERT") &!
}
redisplay2() {
builtin zle .redisplay
(true ; show_mode "NORMAL") &!
}
zle -N redisplay
zle -N redisplay2
bindkey -M viins "^X^R" redisplay
bindkey -M vicmd "^X^R" redisplay2
screenclear () {
echo -n "\033[2J\033[400H"
builtin zle .redisplay
(true ; show_mode "INSERT") &!
}
zle -N screenclear
bindkey "\f" screenclear
screenclearx () {
repeat 2 print
local MYLINE="$LBUFFER$RBUFFER"
highlight $MYLINE
repeat 4 print
builtin zle redisplay
}
zle -N screenclearx
bindkey "^Xl" screenclearx
show_mode() {
local COL
local x
COL=$[COLUMNS-3]
COL=$[COL-$#1]
x=$(echo $PREBUFFER | wc -l )
x=$[x+1]
echo -n "^[7^[[$x;A^[[0;G"
echo -n ""
echo -n "^[[0;37;44m--$1--^[[0m"
echo -n "^[8"
}
zmodload zsh/parameter
### vi-add-eol (unbound) (A) (unbound)
### Move to the end of the line and enter insert mode.
vi-add-eol() {
show_mode "INSERT"
builtin zle .vi-add-eol
}
zle -N vi-add-eol
bindkey -M vicmd "A" vi-add-eol
### vi-add-next (unbound) (a) (unbound)
### Enter insert mode after the current cursor posi
### tion, without changing lines.
vi-add-next() {
show_mode "INSERT"
builtin zle .vi-add-next
# OLDLBUFFER=$LBUFFER
# OLDRBUFFER=$RBUFFER
# NNUMERIC=$NUMERIC
# bindkey -M viins "^[" vi-cmd-mode-a
}
zle -N vi-add-next
bindkey -M vicmd "a" vi-add-next
### vi-change (unbound) (c) (unbound)
### Read a movement command from the keyboard, and kill
### from the cursor position to the endpoint of the
### movement. Then enter insert mode. If the command
### is vi-change, change the current line.
vi-change() {
show_mode "INSERT"
builtin zle .vi-change
}
zle -N vi-change
bindkey -M vicmd "c" vi-change
### vi-change-eol (unbound) (C) (unbound)
### Kill to the end of the line and enter insert mode.
vi-change-eol() {
show_mode "INSERT"
builtin zle .vi-change-eol
}
zle -N vi-change-eol
bindkey -M vicmd "C" vi-change-eol
### vi-change-whole-line (unbound) (S) (unbound)
### Kill the current line and enter insert mode.
vi-change-whole-line() {
show_mode "INSERT"
builtin zle .vi-change-whole-line
}
zle -N vi-change-whole-line
bindkey -M vicmd "S" vi-change-whole-line
### vi-insert (unbound) (i) (unbound)
### Enter insert mode.
vi-insert() {
show_mode "INSERT"
builtin zle .vi-insert
}
zle -N vi-insert
bindkey -M vicmd "i" vi-insert
### vi-insert-bol (unbound) (I) (unbound)
### Move to the first non-blank character on the line
### and enter insert mode.
vi-insert-bol() {
show_mode "INSERT"
builtin zle .vi-insert-bol
}
zle -N vi-insert-bol
bindkey -M vicmd "I" vi-insert-bol
### vi-open-line-above (unbound) (O) (unbound)
### Open a line above the cursor and enter insert mode.
vi-open-line-above() {
show_mode "INSERT"
builtin zle .vi-open-line-above
}
zle -N vi-open-line-above
bindkey -M vicmd "O" vi-open-line-above
### vi-open-line-below (unbound) (o) (unbound)
### Open a line below the cursor and enter insert mode.
vi-open-line-below() {
show_mode "INSERT"
builtin zle .vi-open-line-below
}
zle -N vi-open-line-below
bindkey -M vicmd "o" vi-open-line-below
### vi-substitute (unbound) (s) (unbound)
### Substitute the next character(s).
vi-substitute() {
show_mode "INSERT"
builtin zle .vi-substitute
}
zle -N vi-substitute
bindkey -M vicmd "s" vi-substitute
### vi-replace (unbound) (R) (unbound)
### Enter overwrite mode.
###
vi-replace() {
show_mode "REPLACE"
builtin zle .vi-replace
}
zle -N vi-replace
bindkey -M vicmd "R" vi-replace
### vi-cmd-mode (^X^V) (unbound) (^[)
### Enter command mode; that is, select the `vicmd'
### keymap. Yes, this is bound by default in emacs
### mode.
vi-cmd-mode() {
show_mode "NORMAL"
builtin zle .vi-cmd-mode
}
zle -N vi-cmd-mode
bindkey -M viins "^[" vi-cmd-mode
### vi-oper-swap-case
### Read a movement command from the keyboard, and swap
### the case of all characters from the cursor position
### to the endpoint of the movement. If the movement
### command is vi-oper-swap-case, swap the case of all
### characters on the current line.
###
bindkey -M vicmd "g~" vi-oper-swap-case
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: vim-a-like vi mode status bar
2002-02-16 17:48 ` Thomas Köhler
@ 2002-02-16 20:05 ` Ian Lynagh
2002-02-17 18:57 ` Thomas Köhler
0 siblings, 1 reply; 5+ messages in thread
From: Ian Lynagh @ 2002-02-16 20:05 UTC (permalink / raw)
To: zsh-users
Hi,
On Sat, Feb 16, 2002 at 06:48:05PM +0100, Thomas Köhler wrote:
>
> Ian Lynagh wrote [020216 18:28]:
> > I have thought it would be nice to have a vim-a-like indicator of
> > whether or not you are insert or command mode when using the vi line
> > editting mode for a long time now. In a burst of enthusiasm I have put
> > something together over the last couple of days (attached). However it's
> > not quite as nice as it might have been and I have run into a few
> > annoyances along the way.
>
> Well, I use something similar. Of course, I have a multiline
Thanks, very interesting to see another implementation.
> prompt, so what I have here might work for you, but it might need
> some adjustment - the escape sequences for moving the cursor
> might not work for your type of terminal...
That's an approach I thought of but decided against, partly because of
the potential terminal issues and partly because of the cases like
multi-line input and screen clearing. However, you seem to have these
mostly[0] sussed so I might switch to this with a simple command to
switch to a simpler prompt if I do happen to be using a less fancy
terminal.
[0] It still looks like it has problems when the prompt has scrolled off
the top of the screen, at least in an rxvt.
This should also solve a few of my current problems (flicker, characters
not being echoed when pasted and having the default state shown).
I do have a couple of further questions for you though...
> redisplay() {
> builtin zle .redisplay
> ( true ; show_mode "INSERT") &!
> }
I am not sure why you have the &! here - if it is worth doing then that
implies you might do something else before it has finished in which case
your cursor might not be where you think it is?
It also seems to me you might be better off with a variable (or zstyle
lookup or whatever) for the current state and a single redisplay. This
would have the advantage that you wouldn't have to worry about things
being rebound incorrectly later on.
> zle -N redisplay
Just overwriting the built-in widgets rather than aliasing seems so
*obvious* now how did I ever not think of it? Too caught up in the
excitement of being able to alias them I think!
> show_mode() {
> local COL
> local x
> COL=$[COLUMNS-3]
> COL=$[COL-$#1]
> x=$(echo $PREBUFFER | wc -l )
> x=$[x+1]
> echo -n "^[7^[[$x;A^[[0;G"
> echo -n ""
> echo -n "^[[0;37;44m--$1--^[[0m"
> echo -n "^[8"
> }
Am I missing something or is COL never actually used?
And doesn't
echo -n ""
do nothing?
Thanks
Ian
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: vim-a-like vi mode status bar
2002-02-16 20:05 ` Ian Lynagh
@ 2002-02-17 18:57 ` Thomas Köhler
0 siblings, 0 replies; 5+ messages in thread
From: Thomas Köhler @ 2002-02-17 18:57 UTC (permalink / raw)
To: zsh-users
[-- Attachment #1: Type: text/plain, Size: 5214 bytes --]
Hi,
Ian Lynagh wrote [020217 19:03]:
> On Sat, Feb 16, 2002 at 06:48:05PM +0100, Thomas Köhler wrote:
[...]
> > prompt, so what I have here might work for you, but it might need
> > some adjustment - the escape sequences for moving the cursor
> > might not work for your type of terminal...
>
> That's an approach I thought of but decided against, partly
> because of the potential terminal issues and partly because of
> the cases like multi-line input and screen clearing. However,
> you seem to have these mostly[0] sussed so I might switch to
> this with a simple command to switch to a simpler prompt if I
> do happen to be using a less fancy terminal.
That idea is not so bad, though I usually have very usuable
terminal definitions :-)
> [0] It still looks like it has problems when the prompt has
> scrolled off the top of the screen, at least in an rxvt.
In some cases, it doesn't work correctly, yes. This includes the
case when you type a very long line, a wrap happens and you
switch modes then - bad luck, --NORMAL-- appears in the wrong
place (one line below). But that doesn't happen enough to bother
me for now...
> This should also solve a few of my current problems (flicker,
> characters not being echoed when pasted and having the default
> state shown).
Yes, there's quite a few issues to resolve when you want to write
something to some special position in the terminal...
> I do have a couple of further questions for you though...
No problem :-)
> > redisplay() {
> > builtin zle .redisplay
> > ( true ; show_mode "INSERT") &!
> > }
>
> I am not sure why you have the &! here - if it is worth doing
> then that implies you might do something else before it has
> finished in which case your cursor might not be where you think
> it is?
I've inserted those &! in all places because for some situations,
the cursor was not back to its original position yet before the
function has been called, so by this little trick, the function
returns, the cursor is back, and _then_ the "INSERT" is being
drawed. Funny issue indeed. I don't remember offhand which of
those &! I really needed, and I just dodn't mind because it works
OK for now...
> It also seems to me you might be better off with a variable (or
> zstyle lookup or whatever) for the current state and a single
> redisplay. This would have the advantage that you wouldn't have
> to worry about things being rebound incorrectly later on.
Maybe, didn't evaluate that much further. Perhaps worth thinking
about it...
> > zle -N redisplay
>
> Just overwriting the built-in widgets rather than aliasing seems so
> *obvious* now how did I ever not think of it? Too caught up in the
> excitement of being able to alias them I think!
That idea came to my mind after reading zsh-users some day, and
once you find the trick, all seems so obvious and you think "why
have I been so silly?". It's always the same :-)
> > show_mode() {
> > local COL
> > local x
> > COL=$[COLUMNS-3]
> > COL=$[COL-$#1]
> > x=$(echo $PREBUFFER | wc -l )
> > x=$[x+1]
> > echo -n "^[7^[[$x;A^[[0;G"
> > echo -n ""
> > echo -n "^[[0;37;44m--$1--^[[0m"
> > echo -n "^[8"
> > }
>
> Am I missing something or is COL never actually used?
Well... no, you're not missing anything, I just forgot to remove
it, it was in there in my first version (and has been used then
because I used to have the mode on the right hand side instead of
the left hand side).
> And doesn't
> echo -n ""
> do nothing?
Actually, it prints an empty string :-)
One thing I'm thinking of at the moment: Some more issues (where
to put the "showmode") could be resolved better by always using
the same position on the screen - for example, always on the last
line, at the left hand side. That way, some fidling around with
$LINES might be needed (as I used to use $COLUMNS in my original
version, but then I decided to put the showmode feature to the
left hand side, and, well, put a clock[1] on the right hand
side), and one would have to create a long prompt (part of which
would be overwritten when you're down at the bottom), but it
might be a better idea? Perhaps worth a try...
[1] Don't try this at home: Sometimes there's a race condition
when zsh tries to complete things and that little cron comes in
the way, and so sometimes (not very often, but still sometimes)
zsh crashes. It used to be worse back in 3.1.9-dev-xx-days,
though :)
Here it is anyways, for those who still want it...
### a clock in the prompt. Yes, this _is_ cool.
trap CRON ALRM
TMOUT=1
CRON() {
local STRING
local COL
local x
STRING=$(date)
COL=$[COLUMNS-5]
COL=$[COL-$#STRING]
x=$(echo $PREBUFFER | wc -l )
x=$[x+1]
echo -n "^[7^[[$x;A^[[$COL;G^[[0;37;44m-- $STRING --^[[0m^[8"
}
> Thanks
> Ian
Ciao,
Thomas
--
Thomas Köhler Email: jean-luc@picard.franken.de | LCARS - Linux
<>< WWW: http://jeanluc-picard.de | for Computers
IRC: jeanluc | on All Real
PGP public key available from Homepage! | Starships
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: vim-a-like vi mode status bar
2002-02-16 17:20 vim-a-like vi mode status bar Ian Lynagh
2002-02-16 17:48 ` Thomas Köhler
@ 2002-02-20 22:12 ` Steve Talley
1 sibling, 0 replies; 5+ messages in thread
From: Steve Talley @ 2002-02-20 22:12 UTC (permalink / raw)
To: Ian Lynagh; +Cc: zsh-users
[-- Attachment #1: Type: text/plain, Size: 1485 bytes --]
I have a mode line that appears below the command line (attached). It
has a bug here and there, but is fairly solid and pretty simple.
Steve
Ian Lynagh wrote:
> Hi all
>
> I have thought it would be nice to have a vim-a-like indicator of
> whether or not you are insert or command mode when using the vi line
> editting mode for a long time now. In a burst of enthusiasm I have
> put something together over the last couple of days (attached).
> However it's not quite as nice as it might have been and I have run
> into a few annoyances along the way.
>
> Initially I was planning to have the indicator in the prompt.
> However AFAICT once the prompt has been displayed it is cached, so
> even if you for zsh to redraw it (I tried various things like "zle
> redisplay", "zle push-input; zle get-line", "zle -R") it just
> redraws the old one. Did I miss a way to do this?
>
> Is there a reason why it shouldn't be possible to pipe something
> into source? Or another way to do it without a temporary file?
>
> With the script attached, if I paste a command in then only the
> first character is visible until I press ^R. If I type something
> else first then it works fine (even if I first delete what I
> typed!). Perhaps this is a bug?
>
> I also couldn't find a way to set the statusbar after accepting a
> command. zsh -M complains it's not being called from a widget if I
> call it from precmd.
>
> Finally I would welcome any comments/criticisms on the code!
>
> Thanks Ian
[-- Attachment #2: zshmode --]
[-- Type: text/plain, Size: 2387 bytes --]
#
# Set vi mode status bar
#
#
# Reads until the given character has been entered.
#
readuntil () {
typeset a
while [ "$a" != "$1" ]
do
read -E -k 1 a
done
}
#
# If the $SHOWMODE variable is set, displays the vi mode, specified by
# the $VIMODE variable, under the current command line.
#
# Arguments:
#
# 1 (optional): Beyond normal calculations, the number of additional
# lines to move down before printing the mode. Defaults to zero.
#
showmode() {
typeset movedown
typeset row
# Get number of lines down to print mode
movedown=$(($(echo "$RBUFFER" | wc -l) + ${1:-0}))
# Get current row position
echo -n "\e[6n"
row="${${$(readuntil R)#*\[}%;*}"
# Are we at the bottom of the terminal?
if [ $((row+movedown)) -gt "$LINES" ]
then
# Scroll terminal up one line
echo -n "\e[1S"
# Move cursor up one line
echo -n "\e[1A"
fi
# Save cursor position
echo -n "\e[s"
# Move cursor to start of line $movedown lines down
echo -n "\e[$movedown;E"
# Change font attributes
echo -n "\e[1m"
# Has a mode been set?
if [ -n "$VIMODE" ]
then
# Print mode line
echo -n "-- $VIMODE -- "
else
# Clear mode line
echo -n "\e[0K"
fi
# Restore font
echo -n "\e[0m"
# Restore cursor position
echo -n "\e[u"
}
clearmode() {
VIMODE= showmode
}
#
# Temporary function to extend built-in widgets to display mode.
#
# 1: The name of the widget.
#
# 2: The mode string.
#
# 3 (optional): Beyond normal calculations, the number of additional
# lines to move down before printing the mode. Defaults to zero.
#
makemodal () {
# Create new function
eval "$1() { zle .'$1'; ${2:+VIMODE='$2'}; showmode $3 }"
# Create new widget
zle -N "$1"
}
# Extend widgets
makemodal vi-add-eol INSERT
makemodal vi-add-next INSERT
makemodal vi-change INSERT
makemodal vi-change-eol INSERT
makemodal vi-change-whole-line INSERT
makemodal vi-insert INSERT
makemodal vi-insert-bol INSERT
makemodal vi-open-line-above INSERT
makemodal vi-substitute INSERT
makemodal vi-open-line-below INSERT 1
makemodal vi-replace REPLACE
makemodal vi-cmd-mode NORMAL
unfunction makemodal
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-02-20 22:13 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-02-16 17:20 vim-a-like vi mode status bar Ian Lynagh
2002-02-16 17:48 ` Thomas Köhler
2002-02-16 20:05 ` Ian Lynagh
2002-02-17 18:57 ` Thomas Köhler
2002-02-20 22:12 ` Steve Talley
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).