[comp.editors] Typing long commands in vi

steveha@microsoft.UUCP (Steve Hastings) (08/10/90)

For "power-users" of vi or ex, here is a useful tip for typing long
commands.

Some long, powerful vi commands can be hard to get right in one try.  For
example, yesterday I wanted to convert lines of the form

#define foo 99

to

[[foo]]=99

and the command I used was

:.,$s/^#define[ \t]\([^ \t]*\)[ \t]*\(.*\)/[[\1]]=\2/

(Where the "\t" appear above, I really hit the Tab key; vi doesn't support
\t escapes in character sets.)


Now, I used to get really frustrated trying to get such commands right.
(These days, I get it right in two tries or less, most of the time, but it
took a lot of practice!)  vi has two features you can use to make this
easier.

The first is the :source filename command (:so filename is the abbreviation)
that reads in a file.  Edit a scratch file, enter the command you wish to
execute, and source the file.  If you didn't get it right, undo the
command, switch back to the other file, and edit the command and try again.
(Note that you can use :so # to source the file if you just switched back
from it.)  This technique is good for ex commands like g// or s///.

The other way uses named buffers and the @ command.  The @ command executes
a command stored inside a named buffer.  So open a new line right in your
source text, type the command then and there, and use the yank command to
put it in a named buffer.  Once it is in there, execute the command as many
times as you want with @.  If you made a typing error or want to change the
command, edit the line and yank it again.  If you deleted the original
line, paste that buffer back in, edit it, and yank it again.  This works
well with vi commands, or ex commands preceded by a colon.  (Note that if
you use the command :@ you are using the ex @ command instead of the vi @
command, and it will expect ex commands inside the buffer instead of vi
commands.)

By the way, I know that the long command I showed above for munging #define
lines works.  I used the @ command and named buffers to test it right from
the text of this message!
-- 
Steve "I don't speak for Microsoft" Hastings    ===^=== :::::
uunet!microsoft!steveha  steveha@microsoft.uucp    ` \\==|

lee@sq.sq.com (Liam R. E. Quin) (08/13/90)

steveha@microsoft.UUCP (Steve Hastings) writes:
>Some long, powerful vi commands can be hard to get right in one try.
and suggests two ways to make it easier.

I think it worth clarifying this a little.

One way is to type
:.,$s/hello/goodbye
or whatever, *into the text*, move onto the line if necessary, and say
	"ayy
to put a copy of the line into register a, or
	"add
to delete the line altogether, and then
	@a
to execute the contents of register a -- i.e., to do the substitution.

You could put
map g "add@a
into your .exrc, and then you simply type a g on the command.

If you have deleted the command into the register, and then you found you
got it wrong, you can bring it back again with
	"ap
or
	"aP
if you want.  Of course, you can undo the delete as well.

If instead of doing "add you move to the start of the line and do "ad$
there will be no newline at the end of the register, of course, so you
will be left (when you do @a) on the bottom line with
the cursor here ---+
:.,$s/hello/goodbyeX
so you can backspace over the command or add to it.  I sometimes use this
with
:!ls file | awk '{something ghastly here}' | sed .....
so I can build the command up easily.

This technique was used in the word-completion macros posted here recently.

Lee
-- 
Liam R. E. Quin,  lee@sq.com, {utai,utzoo}!sq!lee,  SoftQuad Inc., Toronto
``He left her a copy of his calculations [...]  Since she was a cystologist,
  she might have analysed the equations, but at the moment she was occupied
  with knitting a bootee.''  [John Boyd, Pollinators of Eden, 217]

dave@aspect.UUCP (Dave Corcoran) (08/13/90)

In article <56433@microsoft.UUCP>, steveha@microsoft.UUCP (Steve Hastings) writes:
> The other way uses named buffers and the @ command.  The @ command executes
> a command stored inside a named buffer.  So open a new line right in your
> source text, type the command then and there, and use the yank command to
> put it in a named buffer.  Once it is in there, execute the command as many
> times as you want with @.  If you made a typing error or want to change the
> command, edit the line and yank it again.  If you deleted the original
> line, paste that buffer back in, edit it, and yank it again.

All is fine unless the macro chokes: 

I have one objection to using the technique of putting editing macro
in a register (say z) and using @z to invoke it. The vi (visual interface) I
use gobbles the macro if an error was encountered during execution and I
cannot retrieve it with

	"zp

I offer the following to those who are interested.
It is straightforward although it has the distinct disadvantage of only allowing
ex commands (as opposed to vi). You could cause the ex macro to store a vi
string in a register and then invoke it via @z.

In order to get this to work create a 3 line file in your current directory
named mac.ex which looks like this. 

---------------------cut here-----------------------
"+

"-
----------------------cut here----------------------

then type

	]m

edit any number of lines between the "+ and "-.

Then type

	[m

to store the macro and

	]e

to execute it.

Put this in your .exrc. (This is the cat -v version)

---------------------- cut here----------------------
"general purpose maps
"
"store macro
:map [m ?^"^V^M:.,/^"-/w! mac.ex^V^M:.,/^"-/d^V^M
"
"retrieve macro
:map ]m :r mac.ex^V^M
"
"execute macro
:map ]e :so mac.ex^V^M
---------------------- cut here----------------------


-- 
--
David Corcoran		-@@
uunet!aspect!dave	  ~
Good, fast, cheap; pick any two.

mercer@npdiss1.StPaul.NCR.COMDan Mercer) (08/16/90)

In article <3672@aspect.UUCP> dave@aspect.UUCP (Dave Corcoran) writes:
:In article <56433@microsoft.UUCP>, steveha@microsoft.UUCP (Steve Hastings) writes:
:> The other way uses named buffers and the @ command.  The @ command executes
:> a command stored inside a named buffer.  So open a new line right in your
:> source text, type the command then and there, and use the yank command to
:> put it in a named buffer.  Once it is in there, execute the command as many
:> times as you want with @.  If you made a typing error or want to change the
:> command, edit the line and yank it again.  If you deleted the original
:> line, paste that buffer back in, edit it, and yank it again.
:
:All is fine unless the macro chokes: 
:
:I have one objection to using the technique of putting editing macro
:in a register (say z) and using @z to invoke it. The vi (visual interface) I
:use gobbles the macro if an error was encountered during execution and I
:cannot retrieve it with
:
:	"zp
:

It isn't the macro that is gobbled,  it is the macro process that must
be unblocked.  Just yank something into a different register and you
now will find that you can retrieve your original macro.

For instance,  the macro:

yyppppp

when invoked returns the error message:

Cannot put inside global/macro

A "zp will now not recover the macro.  However a "ayy"zp will recoevr
it.  In fact,  so will a yy"zp.  Interestingly enough,  when I invoked
the macro on the last line in this file,  the first line was copied 
after it and the cursor moved to the new line.  But the line wasn't
really in the file!  A ^L caused it to be redisplayed,  but after
moving the cursor off it,  it couldn't be moved back on the line.
Very strange (I've seen it before).
-- 

Dan Mercer
Reply-To: mercer@npdiss1.StPaul.NCR.COM (Dan Mercer)
"MAN - the only one word oxymoron in the English Language"