xref: /netbsd-src/external/bsd/nvi/docs/internals/input (revision 4391d5e9d4f291db41e3b3ba26a01b5e51364aae)
1*4391d5e9Schristos#	@(#)input	5.5 (Berkeley) 7/2/94
2*4391d5e9Schristos
3*4391d5e9SchristosMAPS, EXECUTABLE BUFFERS AND INPUT IN EX/VI:
4*4391d5e9Schristos
5*4391d5e9SchristosThe basic rule is that input in ex/vi is a stack.  Every time a key which
6*4391d5e9Schristosgets expanded is encountered, it is expanded and the expansion is treated
7*4391d5e9Schristosas if it were input from the user.  So, maps and executable buffers are
8*4391d5e9Schristossimply pushed onto the stack from which keys are returned.  The exception
9*4391d5e9Schristosis that if the "remap" option is turned off, only a single map expansion
10*4391d5e9Schristosis done.  I intend to be fully backward compatible with this.
11*4391d5e9Schristos
12*4391d5e9SchristosHistorically, if the mode of the editor changed (ex to vi or vice versa),
13*4391d5e9Schristosany queued input was silently discarded.  I don't see any reason to either
14*4391d5e9Schristossupport or not support this semantic.  I intend to retain the queued input,
15*4391d5e9Schristosmostly because it's simpler than throwing it away.
16*4391d5e9Schristos
17*4391d5e9SchristosHistorically, neither the initial command on the command line (the + flag)
18*4391d5e9Schristosor the +cmd associated with the ex and edit commands was subject to mapping.
19*4391d5e9SchristosAlso, while the +cmd appears to be subject to "@buffer" expansion, once
20*4391d5e9Schristosexpanded it doesn't appear to work correctly.  I don't see any reason to
21*4391d5e9Schristoseither support or not support these semantics, so, for consistency, I intend
22*4391d5e9Schristosto pass both the initial command and the command associated with ex and edit
23*4391d5e9Schristoscommands through the standard mapping and @ buffer expansion.
24*4391d5e9Schristos
25*4391d5e9SchristosOne other difference between the historic ex/vi and nex/nvi is that nex
26*4391d5e9Schristosdisplays the executed buffers as it executes them.  This means that if
27*4391d5e9Schristosthe file is:
28*4391d5e9Schristos
29*4391d5e9Schristos	set term=xterm
30*4391d5e9Schristos	set term=yterm
31*4391d5e9Schristos	set term=yterm
32*4391d5e9Schristos
33*4391d5e9Schristosthe user will see the following during a typical edit session:
34*4391d5e9Schristos
35*4391d5e9Schristos	nex testfile
36*4391d5e9Schristos	testfile: unmodified: line 3
37*4391d5e9Schristos	:1,$yank a
38*4391d5e9Schristos	:@a
39*4391d5e9Schristos	:set term=zterm
40*4391d5e9Schristos	:set term=yterm
41*4391d5e9Schristos	:set term=xterm
42*4391d5e9Schristos	:q!
43*4391d5e9Schristos
44*4391d5e9SchristosThis seems like a feature and unlikely to break anything, so I don't
45*4391d5e9Schristosintend to match historic practice in this area.
46*4391d5e9Schristos
47*4391d5e9SchristosThe rest of this document is a set of conclusions as to how I believe
48*4391d5e9Schristosthe historic maps and @ buffers work.  The summary is as follows:
49*4391d5e9Schristos
50*4391d5e9Schristos1: For buffers that are cut in "line mode", or buffers that are not cut
51*4391d5e9Schristos   in line mode but which contain portions of more than a single line, a
52*4391d5e9Schristos   trailing <newline> character appears in the input for each line in the
53*4391d5e9Schristos   buffer when it is executed.  For buffers not cut in line mode and which
54*4391d5e9Schristos   contain portions of only a single line, no additional characters
55*4391d5e9Schristos   appear in the input.
56*4391d5e9Schristos2: Executable buffers that execute other buffers don't load their
57*4391d5e9Schristos   contents until they execute them.
58*4391d5e9Schristos3: Maps and executable buffers are copied when they are executed --
59*4391d5e9Schristos   they can be modified by the command but that does not change their
60*4391d5e9Schristos   actions.
61*4391d5e9Schristos4: Historically, executable buffers are discarded if the editor
62*4391d5e9Schristos   switches between ex and vi modes.
63*4391d5e9Schristos5: Executable buffers inside of map commands are expanded normally.
64*4391d5e9Schristos   Maps inside of executable buffers are expanded normally.
65*4391d5e9Schristos6: If an error is encountered while executing a mapped command or buffer,
66*4391d5e9Schristos   the rest of the mapped command/buffer is discarded.  No user input
67*4391d5e9Schristos   characters are discarded.
68*4391d5e9Schristos7: Characters in executable buffers are remapped.
69*4391d5e9Schristos8: Characters in executable buffers are not quoted.
70*4391d5e9Schristos
71*4391d5e9SchristosIndividual test cases follow.  Note, in the test cases, control characters
72*4391d5e9Schristosare not literal and will have to be replaced to make the test cases work.
73*4391d5e9Schristos
74*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
75*4391d5e9Schristos1: For buffers that are cut in "line mode", or buffers that are not cut
76*4391d5e9Schristos   in line mode but which contain portions of more than a single line, a
77*4391d5e9Schristos   trailing <newline> character appears in the input for each line in the
78*4391d5e9Schristos   buffer when it is executed.  For buffers not cut in line mode and which
79*4391d5e9Schristos   contain portions of only a single line, no additional characters
80*4391d5e9Schristos   appear in the input.
81*4391d5e9Schristos
82*4391d5e9Schristos===   test file   ===
83*4391d5e9Schristos3Gw
84*4391d5e9Schristosw
85*4391d5e9Schristosline 1 foo bar baz
86*4391d5e9Schristosline 2 foo bar baz
87*4391d5e9Schristosline 3 foo bar baz
88*4391d5e9Schristos=== end test file ===
89*4391d5e9Schristos
90*4391d5e9Schristos   If the first line is loaded into 'a' and executed:
91*4391d5e9Schristos
92*4391d5e9Schristos1G"ayy@a
93*4391d5e9Schristos
94*4391d5e9Schristos   The cursor ends up on the '2', a result of pushing "3Gw^J" onto
95*4391d5e9Schristos   the stack.
96*4391d5e9Schristos
97*4391d5e9Schristos   If the first two lines are loaded into 'a' and executed:
98*4391d5e9Schristos
99*4391d5e9Schristos1G2"ayy@a
100*4391d5e9Schristos
101*4391d5e9Schristos   The cursor ends up on the 'f' in "foo" in the fifth line of the
102*4391d5e9Schristos   file, a result of pushing "3Gw^Jw^J" onto the stack.
103*4391d5e9Schristos
104*4391d5e9Schristos   If the first line is loaded into 'a', but not using line mode,
105*4391d5e9Schristos   and executed:
106*4391d5e9Schristos
107*4391d5e9Schristos1G"ay$@a
108*4391d5e9Schristos
109*4391d5e9Schristos   The cursor ends up on the '1', a result of pushing "3Gw" onto
110*4391d5e9Schristos   the stack
111*4391d5e9Schristos
112*4391d5e9Schristos   If the first two lines are loaded into 'a', but not using line mode,
113*4391d5e9Schristos   and executed:
114*4391d5e9Schristos
115*4391d5e9Schristos1G2"ay$@a
116*4391d5e9Schristos
117*4391d5e9Schristos   The cursor ends up on the 'f' in "foo" in the fifth line of the
118*4391d5e9Schristos   file, a result of pushing "3Gw^Jw^J" onto the stack.
119*4391d5e9Schristos
120*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
121*4391d5e9Schristos2: Executable buffers that execute other buffers don't load their
122*4391d5e9Schristos   contents until they execute them.
123*4391d5e9Schristos
124*4391d5e9Schristos===   test file   ===
125*4391d5e9SchristoscwLOAD B^[
126*4391d5e9Schristosline 1 foo bar baz
127*4391d5e9Schristosline 2 foo bar baz
128*4391d5e9Schristosline 3 foo bar baz
129*4391d5e9Schristos@a@b
130*4391d5e9Schristos"byy
131*4391d5e9Schristos=== end test file ===
132*4391d5e9Schristos
133*4391d5e9Schristos   The command is loaded into 'e', and then executed.  'e' executes
134*4391d5e9Schristos   'a', which loads 'b', then 'e' executes 'b'.
135*4391d5e9Schristos
136*4391d5e9Schristos5G"eyy6G"ayy1G@e
137*4391d5e9Schristos
138*4391d5e9Schristos   The output should be:
139*4391d5e9Schristos
140*4391d5e9Schristos===   output file   ===
141*4391d5e9SchristoscwLOAD B^[
142*4391d5e9SchristosLOAD B 1 foo bar baz
143*4391d5e9Schristosline 2 foo bar baz
144*4391d5e9Schristosline 3 foo bar baz
145*4391d5e9Schristos@a@b
146*4391d5e9Schristos"byy
147*4391d5e9Schristos=== end output file ===
148*4391d5e9Schristos
149*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
150*4391d5e9Schristos3: Maps and executable buffers are copied when they are executed --
151*4391d5e9Schristos   they can be modified by the command but that does not change their
152*4391d5e9Schristos   actions.
153*4391d5e9Schristos
154*4391d5e9Schristos   Executable buffers:
155*4391d5e9Schristos
156*4391d5e9Schristos===   test file   ===
157*4391d5e9Schristosline 1 foo bar baz
158*4391d5e9Schristosline 2 foo bar baz
159*4391d5e9Schristosline 3 foo bar baz
160*4391d5e9Schristos@a@b
161*4391d5e9Schristos"eyy
162*4391d5e9SchristoscwEXECUTE B^[
163*4391d5e9Schristos=== end test file ===
164*4391d5e9Schristos
165*4391d5e9Schristos4G"eyy5G"ayy6G"byy1G@eG"ep
166*4391d5e9Schristos
167*4391d5e9Schristos   The command is loaded into 'e', and then executed.  'e' executes
168*4391d5e9Schristos   'a', which loads 'e', then 'e' executes 'b' anyway.
169*4391d5e9Schristos
170*4391d5e9Schristos   The output should be:
171*4391d5e9Schristos
172*4391d5e9Schristos===   output file   ===
173*4391d5e9Schristosline 1 foo bar baz
174*4391d5e9SchristosEXECUTE B 2 foo bar baz
175*4391d5e9Schristosline 3 foo bar baz
176*4391d5e9Schristos@a@b
177*4391d5e9Schristos"eyy
178*4391d5e9SchristoscwEXECUTE B^[
179*4391d5e9Schristosline 1 foo bar baz
180*4391d5e9Schristos=== end output file ===
181*4391d5e9Schristos
182*4391d5e9Schristos   Maps:
183*4391d5e9Schristos
184*4391d5e9Schristos===   test file   ===
185*4391d5e9SchristosCine 1 foo bar baz
186*4391d5e9Schristosline 2 foo bar baz
187*4391d5e9Schristosline 3 foo bar baz
188*4391d5e9Schristos=== end test file ===
189*4391d5e9Schristos
190*4391d5e9Schristos   Entering the command ':map = :map = rB^V^MrA^M1G==' shows that
191*4391d5e9Schristos   the first time the '=' is entered the '=' map is set and the
192*4391d5e9Schristos   character is changed to 'A', the second time the character is
193*4391d5e9Schristos   changed to 'B'.
194*4391d5e9Schristos
195*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
196*4391d5e9Schristos4: Historically, executable buffers are discarded if the editor
197*4391d5e9Schristos   switches between ex and vi modes.
198*4391d5e9Schristos
199*4391d5e9Schristos===   test file   ===
200*4391d5e9Schristosline 1 foo bar baz
201*4391d5e9Schristosline 2 foo bar baz
202*4391d5e9Schristosline 3 foo bar baz
203*4391d5e9SchristoscwCHANGE^[Q:set
204*4391d5e9Schristosset|visual|1Gwww
205*4391d5e9Schristos=== end test file ===
206*4391d5e9Schristos
207*4391d5e9Schristosvi testfile
208*4391d5e9Schristos4G"ayy@a
209*4391d5e9Schristos
210*4391d5e9Schristosex testfile
211*4391d5e9Schristos$p
212*4391d5e9Schristosyank a
213*4391d5e9Schristos@a
214*4391d5e9Schristos
215*4391d5e9Schristos   In vi, the command is loaded into 'a' and then executed.  The command
216*4391d5e9Schristos   subsequent to the 'Q' is (historically, silently) discarded.
217*4391d5e9Schristos
218*4391d5e9Schristos   In ex, the command is loaded into 'a' and then executed.  The command
219*4391d5e9Schristos   subsequent to the 'visual' is (historically, silently) discarded.  The
220*4391d5e9Schristos   first set command is output by ex, although refreshing the screen usually
221*4391d5e9Schristos   causes it not to be seen.
222*4391d5e9Schristos
223*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
224*4391d5e9Schristos5: Executable buffers inside of map commands are expanded normally.
225*4391d5e9Schristos   Maps inside of executable buffers are expanded normally.
226*4391d5e9Schristos
227*4391d5e9Schristos   Buffers inside of map commands:
228*4391d5e9Schristos
229*4391d5e9Schristos===   test file   ===
230*4391d5e9Schristosline 1 foo bar baz
231*4391d5e9Schristosline 2 foo bar baz
232*4391d5e9Schristosline 3 foo bar baz
233*4391d5e9SchristoscwREPLACE BY A^[
234*4391d5e9Schristos=== end test file ===
235*4391d5e9Schristos
236*4391d5e9Schristos4G"ay$:map x @a
237*4391d5e9Schristos1Gx
238*4391d5e9Schristos
239*4391d5e9Schristos   The output should be:
240*4391d5e9Schristos
241*4391d5e9Schristos===   output file   ===
242*4391d5e9SchristosREPLACE BY A 1 foo bar baz
243*4391d5e9Schristosline 2 foo bar baz
244*4391d5e9Schristosline 3 foo bar baz
245*4391d5e9SchristoscwREPLACE BY A^[
246*4391d5e9Schristos=== end output file ===
247*4391d5e9Schristos
248*4391d5e9Schristos   Maps commands inside of executable buffers:
249*4391d5e9Schristos
250*4391d5e9Schristos===   test file   ===
251*4391d5e9Schristosline 1 foo bar baz
252*4391d5e9Schristosline 2 foo bar baz
253*4391d5e9Schristosline 3 foo bar baz
254*4391d5e9SchristosX
255*4391d5e9Schristos=== end test file ===
256*4391d5e9Schristos
257*4391d5e9Schristos:map X cwREPLACE BY XMAP^[
258*4391d5e9Schristos4G"ay$1G@a
259*4391d5e9Schristos
260*4391d5e9Schristos   The output should be:
261*4391d5e9Schristos
262*4391d5e9Schristos===   output file   ===
263*4391d5e9SchristosREPLACE BY XMAP 1 foo bar baz
264*4391d5e9Schristosline 2 foo bar baz
265*4391d5e9Schristosline 3 foo bar baz
266*4391d5e9SchristosX
267*4391d5e9Schristos=== end output file ===
268*4391d5e9Schristos
269*4391d5e9Schristos   Here's a test that does both, repeatedly.
270*4391d5e9Schristos
271*4391d5e9Schristos===   test file   ===
272*4391d5e9Schristosline 1 foo bar baz
273*4391d5e9Schristosline 2 foo bar baz
274*4391d5e9Schristosline 3 foo bar baz
275*4391d5e9SchristosX
276*4391d5e9SchristosY
277*4391d5e9SchristoscwREPLACED BY C^[
278*4391d5e9Schristosblank line
279*4391d5e9Schristos=== end test file ===
280*4391d5e9Schristos
281*4391d5e9Schristos:map x @a
282*4391d5e9Schristos4G"ay$
283*4391d5e9Schristos:map X @b
284*4391d5e9Schristos5G"by$
285*4391d5e9Schristos:map Y @c
286*4391d5e9Schristos6G"cy$
287*4391d5e9Schristos1Gx
288*4391d5e9Schristos
289*4391d5e9Schristos   The output should be:
290*4391d5e9Schristos
291*4391d5e9Schristos===   output file   ===
292*4391d5e9SchristosREPLACED BY C 1 foo bar baz
293*4391d5e9Schristosline 2 foo bar baz
294*4391d5e9Schristosline 3 foo bar baz
295*4391d5e9SchristosX
296*4391d5e9SchristosY
297*4391d5e9SchristoscwREPLACED BY C^[
298*4391d5e9Schristosblank line
299*4391d5e9Schristos=== end output file ===
300*4391d5e9Schristos
301*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
302*4391d5e9Schristos6: If an error is encountered while executing a mapped command or
303*4391d5e9Schristos   a buffer, the rest of the mapped command/buffer is discarded.  No
304*4391d5e9Schristos   user input characters are discarded.
305*4391d5e9Schristos
306*4391d5e9Schristos===   test file   ===
307*4391d5e9Schristosline 1 foo bar baz
308*4391d5e9Schristosline 2 foo bar baz
309*4391d5e9Schristosline 3 foo bar baz
310*4391d5e9Schristos:map = 10GcwREPLACMENT^V^[^[
311*4391d5e9Schristos=== end test file ===
312*4391d5e9Schristos
313*4391d5e9Schristos   The above mapping fails, however, if the 10G is changed to 1, 2,
314*4391d5e9Schristos   or 3G, it will succeed.
315*4391d5e9Schristos
316*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
317*4391d5e9Schristos7: Characters in executable buffers are remapped.
318*4391d5e9Schristos
319*4391d5e9Schristos===   test file   ===
320*4391d5e9Schristosabcdefghijklmnnop
321*4391d5e9Schristosggg
322*4391d5e9Schristos=== end test file ===
323*4391d5e9Schristos
324*4391d5e9Schristos:map g x
325*4391d5e9Schristos2G"ay$1G@a
326*4391d5e9Schristos
327*4391d5e9Schristos   The output should be:
328*4391d5e9Schristos
329*4391d5e9Schristos===   output file   ===
330*4391d5e9Schristosdefghijklmnnop
331*4391d5e9Schristosggg
332*4391d5e9Schristos=== end output file ===
333*4391d5e9Schristos
334*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
335*4391d5e9Schristos8: Characters in executable buffers are not quoted.
336*4391d5e9Schristos
337*4391d5e9Schristos===   test file   ===
338*4391d5e9SchristosiFOO^[
339*4391d5e9Schristos
340*4391d5e9Schristos=== end test file ===
341*4391d5e9Schristos
342*4391d5e9Schristos1G"ay$2G@a
343*4391d5e9Schristos
344*4391d5e9Schristos   The output should be:
345*4391d5e9Schristos
346*4391d5e9Schristos===   output file   ===
347*4391d5e9SchristosiFOO^[
348*4391d5e9SchristosFOO
349*4391d5e9Schristos=== end output file ===
350*4391d5e9Schristos=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
351