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