From 32b8fac2799ac7cec613e84a3eb9c009141b6a3a Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 25 Apr 2016 22:27:19 -0700 Subject: 2866 --- html/edit/011-editor-undo.mu.html | 1130 +++++++++++++++++++------------------ 1 file changed, 579 insertions(+), 551 deletions(-) (limited to 'html/edit/011-editor-undo.mu.html') diff --git a/html/edit/011-editor-undo.mu.html b/html/edit/011-editor-undo.mu.html index 99b13730..18d6843a 100644 --- a/html/edit/011-editor-undo.mu.html +++ b/html/edit/011-editor-undo.mu.html @@ -46,13 +46,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color container insert-operation [ before-row:number before-column:number - before-top-of-screen:address:shared:duplex-list:character + before-top-of-screen:address:duplex-list:character after-row:number after-column:number - after-top-of-screen:address:shared:duplex-list:character + after-top-of-screen:address:duplex-list:character # inserted text is from 'insert-from' until 'insert-until'; list doesn't have to terminate - insert-from:address:shared:duplex-list:character - insert-until:address:shared:duplex-list:character + insert-from:address:duplex-list:character + insert-until:address:duplex-list:character tag:number # event causing this operation; might be used to coalesce runs of similar events # 0: no coalesce (enter+indent) # 1: regular alphanumeric characters @@ -61,10 +61,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color container move-operation [ before-row:number before-column:number - before-top-of-screen:address:shared:duplex-list:character + before-top-of-screen:address:duplex-list:character after-row:number after-column:number - after-top-of-screen:address:shared:duplex-list:character + after-top-of-screen:address:duplex-list:character tag:number # event causing this operation; might be used to coalesce runs of similar events # 0: no coalesce (touch events, etc) # 1: left arrow @@ -76,13 +76,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color container delete-operation [ before-row:number before-column:number - before-top-of-screen:address:shared:duplex-list:character + before-top-of-screen:address:duplex-list:character after-row:number after-column:number - after-top-of-screen:address:shared:duplex-list:character - deleted-text:address:shared:duplex-list:character - delete-from:address:shared:duplex-list:character - delete-until:address:shared:duplex-list:character + after-top-of-screen:address:duplex-list:character + deleted-text:address:duplex-list:character + delete-from:address:duplex-list:character + delete-until:address:duplex-list:character tag:number # event causing this operation; might be used to coalesce runs of similar events # 0: no coalesce (ctrl-k, ctrl-u) # 1: backspace @@ -91,21 +91,23 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color # every editor accumulates a list of operations to undo/redo container editor-data [ - undo:address:shared:list:address:shared:operation - redo:address:shared:list:address:shared:operation + undo:address:list:address:operation + redo:address:list:address:operation ] # ctrl-z - undo operation after <handle-special-character> [ { - undo?:boolean <- equal *c, 26/ctrl-z + undo?:boolean <- equal c, 26/ctrl-z break-unless undo? - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset - break-unless *undo - op:address:shared:operation <- first *undo - *undo <- rest *undo - redo:address:address:shared:list:address:shared:operation <- get-address *editor, redo:offset - *redo <- push op, *redo + undo:address:list:address:operation <- get *editor, undo:offset + break-unless undo + op:address:operation <- first undo + undo <- rest undo + *editor <- put *editor, undo:offset, undo + redo:address:list:address:operation <- get *editor, redo:offset + redo <- push op, redo + *editor <- put *editor, redo:offset, redo <handle-undo> return screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render } @@ -114,14 +116,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color # ctrl-y - redo operation after <handle-special-character> [ { - redo?:boolean <- equal *c, 25/ctrl-y + redo?:boolean <- equal c, 25/ctrl-y break-unless redo? - redo:address:address:shared:list:address:shared:operation <- get-address *editor, redo:offset - break-unless *redo - op:address:shared:operation <- first *redo - *redo <- rest *redo - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset - *undo <- push op, *undo + redo:address:list:address:operation <- get *editor, redo:offset + break-unless redo + op:address:operation <- first redo + redo <- rest redo + *editor <- put *editor, redo:offset, redo + undo:address:list:address:operation <- get *editor, undo:offset + undo <- push op, undo + *editor <- put *editor, undo:offset, undo <handle-redo> return screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render } @@ -132,19 +136,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-typing [ # create an editor and type a character assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data assume-console [ type [0] ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # character should be gone screen-should-contain [ @@ -158,7 +162,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -170,53 +174,57 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color # save operation to undo after <insert-character-begin> [ - top-before:address:shared:duplex-list:character <- get *editor, top-of-screen:offset - cursor-before:address:shared:duplex-list:character <- copy *before-cursor + top-before:address:duplex-list:character <- get *editor, top-of-screen:offset + cursor-before:address:duplex-list:character <- get *editor, before-cursor:offset ] before <insert-character-end> [ - top-after:address:shared:duplex-list:character <- get *editor, top-of-screen:offset - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset + top-after:address:duplex-list:character <- get *editor, top-of-screen:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + undo:address:list:address:operation <- get *editor, undo:offset { # if previous operation was an insert, coalesce this operation with it - break-unless *undo - op:address:shared:operation <- first *undo - typing:address:insert-operation <- maybe-convert *op, typing:variant - break-unless typing - previous-coalesce-tag:number <- get *typing, tag:offset + break-unless undo + op:address:operation <- first undo + typing:insert-operation, is-insert?:boolean <- maybe-convert *op, typing:variant + break-unless is-insert? + previous-coalesce-tag:number <- get typing, tag:offset break-unless previous-coalesce-tag - insert-until:address:address:shared:duplex-list:character <- get-address *typing, insert-until:offset - *insert-until <- next *before-cursor - after-row:address:number <- get-address *typing, after-row:offset - *after-row <- copy *cursor-row - after-column:address:number <- get-address *typing, after-column:offset - *after-column <- copy *cursor-column - after-top:address:address:shared:duplex-list:character <- get-address *typing, after-top-of-screen:offset - *after-top <- get *editor, top-of-screen:offset + before-cursor:address:duplex-list:character <- get *editor, before-cursor:offset + insert-until:address:duplex-list:character <- next before-cursor + typing <- put typing, insert-until:offset, insert-until + typing <- put typing, after-row:offset, cursor-row + typing <- put typing, after-column:offset, cursor-column + typing <- put typing, after-top-of-screen:offset, top-after + *op <- merge 0/insert-operation, typing break +done-adding-insert-operation:label } # if not, create a new operation - insert-from:address:shared:duplex-list:character <- next cursor-before - insert-to:address:shared:duplex-list:character <- next insert-from - op:address:shared:operation <- new operation:type - *op <- merge 0/insert-operation, save-row/before, save-column/before, top-before, *cursor-row/after, *cursor-column/after, top-after, insert-from, insert-to, 1/coalesce + insert-from:address:duplex-list:character <- next cursor-before + insert-to:address:duplex-list:character <- next insert-from + op:address:operation <- new operation:type + *op <- merge 0/insert-operation, save-row/before, save-column/before, top-before, cursor-row/after, cursor-column/after, top-after, insert-from, insert-to, 1/coalesce editor <- add-operation editor, op +done-adding-insert-operation ] # enter operations never coalesce with typing before or after after <insert-enter-begin> [ - cursor-row-before:number <- copy *cursor-row - cursor-column-before:number <- copy *cursor-column - top-before:address:shared:duplex-list:character <- get *editor, top-of-screen:offset - cursor-before:address:shared:duplex-list:character <- copy *before-cursor + cursor-row-before:number <- copy cursor-row + cursor-column-before:number <- copy cursor-column + top-before:address:duplex-list:character <- get *editor, top-of-screen:offset + cursor-before:address:duplex-list:character <- get *editor, before-cursor:offset ] before <insert-enter-end> [ - top-after:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + top-after:address:duplex-list:character <- get *editor, top-of-screen:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-row:offset # never coalesce - insert-from:address:shared:duplex-list:character <- next cursor-before - insert-to:address:shared:duplex-list:character <- next *before-cursor - op:address:shared:operation <- new operation:type - *op <- merge 0/insert-operation, cursor-row-before, cursor-column-before, top-before, *cursor-row/after, *cursor-column/after, top-after, insert-from, insert-to, 0/never-coalesce + insert-from:address:duplex-list:character <- next cursor-before + before-cursor:address:duplex-list:character <- get *editor, before-cursor:offset + insert-to:address:duplex-list:character <- next before-cursor + op:address:operation <- new operation:type + *op <- merge 0/insert-operation, cursor-row-before, cursor-column-before, top-before, cursor-row/after, cursor-column/after, top-after, insert-from, insert-to, 0/never-coalesce editor <- add-operation editor, op ] @@ -224,48 +232,53 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color # redo stack, because it's now obsolete. # Beware: since we're counting cursor moves as operations, this means just # moving the cursor can lose work on the undo stack. -def add-operation editor:address:shared:editor-data, op:address:shared:operation -> editor:address:shared:editor-data [ +def add-operation editor:address:editor-data, op:address:operation -> editor:address:editor-data [ local-scope load-ingredients - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset - *undo <- push op *undo - redo:address:address:shared:list:address:shared:operation <- get-address *editor, redo:offset - *redo <- copy 0 + undo:address:list:address:operation <- get *editor, undo:offset + undo <- push op undo + *editor <- put *editor, undo:offset, undo + redo:address:list:address:operation <- get *editor, redo:offset + redo <- copy 0 + *editor <- put *editor, redo:offset, redo return editor/same-as-ingredient:0 ] after <handle-undo> [ { - typing:address:insert-operation <- maybe-convert *op, typing:variant - break-unless typing - start:address:shared:duplex-list:character <- get *typing, insert-from:offset - end:address:shared:duplex-list:character <- get *typing, insert-until:offset + typing:insert-operation, is-insert?:boolean <- maybe-convert *op, typing:variant + break-unless is-insert? + start:address:duplex-list:character <- get typing, insert-from:offset + end:address:duplex-list:character <- get typing, insert-until:offset # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - *before-cursor <- prev start - remove-between *before-cursor, end - *cursor-row <- get *typing, before-row:offset - *cursor-column <- get *typing, before-column:offset - top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - *top <- get *typing, before-top-of-screen:offset + before-cursor:address:duplex-list:character <- prev start + *editor <- put *editor, before-cursor:offset, before-cursor + remove-between before-cursor, end + cursor-row <- get typing, before-row:offset + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- get typing, before-column:offset + *editor <- put *editor, cursor-column:offset, cursor-column + top:address:duplex-list:character <- get typing, before-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] scenario editor-can-undo-typing-multiple [ # create an editor and type multiple characters assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data assume-console [ type [012] ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # all characters must be gone screen-should-contain [ @@ -279,14 +292,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-typing-multiple-2 [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [a] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [a] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # type some characters assume-console [ type [012] ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . .012a . @@ -298,7 +311,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # back to original text screen-should-contain [ @@ -312,7 +325,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [3] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -325,15 +338,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-typing-enter [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [ abc] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [ abc] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # new line assume-console [ left-click 1, 8 press enter ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . . abc . @@ -342,8 +355,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color . . ] # line is indented - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 2 4 <- 2 @@ -353,10 +366,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 5 @@ -373,7 +386,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -388,14 +401,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-redo-typing [ # create an editor, type something, undo assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [a] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [a] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data assume-console [ type [012] press ctrl-z ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . .a . @@ -407,7 +420,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # all characters must be back screen-should-contain [ @@ -421,7 +434,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [3] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -433,30 +446,33 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color after <handle-redo> [ { - typing:address:insert-operation <- maybe-convert *op, typing:variant - break-unless typing - insert-from:address:shared:duplex-list:character <- get *typing, insert-from:offset # ignore insert-to because it's already been spliced away - # assert insert-to matches next(*before-cursor) - insert-range *before-cursor, insert-from + typing:insert-operation, is-insert?:boolean <- maybe-convert *op, typing:variant + break-unless is-insert? + before-cursor <- get *editor, before-cursor:offset + insert-from:address:duplex-list:character <- get typing, insert-from:offset # ignore insert-to because it's already been spliced away + # assert insert-to matches next(before-cursor) + insert-range before-cursor, insert-from # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - *cursor-row <- get *typing, after-row:offset - *cursor-column <- get *typing, after-column:offset - top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - *top <- get *typing, after-top-of-screen:offset + cursor-row <- get typing, after-row:offset + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- get typing, after-column:offset + *editor <- put *editor, cursor-column:offset, cursor-column + top:address:duplex-list:character <- get typing, after-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] scenario editor-redo-typing-empty [ # create an editor, type something, undo assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data assume-console [ type [012] press ctrl-z ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . . . @@ -468,7 +484,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # all characters must be back screen-should-contain [ @@ -482,7 +498,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [3] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -495,21 +511,21 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-work-clears-redo-stack [ # create an editor with some text, do some work, undo assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data assume-console [ type [1] press ctrl-z ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # do some more work assume-console [ type [0] ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . .0abc . @@ -522,7 +538,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # nothing should happen screen-should-contain [ @@ -537,9 +553,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-redo-typing-and-enter-and-tab [ # create an editor assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # insert some text and tabs, hit enter, some more text and tabs assume-console [ press tab @@ -550,7 +566,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press tab type [efg] ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . . ab cd . @@ -558,8 +574,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 2 4 <- 7 @@ -569,11 +585,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # typing in second line deleted, but not indent - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 2 4 <- 2 @@ -590,11 +606,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # indent and newline deleted - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 8 @@ -610,11 +626,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # empty screen - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 0 @@ -630,11 +646,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # first line inserted - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 8 @@ -650,11 +666,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # newline and indent inserted - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 2 4 <- 2 @@ -671,11 +687,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # indent and newline deleted - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 2 4 <- 7 @@ -694,24 +710,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-touch [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # move the cursor assume-console [ left-click 3, 1 ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # click undone memory-should-contain [ @@ -723,7 +739,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -735,49 +751,49 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] after <move-cursor-begin> [ - before-cursor-row:number <- get *editor, cursor-row:offset - before-cursor-column:number <- get *editor, cursor-column:offset - before-top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + cursor-row-before:number <- get *editor, cursor-row:offset + cursor-column-before:number <- get *editor, cursor-column:offset + top-before:address:duplex-list:character <- get *editor, top-of-screen:offset ] before <move-cursor-end> [ - after-cursor-row:number <- get *editor, cursor-row:offset - after-cursor-column:number <- get *editor, cursor-column:offset - after-top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + top-after:address:duplex-list:character <- get *editor, top-of-screen:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset { break-unless undo-coalesce-tag # if previous operation was also a move, and also had the same coalesce # tag, coalesce with it - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset - break-unless *undo - op:address:shared:operation <- first *undo - move:address:move-operation <- maybe-convert *op, move:variant - break-unless move - previous-coalesce-tag:number <- get *move, tag:offset + undo:address:list:address:operation <- get *editor, undo:offset + break-unless undo + op:address:operation <- first undo + move:move-operation, is-move?:boolean <- maybe-convert *op, move:variant + break-unless is-move? + previous-coalesce-tag:number <- get move, tag:offset coalesce?:boolean <- equal undo-coalesce-tag, previous-coalesce-tag break-unless coalesce? - after-row:address:number <- get-address *move, after-row:offset - *after-row <- copy after-cursor-row - after-column:address:number <- get-address *move, after-column:offset - *after-column <- copy after-cursor-column - after-top:address:address:shared:duplex-list:character <- get-address *move, after-top-of-screen:offset - *after-top <- get *editor, top-of-screen:offset + move <- put move, after-row:offset, cursor-row + move <- put move, after-column:offset, cursor-column + move <- put move, after-top-of-screen:offset, top-after + *op <- merge 1/move-operation, move break +done-adding-move-operation:label } - op:address:shared:operation <- new operation:type - *op <- merge 1/move-operation, before-cursor-row, before-cursor-column, before-top-of-screen, after-cursor-row, after-cursor-column, after-top-of-screen, undo-coalesce-tag + op:address:operation <- new operation:type + *op <- merge 1/move-operation, cursor-row-before, cursor-column-before, top-before, cursor-row/after, cursor-column/after, top-after, undo-coalesce-tag editor <- add-operation editor, op +done-adding-move-operation ] after <handle-undo> [ { - move:address:move-operation <- maybe-convert *op, move:variant - break-unless move + move:move-operation, is-move?:boolean <- maybe-convert *op, move:variant + break-unless is-move? # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - *cursor-row <- get *move, before-row:offset - *cursor-column <- get *move, before-column:offset - *top <- get *move, before-top-of-screen:offset + cursor-row <- get move, before-row:offset + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- get move, before-column:offset + *editor <- put *editor, cursor-column:offset, cursor-column + top:address:duplex-list:character <- get move, before-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] @@ -785,18 +801,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color # screen has 1 line for menu + 3 lines assume-screen 5/width, 4/height # editor contains a wrapped line - 1:address:shared:array:character <- new [a + 1:address:array:character <- new [a b cdefgh] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right # position cursor at end of screen and try to move right assume-console [ left-click 3, 3 press right-arrow ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset # screen scrolls screen-should-contain [ . . @@ -813,9 +829,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moved back memory-should-contain [ @@ -834,7 +850,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -847,25 +863,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-left-arrow [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # move the cursor assume-console [ left-click 3, 1 press left-arrow ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moves back memory-should-contain [ @@ -877,7 +893,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -891,19 +907,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-up-arrow [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # move the cursor assume-console [ left-click 3, 1 press up-arrow ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 2 4 <- 1 @@ -913,9 +929,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moves back memory-should-contain [ @@ -927,7 +943,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -941,25 +957,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-down-arrow [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # move the cursor assume-console [ left-click 2, 1 press down-arrow ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moves back memory-should-contain [ @@ -971,7 +987,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -985,27 +1001,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-ctrl-f [ # create an editor with multiple pages of text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [a + 1:address:array:character <- new [a b c d e f] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # scroll the page assume-console [ press ctrl-f ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # screen should again show page 1 screen-should-contain [ @@ -1020,27 +1036,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-page-down [ # create an editor with multiple pages of text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [a + 1:address:array:character <- new [a b c d e f] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # scroll the page assume-console [ press page-down ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # screen should again show page 1 screen-should-contain [ @@ -1055,28 +1071,28 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-ctrl-b [ # create an editor with multiple pages of text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [a + 1:address:array:character <- new [a b c d e f] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # scroll the page down and up assume-console [ press page-down press ctrl-b ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # screen should again show page 2 screen-should-contain [ @@ -1091,28 +1107,28 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-page-up [ # create an editor with multiple pages of text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [a + 1:address:array:character <- new [a b c d e f] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # scroll the page down and up assume-console [ press page-down press page-up ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # screen should again show page 2 screen-should-contain [ @@ -1127,25 +1143,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-ctrl-a [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # move the cursor, then to start of line assume-console [ left-click 2, 1 press ctrl-a ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moves back memory-should-contain [ @@ -1157,7 +1173,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -1171,25 +1187,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-home [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # move the cursor, then to start of line assume-console [ left-click 2, 1 press home ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moves back memory-should-contain [ @@ -1201,7 +1217,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -1215,25 +1231,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-ctrl-e [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # move the cursor, then to start of line assume-console [ left-click 2, 1 press ctrl-e ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moves back memory-should-contain [ @@ -1245,7 +1261,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -1259,25 +1275,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-end [ # create an editor with some text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # move the cursor, then to start of line assume-console [ left-click 2, 1 press end ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data # undo assume-console [ press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moves back memory-should-contain [ @@ -1289,7 +1305,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -1300,20 +1316,131 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] +scenario editor-can-undo-multiple-arrows-in-the-same-direction [ + # create an editor with some text + assume-screen 10/width, 5/height + 1:address:array:character <- new [abc +def +ghi] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data + # move the cursor + assume-console [ + left-click 2, 1 + press right-arrow + press right-arrow + press up-arrow + ] + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset + memory-should-contain [ + 3 <- 1 + 4 <- 3 + ] + # undo + assume-console [ + press ctrl-z + ] + run [ + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset + ] + # up-arrow is undone + memory-should-contain [ + 3 <- 2 + 4 <- 3 + ] + # undo again + assume-console [ + press ctrl-z + ] + run [ + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset + ] + # both right-arrows are undone + memory-should-contain [ + 3 <- 2 + 4 <- 1 + ] +] + +# redo cursor movement and scroll + +scenario editor-redo-touch [ + # create an editor with some text, click on a character, undo + assume-screen 10/width, 5/height + 1:address:array:character <- new [abc +def +ghi] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data + assume-console [ + left-click 3, 1 + press ctrl-z + ] + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + # redo + assume-console [ + press ctrl-y + ] + run [ + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset + ] + # cursor moves to left-click + memory-should-contain [ + 3 <- 3 + 4 <- 1 + ] + # cursor should be in the right place + assume-console [ + type [1] + ] + run [ + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + ] + screen-should-contain [ + . . + .abc . + .def . + .g1hi . + .┈┈┈┈┈┈┈┈┈┈. + ] +] + +after <handle-redo> [ + { + move:move-operation, is-move?:boolean <- maybe-convert *op, move:variant + break-unless is-move? + # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen + cursor-row <- get move, after-row:offset + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- get move, after-column:offset + *editor <- put *editor, cursor-column:offset, cursor-column + top:address:duplex-list:character <- get move, after-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top + } +] + scenario editor-separates-undo-insert-from-undo-cursor-move [ # create an editor, type some text, move the cursor, type some more text assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data assume-console [ type [abc] left-click 1, 1 type [d] ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset screen-should-contain [ . . .adbc . @@ -1329,9 +1456,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # last letter typed is deleted screen-should-contain [ @@ -1349,9 +1476,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # no change to screen; cursor moves screen-should-contain [ @@ -1369,9 +1496,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # screen empty screen-should-contain [ @@ -1389,9 +1516,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # first insert screen-should-contain [ @@ -1409,9 +1536,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # cursor moves screen-should-contain [ @@ -1420,6 +1547,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .┈┈┈┈┈┈┈┈┈┈. . . ] + # cursor moves memory-should-contain [ 3 <- 1 4 <- 1 @@ -1429,9 +1557,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset ] # second insert screen-should-contain [ @@ -1446,138 +1574,29 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -scenario editor-can-undo-multiple-arrows-in-the-same-direction [ - # create an editor with some text - assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc -def -ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data - # move the cursor - assume-console [ - left-click 2, 1 - press right-arrow - press right-arrow - press up-arrow - ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset - memory-should-contain [ - 3 <- 1 - 4 <- 3 - ] - # undo - assume-console [ - press ctrl-z - ] - run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset - ] - # up-arrow is undone - memory-should-contain [ - 3 <- 2 - 4 <- 3 - ] - # undo again - assume-console [ - press ctrl-z - ] - run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset - ] - # both right-arrows are undone - memory-should-contain [ - 3 <- 2 - 4 <- 1 - ] -] - -# redo cursor movement and scroll - -scenario editor-redo-touch [ - # create an editor with some text, click on a character, undo - assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc -def -ghi] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data - assume-console [ - left-click 3, 1 - press ctrl-z - ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - # redo - assume-console [ - press ctrl-y - ] - run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset - ] - # cursor moves to left-click - memory-should-contain [ - 3 <- 3 - 4 <- 1 - ] - # cursor should be in the right place - assume-console [ - type [1] - ] - run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data - ] - screen-should-contain [ - . . - .abc . - .def . - .g1hi . - .┈┈┈┈┈┈┈┈┈┈. - ] -] - -after <handle-redo> [ - { - move:address:move-operation <- maybe-convert *op, move:variant - break-unless move - # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - *cursor-row <- get *move, after-row:offset - *cursor-column <- get *move, after-column:offset - top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - *top <- get *move, after-top-of-screen:offset - } -] - # undo backspace scenario editor-can-undo-and-redo-backspace [ # create an editor assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # insert some text and hit backspace assume-console [ type [abc] press backspace press backspace ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . .a . .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1587,10 +1606,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 3 @@ -1606,10 +1625,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1624,39 +1643,39 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color # save operation to undo after <backspace-character-begin> [ - top-before:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + top-before:address:duplex-list:character <- get *editor, top-of-screen:offset ] before <backspace-character-end> [ { break-unless backspaced-cell # backspace failed; don't add an undo operation - top-after:address:shared:duplex-list:character <- get *editor, top-of-screen:offset - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset + top-after:address:duplex-list:character <- get *editor, top-of-screen:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-row:offset + before-cursor:address:duplex-list:character <- get *editor, before-cursor:offset + undo:address:list:address:operation <- get *editor, undo:offset { # if previous operation was an insert, coalesce this operation with it break-unless *undo - op:address:shared:operation <- first *undo - deletion:address:delete-operation <- maybe-convert *op, delete:variant - break-unless deletion - previous-coalesce-tag:number <- get *deletion, tag:offset + op:address:operation <- first undo + deletion:delete-operation, is-delete?:boolean <- maybe-convert *op, delete:variant + break-unless is-delete? + previous-coalesce-tag:number <- get deletion, tag:offset coalesce?:boolean <- equal previous-coalesce-tag, 1/coalesce-backspace break-unless coalesce? - delete-from:address:address:shared:duplex-list:character <- get-address *deletion, delete-from:offset - *delete-from <- copy *before-cursor - backspaced-so-far:address:address:shared:duplex-list:character <- get-address *deletion, deleted-text:offset - insert-range backspaced-cell, *backspaced-so-far - *backspaced-so-far <- copy backspaced-cell - after-row:address:number <- get-address *deletion, after-row:offset - *after-row <- copy *cursor-row - after-column:address:number <- get-address *deletion, after-column:offset - *after-column <- copy *cursor-column - after-top:address:address:shared:duplex-list:character <- get-address *deletion, after-top-of-screen:offset - *after-top <- get *editor, top-of-screen:offset + deletion <- put deletion, delete-from:offset, before-cursor + backspaced-so-far:address:duplex-list:character <- get deletion, deleted-text:offset + insert-range backspaced-cell, backspaced-so-far + deletion <- put deletion, deleted-text:offset, backspaced-cell + deletion <- put deletion, after-row:offset, cursor-row + deletion <- put deletion, after-column:offset, cursor-column + deletion <- put deletion, after-top-of-screen:offset, top-after + *op <- merge 2/delete-operation, deletion break +done-adding-backspace-operation:label } # if not, create a new operation - op:address:shared:operation <- new operation:type - deleted-until:address:shared:duplex-list:character <- next *before-cursor - *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 + op:address:operation <- new operation:type + deleted-until:address:duplex-list:character <- next before-cursor + *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 editor <- add-operation editor, op +done-adding-backspace-operation } @@ -1664,35 +1683,39 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color after <handle-undo> [ { - deletion:address:delete-operation <- maybe-convert *op, delete:variant - break-unless deletion - start2:address:address:shared:duplex-list:character <- get-address *editor, data:offset - anchor:address:shared:duplex-list:character <- get *deletion, delete-from:offset + deletion:delete-operation, is-delete?:boolean <- maybe-convert *op, delete:variant + break-unless is-delete? + anchor:address:duplex-list:character <- get deletion, delete-from:offset break-unless anchor - deleted:address:shared:duplex-list:character <- get *deletion, deleted-text:offset - old-cursor:address:shared:duplex-list:character <- last deleted + deleted:address:duplex-list:character <- get deletion, deleted-text:offset + old-cursor:address:duplex-list:character <- last deleted insert-range anchor, deleted # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - *before-cursor <- copy old-cursor - *cursor-row <- get *deletion, before-row:offset - *cursor-column <- get *deletion, before-column:offset - top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - *top <- get *deletion, before-top-of-screen:offset + before-cursor <- copy old-cursor + cursor-row <- get deletion, before-row:offset + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- get deletion, before-column:offset + *editor <- put *editor, cursor-column:offset, cursor-column + top:address:duplex-list:character <- get deletion, before-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] after <handle-redo> [ { - deletion:address:delete-operation <- maybe-convert *op, delete:variant - break-unless deletion - start:address:shared:duplex-list:character <- get *deletion, delete-from:offset - end:address:shared:duplex-list:character <- get *deletion, delete-until:offset + deletion:delete-operation, is-delete?:boolean <- maybe-convert *op, delete:variant + break-unless is-delete? + start:address:duplex-list:character <- get deletion, delete-from:offset + end:address:duplex-list:character <- get deletion, delete-until:offset + data:address:duplex-list:character <- get *editor, data:offset remove-between start, end # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - *cursor-row <- get *deletion, after-row:offset - *cursor-column <- get *deletion, after-column:offset - top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - *top <- get *deletion, after-top-of-screen:offset + cursor-row <- get deletion, after-row:offset + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- get deletion, after-column:offset + *editor <- put *editor, cursor-column:offset, cursor-column + top:address:duplex-list:character <- get deletion, before-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] @@ -1701,9 +1724,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-and-redo-delete [ # create an editor assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # insert some text and hit delete and backspace a few times assume-console [ type [abcdef] @@ -1713,15 +1736,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press delete press delete ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . .af . .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1731,10 +1754,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1750,10 +1773,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 2 @@ -1769,10 +1792,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 2 @@ -1788,11 +1811,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # first line inserted - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 2 @@ -1808,11 +1831,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # first line inserted - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1828,11 +1851,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # first line inserted - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1846,38 +1869,40 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] after <delete-character-begin> [ - top-before:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + top-before:address:duplex-list:character <- get *editor, top-of-screen:offset ] before <delete-character-end> [ { break-unless deleted-cell # delete failed; don't add an undo operation - top-after:address:shared:duplex-list:character <- get *editor, top-of-screen:offset - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset + top-after:address:duplex-list:character <- get *editor, top-of-screen:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + before-cursor:address:duplex-list:character <- get *editor, before-cursor:offset + undo:address:list:address:operation <- get *editor, undo:offset { # if previous operation was an insert, coalesce this operation with it - break-unless *undo - op:address:shared:operation <- first *undo - deletion:address:delete-operation <- maybe-convert *op, delete:variant - break-unless deletion - previous-coalesce-tag:number <- get *deletion, tag:offset + break-unless undo + op:address:operation <- first undo + deletion:delete-operation, is-delete?:boolean <- maybe-convert *op, delete:variant + break-unless is-delete? + previous-coalesce-tag:number <- get deletion, tag:offset coalesce?:boolean <- equal previous-coalesce-tag, 2/coalesce-delete break-unless coalesce? - delete-until:address:address:shared:duplex-list:character <- get-address *deletion, delete-until:offset - *delete-until <- next *before-cursor - deleted-so-far:address:address:shared:duplex-list:character <- get-address *deletion, deleted-text:offset - *deleted-so-far <- append *deleted-so-far, deleted-cell - after-row:address:number <- get-address *deletion, after-row:offset - *after-row <- copy *cursor-row - after-column:address:number <- get-address *deletion, after-column:offset - *after-column <- copy *cursor-column - after-top:address:address:shared:duplex-list:character <- get-address *deletion, after-top-of-screen:offset - *after-top <- get *editor, top-of-screen:offset + delete-until:address:duplex-list:character <- next before-cursor + deletion <- put deletion, delete-until:offset, delete-until + deleted-so-far:address:duplex-list:character <- get deletion, deleted-text:offset + deleted-so-far <- append deleted-so-far, deleted-cell + deletion <- put deletion, deleted-text:offset, deleted-so-far + deletion <- put deletion, after-row:offset, cursor-row + deletion <- put deletion, after-column:offset, cursor-column + deletion <- put deletion, after-top-of-screen:offset, top-after + *op <- merge 2/delete-operation, deletion break +done-adding-delete-operation:label } # if not, create a new operation - op:address:shared:operation <- new operation:type - deleted-until:address:shared:duplex-list:character <- next *before-cursor - *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 + op:address:operation <- new operation:type + deleted-until:address:duplex-list:character <- next before-cursor + *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 editor <- add-operation editor, op +done-adding-delete-operation } @@ -1888,16 +1913,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-and-redo-ctrl-k [ # create an editor assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # insert some text and hit delete and backspace a few times assume-console [ left-click 1, 1 press ctrl-k ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . .a . @@ -1905,8 +1930,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1916,7 +1941,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -1925,8 +1950,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1936,7 +1961,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # first line inserted screen-should-contain [ @@ -1946,8 +1971,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 1 @@ -1957,7 +1982,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -1969,16 +1994,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] after <delete-to-end-of-line-begin> [ - top-before:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + top-before:address:duplex-list:character <- get *editor, top-of-screen:offset ] before <delete-to-end-of-line-end> [ { break-unless deleted-cells # delete failed; don't add an undo operation - top-after:address:shared:duplex-list:character <- get *editor, top-of-screen:offset - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset - op:address:shared:operation <- new operation:type - deleted-until:address:shared:duplex-list:character <- next *before-cursor - *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 + top-after:address:duplex-list:character <- get *editor, top-of-screen:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + deleted-until:address:duplex-list:character <- next before-cursor + op:address:operation <- new operation:type + *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 editor <- add-operation editor, op +done-adding-delete-operation } @@ -1989,16 +2015,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-and-redo-ctrl-u [ # create an editor assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [abc + 1:address:array:character <- new [abc def] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # insert some text and hit delete and backspace a few times assume-console [ left-click 1, 2 press ctrl-u ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . .c . @@ -2006,8 +2032,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 0 @@ -2017,7 +2043,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-z ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -2026,8 +2052,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 2 @@ -2037,7 +2063,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press ctrl-y ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] # first line inserted screen-should-contain [ @@ -2047,8 +2073,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .┈┈┈┈┈┈┈┈┈┈. . . ] - 3:number <- get *2:address:shared:editor-data, cursor-row:offset - 4:number <- get *2:address:shared:editor-data, cursor-column:offset + 3:number <- get *2:address:editor-data, cursor-row:offset + 4:number <- get *2:address:editor-data, cursor-column:offset memory-should-contain [ 3 <- 1 4 <- 0 @@ -2058,7 +2084,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data ] screen-should-contain [ . . @@ -2070,16 +2096,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] after <delete-to-start-of-line-begin> [ - top-before:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + top-before:address:duplex-list:character <- get *editor, top-of-screen:offset ] before <delete-to-start-of-line-end> [ { break-unless deleted-cells # delete failed; don't add an undo operation - top-after:address:shared:duplex-list:character <- get *editor, top-of-screen:offset - undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset - op:address:shared:operation <- new operation:type - deleted-until:address:shared:duplex-list:character <- next *before-cursor - *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 + top-after:address:duplex-list:character <- get *editor, top-of-screen:offset + op:address:operation <- new operation:type + before-cursor:address:duplex-list:character <- get *editor, before-cursor:offset + deleted-until:address:duplex-list:character <- next before-cursor + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + *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 editor <- add-operation editor, op +done-adding-delete-operation } @@ -2088,16 +2116,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color scenario editor-can-undo-and-redo-ctrl-u-2 [ # create an editor assume-screen 10/width, 5/height - 1:address:shared:array:character <- new [] - 2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right - editor-render screen, 2:address:shared:editor-data + 1:address:array:character <- new [] + 2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right + editor-render screen, 2:address:editor-data # insert some text and hit delete and backspace a few times assume-console [ type [abc] press ctrl-u press ctrl-z ] - editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data + editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data screen-should-contain [ . . .abc . -- cgit 1.4.1-2-gfad0