[comp.sys.hp] 'evi' --- a script that makes vi

irf@kuling.UUCP (Bo Thide) (01/01/88)

The standard UNIX visual display editors vi(1), vedit(1), view(1)
are *much* more powerful than you would think in the first place.
In fact, just like Emacs can be put in a vi mode, vi can be put
in a kind of Emacs mode as shown by the following first attempt to do so.

If only vi was improved in four ways:
 
 1. Make 'h' and 'l' wrap around to other lines

 2. Remove the silly left movement of the cursor when changing from
    input to command mode (which makes a command behave differently
    when issued at the leftmost column than in any other column!)

 3. Increase the size of the macro stack by at least a factor of 2

 4. Make 'j' and 'k' ALWAYS move vertically down or up (also if the
    line moved to is empty!)

I would say vi would be the best editor of all.  The full emulation
of Emacs, WordPerfect and other editors/word processors would then
be a piece of cake... (if you really need that).

Comments on my 'evi' script are most welcome.

--Bo

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

#         EVI -- The Emacs mode VI or the Expert's VI
# 
#                              by
# 
#                          Bo Thide'
#              Swedish Institute of Space Physics
#                   S-755 90 Uppsala, Sweden
#        UUCP: ..enea!kuling!irfu!bt  or  bt@irfu.UUCP
#
# evi 0.1, Jan 1, 1988
# 
# 
# This  is  a  test  version  of  an  advanced  macro  package
# providing an  Emacs-like,  modeless  user  interface  to the
# vi(1) display  editor  family.  Run as a Bourne shell script
# 'evi' replaces the existing  EXINIT string by another EXINIT
# string  consisting  mainly of macros in input mode (":map!")
# that emulate a subsest of Emacs (or Word  Perfect)  commands
# as  exactly  as  possible.  Then  vi(1) is run, with the new
# EXINIT string,  through an exec(1)  command.  Since ESC is a
# reserved  (unmappable)  character  in vi(1)  the meta key is
# used to map  8-bit  characters.  This  works  for the  HP-UX
# vi(1) but will not work for other versions of UNIX that only
# support 7-bit ASCII editors and shells.
# 
# A limiting factor for the number of commands emulated is the
# size of the vi(1)  macro  buffer.  The  current  size of the
# macro package is nearly  maximum for HP-UX.  Other  versions
# of vi(1) are known to have smaller buffers.
# 
# Unfortunately the vi(1) commands 'h' and 'l' cannot move the
# cursor to another line (I consider this a serious drawback!)
# so special tricks have been used to emulate line wrap-around
# for the Emacs C-f and C-b commands.  So, for instance,  will
# the C-b command (in vi(1) input mode) at the  beginning of a
# line  cause an error  (beep or  flash!)  that will  take you
# into vi(1)  command mode.  However,  since the vi(1) command
# 'b' can back to the previous  line I have included a command
# mode macro (:map ^B bA) which backs to the last  position of
# the  previous  line and places  vi(1) in input mode again so
# that  subsequent  C-b commands work as expected.  A nuisance
# with vi(1) is that  changing from input to command mode will
# reposition  the cursor one step left.  This is really stupid
# and causes  strange  cursor  movements at the beginning of a
# line.  I have found no way to fool vi(1) here!
# 
# Hitting ",," toggles  between vi and Emacs modes letting you
# change mode instantaneously.  Many commands are missing from
# the Emacs mode and hence vi mode is the only way to get what
# you want.
#
# The following script has been run through 'cat -tv' in order
# that it can be e-mailed safely.   Insert the proper CTRL and
# META sequences where needed!
#
EXINIT="map! ^V^V ,,^F,,\
|map! M-v ,,^B,,\
|map! ,, ^[:so /users/res/bt/vi/e-mode.unmap^[:\"Vi mode^[\
|map! ^A ^[I\
|map! ^D ^[lxi\
|map! ^E ^[A\
|map! ^V^H ^[xi\
|map! ^K ^[lDa\
|map! ^L ^[lmzz.\`zi\
|map! ^N ^[ja\
|map! ^O ^[o\
|map! ^P ^[ka\
|map! ^^ ~\
|map! M-a ^[l(i\
|map! M-b ^[bi\
|map! M-e ^[l)i\
|map! M-f ^[lwi\
|map! M-d ^[ldwi\
|map! M-k ^[ld)i\
|map! M-h ^[dbxi\
|map! M-> ^[GA\
|map! M-< ^[1GI\
|map! ^X:  ^[:so /users/res/bt/vi/e-command.map^[mzLo^[:\
|map! ^X^C ^[ZZ\
|map! ^_ ^X:\"Type /regexp<CR>^[I/\
|map! ^R ^X:\"Type /regexp<CR>^[I?\
|map! M-5 ^X:\"Type /old/new/[g]<CR>^[I:%substitute///g^[2hi\
|map ,, :so /users/res/bt/vi/e-mode.map^[:\"Emacs mode^[i\
|map ^D xJi\
"
export EXINIT 
echo "$CLEAR$TSL$REV Vi mode --- Hit ,, to toggle between Emacs and Vi modes --- $SGR0$FSL"
sleep 1
exec /usr/bin/vi $*

-------------------------------cut here-------------------------------------

In the above $CLEAR, $TSL and $REV are strings containing necessary escape
sequences, evaluated at login time, for clearing the screen, moving to the
status line and entering reverse video mode, respectively.  Similarly, $SGR0
and $FSL unsets graphics rendition and moves the cursor back from the status
line.  All these strings are to be provided at your discretion through suitable
tput(1) calls.  If not provided, the help text will appear in the next line
on the screen.  Their absence will not affect the functionality of 'evi'.

For some obscure reason (at least for me) certain mappings/unmappings
cannot be done in the script itself but have to be introduced by a :source
command (see lines containing ":so" above).  Here follows all source files
needed (each filtered through 'cat -tv' to make them e-mailable):

-(e-mode.map)---------------------cut here-------------------------------------
map! ^B ^[hli
map! ^F ^[la
map ^A I
map ^B bA
map ^E A
map ^F +I
map ^K ddi
map ^V^H k$Ja
map ^N ji
map ^P ki
map M-a (i
map M-d dwi
map M-f +I
map M-k d)i
-(e-mode.unmap)-------------------cut here-------------------------------------
unmap! ^B
unmap! ^F
unmap ^B
unmap ^E
unmap ^F
unmap ^V^H
unmap ^N
unmap ^P
unmap M-d
-(e-command.unmap)----------------cut here-------------------------------------
:map! ^M ^["zdd`z@z:so /users/res/bt/vi/e-ctrlm.unmap^[:"Emacs mode^[i
-(e-ctrlm.unmap)------------------cut here-------------------------------------
:unmap! ^M