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