summaryrefslogtreecommitdiffstats
path: root/contrib/nvi/docs/internals/input
blob: 9a7506ee2337b3ef346454eb7eb4542ed8fbcac4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
#	@(#)input	5.5 (Berkeley) 7/2/94

MAPS, EXECUTABLE BUFFERS AND INPUT IN EX/VI:

The basic rule is that input in ex/vi is a stack.  Every time a key which
gets expanded is encountered, it is expanded and the expansion is treated
as if it were input from the user.  So, maps and executable buffers are
simply pushed onto the stack from which keys are returned.  The exception
is that if the "remap" option is turned off, only a single map expansion
is done.  I intend to be fully backward compatible with this.

Historically, if the mode of the editor changed (ex to vi or vice versa),
any queued input was silently discarded.  I don't see any reason to either
support or not support this semantic.  I intend to retain the queued input,
mostly because it's simpler than throwing it away.

Historically, neither the initial command on the command line (the + flag)
or the +cmd associated with the ex and edit commands was subject to mapping.
Also, while the +cmd appears to be subject to "@buffer" expansion, once
expanded it doesn't appear to work correctly.  I don't see any reason to
either support or not support these semantics, so, for consistency, I intend
to pass both the initial command and the command associated with ex and edit
commands through the standard mapping and @ buffer expansion.

One other difference between the historic ex/vi and nex/nvi is that nex
displays the executed buffers as it executes them.  This means that if
the file is:

	set term=xterm
	set term=yterm
	set term=yterm

the user will see the following during a typical edit session:

	nex testfile
	testfile: unmodified: line 3
	:1,$yank a
	:@a
	:set term=zterm
	:set term=yterm
	:set term=xterm
	:q!

This seems like a feature and unlikely to break anything, so I don't
intend to match historic practice in this area.

The rest of this document is a set of conclusions as to how I believe
the historic maps and @ buffers work.  The summary is as follows:

1: For buffers that are cut in "line mode", or buffers that are not cut
   in line mode but which contain portions of more than a single line, a
   trailing <newline> character appears in the input for each line in the
   buffer when it is executed.  For buffers not cut in line mode and which
   contain portions of only a single line, no additional characters
   appear in the input.
2: Executable buffers that execute other buffers don't load their
   contents until they execute them.
3: Maps and executable buffers are copied when they are executed --
   they can be modified by the command but that does not change their
   actions.
4: Historically, executable buffers are discarded if the editor
   switches between ex and vi modes.
5: Executable buffers inside of map commands are expanded normally.
   Maps inside of executable buffers are expanded normally.
6: If an error is encountered while executing a mapped command or buffer,
   the rest of the mapped command/buffer is discarded.  No user input
   characters are discarded.
7: Characters in executable buffers are remapped.
8: Characters in executable buffers are not quoted.

Individual test cases follow.  Note, in the test cases, control characters
are not literal and will have to be replaced to make the test cases work.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1: For buffers that are cut in "line mode", or buffers that are not cut
   in line mode but which contain portions of more than a single line, a
   trailing <newline> character appears in the input for each line in the
   buffer when it is executed.  For buffers not cut in line mode and which
   contain portions of only a single line, no additional characters
   appear in the input.

===   test file   ===
3Gw
w
line 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
=== end test file ===

   If the first line is loaded into 'a' and executed:

1G"ayy@a

   The cursor ends up on the '2', a result of pushing "3Gw^J" onto
   the stack.

   If the first two lines are loaded into 'a' and executed:

1G2"ayy@a

   The cursor ends up on the 'f' in "foo" in the fifth line of the
   file, a result of pushing "3Gw^Jw^J" onto the stack.

   If the first line is loaded into 'a', but not using line mode,
   and executed:

1G"ay$@a

   The cursor ends up on the '1', a result of pushing "3Gw" onto
   the stack

   If the first two lines are loaded into 'a', but not using line mode,
   and executed:

1G2"ay$@a

   The cursor ends up on the 'f' in "foo" in the fifth line of the
   file, a result of pushing "3Gw^Jw^J" onto the stack.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
