From 9e751bb8c0cdf771d34c839cb6591d892b8e62de Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Tue, 7 Mar 2017 01:41:48 -0800 Subject: 3761 --- html/edit/012-editor-undo.mu.html | 1633 +++++++++++++++++++------------------ 1 file changed, 817 insertions(+), 816 deletions(-) (limited to 'html/edit/012-editor-undo.mu.html') diff --git a/html/edit/012-editor-undo.mu.html b/html/edit/012-editor-undo.mu.html index 023ecc94..39255865 100644 --- a/html/edit/012-editor-undo.mu.html +++ b/html/edit/012-editor-undo.mu.html @@ -15,16 +15,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color a { text-decoration: none; } a:hover { text-decoration: underline; } * { font-size: 12pt; font-size: 1em; } -.muData { color: #ffff00; } -.muControl { color: #c0a020; } +.Conceal { color: #4e4e4e; } +.muRecipe { color: #ff8700; } .Special { color: #c00000; } .Delimiter { color: #800080; } .SalientComment { color: #00ffff; } .Constant { color: #00a0a0; } .LineNr { color: #444444; } .Comment { color: #9090ff; } -.muRecipe { color: #ff8700; } +.muControl { color: #c0a020; } .muScenario { color: #00af00; } +.muData { color: #ffff00; } --> @@ -80,8 +81,8 @@ if ('onhashchange' in window) { 19 insert-from:&:duplex-list:char 20 insert-until:&:duplex-list:char 21 tag:num # event causing this operation; might be used to coalesce runs of similar events - 22 # 0: no coalesce (enter+indent) - 23 # 1: regular alphanumeric characters + 22 ¦ # 0: no coalesce (enter+indent) + 23 ¦ # 1: regular alphanumeric characters 24 ] 25 26 container move-operation [ @@ -92,11 +93,11 @@ if ('onhashchange' in window) { 31 after-column:num 32 after-top-of-screen:&:duplex-list:char 33 tag:num # event causing this operation; might be used to coalesce runs of similar events - 34 # 0: no coalesce (touch events, etc) - 35 # 1: left arrow - 36 # 2: right arrow - 37 # 3: up arrow - 38 # 4: down arrow + 34 ¦ # 0: no coalesce (touch events, etc) + 35 ¦ # 1: left arrow + 36 ¦ # 2: right arrow + 37 ¦ # 3: up arrow + 38 ¦ # 4: down arrow 39 ] 40 41 container delete-operation [ @@ -110,9 +111,9 @@ if ('onhashchange' in window) { 49 delete-from:&:duplex-list:char 50 delete-until:&:duplex-list:char 51 tag:num # event causing this operation; might be used to coalesce runs of similar events - 52 # 0: no coalesce (ctrl-k, ctrl-u) - 53 # 1: backspace - 54 # 2: delete + 52 ¦ # 0: no coalesce (ctrl-k, ctrl-u) + 53 ¦ # 1: backspace + 54 ¦ # 2: delete 55 ] 56 57 # every editor accumulates a list of operations to undo/redo @@ -124,36 +125,36 @@ if ('onhashchange' in window) { 63 # ctrl-z - undo operation 64 after <handle-special-character> [ 65 { - 66 undo?:bool <- equal c, 26/ctrl-z - 67 break-unless undo? - 68 undo:&:list:&:operation <- get *editor, undo:offset - 69 break-unless undo - 70 op:&:operation <- first undo - 71 undo <- rest undo - 72 *editor <- put *editor, undo:offset, undo - 73 redo:&:list:&:operation <- get *editor, redo:offset - 74 redo <- push op, redo - 75 *editor <- put *editor, redo:offset, redo - 76 <handle-undo> - 77 return 1/go-render + 66 ¦ undo?:bool <- equal c, 26/ctrl-z + 67 ¦ break-unless undo? + 68 ¦ undo:&:list:&:operation <- get *editor, undo:offset + 69 ¦ break-unless undo + 70 ¦ op:&:operation <- first undo + 71 ¦ undo <- rest undo + 72 ¦ *editor <- put *editor, undo:offset, undo + 73 ¦ redo:&:list:&:operation <- get *editor, redo:offset + 74 ¦ redo <- push op, redo + 75 ¦ *editor <- put *editor, redo:offset, redo + 76 ¦ <handle-undo> + 77 ¦ return 1/go-render 78 } 79 ] 80 81 # ctrl-y - redo operation 82 after <handle-special-character> [ 83 { - 84 redo?:bool <- equal c, 25/ctrl-y - 85 break-unless redo? - 86 redo:&:list:&:operation <- get *editor, redo:offset - 87 break-unless redo - 88 op:&:operation <- first redo - 89 redo <- rest redo - 90 *editor <- put *editor, redo:offset, redo - 91 undo:&:list:&:operation <- get *editor, undo:offset - 92 undo <- push op, undo - 93 *editor <- put *editor, undo:offset, undo - 94 <handle-redo> - 95 return 1/go-render + 84 ¦ redo?:bool <- equal c, 25/ctrl-y + 85 ¦ break-unless redo? + 86 ¦ redo:&:list:&:operation <- get *editor, redo:offset + 87 ¦ break-unless redo + 88 ¦ op:&:operation <- first redo + 89 ¦ redo <- rest redo + 90 ¦ *editor <- put *editor, redo:offset, redo + 91 ¦ undo:&:list:&:operation <- get *editor, undo:offset + 92 ¦ undo <- push op, undo + 93 ¦ *editor <- put *editor, undo:offset, undo + 94 ¦ <handle-redo> + 95 ¦ return 1/go-render 96 } 97 ] 98 @@ -166,35 +167,35 @@ if ('onhashchange' in window) { 105 e:&:editor <- new-editor [], 0/left, 10/right 106 editor-render screen, e 107 assume-console [ - 108 type [0] + 108 ¦ type [0] 109 ] 110 editor-event-loop screen, console, e 111 # undo 112 assume-console [ - 113 press ctrl-z + 113 ¦ press ctrl-z 114 ] 115 run [ - 116 editor-event-loop screen, console, e + 116 ¦ editor-event-loop screen, console, e 117 ] 118 # character should be gone 119 screen-should-contain [ - 120 . . - 121 . . - 122 .╌╌╌╌╌╌╌╌╌╌. - 123 . . + 120 ¦ . . + 121 ¦ . . + 122 ¦ .╌╌╌╌╌╌╌╌╌╌. + 123 ¦ . . 124 ] 125 # cursor should be in the right place 126 assume-console [ - 127 type [1] + 127 ¦ type [1] 128 ] 129 run [ - 130 editor-event-loop screen, console, e + 130 ¦ editor-event-loop screen, console, e 131 ] 132 screen-should-contain [ - 133 . . - 134 .1 . - 135 .╌╌╌╌╌╌╌╌╌╌. - 136 . . + 133 ¦ . . + 134 ¦ .1 . + 135 ¦ .╌╌╌╌╌╌╌╌╌╌. + 136 ¦ . . 137 ] 138 ] 139 @@ -209,21 +210,21 @@ if ('onhashchange' in window) { 148 cursor-column:num <- get *editor, cursor-column:offset 149 undo:&:list:&:operation <- get *editor, undo:offset 150 { - 151 # if previous operation was an insert, coalesce this operation with it - 152 break-unless undo - 153 op:&:operation <- first undo - 154 typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant - 155 break-unless is-insert? - 156 previous-coalesce-tag:num <- get typing, tag:offset - 157 break-unless previous-coalesce-tag - 158 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset - 159 insert-until:&:duplex-list:char <- next before-cursor - 160 typing <- put typing, insert-until:offset, insert-until - 161 typing <- put typing, after-row:offset, cursor-row - 162 typing <- put typing, after-column:offset, cursor-column - 163 typing <- put typing, after-top-of-screen:offset, top-after - 164 *op <- merge 0/insert-operation, typing - 165 break +done-adding-insert-operation + 151 ¦ # if previous operation was an insert, coalesce this operation with it + 152 ¦ break-unless undo + 153 ¦ op:&:operation <- first undo + 154 ¦ typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant + 155 ¦ break-unless is-insert? + 156 ¦ previous-coalesce-tag:num <- get typing, tag:offset + 157 ¦ break-unless previous-coalesce-tag + 158 ¦ before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset + 159 ¦ insert-until:&:duplex-list:char <- next before-cursor + 160 ¦ typing <- put typing, insert-until:offset, insert-until + 161 ¦ typing <- put typing, after-row:offset, cursor-row + 162 ¦ typing <- put typing, after-column:offset, cursor-column + 163 ¦ typing <- put typing, after-top-of-screen:offset, top-after + 164 ¦ *op <- merge 0/insert-operation, typing + 165 ¦ break +done-adding-insert-operation 166 } 167 # if not, create a new operation 168 insert-from:&:duplex-list:char <- next cursor-before @@ -271,20 +272,20 @@ if ('onhashchange' in window) { 210 211 after <handle-undo> [ 212 { - 213 typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant - 214 break-unless is-insert? - 215 start:&:duplex-list:char <- get typing, insert-from:offset - 216 end:&:duplex-list:char <- get typing, insert-until:offset - 217 # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - 218 before-cursor:&:duplex-list:char <- prev start - 219 *editor <- put *editor, before-cursor:offset, before-cursor - 220 remove-between before-cursor, end - 221 cursor-row <- get typing, before-row:offset - 222 *editor <- put *editor, cursor-row:offset, cursor-row - 223 cursor-column <- get typing, before-column:offset - 224 *editor <- put *editor, cursor-column:offset, cursor-column - 225 top:&:duplex-list:char <- get typing, before-top-of-screen:offset - 226 *editor <- put *editor, top-of-screen:offset, top + 213 ¦ typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant + 214 ¦ break-unless is-insert? + 215 ¦ start:&:duplex-list:char <- get typing, insert-from:offset + 216 ¦ end:&:duplex-list:char <- get typing, insert-until:offset + 217 ¦ # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen + 218 ¦ before-cursor:&:duplex-list:char <- prev start + 219 ¦ *editor <- put *editor, before-cursor:offset, before-cursor + 220 ¦ remove-between before-cursor, end + 221 ¦ cursor-row <- get typing, before-row:offset + 222 ¦ *editor <- put *editor, cursor-row:offset, cursor-row + 223 ¦ cursor-column <- get typing, before-column:offset + 224 ¦ *editor <- put *editor, cursor-column:offset, cursor-column + 225 ¦ top:&:duplex-list:char <- get typing, before-top-of-screen:offset + 226 ¦ *editor <- put *editor, top-of-screen:offset, top 227 } 228 ] 229 @@ -295,22 +296,22 @@ if ('onhashchange' in window) { 234 e:&:editor <- new-editor [], 0/left, 10/right 235 editor-render screen, e 236 assume-console [ - 237 type [012] + 237 ¦ type [012] 238 ] 239 editor-event-loop screen, console, e 240 # undo 241 assume-console [ - 242 press ctrl-z + 242 ¦ press ctrl-z 243 ] 244 run [ - 245 editor-event-loop screen, console, e + 245 ¦ editor-event-loop screen, console, e 246 ] 247 # all characters must be gone 248 screen-should-contain [ - 249 . . - 250 . . - 251 .╌╌╌╌╌╌╌╌╌╌. - 252 . . + 249 ¦ . . + 250 ¦ . . + 251 ¦ .╌╌╌╌╌╌╌╌╌╌. + 252 ¦ . . 253 ] 254 ] 255 @@ -322,41 +323,41 @@ if ('onhashchange' in window) { 261 editor-render screen, e 262 # type some characters 263 assume-console [ - 264 type [012] + 264 ¦ type [012] 265 ] 266 editor-event-loop screen, console, e 267 screen-should-contain [ - 268 . . - 269 .012a . - 270 .╌╌╌╌╌╌╌╌╌╌. - 271 . . + 268 ¦ . . + 269 ¦ .012a . + 270 ¦ .╌╌╌╌╌╌╌╌╌╌. + 271 ¦ . . 272 ] 273 # undo 274 assume-console [ - 275 press ctrl-z + 275 ¦ press ctrl-z 276 ] 277 run [ - 278 editor-event-loop screen, console, e + 278 ¦ editor-event-loop screen, console, e 279 ] 280 # back to original text 281 screen-should-contain [ - 282 . . - 283 .a . - 284 .╌╌╌╌╌╌╌╌╌╌. - 285 . . + 282 ¦ . . + 283 ¦ .a . + 284 ¦ .╌╌╌╌╌╌╌╌╌╌. + 285 ¦ . . 286 ] 287 # cursor should be in the right place 288 assume-console [ - 289 type [3] + 289 ¦ type [3] 290 ] 291 run [ - 292 editor-event-loop screen, console, e + 292 ¦ editor-event-loop screen, console, e 293 ] 294 screen-should-contain [ - 295 . . - 296 .3a . - 297 .╌╌╌╌╌╌╌╌╌╌. - 298 . . + 295 ¦ . . + 296 ¦ .3a . + 297 ¦ .╌╌╌╌╌╌╌╌╌╌. + 298 ¦ . . 299 ] 300 ] 301 @@ -368,56 +369,56 @@ if ('onhashchange' in window) { 307 editor-render screen, e 308 # new line 309 assume-console [ - 310 left-click 1, 8 - 311 press enter + 310 ¦ left-click 1, 8 + 311 ¦ press enter 312 ] 313 editor-event-loop screen, console, e 314 screen-should-contain [ - 315 . . - 316 . abc . - 317 . . - 318 .╌╌╌╌╌╌╌╌╌╌. - 319 . . + 315 ¦ . . + 316 ¦ . abc . + 317 ¦ . . + 318 ¦ .╌╌╌╌╌╌╌╌╌╌. + 319 ¦ . . 320 ] 321 # line is indented 322 3:num/raw <- get *e, cursor-row:offset 323 4:num/raw <- get *e, cursor-column:offset 324 memory-should-contain [ - 325 3 <- 2 - 326 4 <- 2 + 325 ¦ 3 <- 2 + 326 ¦ 4 <- 2 327 ] 328 # undo 329 assume-console [ - 330 press ctrl-z + 330 ¦ press ctrl-z 331 ] 332 run [ - 333 editor-event-loop screen, console, e + 333 ¦ editor-event-loop screen, console, e 334 ] 335 3:num/raw <- get *e, cursor-row:offset 336 4:num/raw <- get *e, cursor-column:offset 337 memory-should-contain [ - 338 3 <- 1 - 339 4 <- 5 + 338 ¦ 3 <- 1 + 339 ¦ 4 <- 5 340 ] 341 # back to original text 342 screen-should-contain [ - 343 . . - 344 . abc . - 345 .╌╌╌╌╌╌╌╌╌╌. - 346 . . + 343 ¦ . . + 344 ¦ . abc . + 345 ¦ .╌╌╌╌╌╌╌╌╌╌. + 346 ¦ . . 347 ] 348 # cursor should be at end of line 349 assume-console [ - 350 type [1] + 350 ¦ type [1] 351 ] 352 run [ - 353 editor-event-loop screen, console, e + 353 ¦ editor-event-loop screen, console, e 354 ] 355 screen-should-contain [ - 356 . . - 357 . abc1 . - 358 .╌╌╌╌╌╌╌╌╌╌. - 359 . . + 356 ¦ . . + 357 ¦ . abc1 . + 358 ¦ .╌╌╌╌╌╌╌╌╌╌. + 359 ¦ . . 360 ] 361 ] 362 @@ -430,60 +431,60 @@ if ('onhashchange' in window) { 369 e:&:editor <- new-editor [a], 0/left, 10/right 370 editor-render screen, e 371 assume-console [ - 372 type [012] - 373 press ctrl-z + 372 ¦ type [012] + 373 ¦ press ctrl-z 374 ] 375 editor-event-loop screen, console, e 376 screen-should-contain [ - 377 . . - 378 .a . - 379 .╌╌╌╌╌╌╌╌╌╌. - 380 . . + 377 ¦ . . + 378 ¦ .a . + 379 ¦ .╌╌╌╌╌╌╌╌╌╌. + 380 ¦ . . 381 ] 382 # redo 383 assume-console [ - 384 press ctrl-y + 384 ¦ press ctrl-y 385 ] 386 run [ - 387 editor-event-loop screen, console, e + 387 ¦ editor-event-loop screen, console, e 388 ] 389 # all characters must be back 390 screen-should-contain [ - 391 . . - 392 .012a . - 393 .╌╌╌╌╌╌╌╌╌╌. - 394 . . + 391 ¦ . . + 392 ¦ .012a . + 393 ¦ .╌╌╌╌╌╌╌╌╌╌. + 394 ¦ . . 395 ] 396 # cursor should be in the right place 397 assume-console [ - 398 type [3] + 398 ¦ type [3] 399 ] 400 run [ - 401 editor-event-loop screen, console, e + 401 ¦ editor-event-loop screen, console, e 402 ] 403 screen-should-contain [ - 404 . . - 405 .0123a . - 406 .╌╌╌╌╌╌╌╌╌╌. - 407 . . + 404 ¦ . . + 405 ¦ .0123a . + 406 ¦ .╌╌╌╌╌╌╌╌╌╌. + 407 ¦ . . 408 ] 409 ] 410 411 after <handle-redo> [ 412 { - 413 typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant - 414 break-unless is-insert? - 415 before-cursor <- get *editor, before-cursor:offset - 416 insert-from:&:duplex-list:char <- get typing, insert-from:offset # ignore insert-to because it's already been spliced away - 417 # assert insert-to matches next(before-cursor) - 418 insert-range before-cursor, insert-from - 419 # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - 420 cursor-row <- get typing, after-row:offset - 421 *editor <- put *editor, cursor-row:offset, cursor-row - 422 cursor-column <- get typing, after-column:offset - 423 *editor <- put *editor, cursor-column:offset, cursor-column - 424 top:&:duplex-list:char <- get typing, after-top-of-screen:offset - 425 *editor <- put *editor, top-of-screen:offset, top + 413 ¦ typing:insert-operation, is-insert?:bool <- maybe-convert *op, typing:variant + 414 ¦ break-unless is-insert? + 415 ¦ before-cursor <- get *editor, before-cursor:offset + 416 ¦ insert-from:&:duplex-list:char <- get typing, insert-from:offset # ignore insert-to because it's already been spliced away + 417 ¦ # assert insert-to matches next(before-cursor) + 418 ¦ insert-range before-cursor, insert-from + 419 ¦ # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen + 420 ¦ cursor-row <- get typing, after-row:offset + 421 ¦ *editor <- put *editor, cursor-row:offset, cursor-row + 422 ¦ cursor-column <- get typing, after-column:offset + 423 ¦ *editor <- put *editor, cursor-column:offset, cursor-column + 424 ¦ top:&:duplex-list:char <- get typing, after-top-of-screen:offset + 425 ¦ *editor <- put *editor, top-of-screen:offset, top 426 } 427 ] 428 @@ -494,42 +495,42 @@ if ('onhashchange' in window) { 433 e:&:editor <- new-editor [], 0/left, 10/right 434 editor-render screen, e 435 assume-console [ - 436 type [012] - 437 press ctrl-z + 436 ¦ type [012] + 437 ¦ press ctrl-z 438 ] 439 editor-event-loop screen, console, e 440 screen-should-contain [ - 441 . . - 442 . . - 443 .╌╌╌╌╌╌╌╌╌╌. - 444 . . + 441 ¦ . . + 442 ¦ . . + 443 ¦ .╌╌╌╌╌╌╌╌╌╌. + 444 ¦ . . 445 ] 446 # redo 447 assume-console [ - 448 press ctrl-y + 448 ¦ press ctrl-y 449 ] 450 run [ - 451 editor-event-loop screen, console, e + 451 ¦ editor-event-loop screen, console, e 452 ] 453 # all characters must be back 454 screen-should-contain [ - 455 . . - 456 .012 . - 457 .╌╌╌╌╌╌╌╌╌╌. - 458 . . + 455 ¦ . . + 456 ¦ .012 . + 457 ¦ .╌╌╌╌╌╌╌╌╌╌. + 458 ¦ . . 459 ] 460 # cursor should be in the right place 461 assume-console [ - 462 type [3] + 462 ¦ type [3] 463 ] 464 run [ - 465 editor-event-loop screen, console, e + 465 ¦ editor-event-loop screen, console, e 466 ] 467 screen-should-contain [ - 468 . . - 469 .0123 . - 470 .╌╌╌╌╌╌╌╌╌╌. - 471 . . + 468 ¦ . . + 469 ¦ .0123 . + 470 ¦ .╌╌╌╌╌╌╌╌╌╌. + 471 ¦ . . 472 ] 473 ] 474 @@ -543,36 +544,36 @@ if ('onhashchange' in window) { 482 e:&:editor <- new-editor contents, 0/left, 10/right 483 editor-render screen, e 484 assume-console [ - 485 type [1] - 486 press ctrl-z + 485 ¦ type [1] + 486 ¦ press ctrl-z 487 ] 488 editor-event-loop screen, console, e 489 # do some more work 490 assume-console [ - 491 type [0] + 491 ¦ type [0] 492 ] 493 editor-event-loop screen, console, e 494 screen-should-contain [ - 495 . . - 496 .0abc . - 497 .def . - 498 .ghi . - 499 .╌╌╌╌╌╌╌╌╌╌. + 495 ¦ . . + 496 ¦ .0abc . + 497 ¦ .def . + 498 ¦ .ghi . + 499 ¦ .╌╌╌╌╌╌╌╌╌╌. 500 ] 501 # redo 502 assume-console [ - 503 press ctrl-y + 503 ¦ press ctrl-y 504 ] 505 run [ - 506 editor-event-loop screen, console, e + 506 ¦ editor-event-loop screen, console, e 507 ] 508 # nothing should happen 509 screen-should-contain [ - 510 . . - 511 .0abc . - 512 .def . - 513 .ghi . - 514 .╌╌╌╌╌╌╌╌╌╌. + 510 ¦ . . + 511 ¦ .0abc . + 512 ¦ .def . + 513 ¦ .ghi . + 514 ¦ .╌╌╌╌╌╌╌╌╌╌. 515 ] 516 ] 517 @@ -584,150 +585,150 @@ if ('onhashchange' in window) { 523 editor-render screen, e 524 # insert some text and tabs, hit enter, some more text and tabs 525 assume-console [ - 526 press tab - 527 type [ab] - 528 press tab - 529 type [cd] - 530 press enter - 531 press tab - 532 type [efg] + 526 ¦ press tab + 527 ¦ type [ab] + 528 ¦ press tab + 529 ¦ type [cd] + 530 ¦ press enter + 531 ¦ press tab + 532 ¦ type [efg] 533 ] 534 editor-event-loop screen, console, e 535 screen-should-contain [ - 536 . . - 537 . ab cd . - 538 . efg . - 539 .╌╌╌╌╌╌╌╌╌╌. - 540 . . + 536 ¦ . . + 537 ¦ . ab cd . + 538 ¦ . efg . + 539 ¦ .╌╌╌╌╌╌╌╌╌╌. + 540 ¦ . . 541 ] 542 3:num/raw <- get *e, cursor-row:offset 543 4:num/raw <- get *e, cursor-column:offset 544 memory-should-contain [ - 545 3 <- 2 - 546 4 <- 7 + 545 ¦ 3 <- 2 + 546 ¦ 4 <- 7 547 ] 548 # undo 549 assume-console [ - 550 press ctrl-z + 550 ¦ press ctrl-z 551 ] 552 run [ - 553 editor-event-loop screen, console, e + 553 ¦ editor-event-loop screen, console, e 554 ] 555 # typing in second line deleted, but not indent 556 3:num/raw <- get *e, cursor-row:offset 557 4:num/raw <- get *e, cursor-column:offset 558 memory-should-contain [ - 559 3 <- 2 - 560 4 <- 2 + 559 ¦ 3 <- 2 + 560 ¦ 4 <- 2 561 ] 562 screen-should-contain [ - 563 . . - 564 . ab cd . - 565 . . - 566 .╌╌╌╌╌╌╌╌╌╌. - 567 . . + 563 ¦ . . + 564 ¦ . ab cd . + 565 ¦ . . + 566 ¦ .╌╌╌╌╌╌╌╌╌╌. + 567 ¦ . . 568 ] 569 # undo again 570 assume-console [ - 571 press ctrl-z + 571 ¦ press ctrl-z 572 ] 573 run [ - 574 editor-event-loop screen, console, e + 574 ¦ editor-event-loop screen, console, e 575 ] 576 # indent and newline deleted 577 3:num/raw <- get *e, cursor-row:offset 578 4:num/raw <- get *e, cursor-column:offset 579 memory-should-contain [ - 580 3 <- 1 - 581 4 <- 8 + 580 ¦ 3 <- 1 + 581 ¦ 4 <- 8 582 ] 583 screen-should-contain [ - 584 . . - 585 . ab cd . - 586 .╌╌╌╌╌╌╌╌╌╌. - 587 . . + 584 ¦ . . + 585 ¦ . ab cd . + 586 ¦ .╌╌╌╌╌╌╌╌╌╌. + 587 ¦ . . 588 ] 589 # undo again 590 assume-console [ - 591 press ctrl-z + 591 ¦ press ctrl-z 592 ] 593 run [ - 594 editor-event-loop screen, console, e + 594 ¦ editor-event-loop screen, console, e 595 ] 596 # empty screen 597 3:num/raw <- get *e, cursor-row:offset 598 4:num/raw <- get *e, cursor-column:offset 599 memory-should-contain [ - 600 3 <- 1 - 601 4 <- 0 + 600 ¦ 3 <- 1 + 601 ¦ 4 <- 0 602 ] 603 screen-should-contain [ - 604 . . - 605 . . - 606 .╌╌╌╌╌╌╌╌╌╌. - 607 . . + 604 ¦ . . + 605 ¦ . . + 606 ¦ .╌╌╌╌╌╌╌╌╌╌. + 607 ¦ . . 608 ] 609 # redo 610 assume-console [ - 611 press ctrl-y + 611 ¦ press ctrl-y 612 ] 613 run [ - 614 editor-event-loop screen, console, e + 614 ¦ editor-event-loop screen, console, e 615 ] 616 # first line inserted 617 3:num/raw <- get *e, cursor-row:offset 618 4:num/raw <- get *e, cursor-column:offset 619 memory-should-contain [ - 620 3 <- 1 - 621 4 <- 8 + 620 ¦ 3 <- 1 + 621 ¦ 4 <- 8 622 ] 623 screen-should-contain [ - 624 . . - 625 . ab cd . - 626 .╌╌╌╌╌╌╌╌╌╌. - 627 . . + 624 ¦ . . + 625 ¦ . ab cd . + 626 ¦ .╌╌╌╌╌╌╌╌╌╌. + 627 ¦ . . 628 ] 629 # redo again 630 assume-console [ - 631 press ctrl-y + 631 ¦ press ctrl-y 632 ] 633 run [ - 634 editor-event-loop screen, console, e + 634 ¦ editor-event-loop screen, console, e 635 ] 636 # newline and indent inserted 637 3:num/raw <- get *e, cursor-row:offset 638 4:num/raw <- get *e, cursor-column:offset 639 memory-should-contain [ - 640 3 <- 2 - 641 4 <- 2 + 640 ¦ 3 <- 2 + 641 ¦ 4 <- 2 642 ] 643 screen-should-contain [ - 644 . . - 645 . ab cd . - 646 . . - 647 .╌╌╌╌╌╌╌╌╌╌. - 648 . . + 644 ¦ . . + 645 ¦ . ab cd . + 646 ¦ . . + 647 ¦ .╌╌╌╌╌╌╌╌╌╌. + 648 ¦ . . 649 ] 650 # redo again 651 assume-console [ - 652 press ctrl-y + 652 ¦ press ctrl-y 653 ] 654 run [ - 655 editor-event-loop screen, console, e + 655 ¦ editor-event-loop screen, console, e 656 ] 657 # indent and newline deleted 658 3:num/raw <- get *e, cursor-row:offset 659 4:num/raw <- get *e, cursor-column:offset 660 memory-should-contain [ - 661 3 <- 2 - 662 4 <- 7 + 661 ¦ 3 <- 2 + 662 ¦ 4 <- 7 663 ] 664 screen-should-contain [ - 665 . . - 666 . ab cd . - 667 . efg . - 668 .╌╌╌╌╌╌╌╌╌╌. - 669 . . + 665 ¦ . . + 666 ¦ . ab cd . + 667 ¦ . efg . + 668 ¦ .╌╌╌╌╌╌╌╌╌╌. + 669 ¦ . . 670 ] 671 ] 672 @@ -744,36 +745,36 @@ if ('onhashchange' in window) { 683 editor-render screen, e 684 # move the cursor 685 assume-console [ - 686 left-click 3, 1 + 686 ¦ left-click 3, 1 687 ] 688 editor-event-loop screen, console, e 689 # undo 690 assume-console [ - 691 press ctrl-z + 691 ¦ press ctrl-z 692 ] 693 run [ - 694 editor-event-loop screen, console, e + 694 ¦ editor-event-loop screen, console, e 695 ] 696 # click undone 697 3:num/raw <- get *e, cursor-row:offset 698 4:num/raw <- get *e, cursor-column:offset 699 memory-should-contain [ - 700 3 <- 1 - 701 4 <- 0 + 700 ¦ 3 <- 1 + 701 ¦ 4 <- 0 702 ] 703 # cursor should be in the right place 704 assume-console [ - 705 type [1] + 705 ¦ type [1] 706 ] 707 run [ - 708 editor-event-loop screen, console, e + 708 ¦ editor-event-loop screen, console, e 709 ] 710 screen-should-contain [ - 711 . . - 712 .1abc . - 713 .def . - 714 .ghi . - 715 .╌╌╌╌╌╌╌╌╌╌. + 711 ¦ . . + 712 ¦ .1abc . + 713 ¦ .def . + 714 ¦ .ghi . + 715 ¦ .╌╌╌╌╌╌╌╌╌╌. 716 ] 717 ] 718 @@ -787,22 +788,22 @@ if ('onhashchange' in window) { 726 cursor-row:num <- get *editor, cursor-row:offset 727 cursor-column:num <- get *editor, cursor-column:offset 728 { - 729 break-unless undo-coalesce-tag - 730 # if previous operation was also a move, and also had the same coalesce - 731 # tag, coalesce with it - 732 undo:&:list:&:operation <- get *editor, undo:offset - 733 break-unless undo - 734 op:&:operation <- first undo - 735 move:move-operation, is-move?:bool <- maybe-convert *op, move:variant - 736 break-unless is-move? - 737 previous-coalesce-tag:num <- get move, tag:offset - 738 coalesce?:bool <- equal undo-coalesce-tag, previous-coalesce-tag - 739 break-unless coalesce? - 740 move <- put move, after-row:offset, cursor-row - 741 move <- put move, after-column:offset, cursor-column - 742 move <- put move, after-top-of-screen:offset, top-after - 743 *op <- merge 1/move-operation, move - 744 break +done-adding-move-operation + 729 ¦ break-unless undo-coalesce-tag + 730 ¦ # if previous operation was also a move, and also had the same coalesce + 731 ¦ # tag, coalesce with it + 732 ¦ undo:&:list:&:operation <- get *editor, undo:offset + 733 ¦ break-unless undo + 734 ¦ op:&:operation <- first undo + 735 ¦ move:move-operation, is-move?:bool <- maybe-convert *op, move:variant + 736 ¦ break-unless is-move? + 737 ¦ previous-coalesce-tag:num <- get move, tag:offset + 738 ¦ coalesce?:bool <- equal undo-coalesce-tag, previous-coalesce-tag + 739 ¦ break-unless coalesce? + 740 ¦ move <- put move, after-row:offset, cursor-row + 741 ¦ move <- put move, after-column:offset, cursor-column + 742 ¦ move <- put move, after-top-of-screen:offset, top-after + 743 ¦ *op <- merge 1/move-operation, move + 744 ¦ break +done-adding-move-operation 745 } 746 op:&:operation <- new operation:type 747 *op <- merge 1/move-operation, cursor-row-before, cursor-column-before, top-before, cursor-row/after, cursor-column/after, top-after, undo-coalesce-tag @@ -812,15 +813,15 @@ if ('onhashchange' in window) { 751 752 after <handle-undo> [ 753 { - 754 move:move-operation, is-move?:bool <- maybe-convert *op, move:variant - 755 break-unless is-move? - 756 # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - 757 cursor-row <- get move, before-row:offset - 758 *editor <- put *editor, cursor-row:offset, cursor-row - 759 cursor-column <- get move, before-column:offset - 760 *editor <- put *editor, cursor-column:offset, cursor-column - 761 top:&:duplex-list:char <- get move, before-top-of-screen:offset - 762 *editor <- put *editor, top-of-screen:offset, top + 754 ¦ move:move-operation, is-move?:bool <- maybe-convert *op, move:variant + 755 ¦ break-unless is-move? + 756 ¦ # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen + 757 ¦ cursor-row <- get move, before-row:offset + 758 ¦ *editor <- put *editor, cursor-row:offset, cursor-row + 759 ¦ cursor-column <- get move, before-column:offset + 760 ¦ *editor <- put *editor, cursor-column:offset, cursor-column + 761 ¦ top:&:duplex-list:char <- get move, before-top-of-screen:offset + 762 ¦ *editor <- put *editor, top-of-screen:offset, top 763 } 764 ] 765 @@ -835,56 +836,56 @@ if ('onhashchange' in window) { 774 e:&:editor <- new-editor contents, 0/left, 5/right 775 # position cursor at end of screen and try to move right 776 assume-console [ - 777 left-click 3, 3 - 778 press right-arrow + 777 ¦ left-click 3, 3 + 778 ¦ press right-arrow 779 ] 780 editor-event-loop screen, console, e 781 3:num/raw <- get *e, cursor-row:offset 782 4:num/raw <- get *e, cursor-column:offset 783 # screen scrolls 784 screen-should-contain [ - 785 . . - 786 .b . - 787 .cdef↩. - 788 .gh . + 785 ¦ . . + 786 ¦ .b . + 787 ¦ .cdef↩. + 788 ¦ .gh . 789 ] 790 memory-should-contain [ - 791 3 <- 3 - 792 4 <- 0 + 791 ¦ 3 <- 3 + 792 ¦ 4 <- 0 793 ] 794 # undo 795 assume-console [ - 796 press ctrl-z + 796 ¦ press ctrl-z 797 ] 798 run [ - 799 editor-event-loop screen, console, e + 799 ¦ editor-event-loop screen, console, e 800 ] 801 # cursor moved back 802 3:num/raw <- get *e, cursor-row:offset 803 4:num/raw <- get *e, cursor-column:offset 804 memory-should-contain [ - 805 3 <- 3 - 806 4 <- 3 + 805 ¦ 3 <- 3 + 806 ¦ 4 <- 3 807 ] 808 # scroll undone 809 screen-should-contain [ - 810 . . - 811 .a . - 812 .b . - 813 .cdef↩. + 810 ¦ . . + 811 ¦ .a . + 812 ¦ .b . + 813 ¦ .cdef↩. 814 ] 815 # cursor should be in the right place 816 assume-console [ - 817 type [1] + 817 ¦ type [1] 818 ] 819 run [ - 820 editor-event-loop screen, console, e + 820 ¦ editor-event-loop screen, console, e 821 ] 822 screen-should-contain [ - 823 . . - 824 .b . - 825 .cde1↩. - 826 .fgh . + 823 ¦ . . + 824 ¦ .b . + 825 ¦ .cde1↩. + 826 ¦ .fgh . 827 ] 828 ] 829 @@ -899,37 +900,37 @@ if ('onhashchange' in window) { 838 editor-render screen, e 839 # move the cursor 840 assume-console [ - 841 left-click 3, 1 - 842 press left-arrow + 841 ¦ left-click 3, 1 + 842 ¦ press left-arrow 843 ] 844 editor-event-loop screen, console, e 845 # undo 846 assume-console [ - 847 press ctrl-z + 847 ¦ press ctrl-z 848 ] 849 run [ - 850 editor-event-loop screen, console, e + 850 ¦ editor-event-loop screen, console, e 851 ] 852 # cursor moves back 853 3:num/raw <- get *e, cursor-row:offset 854 4:num/raw <- get *e, cursor-column:offset 855 memory-should-contain [ - 856 3 <- 3 - 857 4 <- 1 + 856 ¦ 3 <- 3 + 857 ¦ 4 <- 1 858 ] 859 # cursor should be in the right place 860 assume-console [ - 861 type [1] + 861 ¦ type [1] 862 ] 863 run [ - 864 editor-event-loop screen, console, e + 864 ¦ editor-event-loop screen, console, e 865 ] 866 screen-should-contain [ - 867 . . - 868 .abc . - 869 .def . - 870 .g1hi . - 871 .╌╌╌╌╌╌╌╌╌╌. + 867 ¦ . . + 868 ¦ .abc . + 869 ¦ .def . + 870 ¦ .g1hi . + 871 ¦ .╌╌╌╌╌╌╌╌╌╌. 872 ] 873 ] 874 @@ -944,43 +945,43 @@ if ('onhashchange' in window) { 883 editor-render screen, e 884 # move the cursor 885 assume-console [ - 886 left-click 3, 1 - 887 press up-arrow + 886 ¦ left-click 3, 1 + 887 ¦ press up-arrow 888 ] 889 editor-event-loop screen, console, e 890 3:num/raw <- get *e, cursor-row:offset 891 4:num/raw <- get *e, cursor-column:offset 892 memory-should-contain [ - 893 3 <- 2 - 894 4 <- 1 + 893 ¦ 3 <- 2 + 894 ¦ 4 <- 1 895 ] 896 # undo 897 assume-console [ - 898 press ctrl-z + 898 ¦ press ctrl-z 899 ] 900 run [ - 901 editor-event-loop screen, console, e + 901 ¦ editor-event-loop screen, console, e 902 ] 903 # cursor moves back 904 3:num/raw <- get *e, cursor-row:offset 905 4:num/raw <- get *e, cursor-column:offset 906 memory-should-contain [ - 907 3 <- 3 - 908 4 <- 1 + 907 ¦ 3 <- 3 + 908 ¦ 4 <- 1 909 ] 910 # cursor should be in the right place 911 assume-console [ - 912 type [1] + 912 ¦ type [1] 913 ] 914 run [ - 915 editor-event-loop screen, console, e + 915 ¦ editor-event-loop screen, console, e 916 ] 917 screen-should-contain [ - 918 . . - 919 .abc . - 920 .def . - 921 .g1hi . - 922 .╌╌╌╌╌╌╌╌╌╌. + 918 ¦ . . + 919 ¦ .abc . + 920 ¦ .def . + 921 ¦ .g1hi . + 922 ¦ .╌╌╌╌╌╌╌╌╌╌. 923 ] 924 ] 925 @@ -995,37 +996,37 @@ if ('onhashchange' in window) { 934 editor-render screen, e 935 # move the cursor 936 assume-console [ - 937 left-click 2, 1 - 938 press down-arrow + 937 ¦ left-click 2, 1 + 938 ¦ press down-arrow 939 ] 940 editor-event-loop screen, console, e 941 # undo 942 assume-console [ - 943 press ctrl-z + 943 ¦ press ctrl-z 944 ] 945 run [ - 946 editor-event-loop screen, console, e + 946 ¦ editor-event-loop screen, console, e 947 ] 948 # cursor moves back 949 3:num/raw <- get *e, cursor-row:offset 950 4:num/raw <- get *e, cursor-column:offset 951 memory-should-contain [ - 952 3 <- 2 - 953 4 <- 1 + 952 ¦ 3 <- 2 + 953 ¦ 4 <- 1 954 ] 955 # cursor should be in the right place 956 assume-console [ - 957 type [1] + 957 ¦ type [1] 958 ] 959 run [ - 960 editor-event-loop screen, console, e + 960 ¦ editor-event-loop screen, console, e 961 ] 962 screen-should-contain [ - 963 . . - 964 .abc . - 965 .d1ef . - 966 .ghi . - 967 .╌╌╌╌╌╌╌╌╌╌. + 963 ¦ . . + 964 ¦ .abc . + 965 ¦ .d1ef . + 966 ¦ .ghi . + 967 ¦ .╌╌╌╌╌╌╌╌╌╌. 968 ] 969 ] 970 @@ -1043,23 +1044,23 @@ if ('onhashchange' in window) { 982 editor-render screen, e 983 # scroll the page 984 assume-console [ - 985 press ctrl-f + 985 ¦ press ctrl-f 986 ] 987 editor-event-loop screen, console, e 988 # undo 989 assume-console [ - 990 press ctrl-z + 990 ¦ press ctrl-z 991 ] 992 run [ - 993 editor-event-loop screen, console, e + 993 ¦ editor-event-loop screen, console, e 994 ] 995 # screen should again show page 1 996 screen-should-contain [ - 997 . . - 998 .a . - 999 .b . -1000 .c . -1001 .d . + 997 ¦ . . + 998 ¦ .a . + 999 ¦ .b . +1000 ¦ .c . +1001 ¦ .d . 1002 ] 1003 ] 1004 @@ -1077,23 +1078,23 @@ if ('onhashchange' in window) { 1016 editor-render screen, e 1017 # scroll the page 1018 assume-console [ -1019 press page-down +1019 ¦ press page-down 1020 ] 1021 editor-event-loop screen, console, e 1022 # undo 1023 assume-console [ -1024 press ctrl-z +1024 ¦ press ctrl-z 1025 ] 1026 run [ -1027 editor-event-loop screen, console, e +1027 ¦ editor-event-loop screen, console, e 1028 ] 1029 # screen should again show page 1 1030 screen-should-contain [ -1031 . . -1032 .a . -1033 .b . -1034 .c . -1035 .d . +1031 ¦ . . +1032 ¦ .a . +1033 ¦ .b . +1034 ¦ .c . +1035 ¦ .d . 1036 ] 1037 ] 1038 @@ -1111,24 +1112,24 @@ if ('onhashchange' in window) { 1050 editor-render screen, e 1051 # scroll the page down and up 1052 assume-console [ -1053 press page-down -1054 press ctrl-b +1053 ¦ press page-down +1054 ¦ press ctrl-b 1055 ] 1056 editor-event-loop screen, console, e 1057 # undo 1058 assume-console [ -1059 press ctrl-z +1059 ¦ press ctrl-z 1060 ] 1061 run [ -1062 editor-event-loop screen, console, e +1062 ¦ editor-event-loop screen, console, e 1063 ] 1064 # screen should again show page 2 1065 screen-should-contain [ -1066 . . -1067 .d . -1068 .e . -1069 .f . -1070 .╌╌╌╌╌╌╌╌╌╌. +1066 ¦ . . +1067 ¦ .d . +1068 ¦ .e . +1069 ¦ .f . +1070 ¦ .╌╌╌╌╌╌╌╌╌╌. 1071 ] 1072 ] 1073 @@ -1146,24 +1147,24 @@ if ('onhashchange' in window) { 1085 editor-render screen, e 1086 # scroll the page down and up 1087 assume-console [ -1088 press page-down -1089 press page-up +1088 ¦ press page-down +1089 ¦ press page-up 1090 ] 1091 editor-event-loop screen, console, e 1092 # undo 1093 assume-console [ -1094 press ctrl-z +1094 ¦ press ctrl-z 1095 ] 1096 run [ -1097 editor-event-loop screen, console, e +1097 ¦ editor-event-loop screen, console, e 1098 ] 1099 # screen should again show page 2 1100 screen-should-contain [ -1101 . . -1102 .d . -1103 .e . -1104 .f . -1105 .╌╌╌╌╌╌╌╌╌╌. +1101 ¦ . . +1102 ¦ .d . +1103 ¦ .e . +1104 ¦ .f . +1105 ¦ .╌╌╌╌╌╌╌╌╌╌. 1106 ] 1107 ] 1108 @@ -1178,37 +1179,37 @@ if ('onhashchange' in window) { 1117 editor-render screen, e 1118 # move the cursor, then to start of line 1119 assume-console [ -1120 left-click 2, 1 -1121 press ctrl-a +1120 ¦ left-click 2, 1 +1121 ¦ press ctrl-a 1122 ] 1123 editor-event-loop screen, console, e 1124 # undo 1125 assume-console [ -1126 press ctrl-z +1126 ¦ press ctrl-z 1127 ] 1128 run [ -1129 editor-event-loop screen, console, e +1129 ¦ editor-event-loop screen, console, e 1130 ] 1131 # cursor moves back 1132 3:num/raw <- get *e, cursor-row:offset 1133 4:num/raw <- get *e, cursor-column:offset 1134 memory-should-contain [ -1135 3 <- 2 -1136 4 <- 1 +1135 ¦ 3 <- 2 +1136 ¦ 4 <- 1 1137 ] 1138 # cursor should be in the right place 1139 assume-console [ -1140 type [1] +1140 ¦ type [1] 1141 ] 1142 run [ -1143 editor-event-loop screen, console, e +1143 ¦ editor-event-loop screen, console, e 1144 ] 1145 screen-should-contain [ -1146 . . -1147 .abc . -1148 .d1ef . -1149 .ghi . -1150 .╌╌╌╌╌╌╌╌╌╌. +1146 ¦ . . +1147 ¦ .abc . +1148 ¦ .d1ef . +1149 ¦ .ghi . +1150 ¦ .╌╌╌╌╌╌╌╌╌╌. 1151 ] 1152 ] 1153 @@ -1223,37 +1224,37 @@ if ('onhashchange' in window) { 1162 editor-render screen, e 1163 # move the cursor, then to start of line 1164 assume-console [ -1165 left-click 2, 1 -1166 press home +1165 ¦ left-click 2, 1 +1166 ¦ press home 1167 ] 1168 editor-event-loop screen, console, e 1169 # undo 1170 assume-console [ -1171 press ctrl-z +1171 ¦ press ctrl-z 1172 ] 1173 run [ -1174 editor-event-loop screen, console, e +1174 ¦ editor-event-loop screen, console, e 1175 ] 1176 # cursor moves back 1177 3:num/raw <- get *e, cursor-row:offset 1178 4:num/raw <- get *e, cursor-column:offset 1179 memory-should-contain [ -1180 3 <- 2 -1181 4 <- 1 +1180 ¦ 3 <- 2 +1181 ¦ 4 <- 1 1182 ] 1183 # cursor should be in the right place 1184 assume-console [ -1185 type [1] +1185 ¦ type [1] 1186 ] 1187 run [ -1188 editor-event-loop screen, console, e +1188 ¦ editor-event-loop screen, console, e 1189 ] 1190 screen-should-contain [ -1191 . . -1192 .abc . -1193 .d1ef . -1194 .ghi . -1195 .╌╌╌╌╌╌╌╌╌╌. +1191 ¦ . . +1192 ¦ .abc . +1193 ¦ .d1ef . +1194 ¦ .ghi . +1195 ¦ .╌╌╌╌╌╌╌╌╌╌. 1196 ] 1197 ] 1198 @@ -1268,37 +1269,37 @@ if ('onhashchange' in window) { 1207 editor-render screen, e 1208 # move the cursor, then to start of line 1209 assume-console [ -1210 left-click 2, 1 -1211 press ctrl-e +1210 ¦ left-click 2, 1 +1211 ¦ press ctrl-e 1212 ] 1213 editor-event-loop screen, console, e 1214 # undo 1215 assume-console [ -1216 press ctrl-z +1216 ¦ press ctrl-z 1217 ] 1218 run [ -1219 editor-event-loop screen, console, e +1219 ¦ editor-event-loop screen, console, e 1220 ] 1221 # cursor moves back 1222 3:num/raw <- get *e, cursor-row:offset 1223 4:num/raw <- get *e, cursor-column:offset 1224 memory-should-contain [ -1225 3 <- 2 -1226 4 <- 1 +1225 ¦ 3 <- 2 +1226 ¦ 4 <- 1 1227 ] 1228 # cursor should be in the right place 1229 assume-console [ -1230 type [1] +1230 ¦ type [1] 1231 ] 1232 run [ -1233 editor-event-loop screen, console, e +1233 ¦ editor-event-loop screen, console, e 1234 ] 1235 screen-should-contain [ -1236 . . -1237 .abc . -1238 .d1ef . -1239 .ghi . -1240 .╌╌╌╌╌╌╌╌╌╌. +1236 ¦ . . +1237 ¦ .abc . +1238 ¦ .d1ef . +1239 ¦ .ghi . +1240 ¦ .╌╌╌╌╌╌╌╌╌╌. 1241 ] 1242 ] 1243 @@ -1313,37 +1314,37 @@ if ('onhashchange' in window) { 1252 editor-render screen, e 1253 # move the cursor, then to start of line 1254 assume-console [ -1255 left-click 2, 1 -1256 press end +1255 ¦ left-click 2, 1 +1256 ¦ press end 1257 ] 1258 editor-event-loop screen, console, e 1259 # undo 1260 assume-console [ -1261 press ctrl-z +1261 ¦ press ctrl-z 1262 ] 1263 run [ -1264 editor-event-loop screen, console, e +1264 ¦ editor-event-loop screen, console, e 1265 ] 1266 # cursor moves back 1267 3:num/raw <- get *e, cursor-row:offset 1268 4:num/raw <- get *e, cursor-column:offset 1269 memory-should-contain [ -1270 3 <- 2 -1271 4 <- 1 +1270 ¦ 3 <- 2 +1271 ¦ 4 <- 1 1272 ] 1273 # cursor should be in the right place 1274 assume-console [ -1275 type [1] +1275 ¦ type [1] 1276 ] 1277 run [ -1278 editor-event-loop screen, console, e +1278 ¦ editor-event-loop screen, console, e 1279 ] 1280 screen-should-contain [ -1281 . . -1282 .abc . -1283 .d1ef . -1284 .ghi . -1285 .╌╌╌╌╌╌╌╌╌╌. +1281 ¦ . . +1282 ¦ .abc . +1283 ¦ .d1ef . +1284 ¦ .ghi . +1285 ¦ .╌╌╌╌╌╌╌╌╌╌. 1286 ] 1287 ] 1288 @@ -1358,45 +1359,45 @@ if ('onhashchange' in window) { 1297 editor-render screen, e 1298 # move the cursor 1299 assume-console [ -1300 left-click 2, 1 -1301 press right-arrow -1302 press right-arrow -1303 press up-arrow +1300 ¦ left-click 2, 1 +1301 ¦ press right-arrow +1302 ¦ press right-arrow +1303 ¦ press up-arrow 1304 ] 1305 editor-event-loop screen, console, e 1306 3:num/raw <- get *e, cursor-row:offset 1307 4:num/raw <- get *e, cursor-column:offset 1308 memory-should-contain [ -1309 3 <- 1 -1310 4 <- 3 +1309 ¦ 3 <- 1 +1310 ¦ 4 <- 3 1311 ] 1312 # undo 1313 assume-console [ -1314 press ctrl-z +1314 ¦ press ctrl-z 1315 ] 1316 run [ -1317 editor-event-loop screen, console, e +1317 ¦ editor-event-loop screen, console, e 1318 ] 1319 # up-arrow is undone 1320 3:num/raw <- get *e, cursor-row:offset 1321 4:num/raw <- get *e, cursor-column:offset 1322 memory-should-contain [ -1323 3 <- 2 -1324 4 <- 3 +1323 ¦ 3 <- 2 +1324 ¦ 4 <- 3 1325 ] 1326 # undo again 1327 assume-console [ -1328 press ctrl-z +1328 ¦ press ctrl-z 1329 ] 1330 run [ -1331 editor-event-loop screen, console, e +1331 ¦ editor-event-loop screen, console, e 1332 ] 1333 # both right-arrows are undone 1334 3:num/raw <- get *e, cursor-row:offset 1335 4:num/raw <- get *e, cursor-column:offset 1336 memory-should-contain [ -1337 3 <- 2 -1338 4 <- 1 +1337 ¦ 3 <- 2 +1338 ¦ 4 <- 1 1339 ] 1340 ] 1341 @@ -1412,51 +1413,51 @@ if ('onhashchange' in window) { 1351 e:&:editor <- new-editor contents, 0/left, 10/right 1352 editor-render screen, e 1353 assume-console [ -1354 left-click 3, 1 -1355 press ctrl-z +1354 ¦ left-click 3, 1 +1355 ¦ press ctrl-z 1356 ] 1357 editor-event-loop screen, console, e 1358 # redo 1359 assume-console [ -1360 press ctrl-y +1360 ¦ press ctrl-y 1361 ] 1362 run [ -1363 editor-event-loop screen, console, e +1363 ¦ editor-event-loop screen, console, e 1364 ] 1365 # cursor moves to left-click 1366 3:num/raw <- get *e, cursor-row:offset 1367 4:num/raw <- get *e, cursor-column:offset 1368 memory-should-contain [ -1369 3 <- 3 -1370 4 <- 1 +1369 ¦ 3 <- 3 +1370 ¦ 4 <- 1 1371 ] 1372 # cursor should be in the right place 1373 assume-console [ -1374 type [1] +1374 ¦ type [1] 1375 ] 1376 run [ -1377 editor-event-loop screen, console, e +1377 ¦ editor-event-loop screen, console, e 1378 ] 1379 screen-should-contain [ -1380 . . -1381 .abc . -1382 .def . -1383 .g1hi . -1384 .╌╌╌╌╌╌╌╌╌╌. +1380 ¦ . . +1381 ¦ .abc . +1382 ¦ .def . +1383 ¦ .g1hi . +1384 ¦ .╌╌╌╌╌╌╌╌╌╌. 1385 ] 1386 ] 1387 1388 after <handle-redo> [ 1389 { -1390 move:move-operation, is-move?:bool <- maybe-convert *op, move:variant -1391 break-unless is-move? -1392 # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen -1393 cursor-row <- get move, after-row:offset -1394 *editor <- put *editor, cursor-row:offset, cursor-row -1395 cursor-column <- get move, after-column:offset -1396 *editor <- put *editor, cursor-column:offset, cursor-column -1397 top:&:duplex-list:char <- get move, after-top-of-screen:offset -1398 *editor <- put *editor, top-of-screen:offset, top +1390 ¦ move:move-operation, is-move?:bool <- maybe-convert *op, move:variant +1391 ¦ break-unless is-move? +1392 ¦ # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen +1393 ¦ cursor-row <- get move, after-row:offset +1394 ¦ *editor <- put *editor, cursor-row:offset, cursor-row +1395 ¦ cursor-column <- get move, after-column:offset +1396 ¦ *editor <- put *editor, cursor-column:offset, cursor-column +1397 ¦ top:&:duplex-list:char <- get move, after-top-of-screen:offset +1398 ¦ *editor <- put *editor, top-of-screen:offset, top 1399 } 1400 ] 1401 @@ -1467,143 +1468,143 @@ if ('onhashchange' in window) { 1406 e:&:editor <- new-editor [], 0/left, 10/right 1407 editor-render screen, e 1408 assume-console [ -1409 type [abc] -1410 left-click 1, 1 -1411 type [d] +1409 ¦ type [abc] +1410 ¦ left-click 1, 1 +1411 ¦ type [d] 1412 ] 1413 editor-event-loop screen, console, e 1414 3:num/raw <- get *e, cursor-row:offset 1415 4:num/raw <- get *e, cursor-column:offset 1416 screen-should-contain [ -1417 . . -1418 .adbc . -1419 .╌╌╌╌╌╌╌╌╌╌. -1420 . . +1417 ¦ . . +1418 ¦ .adbc . +1419 ¦ .╌╌╌╌╌╌╌╌╌╌. +1420 ¦ . . 1421 ] 1422 memory-should-contain [ -1423 3 <- 1 -1424 4 <- 2 +1423 ¦ 3 <- 1 +1424 ¦ 4 <- 2 1425 ] 1426 # undo 1427 assume-console [ -1428 press ctrl-z +1428 ¦ press ctrl-z 1429 ] 1430 run [ -1431 editor-event-loop screen, console, e -1432 3:num/raw <- get *e, cursor-row:offset -1433 4:num/raw <- get *e, cursor-column:offset +1431 ¦ editor-event-loop screen, console, e +1432 ¦ 3:num/raw <- get *e, cursor-row:offset +1433 ¦ 4:num/raw <- get *e, cursor-column:offset 1434 ] 1435 # last letter typed is deleted 1436 screen-should-contain [ -1437 . . -1438 .abc . -1439 .╌╌╌╌╌╌╌╌╌╌. -1440 . . +1437 ¦ . . +1438 ¦ .abc . +1439 ¦ .╌╌╌╌╌╌╌╌╌╌. +1440 ¦ . . 1441 ] 1442 memory-should-contain [ -1443 3 <- 1 -1444 4 <- 1 +1443 ¦ 3 <- 1 +1444 ¦ 4 <- 1 1445 ] 1446 # undo again 1447 assume-console [ -1448 press ctrl-z +1448 ¦ press ctrl-z 1449 ] 1450 run [ -1451 editor-event-loop screen, console, e -1452 3:num/raw <- get *e, cursor-row:offset -1453 4:num/raw <- get *e, cursor-column:offset +1451 ¦ editor-event-loop screen, console, e +1452 ¦ 3:num/raw <- get *e, cursor-row:offset +1453 ¦ 4:num/raw <- get *e, cursor-column:offset 1454 ] 1455 # no change to screen; cursor moves 1456 screen-should-contain [ -1457 . . -1458 .abc . -1459 .╌╌╌╌╌╌╌╌╌╌. -1460 . . +1457 ¦ . . +1458 ¦ .abc . +1459 ¦ .╌╌╌╌╌╌╌╌╌╌. +1460 ¦ . . 1461 ] 1462 memory-should-contain [ -1463 3 <- 1 -1464 4 <- 3 +1463 ¦ 3 <- 1 +1464 ¦ 4 <- 3 1465 ] 1466 # undo again 1467 assume-console [ -1468 press ctrl-z +1468 ¦ press ctrl-z 1469 ] 1470 run [ -1471 editor-event-loop screen, console, e -1472 3:num/raw <- get *e, cursor-row:offset -1473 4:num/raw <- get *e, cursor-column:offset +1471 ¦ editor-event-loop screen, console, e +1472 ¦ 3:num/raw <- get *e, cursor-row:offset +1473 ¦ 4:num/raw <- get *e, cursor-column:offset 1474 ] 1475 # screen empty 1476 screen-should-contain [ -1477 . . -1478 . . -1479 .╌╌╌╌╌╌╌╌╌╌. -1480 . . +1477 ¦ . . +1478 ¦ . . +1479 ¦ .╌╌╌╌╌╌╌╌╌╌. +1480 ¦ . . 1481 ] 1482 memory-should-contain [ -1483 3 <- 1 -1484 4 <- 0 +1483 ¦ 3 <- 1 +1484 ¦ 4 <- 0 1485 ] 1486 # redo 1487 assume-console [ -1488 press ctrl-y +1488 ¦ press ctrl-y 1489 ] 1490 run [ -1491 editor-event-loop screen, console, e -1492 3:num/raw <- get *e, cursor-row:offset -1493 4:num/raw <- get *e, cursor-column:offset +1491 ¦ editor-event-loop screen, console, e +1492 ¦ 3:num/raw <- get *e, cursor-row:offset +1493 ¦ 4:num/raw <- get *e, cursor-column:offset 1494 ] 1495 # first insert 1496 screen-should-contain [ -1497 . . -1498 .abc . -1499 .╌╌╌╌╌╌╌╌╌╌. -1500 . . +1497 ¦ . . +1498 ¦ .abc . +1499 ¦ .╌╌╌╌╌╌╌╌╌╌. +1500 ¦ . . 1501 ] 1502 memory-should-contain [ -1503 3 <- 1 -1504 4 <- 3 +1503 ¦ 3 <- 1 +1504 ¦ 4 <- 3 1505 ] 1506 # redo again 1507 assume-console [ -1508 press ctrl-y +1508 ¦ press ctrl-y 1509 ] 1510 run [ -1511 editor-event-loop screen, console, e -1512 3:num/raw <- get *e, cursor-row:offset -1513 4:num/raw <- get *e, cursor-column:offset +1511 ¦ editor-event-loop screen, console, e +1512 ¦ 3:num/raw <- get *e, cursor-row:offset +1513 ¦ 4:num/raw <- get *e, cursor-column:offset 1514 ] 1515 # cursor moves 1516 screen-should-contain [ -1517 . . -1518 .abc . -1519 .╌╌╌╌╌╌╌╌╌╌. -1520 . . +1517 ¦ . . +1518 ¦ .abc . +1519 ¦ .╌╌╌╌╌╌╌╌╌╌. +1520 ¦ . . 1521 ] 1522 # cursor moves 1523 memory-should-contain [ -1524 3 <- 1 -1525 4 <- 1 +1524 ¦ 3 <- 1 +1525 ¦ 4 <- 1 1526 ] 1527 # redo again 1528 assume-console [ -1529 press ctrl-y +1529 ¦ press ctrl-y 1530 ] 1531 run [ -1532 editor-event-loop screen, console, e -1533 3:num/raw <- get *e, cursor-row:offset -1534 4:num/raw <- get *e, cursor-column:offset +1532 ¦ editor-event-loop screen, console, e +1533 ¦ 3:num/raw <- get *e, cursor-row:offset +1534 ¦ 4:num/raw <- get *e, cursor-column:offset 1535 ] 1536 # second insert 1537 screen-should-contain [ -1538 . . -1539 .adbc . -1540 .╌╌╌╌╌╌╌╌╌╌. -1541 . . +1538 ¦ . . +1539 ¦ .adbc . +1540 ¦ .╌╌╌╌╌╌╌╌╌╌. +1541 ¦ . . 1542 ] 1543 memory-should-contain [ -1544 3 <- 1 -1545 4 <- 2 +1544 ¦ 3 <- 1 +1545 ¦ 4 <- 2 1546 ] 1547 ] 1548 @@ -1617,60 +1618,60 @@ if ('onhashchange' in window) { 1556 editor-render screen, e 1557 # insert some text and hit backspace 1558 assume-console [ -1559 type [abc] -1560 press backspace -1561 press backspace +1559 ¦ type [abc] +1560 ¦ press backspace +1561 ¦ press backspace 1562 ] 1563 editor-event-loop screen, console, e 1564 screen-should-contain [ -1565 . . -1566 .a . -1567 .╌╌╌╌╌╌╌╌╌╌. -1568 . . +1565 ¦ . . +1566 ¦ .a . +1567 ¦ .╌╌╌╌╌╌╌╌╌╌. +1568 ¦ . . 1569 ] 1570 3:num/raw <- get *e, cursor-row:offset 1571 4:num/raw <- get *e, cursor-column:offset 1572 memory-should-contain [ -1573 3 <- 1 -1574 4 <- 1 +1573 ¦ 3 <- 1 +1574 ¦ 4 <- 1 1575 ] 1576 # undo 1577 assume-console [ -1578 press ctrl-z +1578 ¦ press ctrl-z 1579 ] 1580 run [ -1581 editor-event-loop screen, console, e +1581 ¦ editor-event-loop screen, console, e 1582 ] 1583 3:num/raw <- get *e, cursor-row:offset 1584 4:num/raw <- get *e, cursor-column:offset 1585 memory-should-contain [ -1586 3 <- 1 -1587 4 <- 3 +1586 ¦ 3 <- 1 +1587 ¦ 4 <- 3 1588 ] 1589 screen-should-contain [ -1590 . . -1591 .abc . -1592 .╌╌╌╌╌╌╌╌╌╌. -1593 . . +1590 ¦ . . +1591 ¦ .abc . +1592 ¦ .╌╌╌╌╌╌╌╌╌╌. +1593 ¦ . . 1594 ] 1595 # redo 1596 assume-console [ -1597 press ctrl-y +1597 ¦ press ctrl-y 1598 ] 1599 run [ -1600 editor-event-loop screen, console, e +1600 ¦ editor-event-loop screen, console, e 1601 ] 1602 3:num/raw <- get *e, cursor-row:offset 1603 4:num/raw <- get *e, cursor-column:offset 1604 memory-should-contain [ -1605 3 <- 1 -1606 4 <- 1 +1605 ¦ 3 <- 1 +1606 ¦ 4 <- 1 1607 ] 1608 screen-should-contain [ -1609 . . -1610 .a . -1611 .╌╌╌╌╌╌╌╌╌╌. -1612 . . +1609 ¦ . . +1610 ¦ .a . +1611 ¦ .╌╌╌╌╌╌╌╌╌╌. +1612 ¦ . . 1613 ] 1614 ] 1615 @@ -1680,75 +1681,75 @@ if ('onhashchange' in window) { 1619 ] 1620 before <backspace-character-end> [ 1621 { -1622 break-unless backspaced-cell # backspace failed; don't add an undo operation -1623 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset -1624 cursor-row:num <- get *editor, cursor-row:offset -1625 cursor-column:num <- get *editor, cursor-row:offset -1626 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset -1627 undo:&:list:&:operation <- get *editor, undo:offset -1628 { -1629 # if previous operation was an insert, coalesce this operation with it -1630 break-unless undo -1631 op:&:operation <- first undo -1632 deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant -1633 break-unless is-delete? -1634 previous-coalesce-tag:num <- get deletion, tag:offset -1635 coalesce?:bool <- equal previous-coalesce-tag, 1/coalesce-backspace -1636 break-unless coalesce? -1637 deletion <- put deletion, delete-from:offset, before-cursor -1638 backspaced-so-far:&:duplex-list:char <- get deletion, deleted-text:offset -1639 insert-range backspaced-cell, backspaced-so-far -1640 deletion <- put deletion, deleted-text:offset, backspaced-cell -1641 deletion <- put deletion, after-row:offset, cursor-row -1642 deletion <- put deletion, after-column:offset, cursor-column -1643 deletion <- put deletion, after-top-of-screen:offset, top-after -1644 *op <- merge 2/delete-operation, deletion -1645 break +done-adding-backspace-operation -1646 } -1647 # if not, create a new operation -1648 op:&:operation <- new operation:type -1649 deleted-until:&:duplex-list:char <- next before-cursor -1650 *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, backspaced-cell/deleted, before-cursor/delete-from, deleted-until, 1/coalesce-backspace -1651 editor <- add-operation editor, op -1652 +done-adding-backspace-operation +1622 ¦ break-unless backspaced-cell # backspace failed; don't add an undo operation +1623 ¦ top-after:&:duplex-list:char <- get *editor, top-of-screen:offset +1624 ¦ cursor-row:num <- get *editor, cursor-row:offset +1625 ¦ cursor-column:num <- get *editor, cursor-row:offset +1626 ¦ before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset +1627 ¦ undo:&:list:&:operation <- get *editor, undo:offset +1628 ¦ { +1629 ¦ ¦ # if previous operation was an insert, coalesce this operation with it +1630 ¦ ¦ break-unless undo +1631 ¦ ¦ op:&:operation <- first undo +1632 ¦ ¦ deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant +1633 ¦ ¦ break-unless is-delete? +1634 ¦ ¦ previous-coalesce-tag:num <- get deletion, tag:offset +1635 ¦ ¦ coalesce?:bool <- equal previous-coalesce-tag, 1/coalesce-backspace +1636 ¦ ¦ break-unless coalesce? +1637 ¦ ¦ deletion <- put deletion, delete-from:offset, before-cursor +1638 ¦ ¦ backspaced-so-far:&:duplex-list:char <- get deletion, deleted-text:offset +1639 ¦ ¦ insert-range backspaced-cell, backspaced-so-far +1640 ¦ ¦ deletion <- put deletion, deleted-text:offset, backspaced-cell +1641 ¦ ¦ deletion <- put deletion, after-row:offset, cursor-row +1642 ¦ ¦ deletion <- put deletion, after-column:offset, cursor-column +1643 ¦ ¦ deletion <- put deletion, after-top-of-screen:offset, top-after +1644 ¦ ¦ *op <- merge 2/delete-operation, deletion +1645 ¦ ¦ break +done-adding-backspace-operation +1646 ¦ } +1647 ¦ # if not, create a new operation +1648 ¦ op:&:operation <- new operation:type +1649 ¦ deleted-until:&:duplex-list:char <- next before-cursor +1650 ¦ *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, backspaced-cell/deleted, before-cursor/delete-from, deleted-until, 1/coalesce-backspace +1651 ¦ editor <- add-operation editor, op +1652 ¦ +done-adding-backspace-operation 1653 } 1654 ] 1655 1656 after <handle-undo> [ 1657 { -1658 deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant -1659 break-unless is-delete? -1660 anchor:&:duplex-list:char <- get deletion, delete-from:offset -1661 break-unless anchor -1662 deleted:&:duplex-list:char <- get deletion, deleted-text:offset -1663 old-cursor:&:duplex-list:char <- last deleted -1664 insert-range anchor, deleted -1665 # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen -1666 before-cursor <- copy old-cursor -1667 cursor-row <- get deletion, before-row:offset -1668 *editor <- put *editor, cursor-row:offset, cursor-row -1669 cursor-column <- get deletion, before-column:offset -1670 *editor <- put *editor, cursor-column:offset, cursor-column -1671 top:&:duplex-list:char <- get deletion, before-top-of-screen:offset -1672 *editor <- put *editor, top-of-screen:offset, top +1658 ¦ deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant +1659 ¦ break-unless is-delete? +1660 ¦ anchor:&:duplex-list:char <- get deletion, delete-from:offset +1661 ¦ break-unless anchor +1662 ¦ deleted:&:duplex-list:char <- get deletion, deleted-text:offset +1663 ¦ old-cursor:&:duplex-list:char <- last deleted +1664 ¦ insert-range anchor, deleted +1665 ¦ # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen +1666 ¦ before-cursor <- copy old-cursor +1667 ¦ cursor-row <- get deletion, before-row:offset +1668 ¦ *editor <- put *editor, cursor-row:offset, cursor-row +1669 ¦ cursor-column <- get deletion, before-column:offset +1670 ¦ *editor <- put *editor, cursor-column:offset, cursor-column +1671 ¦ top:&:duplex-list:char <- get deletion, before-top-of-screen:offset +1672 ¦ *editor <- put *editor, top-of-screen:offset, top 1673 } 1674 ] 1675 1676 after <handle-redo> [ 1677 { -1678 deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant -1679 break-unless is-delete? -1680 start:&:duplex-list:char <- get deletion, delete-from:offset -1681 end:&:duplex-list:char <- get deletion, delete-until:offset -1682 data:&:duplex-list:char <- get *editor, data:offset -1683 remove-between start, end -1684 # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen -1685 cursor-row <- get deletion, after-row:offset -1686 *editor <- put *editor, cursor-row:offset, cursor-row -1687 cursor-column <- get deletion, after-column:offset -1688 *editor <- put *editor, cursor-column:offset, cursor-column -1689 top:&:duplex-list:char <- get deletion, before-top-of-screen:offset -1690 *editor <- put *editor, top-of-screen:offset, top +1678 ¦ deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant +1679 ¦ break-unless is-delete? +1680 ¦ start:&:duplex-list:char <- get deletion, delete-from:offset +1681 ¦ end:&:duplex-list:char <- get deletion, delete-until:offset +1682 ¦ data:&:duplex-list:char <- get *editor, data:offset +1683 ¦ remove-between start, end +1684 ¦ # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen +1685 ¦ cursor-row <- get deletion, after-row:offset +1686 ¦ *editor <- put *editor, cursor-row:offset, cursor-row +1687 ¦ cursor-column <- get deletion, after-column:offset +1688 ¦ *editor <- put *editor, cursor-column:offset, cursor-column +1689 ¦ top:&:duplex-list:char <- get deletion, before-top-of-screen:offset +1690 ¦ *editor <- put *editor, top-of-screen:offset, top 1691 } 1692 ] 1693 @@ -1762,142 +1763,142 @@ if ('onhashchange' in window) { 1701 editor-render screen, e 1702 # insert some text and hit delete and backspace a few times 1703 assume-console [ -1704 type [abcdef] -1705 left-click 1, 2 -1706 press delete -1707 press backspace -1708 press delete -1709 press delete +1704 ¦ type [abcdef] +1705 ¦ left-click 1, 2 +1706 ¦ press delete +1707 ¦ press backspace +1708 ¦ press delete +1709 ¦ press delete 1710 ] 1711 editor-event-loop screen, console, e 1712 screen-should-contain [ -1713 . . -1714 .af . -1715 .╌╌╌╌╌╌╌╌╌╌. -1716 . . +1713 ¦ . . +1714 ¦ .af . +1715 ¦ .╌╌╌╌╌╌╌╌╌╌. +1716 ¦ . . 1717 ] 1718 3:num/raw <- get *e, cursor-row:offset 1719 4:num/raw <- get *e, cursor-column:offset 1720 memory-should-contain [ -1721 3 <- 1 -1722 4 <- 1 +1721 ¦ 3 <- 1 +1722 ¦ 4 <- 1 1723 ] 1724 # undo deletes 1725 assume-console [ -1726 press ctrl-z +1726 ¦ press ctrl-z 1727 ] 1728 run [ -1729 editor-event-loop screen, console, e +1729 ¦ editor-event-loop screen, console, e 1730 ] 1731 3:num/raw <- get *e, cursor-row:offset 1732 4:num/raw <- get *e, cursor-column:offset 1733 memory-should-contain [ -1734 3 <- 1 -1735 4 <- 1 +1734 ¦ 3 <- 1 +1735 ¦ 4 <- 1 1736 ] 1737 screen-should-contain [ -1738 . . -1739 .adef . -1740 .╌╌╌╌╌╌╌╌╌╌. -1741 . . +1738 ¦ . . +1739 ¦ .adef . +1740 ¦ .╌╌╌╌╌╌╌╌╌╌. +1741 ¦ . . 1742 ] 1743 # undo backspace 1744 assume-console [ -1745 press ctrl-z +1745 ¦ press ctrl-z 1746 ] 1747 run [ -1748 editor-event-loop screen, console, e +1748 ¦ editor-event-loop screen, console, e 1749 ] 1750 3:num/raw <- get *e, cursor-row:offset 1751 4:num/raw <- get *e, cursor-column:offset 1752 memory-should-contain [ -1753 3 <- 1 -1754 4 <- 2 +1753 ¦ 3 <- 1 +1754 ¦ 4 <- 2 1755 ] 1756 screen-should-contain [ -1757 . . -1758 .abdef . -1759 .╌╌╌╌╌╌╌╌╌╌. -1760 . . +1757 ¦ . . +1758 ¦ .abdef . +1759 ¦ .╌╌╌╌╌╌╌╌╌╌. +1760 ¦ . . 1761 ] 1762 # undo first delete 1763 assume-console [ -1764 press ctrl-z +1764 ¦ press ctrl-z 1765 ] 1766 run [ -1767 editor-event-loop screen, console, e +1767 ¦ editor-event-loop screen, console, e 1768 ] 1769 3:num/raw <- get *e, cursor-row:offset 1770 4:num/raw <- get *e, cursor-column:offset 1771 memory-should-contain [ -1772 3 <- 1 -1773 4 <- 2 +1772 ¦ 3 <- 1 +1773 ¦ 4 <- 2 1774 ] 1775 screen-should-contain [ -1776 . . -1777 .abcdef . -1778 .╌╌╌╌╌╌╌╌╌╌. -1779 . . +1776 ¦ . . +1777 ¦ .abcdef . +1778 ¦ .╌╌╌╌╌╌╌╌╌╌. +1779 ¦ . . 1780 ] 1781 # redo first delete 1782 assume-console [ -1783 press ctrl-y +1783 ¦ press ctrl-y 1784 ] 1785 run [ -1786 editor-event-loop screen, console, e +1786 ¦ editor-event-loop screen, console, e 1787 ] 1788 # first line inserted 1789 3:num/raw <- get *e, cursor-row:offset 1790 4:num/raw <- get *e, cursor-column:offset 1791 memory-should-contain [ -1792 3 <- 1 -1793 4 <- 2 +1792 ¦ 3 <- 1 +1793 ¦ 4 <- 2 1794 ] 1795 screen-should-contain [ -1796 . . -1797 .abdef . -1798 .╌╌╌╌╌╌╌╌╌╌. -1799 . . +1796 ¦ . . +1797 ¦ .abdef . +1798 ¦ .╌╌╌╌╌╌╌╌╌╌. +1799 ¦ . . 1800 ] 1801 # redo backspace 1802 assume-console [ -1803 press ctrl-y +1803 ¦ press ctrl-y 1804 ] 1805 run [ -1806 editor-event-loop screen, console, e +1806 ¦ editor-event-loop screen, console, e 1807 ] 1808 # first line inserted 1809 3:num/raw <- get *e, cursor-row:offset 1810 4:num/raw <- get *e, cursor-column:offset 1811 memory-should-contain [ -1812 3 <- 1 -1813 4 <- 1 +1812 ¦ 3 <- 1 +1813 ¦ 4 <- 1 1814 ] 1815 screen-should-contain [ -1816 . . -1817 .adef . -1818 .╌╌╌╌╌╌╌╌╌╌. -1819 . . +1816 ¦ . . +1817 ¦ .adef . +1818 ¦ .╌╌╌╌╌╌╌╌╌╌. +1819 ¦ . . 1820 ] 1821 # redo deletes 1822 assume-console [ -1823 press ctrl-y +1823 ¦ press ctrl-y 1824 ] 1825 run [ -1826 editor-event-loop screen, console, e +1826 ¦ editor-event-loop screen, console, e 1827 ] 1828 # first line inserted 1829 3:num/raw <- get *e, cursor-row:offset 1830 4:num/raw <- get *e, cursor-column:offset 1831 memory-should-contain [ -1832 3 <- 1 -1833 4 <- 1 +1832 ¦ 3 <- 1 +1833 ¦ 4 <- 1 1834 ] 1835 screen-should-contain [ -1836 . . -1837 .af . -1838 .╌╌╌╌╌╌╌╌╌╌. -1839 . . +1836 ¦ . . +1837 ¦ .af . +1838 ¦ .╌╌╌╌╌╌╌╌╌╌. +1839 ¦ . . 1840 ] 1841 ] 1842 @@ -1906,38 +1907,38 @@ if ('onhashchange' in window) { 1845 ] 1846 before <delete-character-end> [ 1847 { -1848 break-unless deleted-cell # delete failed; don't add an undo operation -1849 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset -1850 cursor-row:num <- get *editor, cursor-row:offset -1851 cursor-column:num <- get *editor, cursor-column:offset -1852 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset -1853 undo:&:list:&:operation <- get *editor, undo:offset -1854 { -1855 # if previous operation was an insert, coalesce this operation with it -1856 break-unless undo -1857 op:&:operation <- first undo -1858 deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant -1859 break-unless is-delete? -1860 previous-coalesce-tag:num <- get deletion, tag:offset -1861 coalesce?:bool <- equal previous-coalesce-tag, 2/coalesce-delete -1862 break-unless coalesce? -1863 delete-until:&:duplex-list:char <- next before-cursor -1864 deletion <- put deletion, delete-until:offset, delete-until -1865 deleted-so-far:&:duplex-list:char <- get deletion, deleted-text:offset -1866 deleted-so-far <- append deleted-so-far, deleted-cell -1867 deletion <- put deletion, deleted-text:offset, deleted-so-far -1868 deletion <- put deletion, after-row:offset, cursor-row -1869 deletion <- put deletion, after-column:offset, cursor-column -1870 deletion <- put deletion, after-top-of-screen:offset, top-after -1871 *op <- merge 2/delete-operation, deletion -1872 break +done-adding-delete-operation -1873 } -1874 # if not, create a new operation -1875 op:&:operation <- new operation:type -1876 deleted-until:&:duplex-list:char <- next before-cursor -1877 *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cell/deleted, before-cursor/delete-from, deleted-until, 2/coalesce-delete -1878 editor <- add-operation editor, op -1879 +done-adding-delete-operation +1848 ¦ break-unless deleted-cell # delete failed; don't add an undo operation +1849 ¦ top-after:&:duplex-list:char <- get *editor, top-of-screen:offset +1850 ¦ cursor-row:num <- get *editor, cursor-row:offset +1851 ¦ cursor-column:num <- get *editor, cursor-column:offset +1852 ¦ before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset +1853 ¦ undo:&:list:&:operation <- get *editor, undo:offset +1854 ¦ { +1855 ¦ ¦ # if previous operation was an insert, coalesce this operation with it +1856 ¦ ¦ break-unless undo +1857 ¦ ¦ op:&:operation <- first undo +1858 ¦ ¦ deletion:delete-operation, is-delete?:bool <- maybe-convert *op, delete:variant +1859 ¦ ¦ break-unless is-delete? +1860 ¦ ¦ previous-coalesce-tag:num <- get deletion, tag:offset +1861 ¦ ¦ coalesce?:bool <- equal previous-coalesce-tag, 2/coalesce-delete +1862 ¦ ¦ break-unless coalesce? +1863 ¦ ¦ delete-until:&:duplex-list:char <- next before-cursor +1864 ¦ ¦ deletion <- put deletion, delete-until:offset, delete-until +1865 ¦ ¦ deleted-so-far:&:duplex-list:char <- get deletion, deleted-text:offset +1866 ¦ ¦ deleted-so-far <- append deleted-so-far, deleted-cell +1867 ¦ ¦ deletion <- put deletion, deleted-text:offset, deleted-so-far +1868 ¦ ¦ deletion <- put deletion, after-row:offset, cursor-row +1869 ¦ ¦ deletion <- put deletion, after-column:offset, cursor-column +1870 ¦ ¦ deletion <- put deletion, after-top-of-screen:offset, top-after +1871 ¦ ¦ *op <- merge 2/delete-operation, deletion +1872 ¦ ¦ break +done-adding-delete-operation +1873 ¦ } +1874 ¦ # if not, create a new operation +1875 ¦ op:&:operation <- new operation:type +1876 ¦ deleted-until:&:duplex-list:char <- next before-cursor +1877 ¦ *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cell/deleted, before-cursor/delete-from, deleted-until, 2/coalesce-delete +1878 ¦ editor <- add-operation editor, op +1879 ¦ +done-adding-delete-operation 1880 } 1881 ] 1882 @@ -1953,77 +1954,77 @@ if ('onhashchange' in window) { 1892 editor-render screen, e 1893 # insert some text and hit delete and backspace a few times 1894 assume-console [ -1895 left-click 1, 1 -1896 press ctrl-k +1895 ¦ left-click 1, 1 +1896 ¦ press ctrl-k 1897 ] 1898 editor-event-loop screen, console, e 1899 screen-should-contain [ -1900 . . -1901 .a . -1902 .def . -1903 .╌╌╌╌╌╌╌╌╌╌. -1904 . . +1900 ¦ . . +1901 ¦ .a . +1902 ¦ .def . +1903 ¦ .╌╌╌╌╌╌╌╌╌╌. +1904 ¦ . . 1905 ] 1906 3:num/raw <- get *e, cursor-row:offset 1907 4:num/raw <- get *e, cursor-column:offset 1908 memory-should-contain [ -1909 3 <- 1 -1910 4 <- 1 +1909 ¦ 3 <- 1 +1910 ¦ 4 <- 1 1911 ] 1912 # undo 1913 assume-console [ -1914 press ctrl-z +1914 ¦ press ctrl-z 1915 ] 1916 run [ -1917 editor-event-loop screen, console, e +1917 ¦ editor-event-loop screen, console, e 1918 ] 1919 screen-should-contain [ -1920 . . -1921 .abc . -1922 .def . -1923 .╌╌╌╌╌╌╌╌╌╌. -1924 . . +1920 ¦ . . +1921 ¦ .abc . +1922 ¦ .def . +1923 ¦ .╌╌╌╌╌╌╌╌╌╌. +1924 ¦ . . 1925 ] 1926 3:num/raw <- get *e, cursor-row:offset 1927 4:num/raw <- get *e, cursor-column:offset 1928 memory-should-contain [ -1929 3 <- 1 -1930 4 <- 1 +1929 ¦ 3 <- 1 +1930 ¦ 4 <- 1 1931 ] 1932 # redo 1933 assume-console [ -1934 press ctrl-y +1934 ¦ press ctrl-y 1935 ] 1936 run [ -1937 editor-event-loop screen, console, e +1937 ¦ editor-event-loop screen, console, e 1938 ] 1939 # first line inserted 1940 screen-should-contain [ -1941 . . -1942 .a . -1943 .def . -1944 .╌╌╌╌╌╌╌╌╌╌. -1945 . . +1941 ¦ . . +1942 ¦ .a . +1943 ¦ .def . +1944 ¦ .╌╌╌╌╌╌╌╌╌╌. +1945 ¦ . . 1946 ] 1947 3:num/raw <- get *e, cursor-row:offset 1948 4:num/raw <- get *e, cursor-column:offset 1949 memory-should-contain [ -1950 3 <- 1 -1951 4 <- 1 +1950 ¦ 3 <- 1 +1951 ¦ 4 <- 1 1952 ] 1953 # cursor should be in the right place 1954 assume-console [ -1955 type [1] +1955 ¦ type [1] 1956 ] 1957 run [ -1958 editor-event-loop screen, console, e +1958 ¦ editor-event-loop screen, console, e 1959 ] 1960 screen-should-contain [ -1961 . . -1962 .a1 . -1963 .def . -1964 .╌╌╌╌╌╌╌╌╌╌. -1965 . . +1961 ¦ . . +1962 ¦ .a1 . +1963 ¦ .def . +1964 ¦ .╌╌╌╌╌╌╌╌╌╌. +1965 ¦ . . 1966 ] 1967 ] 1968 @@ -2032,15 +2033,15 @@ if ('onhashchange' in window) { 1971 ] 1972 before <delete-to-end-of-line-end> [ 1973 { -1974 break-unless deleted-cells # delete failed; don't add an undo operation -1975 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset -1976 cursor-row:num <- get *editor, cursor-row:offset -1977 cursor-column:num <- get *editor, cursor-column:offset -1978 deleted-until:&:duplex-list:char <- next before-cursor -1979 op:&:operation <- new operation:type -1980 *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cells/deleted, before-cursor/delete-from, deleted-until, 0/never-coalesce -1981 editor <- add-operation editor, op -1982 +done-adding-delete-operation +1974 ¦ break-unless deleted-cells # delete failed; don't add an undo operation +1975 ¦ top-after:&:duplex-list:char <- get *editor, top-of-screen:offset +1976 ¦ cursor-row:num <- get *editor, cursor-row:offset +1977 ¦ cursor-column:num <- get *editor, cursor-column:offset +1978 ¦ deleted-until:&:duplex-list:char <- next before-cursor +1979 ¦ op:&:operation <- new operation:type +1980 ¦ *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cells/deleted, before-cursor/delete-from, deleted-until, 0/never-coalesce +1981 ¦ editor <- add-operation editor, op +1982 ¦ +done-adding-delete-operation 1983 } 1984 ] 1985 @@ -2056,77 +2057,77 @@ if ('onhashchange' in window) { 1995 editor-render screen, e 1996 # insert some text and hit delete and backspace a few times 1997 assume-console [ -1998 left-click 1, 2 -1999 press ctrl-u +1998 ¦ left-click 1, 2 +1999 ¦ press ctrl-u 2000 ] 2001 editor-event-loop screen, console, e 2002 screen-should-contain [ -2003 . . -2004 .c . -2005 .def . -2006 .╌╌╌╌╌╌╌╌╌╌. -2007 . . +2003 ¦ . . +2004 ¦ .c . +2005 ¦ .def . +2006 ¦ .╌╌╌╌╌╌╌╌╌╌. +2007 ¦ . . 2008 ] 2009 3:num/raw <- get *e, cursor-row:offset 2010 4:num/raw <- get *e, cursor-column:offset 2011 memory-should-contain [ -2012 3 <- 1 -2013 4 <- 0 +2012 ¦ 3 <- 1 +2013 ¦ 4 <- 0 2014 ] 2015 # undo 2016 assume-console [ -2017 press ctrl-z +2017 ¦ press ctrl-z 2018 ] 2019 run [ -2020 editor-event-loop screen, console, e +2020 ¦ editor-event-loop screen, console, e 2021 ] 2022 screen-should-contain [ -2023 . . -2024 .abc . -2025 .def . -2026 .╌╌╌╌╌╌╌╌╌╌. -2027 . . +2023 ¦ . . +2024 ¦ .abc . +2025 ¦ .def . +2026 ¦ .╌╌╌╌╌╌╌╌╌╌. +2027 ¦ . . 2028 ] 2029 3:num/raw <- get *e, cursor-row:offset 2030 4:num/raw <- get *e, cursor-column:offset 2031 memory-should-contain [ -2032 3 <- 1 -2033 4 <- 2 +2032 ¦ 3 <- 1 +2033 ¦ 4 <- 2 2034 ] 2035 # redo 2036 assume-console [ -2037 press ctrl-y +2037 ¦ press ctrl-y 2038 ] 2039 run [ -2040 editor-event-loop screen, console, e +2040 ¦ editor-event-loop screen, console, e 2041 ] 2042 # first line inserted 2043 screen-should-contain [ -2044 . . -2045 .c . -2046 .def . -2047 .╌╌╌╌╌╌╌╌╌╌. -2048 . . +2044 ¦ . . +2045 ¦ .c . +2046 ¦ .def . +2047 ¦ .╌╌╌╌╌╌╌╌╌╌. +2048 ¦ . . 2049 ] 2050 3:num/raw <- get *e, cursor-row:offset 2051 4:num/raw <- get *e, cursor-column:offset 2052 memory-should-contain [ -2053 3 <- 1 -2054 4 <- 0 +2053 ¦ 3 <- 1 +2054 ¦ 4 <- 0 2055 ] 2056 # cursor should be in the right place 2057 assume-console [ -2058 type [1] +2058 ¦ type [1] 2059 ] 2060 run [ -2061 editor-event-loop screen, console, e +2061 ¦ editor-event-loop screen, console, e 2062 ] 2063 screen-should-contain [ -2064 . . -2065 .1c . -2066 .def . -2067 .╌╌╌╌╌╌╌╌╌╌. -2068 . . +2064 ¦ . . +2065 ¦ .1c . +2066 ¦ .def . +2067 ¦ .╌╌╌╌╌╌╌╌╌╌. +2068 ¦ . . 2069 ] 2070 ] 2071 @@ -2135,16 +2136,16 @@ if ('onhashchange' in window) { 2074 ] 2075 before <delete-to-start-of-line-end> [ 2076 { -2077 break-unless deleted-cells # delete failed; don't add an undo operation -2078 top-after:&:duplex-list:char <- get *editor, top-of-screen:offset -2079 op:&:operation <- new operation:type -2080 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset -2081 deleted-until:&:duplex-list:char <- next before-cursor -2082 cursor-row:num <- get *editor, cursor-row:offset -2083 cursor-column:num <- get *editor, cursor-column:offset -2084 *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cells/deleted, before-cursor/delete-from, deleted-until, 0/never-coalesce -2085 editor <- add-operation editor, op -2086 +done-adding-delete-operation +2077 ¦ break-unless deleted-cells # delete failed; don't add an undo operation +2078 ¦ top-after:&:duplex-list:char <- get *editor, top-of-screen:offset +2079 ¦ op:&:operation <- new operation:type +2080 ¦ before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset +2081 ¦ deleted-until:&:duplex-list:char <- next before-cursor +2082 ¦ cursor-row:num <- get *editor, cursor-row:offset +2083 ¦ cursor-column:num <- get *editor, cursor-column:offset +2084 ¦ *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, deleted-cells/deleted, before-cursor/delete-from, deleted-until, 0/never-coalesce +2085 ¦ editor <- add-operation editor, op +2086 ¦ +done-adding-delete-operation 2087 } 2088 ] 2089 @@ -2156,16 +2157,16 @@ if ('onhashchange' in window) { 2095 editor-render screen, e 2096 # insert some text and hit delete and backspace a few times 2097 assume-console [ -2098 type [abc] -2099 press ctrl-u -2100 press ctrl-z +2098 ¦ type [abc] +2099 ¦ press ctrl-u +2100 ¦ press ctrl-z 2101 ] 2102 editor-event-loop screen, console, e 2103 screen-should-contain [ -2104 . . -2105 .abc . -2106 .╌╌╌╌╌╌╌╌╌╌. -2107 . . +2104 ¦ . . +2105 ¦ .abc . +2106 ¦ .╌╌╌╌╌╌╌╌╌╌. +2107 ¦ . . 2108 ] 2109 ] -- cgit 1.4.1-2-gfad0