From d31037ffdcdb8097b91af121a27ef18c15f7e802 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 22 Apr 2016 22:53:39 -0700 Subject: 2854 - purge get-address from sandbox/ app --- sandbox/001-editor.mu | 69 +++-- sandbox/002-typing.mu | 121 +++++---- sandbox/003-shortcuts.mu | 261 ++++++++++-------- sandbox/004-programming-environment.mu | 14 +- sandbox/005-sandbox.mu | 75 +++--- sandbox/006-sandbox-edit.mu | 48 ++-- sandbox/007-sandbox-delete.mu | 51 ++-- sandbox/008-sandbox-test.mu | 25 +- sandbox/009-sandbox-trace.mu | 13 +- sandbox/010-errors.mu | 90 ++----- sandbox/011-editor-undo.mu | 466 +++++++++++++++++---------------- 11 files changed, 644 insertions(+), 589 deletions(-) (limited to 'sandbox') diff --git a/sandbox/001-editor.mu b/sandbox/001-editor.mu index 818f3520..614608c2 100644 --- a/sandbox/001-editor.mu +++ b/sandbox/001-editor.mu @@ -55,25 +55,17 @@ def new-editor s:address:shared:array:character, screen:address:shared:screen, l right <- subtract right, 1 result <- new editor-data:type # initialize screen-related fields - x:address:number <- get-address *result, left:offset - *x <- copy left - x <- get-address *result, right:offset - *x <- copy right - # initialize cursor - x <- get-address *result, cursor-row:offset - *x <- copy 1/top - x <- get-address *result, cursor-column:offset - *x <- copy left - init:address:address:shared:duplex-list:character <- get-address *result, data:offset - *init <- push 167/§, 0/tail - top-of-screen:address:address:shared:duplex-list:character <- get-address *result, top-of-screen:offset - *top-of-screen <- copy *init - y:address:address:shared:duplex-list:character <- get-address *result, before-cursor:offset - *y <- copy *init + *result <- put *result, left:offset, left + *result <- put *result, right:offset, right + # initialize cursor coordinates + *result <- put *result, cursor-row:offset, 1/top + *result <- put *result, cursor-column:offset, left + # initialize empty contents + init:address:shared:duplex-list:character <- push 167/§, 0/tail + *result <- put *result, data:offset, init + *result <- put *result, top-of-screen:offset, init + *result <- put *result, before-cursor:offset, init result <- insert-text result, s - # initialize cursor to top of screen - y <- get-address *result, before-cursor:offset - *y <- copy *init # initial render to screen, just for some old tests _, _, screen, result <- render screen, result @@ -145,9 +137,9 @@ def render screen:address:shared:screen, editor:address:shared:editor-data -> la color:number <- copy 7/white row:number <- copy 1/top column:number <- copy left - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset screen <- move-cursor screen, row, column { +next-character @@ -158,11 +150,11 @@ def render screen:address:shared:screen, editor:address:shared:editor-data -> la # Doing so at the start of each iteration ensures it stays one step behind # the current character. { - at-cursor-row?:boolean <- equal row, *cursor-row + at-cursor-row?:boolean <- equal row, cursor-row break-unless at-cursor-row? - at-cursor?:boolean <- equal column, *cursor-column + at-cursor?:boolean <- equal column, cursor-column break-unless at-cursor? - *before-cursor <- copy prev + before-cursor <- copy prev } c:character <- get *curr, value:offset @@ -172,12 +164,12 @@ def render screen:address:shared:screen, editor:address:shared:editor-data -> la break-unless newline? # adjust cursor if necessary { - at-cursor-row?:boolean <- equal row, *cursor-row + at-cursor-row?:boolean <- equal row, cursor-row break-unless at-cursor-row? - left-of-cursor?:boolean <- lesser-than column, *cursor-column + left-of-cursor?:boolean <- lesser-than column, cursor-column break-unless left-of-cursor? - *cursor-column <- copy column - *before-cursor <- prev curr + cursor-column <- copy column + before-cursor <- prev curr } # clear rest of line in this window clear-line-delimited screen, column, right @@ -210,22 +202,23 @@ def render screen:address:shared:screen, editor:address:shared:editor-data -> la loop } # save first character off-screen - bottom-of-screen:address:address:shared:duplex-list:character <- get-address *editor, bottom-of-screen:offset - *bottom-of-screen <- copy curr + *editor <- put *editor, bottom-of-screen:offset, curr # is cursor to the right of the last line? move to end { - at-cursor-row?:boolean <- equal row, *cursor-row - cursor-outside-line?:boolean <- lesser-or-equal column, *cursor-column + at-cursor-row?:boolean <- equal row, cursor-row + cursor-outside-line?:boolean <- lesser-or-equal column, cursor-column before-cursor-on-same-line?:boolean <- and at-cursor-row?, cursor-outside-line? - above-cursor-row?:boolean <- lesser-than row, *cursor-row + above-cursor-row?:boolean <- lesser-than row, cursor-row before-cursor?:boolean <- or before-cursor-on-same-line?, above-cursor-row? break-unless before-cursor? - *cursor-row <- copy row - *cursor-column <- copy column - *before-cursor <- copy prev + cursor-row <- copy row + cursor-column <- copy column + before-cursor <- copy prev } - bottom:address:number <- get-address *editor, bottom:offset - *bottom <- copy row + *editor <- put *editor, bottom:offset, row + *editor <- put *editor, cursor-row:offset, cursor-row + *editor <- put *editor, cursor-column:offset, cursor-column + *editor <- put *editor, before-cursor:offset, before-cursor return row, column, screen/same-as-ingredient:0, editor/same-as-ingredient:1 ] diff --git a/sandbox/002-typing.mu b/sandbox/002-typing.mu index 7a68bb64..1c27ce98 100644 --- a/sandbox/002-typing.mu +++ b/sandbox/002-typing.mu @@ -83,11 +83,11 @@ def snap-cursor screen:address:shared:screen, editor:address:shared:editor-data, curr <- next curr row:number <- copy 1/top column:number <- copy left - cursor-row:address:number <- get-address *editor, cursor-row:offset - *cursor-row <- copy target-row - cursor-column:address:number <- get-address *editor, cursor-column:offset - *cursor-column <- copy target-column - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset + *editor <- put *editor, cursor-row:offset, target-row + cursor-row:number <- copy target-row + *editor <- put *editor, cursor-column:offset, target-column + cursor-column:number <- copy target-column + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset { +next-character break-unless curr @@ -97,11 +97,12 @@ def snap-cursor screen:address:shared:screen, editor:address:shared:editor-data, # Doing so at the start of each iteration ensures it stays one step behind # the current character. { - at-cursor-row?:boolean <- equal row, *cursor-row + at-cursor-row?:boolean <- equal row, cursor-row break-unless at-cursor-row? - at-cursor?:boolean <- equal column, *cursor-column + at-cursor?:boolean <- equal column, cursor-column break-unless at-cursor? - *before-cursor <- copy prev + before-cursor <- copy prev + *editor <- put *editor, before-cursor:offset, before-cursor } c:character <- get *curr, value:offset { @@ -110,12 +111,14 @@ def snap-cursor screen:address:shared:screen, editor:address:shared:editor-data, break-unless newline? # adjust cursor if necessary { - at-cursor-row?:boolean <- equal row, *cursor-row + at-cursor-row?:boolean <- equal row, cursor-row break-unless at-cursor-row? - left-of-cursor?:boolean <- lesser-than column, *cursor-column + left-of-cursor?:boolean <- lesser-than column, cursor-column break-unless left-of-cursor? - *cursor-column <- copy column - *before-cursor <- copy prev + cursor-column <- copy column + *editor <- put *editor, cursor-column:offset, cursor-column + before-cursor <- copy prev + *editor <- put *editor, before-cursor:offset, before-cursor } # skip to next line row <- add row, 1 @@ -141,15 +144,18 @@ def snap-cursor screen:address:shared:screen, editor:address:shared:editor-data, } # is cursor to the right of the last line? move to end { - at-cursor-row?:boolean <- equal row, *cursor-row - cursor-outside-line?:boolean <- lesser-or-equal column, *cursor-column + at-cursor-row?:boolean <- equal row, cursor-row + cursor-outside-line?:boolean <- lesser-or-equal column, cursor-column before-cursor-on-same-line?:boolean <- and at-cursor-row?, cursor-outside-line? - above-cursor-row?:boolean <- lesser-than row, *cursor-row + above-cursor-row?:boolean <- lesser-than row, cursor-row before-cursor?:boolean <- or before-cursor-on-same-line?, above-cursor-row? break-unless before-cursor? - *cursor-row <- copy row - *cursor-column <- copy column - *before-cursor <- copy prev + cursor-row <- copy row + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- copy column + *editor <- put *editor, cursor-column:offset, cursor-column + before-cursor <- copy prev + *editor <- put *editor, before-cursor:offset, before-cursor } ] @@ -164,11 +170,11 @@ def handle-keyboard-event screen:address:shared:screen, editor:address:shared:ed screen-height:number <- screen-height screen left:number <- get *editor, left:offset right:number <- get *editor, right:offset - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset - save-row:number <- copy *cursor-row - save-column:number <- copy *cursor-column + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + save-row:number <- copy cursor-row + save-column:number <- copy cursor-column # character { c:address:character <- maybe-convert e, text:variant @@ -198,22 +204,24 @@ def handle-keyboard-event screen:address:shared:screen, editor:address:shared:ed def insert-at-cursor editor:address:shared:editor-data, c:character, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean [ local-scope load-ingredients - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset - insert c, *before-cursor - *before-cursor <- next *before-cursor - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + insert c, before-cursor + before-cursor <- next before-cursor + *editor <- put *editor, before-cursor:offset, before-cursor + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset left:number <- get *editor, left:offset right:number <- get *editor, right:offset - save-row:number <- copy *cursor-row - save-column:number <- copy *cursor-column + save-row:number <- copy cursor-row + save-column:number <- copy cursor-column screen-width:number <- screen-width screen screen-height:number <- screen-height screen # occasionally we'll need to mess with the cursor # but mostly we'll just move the cursor right - *cursor-column <- add *cursor-column, 1 - next:address:shared:duplex-list:character <- next *before-cursor + cursor-column <- add cursor-column, 1 + *editor <- put *editor, cursor-column:offset, cursor-column + next:address:shared:duplex-list:character <- next before-cursor { # at end of all text? no need to scroll? just print the character and leave at-end?:boolean <- equal next, 0/null @@ -231,9 +239,9 @@ def insert-at-cursor editor:address:shared:editor-data, c:character, screen:addr { # not at right margin? print the character and rest of line break-unless next - at-right?:boolean <- greater-or-equal *cursor-column, screen-width + at-right?:boolean <- greater-or-equal cursor-column, screen-width break-if at-right? - curr:address:shared:duplex-list:character <- copy *before-cursor + curr:address:shared:duplex-list:character <- copy before-cursor move-cursor screen, save-row, save-column curr-column:number <- copy save-column { @@ -685,14 +693,16 @@ after [ { # if we're at the column just before the wrap indicator wrap-column:number <- subtract right, 1 - at-wrap?:boolean <- greater-or-equal *cursor-column, wrap-column + at-wrap?:boolean <- greater-or-equal cursor-column, wrap-column break-unless at-wrap? - *cursor-column <- subtract *cursor-column, wrap-column - *cursor-column <- add *cursor-column, left - *cursor-row <- add *cursor-row, 1 + cursor-column <- subtract cursor-column, wrap-column + cursor-column <- add cursor-column, left + *editor <- put *editor, cursor-column:offset, cursor-column + cursor-row <- add cursor-row, 1 + *editor <- put *editor, cursor-row:offset, cursor-row # if we're out of the screen, scroll down { - below-screen?:boolean <- greater-or-equal *cursor-row, screen-height + below-screen?:boolean <- greater-or-equal cursor-row, screen-height break-unless below-screen? } @@ -786,8 +796,7 @@ container editor-data [ ] after [ - indent?:address:boolean <- get-address *result, indent?:offset - *indent? <- copy 1/true + *result <- put *result, indent?:offset, 1/true ] scenario editor-moves-cursor-down-after-inserting-newline [ @@ -825,30 +834,34 @@ after [ def insert-new-line-and-indent editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean [ local-scope load-ingredients - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset left:number <- get *editor, left:offset right:number <- get *editor, right:offset screen-height:number <- screen-height screen # insert newline - insert 10/newline, *before-cursor - *before-cursor <- next *before-cursor - *cursor-row <- add *cursor-row, 1 - *cursor-column <- copy left + insert 10/newline, before-cursor + before-cursor <- next before-cursor + *editor <- put *editor, before-cursor:offset, before-cursor + cursor-row <- add cursor-row, 1 + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- copy left + *editor <- put *editor, cursor-column:offset, cursor-column # maybe scroll { - below-screen?:boolean <- greater-or-equal *cursor-row, screen-height # must be equal, never greater + below-screen?:boolean <- greater-or-equal cursor-row, screen-height # must be equal, never greater break-unless below-screen? go-render? <- copy 1/true - *cursor-row <- subtract *cursor-row, 1 # bring back into screen range + cursor-row <- subtract cursor-row, 1 # bring back into screen range + *editor <- put *editor, cursor-row:offset, cursor-row } # indent if necessary indent?:boolean <- get *editor, indent?:offset return-unless indent? d:address:shared:duplex-list:character <- get *editor, data:offset - end-of-previous-line:address:shared:duplex-list:character <- prev *before-cursor + end-of-previous-line:address:shared:duplex-list:character <- prev before-cursor indent:number <- line-indent end-of-previous-line, d i:number <- copy 0 { @@ -992,8 +1005,7 @@ after [ { paste-start?:boolean <- equal *k, 65507/paste-start break-unless paste-start? - indent?:address:boolean <- get-address *editor, indent?:offset - *indent? <- copy 0/false + *editor <- put *editor, indent?:offset, 0/false go-render? <- copy 1/true return } @@ -1003,8 +1015,7 @@ after [ { paste-end?:boolean <- equal *k, 65506/paste-end break-unless paste-end? - indent?:address:boolean <- get-address *editor, indent?:offset - *indent? <- copy 1/true + *editor <- put *editor, indent?:offset, 1/true go-render? <- copy 1/true return } diff --git a/sandbox/003-shortcuts.mu b/sandbox/003-shortcuts.mu index c09c3441..f29773af 100644 --- a/sandbox/003-shortcuts.mu +++ b/sandbox/003-shortcuts.mu @@ -83,18 +83,19 @@ after [ def delete-before-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character [ local-scope load-ingredients - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset data:address:shared:duplex-list:character <- get *editor, data:offset # if at start of text (before-cursor at § sentinel), return - prev:address:shared:duplex-list:character <- prev *before-cursor + prev:address:shared:duplex-list:character <- prev before-cursor go-render?, backspaced-cell <- copy 0/no-more-render, 0/nothing-deleted return-unless prev trace 10, [app], [delete-before-cursor] original-row:number <- get *editor, cursor-row:offset editor, scroll?:boolean <- move-cursor-coordinates-left editor - backspaced-cell:address:shared:duplex-list:character <- copy *before-cursor - data <- remove *before-cursor, data # will also neatly trim next/prev pointers in backspaced-cell/*before-cursor - *before-cursor <- copy prev + backspaced-cell:address:shared:duplex-list:character <- copy before-cursor + data <- remove before-cursor, data # will also neatly trim next/prev pointers in backspaced-cell/before-cursor + before-cursor <- copy prev + *editor <- put *editor, before-cursor:offset, before-cursor go-render? <- copy 1/true return-if scroll? screen-width:number <- screen-width screen @@ -106,7 +107,7 @@ def delete-before-cursor editor:address:shared:editor-data, screen:address:share return-unless same-row? left:number <- get *editor, left:offset right:number <- get *editor, right:offset - curr:address:shared:duplex-list:character <- next *before-cursor + curr:address:shared:duplex-list:character <- next before-cursor screen <- move-cursor screen, cursor-row, cursor-column curr-column:number <- copy cursor-column { @@ -134,24 +135,26 @@ def move-cursor-coordinates-left editor:address:shared:editor-data -> editor:add local-scope load-ingredients before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset left:number <- get *editor, left:offset # if not at left margin, move one character left { - at-left-margin?:boolean <- equal *cursor-column, left + at-left-margin?:boolean <- equal cursor-column, left break-if at-left-margin? trace 10, [app], [decrementing cursor column] - *cursor-column <- subtract *cursor-column, 1 + cursor-column <- subtract cursor-column, 1 + *editor <- put *editor, cursor-column:offset, cursor-column go-render? <- copy 0/false return } # if at left margin, we must move to previous row: - top-of-screen?:boolean <- equal *cursor-row, 1 # exclude menu bar + top-of-screen?:boolean <- equal cursor-row, 1 # exclude menu bar go-render?:boolean <- copy 0/false { break-if top-of-screen? - *cursor-row <- subtract *cursor-row, 1 + cursor-row <- subtract cursor-row, 1 + *editor <- put *editor, cursor-row:offset, cursor-row } { break-unless top-of-screen? @@ -173,18 +176,21 @@ def move-cursor-coordinates-left editor:address:shared:editor-data -> editor:add { break-unless wrap? _, column-offset:number <- divide-with-remainder end-of-line, width - *cursor-column <- add left, column-offset + cursor-column <- add left, column-offset + *editor <- put *editor, cursor-column:offset, cursor-column } { break-if wrap? - *cursor-column <- add left, end-of-line + cursor-column <- add left, end-of-line + *editor <- put *editor, cursor-column:offset, cursor-column } return } # case 2: if previous-character was not newline, we're just at a wrapped line trace 10, [app], [wrapping to previous line] right:number <- get *editor, right:offset - *cursor-column <- subtract right, 1 # leave room for wrap icon + cursor-column <- subtract right, 1 # leave room for wrap icon + *editor <- put *editor, cursor-column:offset, cursor-column ] # takes a pointer 'curr' into the doubly-linked list and its sentinel, counts @@ -345,9 +351,9 @@ after [ def delete-at-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character [ local-scope load-ingredients - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset data:address:shared:duplex-list:character <- get *editor, data:offset - deleted-cell:address:shared:duplex-list:character <- next *before-cursor + deleted-cell:address:shared:duplex-list:character <- next before-cursor go-render? <- copy 0/false return-unless deleted-cell currc:character <- get *deleted-cell, value:offset @@ -356,11 +362,11 @@ def delete-at-cursor editor:address:shared:editor-data, screen:address:shared:sc go-render? <- copy 1/true return-if deleted-newline? # wasn't a newline? render rest of line - curr:address:shared:duplex-list:character <- next *before-cursor # refresh after remove above - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset - screen <- move-cursor screen, *cursor-row, *cursor-column - curr-column:number <- copy *cursor-column + curr:address:shared:duplex-list:character <- next before-cursor # refresh after remove above + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + screen <- move-cursor screen, cursor-row, cursor-column + curr-column:number <- copy cursor-column screen-width:number <- screen-width screen { # hit right margin? give up and let caller render @@ -412,13 +418,14 @@ after [ move-to-next-character?:boolean <- equal *k, 65514/right-arrow break-unless move-to-next-character? # if not at end of text - next-cursor:address:shared:duplex-list:character <- next *before-cursor + next-cursor:address:shared:duplex-list:character <- next before-cursor break-unless next-cursor # scan to next character - *before-cursor <- copy next-cursor + before-cursor <- copy next-cursor + *editor <- put *editor, before-cursor:offset, before-cursor editor, go-render?:boolean <- move-cursor-coordinates-right editor, screen-height - screen <- move-cursor screen, *cursor-row, *cursor-column + screen <- move-cursor screen, cursor-row, cursor-column undo-coalesce-tag:number <- copy 2/right-arrow return @@ -429,8 +436,8 @@ def move-cursor-coordinates-right editor:address:shared:editor-data, screen-heig local-scope load-ingredients before-cursor:address:shared:duplex-list:character <- get *editor before-cursor:offset - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset left:number <- get *editor, left:offset right:number <- get *editor, right:offset # if crossed a newline, move cursor to start of next row @@ -438,13 +445,16 @@ def move-cursor-coordinates-right editor:address:shared:editor-data, screen-heig old-cursor-character:character <- get *before-cursor, value:offset was-at-newline?:boolean <- equal old-cursor-character, 10/newline break-unless was-at-newline? - *cursor-row <- add *cursor-row, 1 - *cursor-column <- copy left - below-screen?:boolean <- greater-or-equal *cursor-row, screen-height # must be equal + cursor-row <- add cursor-row, 1 + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- copy left + *editor <- put *editor, cursor-column:offset, cursor-column + below-screen?:boolean <- greater-or-equal cursor-row, screen-height # must be equal go-render? <- copy 0/false return-unless below-screen? - *cursor-row <- subtract *cursor-row, 1 # bring back into screen range + cursor-row <- subtract cursor-row, 1 # bring back into screen range + *editor <- put *editor, cursor-row:offset, cursor-row go-render? <- copy 1/true return } @@ -452,7 +462,7 @@ def move-cursor-coordinates-right editor:address:shared:editor-data, screen-heig { # if we're at the column just before the wrap indicator wrap-column:number <- subtract right, 1 - at-wrap?:boolean <- equal *cursor-column, wrap-column + at-wrap?:boolean <- equal cursor-column, wrap-column break-unless at-wrap? # and if next character isn't newline next:address:shared:duplex-list:character <- next before-cursor @@ -460,17 +470,21 @@ def move-cursor-coordinates-right editor:address:shared:editor-data, screen-heig next-character:character <- get *next, value:offset newline?:boolean <- equal next-character, 10/newline break-if newline? - *cursor-row <- add *cursor-row, 1 - *cursor-column <- copy left - below-screen?:boolean <- greater-or-equal *cursor-row, screen-height # must be equal + cursor-row <- add cursor-row, 1 + *editor <- put *editor, cursor-row:offset, cursor-row + cursor-column <- copy left + *editor <- put *editor, cursor-column:offset, cursor-column + below-screen?:boolean <- greater-or-equal cursor-row, screen-height # must be equal return-unless below-screen?, editor/same-as-ingredient:0, 0/no-more-render - *cursor-row <- subtract *cursor-row, 1 # bring back into screen range + cursor-row <- subtract cursor-row, 1 # bring back into screen range + *editor <- put *editor, cursor-row:offset, cursor-row go-render? <- copy 1/true return } # otherwise move cursor one character right - *cursor-column <- add *cursor-column, 1 + cursor-column <- add cursor-column, 1 + *editor <- put *editor, cursor-column:offset, cursor-column go-render? <- copy 0/false ] @@ -689,12 +703,13 @@ after [ break-unless move-to-previous-character? trace 10, [app], [left arrow] # if not at start of text (before-cursor at § sentinel) - prev:address:shared:duplex-list:character <- prev *before-cursor + prev:address:shared:duplex-list:character <- prev before-cursor go-render? <- copy 0/false return-unless prev editor, go-render? <- move-cursor-coordinates-left editor - *before-cursor <- copy prev + before-cursor <- copy prev + *editor <- put *editor, before-cursor:offset, before-cursor undo-coalesce-tag:number <- copy 1/left-arrow return @@ -961,19 +976,19 @@ after [ def move-to-previous-line editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [ local-scope load-ingredients - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset left:number <- get *editor, left:offset right:number <- get *editor, right:offset - already-at-top?:boolean <- lesser-or-equal *cursor-row, 1/top + already-at-top?:boolean <- lesser-or-equal cursor-row, 1/top { # if cursor not at top, move it break-if already-at-top? # if not at newline, move to start of line (previous newline) # then scan back another line # if either step fails, give up without modifying cursor or coordinates - curr:address:shared:duplex-list:character <- copy *before-cursor + curr:address:shared:duplex-list:character <- copy before-cursor { old:address:shared:duplex-list:character <- copy curr c2:character <- get *curr, value:offset @@ -991,22 +1006,27 @@ def move-to-previous-line editor:address:shared:editor-data -> editor:address:sh go-render? <- copy 0/false return-if no-motion? } - *before-cursor <- copy curr - *cursor-row <- subtract *cursor-row, 1 + before-cursor <- copy curr + *editor <- put *editor, before-cursor:offset, before-cursor + cursor-row <- subtract cursor-row, 1 + *editor <- put *editor, cursor-row:offset, cursor-row # scan ahead to right column or until end of line - target-column:number <- copy *cursor-column - *cursor-column <- copy left + target-column:number <- copy cursor-column + cursor-column <- copy left + *editor <- put *editor, cursor-column:offset, cursor-column { - done?:boolean <- greater-or-equal *cursor-column, target-column + done?:boolean <- greater-or-equal cursor-column, target-column break-if done? - curr:address:shared:duplex-list:character <- next *before-cursor + curr:address:shared:duplex-list:character <- next before-cursor break-unless curr currc:character <- get *curr, value:offset at-newline?:boolean <- equal currc, 10/newline break-if at-newline? # - *before-cursor <- copy curr - *cursor-column <- add *cursor-column, 1 + before-cursor <- copy curr + *editor <- put *editor, before-cursor:offset, before-cursor + cursor-column <- add cursor-column, 1 + *editor <- put *editor, cursor-column:offset, cursor-column loop } go-render? <- copy 0/false @@ -1186,44 +1206,49 @@ after [ def move-to-next-line editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [ local-scope load-ingredients - cursor-row:address:number <- get-address *editor, cursor-row:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset left:number <- get *editor, left:offset right:number <- get *editor, right:offset last-line:number <- subtract screen-height, 1 - already-at-bottom?:boolean <- greater-or-equal *cursor-row, last-line + already-at-bottom?:boolean <- greater-or-equal cursor-row, last-line { # if cursor not at bottom, move it break-if already-at-bottom? # scan to start of next line, then to right column or until end of line max:number <- subtract right, left - next-line:address:shared:duplex-list:character <- before-start-of-next-line *before-cursor, max + next-line:address:shared:duplex-list:character <- before-start-of-next-line before-cursor, max { # already at end of buffer? try to scroll up (so we can see more # warnings or sandboxes below) - no-motion?:boolean <- equal next-line, *before-cursor + no-motion?:boolean <- equal next-line, before-cursor break-unless no-motion? - scroll?:boolean <- greater-than *cursor-row, 1 + scroll?:boolean <- greater-than cursor-row, 1 break-if scroll?, +try-to-scroll:label go-render? <- copy 0/false return } - *cursor-row <- add *cursor-row, 1 - *before-cursor <- copy next-line - target-column:number <- copy *cursor-column - *cursor-column <- copy left + cursor-row <- add cursor-row, 1 + *editor <- put *editor, cursor-row:offset, cursor-row + before-cursor <- copy next-line + *editor <- put *editor, before-cursor:offset, before-cursor + target-column:number <- copy cursor-column + cursor-column <- copy left + *editor <- put *editor, cursor-column:offset, cursor-column { - done?:boolean <- greater-or-equal *cursor-column, target-column + done?:boolean <- greater-or-equal cursor-column, target-column break-if done? - curr:address:shared:duplex-list:character <- next *before-cursor + curr:address:shared:duplex-list:character <- next before-cursor break-unless curr currc:character <- get *curr, value:offset at-newline?:boolean <- equal currc, 10/newline break-if at-newline? # - *before-cursor <- copy curr - *cursor-column <- add *cursor-column, 1 + before-cursor <- copy curr + *editor <- put *editor, before-cursor:offset, before-cursor + cursor-column <- add cursor-column, 1 + *editor <- put *editor, cursor-column:offset, cursor-column loop } go-render? <- copy 0/false @@ -1328,20 +1353,21 @@ def move-to-start-of-line editor:address:shared:editor-data -> editor:address:sh load-ingredients # update cursor column left:number <- get *editor, left:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset - *cursor-column <- copy left + cursor-column:number <- copy left + *editor <- put *editor, cursor-column:offset, cursor-column # update before-cursor - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset init:address:shared:duplex-list:character <- get *editor, data:offset # while not at start of line, move { - at-start-of-text?:boolean <- equal *before-cursor, init + at-start-of-text?:boolean <- equal before-cursor, init break-if at-start-of-text? - prev:character <- get **before-cursor, value:offset + prev:character <- get *before-cursor, value:offset at-start-of-line?:boolean <- equal prev, 10/newline break-if at-start-of-line? - *before-cursor <- prev *before-cursor - assert *before-cursor, [move-to-start-of-line tried to move before start of text] + before-cursor <- prev before-cursor + *editor <- put *editor, before-cursor:offset, before-cursor + assert before-cursor, [move-to-start-of-line tried to move before start of text] loop } ] @@ -1497,17 +1523,19 @@ after [ def move-to-end-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [ local-scope load-ingredients - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + cursor-column:number <- get *editor, cursor-column:offset # while not at start of line, move { - next:address:shared:duplex-list:character <- next *before-cursor + next:address:shared:duplex-list:character <- next before-cursor break-unless next # end of text nextc:character <- get *next, value:offset at-end-of-line?:boolean <- equal nextc, 10/newline break-if at-end-of-line? - *before-cursor <- copy next - *cursor-column <- add *cursor-column, 1 + before-cursor <- copy next + *editor <- put *editor, before-cursor:offset, before-cursor + cursor-column <- add cursor-column, 1 + *editor <- put *editor, cursor-column:offset, cursor-column loop } ] @@ -1629,9 +1657,9 @@ def delete-to-start-of-line editor:address:shared:editor-data -> result:address: load-ingredients # compute range to delete init:address:shared:duplex-list:character <- get *editor, data:offset - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset - start:address:shared:duplex-list:character <- copy *before-cursor - end:address:shared:duplex-list:character <- next *before-cursor + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + start:address:shared:duplex-list:character <- copy before-cursor + end:address:shared:duplex-list:character <- next before-cursor { at-start-of-text?:boolean <- equal start, init break-if at-start-of-text? @@ -1646,10 +1674,10 @@ def delete-to-start-of-line editor:address:shared:editor-data -> result:address: result:address:shared:duplex-list:character <- next start remove-between start, end # adjust cursor - *before-cursor <- copy start + before-cursor <- copy start + *editor <- put *editor, before-cursor:offset, before-cursor left:number <- get *editor, left:offset - cursor-column:address:number <- get-address *editor, cursor-column:offset - *cursor-column <- copy left + *editor <- put *editor, cursor-column:offset, left ] scenario editor-deletes-to-start-of-line-with-ctrl-u-2 [ @@ -1929,13 +1957,14 @@ d] after [ trace 10, [app], [scroll down] - top-of-screen:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset + top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset left:number <- get *editor, left:offset right:number <- get *editor, right:offset max:number <- subtract right, left - old-top:address:shared:duplex-list:character <- copy *top-of-screen - *top-of-screen <- before-start-of-next-line *top-of-screen, max - no-movement?:boolean <- equal old-top, *top-of-screen + old-top:address:shared:duplex-list:character <- copy top-of-screen + top-of-screen <- before-start-of-next-line top-of-screen, max + *editor <- put *editor, top-of-screen:offset, top-of-screen + no-movement?:boolean <- equal old-top, top-of-screen go-render? <- copy 0/false return-if no-movement? ] @@ -2299,10 +2328,11 @@ d] after [ trace 10, [app], [scroll up] - top-of-screen:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - old-top:address:shared:duplex-list:character <- copy *top-of-screen - *top-of-screen <- before-previous-line *top-of-screen, editor - no-movement?:boolean <- equal old-top, *top-of-screen + top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + old-top:address:shared:duplex-list:character <- copy top-of-screen + top-of-screen <- before-previous-line top-of-screen, editor + *editor <- put *editor, top-of-screen:offset, top-of-screen + no-movement?:boolean <- equal old-top, top-of-screen go-render? <- copy 0/false return-if no-movement? ] @@ -2690,13 +2720,13 @@ after [ { page-down?:boolean <- equal *c, 6/ctrl-f break-unless page-down? - top-of-screen:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - old-top:address:shared:duplex-list:character <- copy *top-of-screen + old-top:address:shared:duplex-list:character <- get *editor, top-of-screen:offset page-down editor undo-coalesce-tag:number <- copy 0/never - no-movement?:boolean <- equal *top-of-screen, old-top + top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + no-movement?:boolean <- equal top-of-screen, old-top go-render? <- not no-movement? return } @@ -2706,13 +2736,13 @@ after [ { page-down?:boolean <- equal *k, 65518/page-down break-unless page-down? - top-of-screen:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - old-top:address:shared:duplex-list:character <- copy *top-of-screen + old-top:address:shared:duplex-list:character <- get *editor, top-of-screen:offset page-down editor undo-coalesce-tag:number <- copy 0/never - no-movement?:boolean <- equal *top-of-screen, old-top + top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + no-movement?:boolean <- equal top-of-screen, old-top go-render? <- not no-movement? return } @@ -2727,19 +2757,21 @@ def page-down editor:address:shared:editor-data -> editor:address:shared:editor- bottom-of-screen:address:shared:duplex-list:character <- get *editor, bottom-of-screen:offset return-unless bottom-of-screen # if not, position cursor at final character - before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset - *before-cursor <- prev bottom-of-screen + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + before-cursor:address:shared:duplex-list:character <- prev bottom-of-screen + *editor <- put *editor, before-cursor:offset, before-cursor # keep one line in common with previous page { - last:character <- get **before-cursor, value:offset + last:character <- get *before-cursor, value:offset newline?:boolean <- equal last, 10/newline break-unless newline?:boolean - *before-cursor <- prev *before-cursor + before-cursor <- prev before-cursor + *editor <- put *editor, before-cursor:offset, before-cursor } # move cursor and top-of-screen to start of that line move-to-start-of-line editor - top-of-screen:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - *top-of-screen <- copy *before-cursor + before-cursor <- get *editor, before-cursor:offset + *editor <- put *editor, top-of-screen:offset, before-cursor ] scenario editor-does-not-scroll-past-end [ @@ -2882,13 +2914,13 @@ after [ { page-up?:boolean <- equal *c, 2/ctrl-b break-unless page-up? - top-of-screen:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - old-top:address:shared:duplex-list:character <- copy *top-of-screen + old-top:address:shared:duplex-list:character <- get *editor, top-of-screen:offset editor <- page-up editor, screen-height undo-coalesce-tag:number <- copy 0/never - no-movement?:boolean <- equal *top-of-screen, old-top + top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + no-movement?:boolean <- equal top-of-screen, old-top go-render? <- not no-movement? return } @@ -2898,13 +2930,13 @@ after [ { page-up?:boolean <- equal *k, 65519/page-up break-unless page-up? - top-of-screen:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset - old-top:address:shared:duplex-list:character <- copy *top-of-screen + old-top:address:shared:duplex-list:character <- get *editor, top-of-screen:offset editor <- page-up editor, screen-height undo-coalesce-tag:number <- copy 0/never - no-movement?:boolean <- equal *top-of-screen, old-top + top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset + no-movement?:boolean <- equal top-of-screen, old-top # don't bother re-rendering if nothing changed. todo: test this go-render? <- not no-movement? return @@ -2916,13 +2948,14 @@ def page-up editor:address:shared:editor-data, screen-height:number -> editor:ad load-ingredients max:number <- subtract screen-height, 1/menu-bar, 1/overlapping-line count:number <- copy 0 - top-of-screen:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset + top-of-screen:address:shared:duplex-list:character <- get *editor, top-of-screen:offset { done?:boolean <- greater-or-equal count, max break-if done? - prev:address:shared:duplex-list:character <- before-previous-line *top-of-screen, editor + prev:address:shared:duplex-list:character <- before-previous-line top-of-screen, editor break-unless prev - *top-of-screen <- copy prev + top-of-screen <- copy prev + *editor <- put *editor, top-of-screen:offset, top-of-screen count <- add count, 1 loop } diff --git a/sandbox/004-programming-environment.mu b/sandbox/004-programming-environment.mu index bbbb45e2..a329c8c1 100644 --- a/sandbox/004-programming-environment.mu +++ b/sandbox/004-programming-environment.mu @@ -33,8 +33,8 @@ def new-programming-environment screen:address:shared:screen, initial-sandbox-co screen <- move-cursor screen, 0/row, button-start print screen, [ run (F4) ], 255/white, 161/reddish # sandbox editor - current-sandbox:address:address:shared:editor-data <- get-address *result, current-sandbox:offset - *current-sandbox <- new-editor initial-sandbox-contents, screen, 0, width/right + current-sandbox:address:shared:editor-data <- new-editor initial-sandbox-contents, screen, 0, width/right + *result <- put *result, current-sandbox:offset, current-sandbox ] @@ -142,13 +142,11 @@ def resize screen:address:shared:screen, env:address:shared:programming-environm width:number <- screen-width screen # update sandbox editor current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset - right:address:number <- get-address *current-sandbox, right:offset - *right <- subtract width, 1 + right:number <- subtract width, 1 + *current-sandbox <- put *current-sandbox right:offset, right # reset cursor - cursor-row:address:number <- get-address *current-sandbox, cursor-row:offset - *cursor-row <- copy 1 - cursor-column:address:number <- get-address *current-sandbox, cursor-column:offset - *cursor-column <- copy 0 + *current-sandbox <- put *current-sandbox, cursor-row:offset, 1 + *current-sandbox <- put *current-sandbox, cursor-column:offset, 0 ] def render-all screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [ diff --git a/sandbox/005-sandbox.mu b/sandbox/005-sandbox.mu index 57a4f5cf..0b6bd79c 100644 --- a/sandbox/005-sandbox.mu +++ b/sandbox/005-sandbox.mu @@ -11,8 +11,7 @@ container programming-environment-data [ ] after [ - render-from:address:number <- get-address *result, render-from:offset - *render-from <- copy -1 + *result <- put *result, render-from:offset, -1 ] container sandbox-data [ @@ -140,21 +139,19 @@ def run-sandboxes env:address:shared:programming-environment-data, screen:addres # if contents exist, first save them # run them and turn them into a new sandbox-data new-sandbox:address:shared:sandbox-data <- new sandbox-data:type - data:address:address:shared:array:character <- get-address *new-sandbox, data:offset - *data <- copy sandbox-contents + *new-sandbox <- put *new-sandbox, data:offset, sandbox-contents # push to head of sandbox list - dest:address:address:shared:sandbox-data <- get-address *env, sandbox:offset - next:address:address:shared:sandbox-data <- get-address *new-sandbox, next-sandbox:offset - *next <- copy *dest - *dest <- copy new-sandbox + dest:address:shared:sandbox-data <- get *env, sandbox:offset + *new-sandbox <- put *new-sandbox, next-sandbox:offset, dest + *env <- put *env, sandbox:offset, new-sandbox # update sandbox count - sandbox-count:address:number <- get-address *env, number-of-sandboxes:offset - *sandbox-count <- add *sandbox-count, 1 + sandbox-count:number <- get *env, number-of-sandboxes:offset + sandbox-count <- add sandbox-count, 1 + *env <- put *env, number-of-sandboxes:offset, sandbox-count # clear sandbox editor - init:address:address:shared:duplex-list:character <- get-address *current-sandbox, data:offset - *init <- push 167/§, 0/tail - top-of-screen:address:address:shared:duplex-list:character <- get-address *current-sandbox, top-of-screen:offset - *top-of-screen <- copy *init + init:address:shared:duplex-list:character <- push 167/§, 0/tail + *current-sandbox <- put *current-sandbox, data:offset, init + *current-sandbox <- put *current-sandbox, top-of-screen:offset, init } # save all sandboxes before running, just in case we die when running save-sandboxes env @@ -193,9 +190,9 @@ def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:prog local-scope load-ingredients data:address:shared:array:character <- get *sandbox, data:offset - response:address:address:shared:array:character <- get-address *sandbox, response:offset - fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset - *response, _, *fake-screen <- run-interactive data + response:address:shared:array:character, _, fake-screen:address:shared:screen <- run-interactive data + *sandbox <- put *sandbox, response:offset, response + *sandbox <- put *sandbox, screen:offset, fake-screen ] def update-status screen:address:shared:screen, msg:address:shared:array:character, color:number -> screen:address:shared:screen [ @@ -268,15 +265,13 @@ def render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbo delete-icon:character <- copy 120/x print screen, delete-icon, 245/grey # save menu row so we can detect clicks to it later - starting-row:address:number <- get-address *sandbox, starting-row-on-screen:offset - *starting-row <- copy row + *sandbox <- put *sandbox, starting-row-on-screen:offset, row # render sandbox contents row <- add row, 1 screen <- move-cursor screen, row, left sandbox-data:address:shared:array:character <- get *sandbox, data:offset row, screen <- render-code screen, sandbox-data, left, right, row - code-ending-row:address:number <- get-address *sandbox, code-ending-row-on-screen:offset - *code-ending-row <- copy row + *sandbox <- put *sandbox, code-ending-row-on-screen:offset, row # render sandbox warnings, screen or response, in that order sandbox-response:address:shared:array:character <- get *sandbox, response:offset @@ -300,10 +295,8 @@ def render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbo # if hidden, reset row attributes { break-unless hidden? - tmp:address:number <- get-address *sandbox, starting-row-on-screen:offset - *tmp <- copy 0 - tmp:address:number <- get-address *sandbox, code-ending-row-on-screen:offset - *tmp <- copy 0 + *sandbox <- put *sandbox, starting-row-on-screen:offset, 0 + *sandbox <- put *sandbox, code-ending-row-on-screen:offset, 0 } # draw next sandbox @@ -318,15 +311,15 @@ def! restore-sandboxes env:address:shared:programming-environment-data -> env:ad load-ingredients # read all scenarios, pushing them to end of a list of scenarios idx:number <- copy 0 - curr:address:address:shared:sandbox-data <- get-address *env, sandbox:offset + curr:address:shared:sandbox-data <- copy 0 + prev:address:shared:sandbox-data <- copy 0 { filename:address:shared:array:character <- to-text idx contents:address:shared:array:character <- restore filename break-unless contents # stop at first error; assuming file didn't exist # create new sandbox for file - *curr <- new sandbox-data:type - data:address:address:shared:array:character <- get-address **curr, data:offset - *data <- copy contents + curr <- new sandbox-data:type + *curr <- put *curr, data:offset, contents # restore expected output for sandbox if it exists { filename <- append filename, [.out] @@ -336,12 +329,16 @@ def! restore-sandboxes env:address:shared:programming-environment-data -> env:ad } +continue idx <- add idx, 1 - curr <- get-address **curr, next-sandbox:offset + { + break-unless prev + *prev <- put *prev, next-sandbox:offset, curr + } + prev <- copy curr loop } + *env <- put *env, sandbox:offset, curr # update sandbox count - number-of-sandboxes:address:number <- get-address *env, number-of-sandboxes:offset - *number-of-sandboxes <- copy idx + *env <- put *env, number-of-sandboxes:offset, idx ] # print the fake sandbox screen to 'screen' with appropriate delimiters @@ -619,12 +616,13 @@ after [ break-unless sandbox # slide down if possible { - render-from:address:number <- get-address *env, render-from:offset + render-from:number <- get *env, render-from:offset number-of-sandboxes:number <- get *env, number-of-sandboxes:offset max:number <- subtract number-of-sandboxes, 1 - at-end?:boolean <- greater-or-equal *render-from, max + at-end?:boolean <- greater-or-equal render-from, max break-if at-end? - *render-from <- add *render-from, 1 + render-from <- add render-from, 1 + *env <- put *env, render-from:offset, render-from } hide-screen screen screen <- render-sandbox-side screen, env @@ -650,10 +648,11 @@ after [ { up?:boolean <- equal *k, 65517/up-arrow break-unless up? - render-from:address:number <- get-address *env, render-from:offset - at-beginning?:boolean <- equal *render-from, -1 + render-from:number <- get *env, render-from:offset + at-beginning?:boolean <- equal render-from, -1 break-if at-beginning? - *render-from <- subtract *render-from, 1 + render-from <- subtract render-from, 1 + *env <- put *env, render-from:offset, render-from hide-screen screen screen <- render-sandbox-side screen, env show-screen screen diff --git a/sandbox/006-sandbox-edit.mu b/sandbox/006-sandbox-edit.mu index d39ec118..c863efe1 100644 --- a/sandbox/006-sandbox-edit.mu +++ b/sandbox/006-sandbox-edit.mu @@ -83,8 +83,7 @@ after [ break-unless sandbox text:address:shared:array:character <- get *sandbox, data:offset current-sandbox <- insert-text current-sandbox, text - render-from:address:number <- get-address *env, render-from:offset - *render-from <- copy -1 + *env <- put *env, render-from:offset, -1 hide-screen screen screen <- render-sandbox-side screen, env screen <- update-cursor screen, current-sandbox, env @@ -104,26 +103,41 @@ def empty-editor? editor:address:shared:editor-data -> result:boolean [ def extract-sandbox env:address:shared:programming-environment-data, click-row:number -> result:address:shared:sandbox-data, env:address:shared:programming-environment-data [ local-scope load-ingredients - sandbox:address:address:shared:sandbox-data <- get-address *env, sandbox:offset - start:number <- get **sandbox, starting-row-on-screen:offset + curr-sandbox:address:shared:sandbox-data <- get *env, sandbox:offset + start:number <- get *curr-sandbox, starting-row-on-screen:offset in-editor?:boolean <- lesser-than click-row, start return-if in-editor?, 0 + first-sandbox?:boolean <- equal click-row, start { - next-sandbox:address:shared:sandbox-data <- get **sandbox, next-sandbox:offset - break-unless next-sandbox - # if click-row < sandbox.next-sandbox.starting-row-on-screen, break - next-start:number <- get *next-sandbox, starting-row-on-screen:offset - found?:boolean <- lesser-than click-row, next-start - break-if found? - sandbox <- get-address **sandbox, next-sandbox:offset - loop + # first sandbox? pop + break-unless first-sandbox? + next-sandbox:address:shared:sandbox-data <- get *curr-sandbox, next-sandbox:offset + *env <- put *env, sandbox:offset, next-sandbox } - # snip sandbox out of its list - result <- copy *sandbox - *sandbox <- copy next-sandbox + { + # not first sandbox? + break-if first-sandbox? + prev-sandbox:address:shared:sandbox-data <- copy curr-sandbox + curr-sandbox <- get *curr-sandbox, next-sandbox:offset + { + next-sandbox:address:shared:sandbox-data <- get *curr-sandbox, next-sandbox:offset + break-unless next-sandbox + # if click-row < sandbox.next-sandbox.starting-row-on-screen, break + next-start:number <- get *next-sandbox, starting-row-on-screen:offset + found?:boolean <- lesser-than click-row, next-start + break-if found? + prev-sandbox <- copy curr-sandbox + curr-sandbox <- copy next-sandbox + loop + } + # snip sandbox out of its list + *prev-sandbox <- put *prev-sandbox, next-sandbox:offset, next-sandbox + } + result <- copy curr-sandbox # update sandbox count - sandbox-count:address:number <- get-address *env, number-of-sandboxes:offset - *sandbox-count <- subtract *sandbox-count, 1 + sandbox-count:number <- get *env, number-of-sandboxes:offset + sandbox-count <- subtract sandbox-count, 1 + *env <- put *env, number-of-sandboxes:offset, sandbox-count ] scenario sandbox-with-print-can-be-edited [ diff --git a/sandbox/007-sandbox-delete.mu b/sandbox/007-sandbox-delete.mu index dbf5d70c..f99012b6 100644 --- a/sandbox/007-sandbox-delete.mu +++ b/sandbox/007-sandbox-delete.mu @@ -85,8 +85,20 @@ def delete-sandbox t:touch-event, env:address:shared:programming-environment-dat at-right?:boolean <- equal click-column, right return-unless at-right?, 0/false click-row:number <- get t, row:offset - prev:address:address:shared:sandbox-data <- get-address *env, sandbox:offset - curr:address:shared:sandbox-data <- get *env, sandbox:offset + { + first:address:shared:sandbox-data <- get *env, sandbox:offset + reply-unless first, 0/false + target-row:number <- get *first, starting-row-on-screen:offset + delete-first?:boolean <- equal target-row, click-row + break-unless delete-first? + new-first:address:shared:sandbox-data <- get *first, next-sandbox:offset + *env <- put *env, sandbox:offset, new-first + env <- fixup-delete env, new-first + return 1/true # force rerender + } + prev:address:shared:sandbox-data <- get *env, sandbox:offset + assert prev, [failed to find any sandboxes!] + curr:address:shared:sandbox-data <- get *prev, next-sandbox:offset { break-unless curr # more sandboxes to check @@ -95,27 +107,36 @@ def delete-sandbox t:touch-event, env:address:shared:programming-environment-dat delete-curr?:boolean <- equal target-row, click-row break-unless delete-curr? # delete this sandbox - *prev <- get *curr, next-sandbox:offset - # update sandbox count - sandbox-count:address:number <- get-address *env, number-of-sandboxes:offset - *sandbox-count <- subtract *sandbox-count, 1 - # if it's the last sandbox and if it was the only sandbox rendered, reset scroll - { - break-if *prev - render-from:address:number <- get-address *env, render-from:offset - reset-scroll?:boolean <- equal *render-from, *sandbox-count - break-unless reset-scroll? - *render-from <- copy -1 - } + next:address:shared:sandbox-data <- get *curr, next-sandbox:offset + *prev <- put *prev, next-sandbox:offset, next + env <- fixup-delete env, next return 1/true # force rerender } - prev <- get-address *curr, next-sandbox:offset + prev <- copy curr curr <- get *curr, next-sandbox:offset loop } return 0/false ] +def fixup-delete env:address:shared:programming-environment-data, next:address:shared:sandbox-data -> env:address:shared:programming-environment-data [ + local-scope + load-ingredients + # update sandbox count + sandbox-count:number <- get *env, number-of-sandboxes:offset + sandbox-count <- subtract sandbox-count, 1 + *env <- put *env, number-of-sandboxes:offset, sandbox-count + { + break-if next + # deleted sandbox was last + render-from:number <- get *env, render-from:offset + reset-scroll?:boolean <- equal render-from, sandbox-count + break-unless reset-scroll? + # deleted sandbox was only sandbox rendered, so reset scroll + *env <- put *env, render-from:offset, -1 + } +] + scenario deleting-sandbox-after-scroll [ trace-until 100/app # trace too long assume-screen 30/width, 10/height diff --git a/sandbox/008-sandbox-test.mu b/sandbox/008-sandbox-test.mu index b64a5980..acd4c04d 100644 --- a/sandbox/008-sandbox-test.mu +++ b/sandbox/008-sandbox-test.mu @@ -98,8 +98,7 @@ before [ ] before [ - expected-response:address:address:shared:array:character <- get-address **curr, expected-response:offset - *expected-response <- copy contents + *curr <- put *curr, expected-response:offset, contents ] # clicks on sandbox responses save it as 'expected' @@ -160,24 +159,25 @@ def find-click-in-sandbox-output env:address:shared:programming-environment-data def toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [ local-scope load-ingredients - expected-response:address:address:shared:array:character <- get-address *sandbox, expected-response:offset + expected-response:address:shared:array:character <- get *sandbox, expected-response:offset { # if expected-response is set, reset - break-unless *expected-response - *expected-response <- copy 0 - return sandbox/same-as-ingredient:0 + break-unless expected-response + *sandbox <- put *sandbox, expected-response:offset, 0 + } + { + # if not, set expected response to the current response + break-if expected-response + response:address:shared:array:character <- get *sandbox, response:offset + *sandbox <- put *sandbox, expected-response:offset, response } - # if not, current response is the expected response - response:address:shared:array:character <- get *sandbox, response:offset - *expected-response <- copy response ] # when rendering a sandbox, color it in red/green if expected response exists after [ { break-unless sandbox-response - response-starting-row:address:number <- get-address *sandbox, response-starting-row-on-screen:offset - *response-starting-row <- copy row + *sandbox <- put *sandbox, response-starting-row-on-screen:offset, row expected-response:address:shared:array:character <- get *sandbox, expected-response:offset break-unless expected-response # fall-through to print in grey response-is-expected?:boolean <- equal expected-response, sandbox-response @@ -194,6 +194,5 @@ after [ ] before [ - tmp:address:number <- get-address *sandbox, response-starting-row-on-screen:offset - *tmp <- copy 0 + *sandbox <- put *sandbox, response-starting-row-on-screen:offset, 0 ] diff --git a/sandbox/009-sandbox-trace.mu b/sandbox/009-sandbox-trace.mu index feecf010..a85a1920 100644 --- a/sandbox/009-sandbox-trace.mu +++ b/sandbox/009-sandbox-trace.mu @@ -123,10 +123,10 @@ def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:prog local-scope load-ingredients data:address:shared:array:character <- get *sandbox, data:offset - response:address:address:shared:array:character <- get-address *sandbox, response:offset - trace:address:address:shared:array:character <- get-address *sandbox, trace:offset - fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset - *response, _, *fake-screen, *trace <- run-interactive data + response:address:shared:array:character, _, fake-screen:address:shared:screen, trace:address:shared:array:character <- run-interactive data + *sandbox <- put *sandbox, response:offset, response + *sandbox <- put *sandbox, screen:offset, fake-screen + *sandbox <- put *sandbox, trace:offset, trace ] # clicks on sandbox code toggle its display-trace? flag @@ -147,8 +147,9 @@ after [ sandbox:address:shared:sandbox-data <- find-click-in-sandbox-code env, click-row break-unless sandbox # toggle its display-trace? property - x:address:boolean <- get-address *sandbox, display-trace?:offset - *x <- not *x + x:boolean <- get *sandbox, display-trace?:offset + x <- not x + *sandbox <- put *sandbox, display-trace?:offset, x hide-screen screen screen <- render-sandbox-side screen, env, 1/clear screen <- update-cursor screen, current-sandbox, env diff --git a/sandbox/010-errors.mu b/sandbox/010-errors.mu index adad4923..a25ade5d 100644 --- a/sandbox/010-errors.mu +++ b/sandbox/010-errors.mu @@ -9,19 +9,18 @@ container programming-environment-data [ def! update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen, test-recipes:address:shared:array:character -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [ local-scope load-ingredients - recipe-errors:address:address:shared:array:character <- get-address *env, recipe-errors:offset { break-if test-recipes - in:address:shared:array:character <- restore [recipes.mu] - *recipe-errors <- reload in + recipe-errors:address:shared:array:character <- restore [recipes.mu] } { break-unless test-recipes - *recipe-errors <- reload test-recipes + recipe-errors <- reload test-recipes } + *env <- put *env, recipe-errors:offset, recipe-errors # if recipe editor has errors, stop { - break-unless *recipe-errors + break-unless recipe-errors update-status screen, [errors found ], 1/red errors-found? <- copy 1/true return @@ -43,18 +42,17 @@ container programming-environment-data [ ] after [ - error-index:address:number <- get-address *result, error-index:offset - *error-index <- copy -1 + *result <- put *result, error-index:offset, -1 ] after [ - error-index:address:number <- get-address *env, error-index:offset - *error-index <- copy -1 + *env <- put *env, error-index:offset, -1 ] before [ { - sandboxes-completed-successfully?:boolean <- equal *error-index, -1 + error-index:number <- get *env, error-index:offset + sandboxes-completed-successfully?:boolean <- equal error-index, -1 break-if sandboxes-completed-successfully? errors-found? <- copy 1/true } @@ -79,30 +77,31 @@ container sandbox-data [ def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [ local-scope load-ingredients - data:address:shared:array:character <- get *sandbox, data:offset - response:address:address:shared:array:character <- get-address *sandbox, response:offset - errors:address:address:shared:array:character <- get-address *sandbox, errors:offset - trace:address:address:shared:array:character <- get-address *sandbox, trace:offset - fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset - recipe-errors:address:shared:array:character <- get *env, recipe-errors:offset { + recipe-errors:address:shared:array:character <- get *env, recipe-errors:offset break-unless recipe-errors - *errors <- copy recipe-errors + *sandbox <- put *sandbox, errors:offset, recipe-errors return } - *response, *errors, *fake-screen, *trace, completed?:boolean <- run-interactive data + data:address:shared:array:character <- get *sandbox, data:offset + response:address:shared:array:character, errors:address:shared:array:character, fake-screen:address:shared:screen, trace:address:shared:array:character, completed?:boolean <- run-interactive data + *sandbox <- put *sandbox, response:offset, response + *sandbox <- put *sandbox, errors:offset, errors + *sandbox <- put *sandbox, screen:offset, fake-screen + *sandbox <- put *sandbox, trace:offset, trace { - break-if *errors + break-if errors break-if completed?:boolean - *errors <- new [took too long! + errors <- new [took too long! ] + *sandbox <- put *sandbox, errors:offset, errors } { - break-unless *errors - error-index:address:number <- get-address *env, error-index:offset - error-not-set?:boolean <- equal *error-index, -1 + break-unless errors + error-index:number <- get *env, error-index:offset + error-not-set?:boolean <- equal error-index, -1 break-unless error-not-set? - *error-index <- copy idx + *env <- put *env, error-index:offset, idx } ] @@ -111,8 +110,7 @@ after [ { sandbox-errors:address:shared:array:character <- get *sandbox, errors:offset break-unless sandbox-errors - response-starting-row:address:number <- get-address *sandbox, response-starting-row-on-screen:offset - *response-starting-row <- copy 0 # no response + *sandbox <- put *sandbox, response-starting-row-on-screen:offset, 0 # no response { break-unless env recipe-errors:address:shared:array:character <- get *env, recipe-errors:offset @@ -180,23 +178,6 @@ scenario run-updates-status-with-first-erroneous-sandbox [ # status line shows that error is in first sandbox screen-should-contain [ . errors found (0) run (F4) . - . . - .━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. - .0 x. - .get foo, x:offset . - .expected a container in 'get foo, x:offset' . - .missing type for foo in 'get foo, x:offset' . - .first ingredient of 'get' should be a container, ↩. - .but got foo . - .━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. - .1 x. - .get foo, x:offset . - .expected a container in 'get foo, x:offset' . - .missing type for foo in 'get foo, x:offset' . - .first ingredient of 'get' should be a container, ↩. - .but got foo . - .━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. - . . ] ] @@ -223,25 +204,6 @@ scenario run-updates-status-with-first-erroneous-sandbox-2 [ # status line shows that error is in second sandbox screen-should-contain [ . errors found (1) run (F4) . - . . - .━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. - .0 x. - .add 2, 2 . - .4 . - .━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. - .1 x. - .get foo, x:offset . - .expected a container in 'get foo, x:offset' . - .missing type for foo in 'get foo, x:offset' . - .first ingredient of 'get' should be a container, ↩. - .but got foo . - .━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. - .2 x. - .get foo, x:offset . - .expected a container in 'get foo, x:offset' . - .missing type for foo in 'get foo, x:offset' . - .first ingredient of 'get' should be a container, ↩. - .but got foo . ] ] @@ -485,8 +447,8 @@ def foo [ .━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. .0 x. .foo . - .foo: expected ingredient 1 of 'get' to have type ↩. - .'offset'; got x:number . + .foo: second ingredient of 'get' should have type ↩. + .'offset', but got x:number . ] ] diff --git a/sandbox/011-editor-undo.mu b/sandbox/011-editor-undo.mu index 5866fb52..07ecb14f 100644 --- a/sandbox/011-editor-undo.mu +++ b/sandbox/011-editor-undo.mu @@ -65,12 +65,14 @@ after [ { 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:shared:list:address:shared:operation <- get *editor, undo:offset + break-unless undo + op:address:shared:operation <- first undo + undo <- rest undo + *editor <- put *editor, undo:offset, undo + redo:address:shared:list:address:shared:operation <- get *editor, redo:offset + redo <- push op, redo + *editor <- put *editor, redo:offset, redo return screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render } @@ -81,12 +83,14 @@ after [ { 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:shared:list:address:shared:operation <- get *editor, redo:offset + break-unless redo + op:address:shared:operation <- first redo + redo <- rest redo + *editor <- put *editor, redo:offset, redo + undo:address:shared:list:address:shared:operation <- get *editor, undo:offset + undo <- push op, undo + *editor <- put *editor, undo:offset, undo return screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render } @@ -136,52 +140,55 @@ scenario editor-can-undo-typing [ # save operation to undo after [ top-before:address:shared:duplex-list:character <- get *editor, top-of-screen:offset - cursor-before:address:shared:duplex-list:character <- copy *before-cursor + cursor-before:address:shared:duplex-list:character <- get *editor, before-cursor:offset ] before [ 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 + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + undo:address:shared:list:address:shared: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 + 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 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:shared:duplex-list:character <- get *editor, before-cursor:offset + insert-until:address:shared: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 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 + *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 [ - cursor-row-before:number <- copy *cursor-row - cursor-column-before:number <- copy *cursor-column + 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-before:address:shared:duplex-list:character <- get *editor, before-cursor:offset ] before [ top-after:address:shared: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 + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + 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 + *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 ] @@ -192,10 +199,12 @@ before [ def add-operation editor:address:shared:editor-data, op:address:shared:operation -> editor:address:shared: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:shared:list:address:shared:operation <- get *editor, undo:offset + undo <- push op undo + *editor <- put *editor, undo:offset, undo + redo:address:shared:list:address:shared:operation <- get *editor, redo:offset + redo <- copy 0 + *editor <- put *editor, redo:offset, redo return editor/same-as-ingredient:0 ] @@ -206,12 +215,15 @@ after [ start:address:shared:duplex-list:character <- get *typing, insert-from:offset end:address:shared: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:shared: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:shared:duplex-list:character <- get *typing, before-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] @@ -400,14 +412,17 @@ after [ { typing:address:insert-operation <- maybe-convert *op, typing:variant break-unless typing + before-cursor <- get *editor, before-cursor:offset 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 + # 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:shared:duplex-list:character <- get *typing, after-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] @@ -700,36 +715,33 @@ ghi] ] after [ - 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:shared:duplex-list:character <- get *editor, top-of-screen:offset ] before [ - 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:shared: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 + undo:address:shared:list:address:shared:operation <- get *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 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 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 <- 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 ] @@ -739,10 +751,12 @@ after [ 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 - 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:shared:duplex-list:character <- get *move, before-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] @@ -1265,6 +1279,117 @@ ghi] ] ] +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 [ + { + 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 + *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:shared: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 @@ -1385,6 +1510,7 @@ scenario editor-separates-undo-insert-from-undo-cursor-move [ .┈┈┈┈┈┈┈┈┈┈. . . ] + # cursor moves memory-should-contain [ 3 <- 1 4 <- 1 @@ -1411,115 +1537,6 @@ scenario editor-separates-undo-insert-from-undo-cursor-move [ ] ] -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 [ - { - 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 [ @@ -1595,33 +1612,32 @@ before [ { 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 + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-row:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + undo:address:shared:list:address:shared: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 + 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 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:shared: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 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 + 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 editor <- add-operation editor, op +done-adding-backspace-operation } @@ -1631,18 +1647,19 @@ after [ { 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 break-unless anchor deleted:address:shared:duplex-list:character <- get *deletion, deleted-text:offset old-cursor:address:shared: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:shared:duplex-list:character <- get *deletion, before-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] @@ -1652,12 +1669,15 @@ after [ 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 + data:address:shared: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:shared:duplex-list:character <- get *deletion, before-top-of-screen:offset + *editor <- put *editor, top-of-screen:offset, top } ] @@ -1817,32 +1837,33 @@ before [ { 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 + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + undo:address:shared:list:address:shared: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 + 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 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:shared:duplex-list:character <- next before-cursor + *deletion <- put *deletion, delete-until:offset, delete-until + deleted-so-far:address:shared: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 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 + 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 editor <- add-operation editor, op +done-adding-delete-operation } @@ -1940,10 +1961,11 @@ before [ { 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 + cursor-row:number <- get *editor, cursor-row:offset + cursor-column:number <- get *editor, cursor-column:offset + deleted-until:address:shared:duplex-list:character <- next before-cursor 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 + *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 } @@ -2041,10 +2063,12 @@ before [ { 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 + before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset + deleted-until:address:shared: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 } -- cgit 1.4.1-2-gfad0