2: Executable buffers that execute other buffers don't load their
   contents until they execute them.

===   test file   ===
cwLOAD B^[
line 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
@a@b
"byy
=== end test file ===

   The command is loaded into 'e', and then executed.  'e' executes
   'a', which loads 'b', then 'e' executes 'b'.

5G"eyy6G"ayy1G@e

   The output should be:

===   output file   ===
cwLOAD B^[
LOAD B 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
@a@b
"byy
=== end output file ===

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
3: Maps and executable buffers are copied when they are executed --
   they can be modified by the command but that does not change their
   actions.

   Executable buffers:

===   test file   ===
line 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
@a@b
"eyy
cwEXECUTE B^[
=== end test file ===

4G"eyy5G"ayy6G"byy1G@eG"ep

   The command is loaded into 'e', and then executed.  'e' executes
   'a', which loads 'e', then 'e' executes 'b' anyway.

   The output should be:

===   output file   ===
line 1 foo bar baz
EXECUTE B 2 foo bar baz
line 3 foo bar baz
@a@b
"eyy
cwEXECUTE B^[
line 1 foo bar baz
=== end output file ===

   Maps:

===   test file   ===
Cine 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
=== end test file ===

   Entering the command ':map = :map = rB^V^MrA^M1G==' shows that
   the first time the '=' is entered the '=' map is set and the
   character is changed to 'A', the second time the character is
   changed to 'B'.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
4: Historically, executable buffers are discarded if the editor
   switches between ex and vi modes.

===   test file   ===
line 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
cwCHANGE^[Q:set
set|visual|1Gwww
=== end test file ===

vi testfile
4G"ayy@a

ex testfile
$p
yank a
@a

   In vi, the command is loaded into 'a' and then executed.  The command
   subsequent to the 'Q' is (historically, silently) discarded.

   In ex, the command is loaded into 'a' and then executed.  The command
   subsequent to the 'visual' is (historically, silently) discarded.  The
   first set command is output by ex, although refreshing the screen usually
   causes it not to be seen.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
5: Executable buffers inside of map commands are expanded normally.
   Maps inside of executable buffers are expanded normally.

   Buffers inside of map commands:

===   test file   ===
line 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
cwREPLACE BY A^[
=== end test file ===

4G"ay$:map x @a
1Gx

   The output should be:

===   output file   ===
REPLACE BY A 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
cwREPLACE BY A^[
=== end output file ===

   Maps commands inside of executable buffers:

===   test file   ===
line 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
X
=== end test file ===

:map X cwREPLACE BY XMAP^[
4G"ay$1G@a

   The output should be:

===   output file   ===
REPLACE BY XMAP 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
X
=== end output file ===

   Here's a test that does both, repeatedly.

===   test file   ===
line 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
X
Y
cwREPLACED BY C^[
blank line
=== end test file ===

:map x @a
4G"ay$
:map X @b
5G"by$
:map Y @c
6G"cy$
1Gx

   The output should be:

===   output file   ===
REPLACED BY C 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
X
Y
cwREPLACED BY C^[
blank line
=== end output file ===

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6: If an error is encountered while executing a mapped command or
   a buffer, the rest of the mapped command/buffer is discarded.  No
   user input characters are discarded.

===   test file   ===
line 1 foo bar baz
line 2 foo bar baz
line 3 foo bar baz
:map = 10GcwREPLACMENT^V^[^[
=== end test file ===

   The above mapping fails, however, if the 10G is changed to 1, 2,
   or 3G, it will succeed.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7: Characters in executable buffers are remapped.

===   test file   ===
abcdefghijklmnnop
ggg
=== end test file ===

:map g x
2G"ay$1G@a

   The output should be:

===   output file   ===
defghijklmnnop
ggg
=== end output file ===

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8: Characters in executable buffers are not quoted.

===   test file   ===
iFOO^[

=== end test file ===

1G"ay$2G@a

   The output should be:

===   output file   ===
iFOO^[
FOO
=== end output file ===
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
OpenPOWER on IntegriCloud