diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-07-12 00:11:56 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-07-12 00:11:56 -0700 |
commit | d5d908dda655c791329563522faad42d7e4ee618 (patch) | |
tree | 628b8a23e13878c45ef39dfbffb860c676da5304 /html/edit.mu.html | |
parent | 9864bdd0792b697d7b03e692ba7f82cf5669c41c (diff) | |
download | mu-d5d908dda655c791329563522faad42d7e4ee618.tar.gz |
1766
Diffstat (limited to 'html/edit.mu.html')
-rw-r--r-- | html/edit.mu.html | 1510 |
1 files changed, 982 insertions, 528 deletions
diff --git a/html/edit.mu.html b/html/edit.mu.html index 8481c441..3eb34a4b 100644 --- a/html/edit.mu.html +++ b/html/edit.mu.html @@ -33,43 +33,71 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } </head> <body> <pre id='vimCodeElement'> -<span class="Comment"># Editor widget: takes a string and screen coordinates, modifying them in place.</span> +<span class="Comment"># Environment for learning programming using mu.</span> <span class="muRecipe">recipe</span> main [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> open-console - width:number<span class="Special"> <- </span>display-width - height:number<span class="Special"> <- </span>display-height - <span class="Comment"># draw a line</span> + initial-recipe:address:array:character<span class="Special"> <- </span>new <span class="Constant">[recipe new-add [</span> +<span class="Constant"> x:number <- next-ingredient</span> +<span class="Constant"> y:number <- next-ingredient</span> +<span class="Constant"> z:number <- add x:number, y:number</span> +<span class="Constant"> reply z:number</span> +<span class="Constant">]</span>] + initial-sandbox:address:array:character<span class="Special"> <- </span>new <span class="Constant">[new-add 2:literal, 3:literal]</span> + env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment <span class="Constant">0:literal/screen</span>, initial-recipe:address:array:character, initial-sandbox:address:array:character + render-all <span class="Constant">0:literal/address</span>, env:address:programming-environment-data + event-loop <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/console</span>, env:address:programming-environment-data +] + +container programming-environment-data [ + recipes:address:editor-data + recipe-warnings:address:array:character + current-sandbox:address:editor-data + sandbox:address:sandbox-data + sandbox-in-focus?:boolean <span class="Comment"># false => focus in recipes; true => focus in current-sandbox</span> +] + +<span class="muRecipe">recipe</span> new-programming-environment [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + initial-recipe-contents:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + initial-sandbox-contents:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + width:number<span class="Special"> <- </span>screen-width screen:address + height:number<span class="Special"> <- </span>screen-height screen:address + <span class="Comment"># top menu</span> + result:address:programming-environment-data<span class="Special"> <- </span>new programming-environment-data:type + draw-horizontal screen:address, <span class="Constant">0:literal</span>, <span class="Constant">0:literal/left</span>, width:number, <span class="Constant">32:literal/space</span>, <span class="Constant">0:literal/black</span>, <span class="Constant">238:literal/grey</span> + button-start:number<span class="Special"> <- </span>subtract width:number, <span class="Constant">20:literal</span> + button-on-screen?:boolean<span class="Special"> <- </span>greater-or-equal button-start:number, <span class="Constant">0:literal</span> + assert button-on-screen?:boolean, <span class="Constant">[screen too narrow for menu]</span> + move-cursor screen:address, <span class="Constant">0:literal/row</span>, button-start:number/column + run-button:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ run (F10) ]</span> + print-string screen:address, run-button:address:array:character, <span class="Constant">255:literal/white</span>, <span class="Constant">161:literal/reddish</span> + <span class="Comment"># dotted line down the middle</span> divider:number, _<span class="Special"> <- </span>divide-with-remainder width:number, <span class="Constant">2:literal</span> - draw-vertical <span class="Constant">0:literal/screen</span>, divider:number, <span class="Constant">0:literal/top</span>, height:number - <span class="Comment"># editor on the left</span> - left:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - left-editor:address:editor-data<span class="Special"> <- </span>new-editor left:address:array:character, <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> <span class="Comment">#divider:number/right</span> - <span class="Comment"># editor on the right</span> - right:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - new-left:number<span class="Special"> <- </span>add divider:number/right, <span class="Constant">1:literal</span> - right-editor:address:editor-data<span class="Special"> <- </span>new-editor right:address:array:character, <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/top</span>, new-left:number, width:number - <span class="Comment"># chain</span> - x:address:address:editor-data<span class="Special"> <- </span>get-address left-editor:address:editor-data/deref, next-editor:offset - x:address:address:editor-data/deref<span class="Special"> <- </span>copy right-editor:address:editor-data - <span class="Comment"># initialize focus</span> - reset-focus left-editor:address:editor-data - cursor-row:number<span class="Special"> <- </span>get left-editor:address:editor-data/deref, cursor-row:offset - cursor-column:number<span class="Special"> <- </span>get left-editor:address:editor-data/deref, cursor-column:offset - move-cursor <span class="Constant">0:literal/screen</span>, cursor-row:number, cursor-column:number - <span class="Comment"># and we're off!</span> - event-loop <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/events</span>, left-editor:address:editor-data - close-console + draw-vertical screen:address, divider:number, <span class="Constant">1:literal/top</span>, height:number, <span class="Constant">9482:literal/vertical-dotted</span> + <span class="Comment"># recipe editor on the left</span> + recipes:address:address:editor-data<span class="Special"> <- </span>get-address result:address:programming-environment-data/deref, recipes:offset + recipes:address:address:editor-data/deref<span class="Special"> <- </span>new-editor initial-recipe-contents:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, divider:number/right + <span class="Comment"># sandbox editor on the right</span> + new-left:number<span class="Special"> <- </span>add divider:number, <span class="Constant">1:literal</span> + new-right:number<span class="Special"> <- </span>add new-left:number, <span class="Constant">5:literal</span> + current-sandbox:address:address:editor-data<span class="Special"> <- </span>get-address result:address:programming-environment-data/deref, current-sandbox:offset + current-sandbox:address:address:editor-data/deref<span class="Special"> <- </span>new-editor initial-sandbox-contents:address:array:character, screen:address, new-left:number, width:number + <span class="Comment"># initialize cursor</span> + update-cursor screen:address, recipes:address:address:editor-data/deref, current-sandbox:address:address:editor-data/deref, <span class="Constant">0:literal/focus-in-recipes</span> + <span class="muControl">reply</span> result:address:programming-environment-data ] <span class="muScenario">scenario</span> editor-initially-prints-string-to-screen [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> run [ 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> . .</span> ] @@ -79,30 +107,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <span class="SalientComment">## text to the screen.</span> container editor-data [ - <span class="Comment"># doubly linked list of characters (head contains a special sentinel)</span> + <span class="Comment"># editable text: doubly linked list of characters (head contains a special sentinel)</span> data:address:duplex-list - <span class="Comment"># location of top-left of screen inside data (scrolling)</span> - top-of-screen:address:duplex-list <span class="Comment"># location before cursor inside data</span> before-cursor:address:duplex-list - screen:address:screen <span class="Comment"># raw bounds of display area on screen</span> - top:number + <span class="Comment"># always displays from row 1 and at most until bottom of screen</span> left:number - bottom:number right:number <span class="Comment"># raw screen coordinates of cursor</span> cursor-row:number cursor-column:number - - <span class="Comment"># pointer to another editor, responsible for a different area of screen.</span> - <span class="Comment"># helps organize editors in a 'chain'.</span> - next-editor:address:editor-data - in-focus?:boolean <span class="Comment"># set for the one editor in this chain currently being edited</span> ] -<span class="Comment"># editor:address, screen:address <- new-editor s:address:array:character, screen:address, top:number, left:number, bottom:number</span> +<span class="Comment"># editor:address, screen:address <- new-editor s:address:array:character, screen:address, left:number, right:number</span> <span class="Comment"># creates a new editor widget and renders its initial appearance to screen.</span> <span class="Comment"># top/left/right constrain the screen area available to the new editor.</span> <span class="Comment"># right is exclusive.</span> @@ -111,42 +130,24 @@ container editor-data [ s:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="Comment"># no clipping of bounds</span> - top:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> left:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> right:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> right:number<span class="Special"> <- </span>subtract right:number, <span class="Constant">1:literal</span> result:address:editor-data<span class="Special"> <- </span>new editor-data:type <span class="Comment"># initialize screen-related fields</span> - sc:address:address:screen<span class="Special"> <- </span>get-address result:address:editor-data/deref, screen:offset - sc:address:address:screen/deref<span class="Special"> <- </span>copy screen:address - x:address:number<span class="Special"> <- </span>get-address result:address:editor-data/deref, top:offset - x:address:number/deref<span class="Special"> <- </span>copy top:number x:address:number<span class="Special"> <- </span>get-address result:address:editor-data/deref, left:offset x:address:number/deref<span class="Special"> <- </span>copy left:number x:address:number<span class="Special"> <- </span>get-address result:address:editor-data/deref, right:offset x:address:number/deref<span class="Special"> <- </span>copy right:number - <span class="Comment"># bottom = top (in case of early exit)</span> - x:address:number<span class="Special"> <- </span>get-address result:address:editor-data/deref, bottom:offset - x:address:number/deref<span class="Special"> <- </span>copy top:number <span class="Comment"># initialize cursor</span> x:address:number<span class="Special"> <- </span>get-address result:address:editor-data/deref, cursor-row:offset - x:address:number/deref<span class="Special"> <- </span>copy top:number + x:address:number/deref<span class="Special"> <- </span>copy <span class="Constant">1:literal/top</span> x:address:number<span class="Special"> <- </span>get-address result:address:editor-data/deref, cursor-column:offset -<span class="CommentedCode">#? $print left:number, [ </span> -<span class="CommentedCode">#? ] #? 1</span> x:address:number/deref<span class="Special"> <- </span>copy left:number - d:address:address:duplex-list<span class="Special"> <- </span>get-address result:address:editor-data/deref, data:offset - d:address:address:duplex-list/deref<span class="Special"> <- </span>push-duplex <span class="Constant">167:literal/§</span>, <span class="Constant">0:literal/tail</span> + init:address:address:duplex-list<span class="Special"> <- </span>get-address result:address:editor-data/deref, data:offset + init:address:address:duplex-list/deref<span class="Special"> <- </span>push-duplex <span class="Constant">167:literal/§</span>, <span class="Constant">0:literal/tail</span> y:address:address:duplex-list<span class="Special"> <- </span>get-address result:address:editor-data/deref, before-cursor:offset - y:address:address:duplex-list/deref<span class="Special"> <- </span>copy d:address:address:duplex-list/deref - init:address:address:duplex-list<span class="Special"> <- </span>get-address result:address:editor-data/deref, top-of-screen:offset - init:address:address:duplex-list/deref<span class="Special"> <- </span>copy d:address:address:duplex-list/deref - <span class="Comment"># set focus</span> - <span class="Comment"># if using multiple editors, must call reset-focus after chaining them all</span> - b:address:boolean<span class="Special"> <- </span>get-address result:address:editor-data/deref, in-focus?:offset - b:address:boolean/deref<span class="Special"> <- </span>copy <span class="Constant">1:literal/true</span> -<span class="CommentedCode">#? $print d:address:address:duplex-list/deref, [ </span> -<span class="CommentedCode">#? ] #? 1</span> + y:address:address:duplex-list/deref<span class="Special"> <- </span>copy init:address:address:duplex-list/deref <span class="Comment"># early exit if s is empty</span> <span class="muControl">reply-unless</span> s:address:array:character, result:address:editor-data len:number<span class="Special"> <- </span>length s:address:array:character/deref @@ -155,15 +156,9 @@ container editor-data [ <span class="Comment"># now we can start appending the rest, character by character</span> curr:address:duplex-list<span class="Special"> <- </span>copy init:address:address:duplex-list/deref <span class="Delimiter">{</span> -<span class="CommentedCode">#? $print idx:number, [ vs ], len:number, [ </span> -<span class="CommentedCode">#? ] #? 1</span> -<span class="CommentedCode">#? $print [append to ], curr:address:duplex-list, [ </span> -<span class="CommentedCode">#? ] #? 1</span> done?:boolean<span class="Special"> <- </span>greater-or-equal idx:number, len:number <span class="muControl">break-if</span> done?:boolean c:character<span class="Special"> <- </span>index s:address:array:character/deref, idx:number -<span class="CommentedCode">#? $print [aa: ], c:character, [ </span> -<span class="CommentedCode">#? ] #? 1</span> insert-duplex c:character, curr:address:duplex-list <span class="Comment"># next iter</span> curr:address:duplex-list<span class="Special"> <- </span>next-duplex curr:address:duplex-list @@ -173,29 +168,24 @@ container editor-data [ <span class="Comment"># initialize cursor to top of screen</span> y:address:address:duplex-list<span class="Special"> <- </span>get-address result:address:editor-data/deref, before-cursor:offset y:address:address:duplex-list/deref<span class="Special"> <- </span>copy init:address:address:duplex-list/deref - <span class="Comment"># perform initial rendering to screen</span> - bottom:address:number<span class="Special"> <- </span>get-address result:address:editor-data/deref, bottom:offset - result:address:editor-data<span class="Special"> <- </span>render result:address:editor-data + <span class="Comment"># initial render to screen, just for some old tests</span> + _, screen:address<span class="Special"> <- </span>render screen:address, result:address:editor-data <span class="muControl">reply</span> result:address:editor-data ] <span class="muScenario">scenario</span> editor-initializes-without-data [ assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span> run [ - 1:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">0:literal/data</span>, screen:address, <span class="Constant">1:literal/top</span>, <span class="Constant">2:literal/left</span>, <span class="Constant">5:literal/right</span> + 1:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">0:literal/data</span>, screen:address, <span class="Constant">2:literal/left</span>, <span class="Constant">5:literal/right</span> 2:editor-data<span class="Special"> <- </span>copy 1:address:editor-data/deref ] memory-should-contain [ - <span class="Comment"># 2 <- just the § sentinel</span> - <span class="Comment"># 3 (top of screen) <- the § sentinel</span> - <span class="Comment"># 4 (before cursor) <- the § sentinel</span> - <span class="Comment"># 5 <- screen</span> - 6<span class="Special"> <- </span>1 <span class="Comment"># top</span> - 7<span class="Special"> <- </span>2 <span class="Comment"># left</span> - 8<span class="Special"> <- </span>1 <span class="Comment"># bottom</span> - 9<span class="Special"> <- </span>4 <span class="Comment"># right (inclusive)</span> - 10<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> - 11<span class="Special"> <- </span>2 <span class="Comment"># cursor column</span> + <span class="Comment"># 2 (data) <- just the § sentinel</span> + <span class="Comment"># 3 (before cursor) <- the § sentinel</span> + 4<span class="Special"> <- </span>2 <span class="Comment"># left</span> + 5<span class="Special"> <- </span>4 <span class="Comment"># right (inclusive)</span> + 6<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> + 7<span class="Special"> <- </span>2 <span class="Comment"># cursor column</span> ] screen-should-contain [ <span class="Constant"> . .</span> @@ -204,23 +194,22 @@ container editor-data [ ] ] +<span class="Comment"># bottom:number, screen:address <- render screen:address, editor:address:editor-data</span> <span class="muRecipe">recipe</span> render [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">40:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> editor:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> -<span class="CommentedCode">#? $print [=== render</span> -<span class="CommentedCode">#? ] #? 2</span> - screen:address<span class="Special"> <- </span>get editor:address:editor-data/deref, screen:offset - top:number<span class="Special"> <- </span>get editor:address:editor-data/deref, top:offset + <span class="muControl">reply-unless</span> editor:address:editor-data, <span class="Constant">1:literal/top</span>, screen:address/same-as-ingredient:0 left:number<span class="Special"> <- </span>get editor:address:editor-data/deref, left:offset screen-height:number<span class="Special"> <- </span>screen-height screen:address right:number<span class="Special"> <- </span>get editor:address:editor-data/deref, right:offset hide-screen screen:address <span class="Comment"># traversing editor</span> - curr:address:duplex-list<span class="Special"> <- </span>get editor:address:editor-data/deref, top-of-screen:offset + curr:address:duplex-list<span class="Special"> <- </span>get editor:address:editor-data/deref, data:offset prev:address:duplex-list<span class="Special"> <- </span>copy curr:address:duplex-list curr:address:duplex-list<span class="Special"> <- </span>next-duplex curr:address:duplex-list <span class="Comment"># traversing screen</span> - row:number<span class="Special"> <- </span>copy top:number + row:number<span class="Special"> <- </span>copy <span class="Constant">1:literal/top</span> column:number<span class="Special"> <- </span>copy left:number cursor-row:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, cursor-row:offset cursor-column:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, cursor-column:offset @@ -228,8 +217,6 @@ container editor-data [ move-cursor screen:address, row:number, column:number <span class="Delimiter">{</span> <span class="Constant"> +next-character</span> -<span class="CommentedCode">#? $print curr:address:duplex-list, [ </span> -<span class="CommentedCode">#? ] #? 1</span> <span class="muControl">break-unless</span> curr:address:duplex-list off-screen?:boolean<span class="Special"> <- </span>greater-or-equal row:number, screen-height:number <span class="muControl">break-if</span> off-screen?:boolean @@ -242,13 +229,8 @@ container editor-data [ at-cursor?:boolean<span class="Special"> <- </span>equal column:number, cursor-column:address:number/deref <span class="muControl">break-unless</span> at-cursor?:boolean before-cursor:address:address:duplex-list/deref<span class="Special"> <- </span>prev-duplex curr:address:duplex-list -<span class="CommentedCode">#? new-prev:character <- get before-cursor:address:address:duplex-list/deref/deref, value:offset #? 1</span> -<span class="CommentedCode">#? $print [render 0: cursor adjusted to after ], new-prev:character, [(], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [)</span> -<span class="CommentedCode">#? ] #? 1</span> <span class="Delimiter">}</span> c:character<span class="Special"> <- </span>get curr:address:duplex-list/deref, value:offset -<span class="CommentedCode">#? $print [rendering ], c:character, [ </span> -<span class="CommentedCode">#? ] #? 2</span> <span class="Delimiter">{</span> <span class="Comment"># newline? move to left rather than 0</span> newline?:boolean<span class="Special"> <- </span>equal c:character, <span class="Constant">10:literal/newline</span> @@ -261,22 +243,9 @@ container editor-data [ <span class="muControl">break-unless</span> left-of-cursor?:boolean cursor-column:address:number/deref<span class="Special"> <- </span>copy column:number before-cursor:address:address:duplex-list/deref<span class="Special"> <- </span>prev-duplex curr:address:duplex-list -<span class="CommentedCode">#? new-prev:character <- get before-cursor:address:address:duplex-list/deref/deref, value:offset #? 1</span> -<span class="CommentedCode">#? $print [render 1: cursor adjusted to after ], new-prev:character, [(], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [)</span> -<span class="CommentedCode">#? ] #? 1</span> <span class="Delimiter">}</span> <span class="Comment"># clear rest of line in this window</span> -<span class="CommentedCode">#? $print row:number, [ ], column:number, [ ], right:number, [ </span> -<span class="CommentedCode">#? ] #? 1</span> - <span class="Delimiter">{</span> - done?:boolean<span class="Special"> <- </span>greater-than column:number, right:number - <span class="muControl">break-if</span> done?:boolean - print-character screen:address, <span class="Constant">32:literal/space</span> - column:number<span class="Special"> <- </span>add column:number, <span class="Constant">1:literal</span> -<span class="CommentedCode">#? $print column:number, [ </span> -<span class="CommentedCode">#? ] #? 1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> + clear-line-delimited screen:address, column:number, right:number <span class="Comment"># skip to next line</span> row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> column:number<span class="Special"> <- </span>copy left:number @@ -286,15 +255,11 @@ container editor-data [ <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> <span class="Delimiter">}</span> <span class="Delimiter">{</span> - <span class="Comment"># at right? more than one letter left in the line? wrap</span> + <span class="Comment"># at right? wrap. even if there's only one more letter left; we need</span> + <span class="Comment"># room for clicking on the cursor after it.</span> at-right?:boolean<span class="Special"> <- </span>equal column:number, right:number <span class="muControl">break-unless</span> at-right?:boolean - next-node:address:duplex-list<span class="Special"> <- </span>next-duplex curr:address:duplex-list - <span class="muControl">break-unless</span> next-node:address:duplex-list - next:character<span class="Special"> <- </span>get next-node:address:duplex-list/deref, value:offset - next-character-is-newline?:boolean<span class="Special"> <- </span>equal next:character, <span class="Constant">10:literal/newline</span> - <span class="muControl">break-if</span> next-character-is-newline?:boolean - <span class="Comment"># wrap</span> + <span class="Comment"># print wrap icon</span> print-character screen:address, <span class="Constant">8617:literal/loop-back-to-left</span>, <span class="Constant">245:literal/grey</span> column:number<span class="Special"> <- </span>copy left:number row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> @@ -308,9 +273,6 @@ container editor-data [ column:number<span class="Special"> <- </span>add column:number, <span class="Constant">1:literal</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="Comment"># bottom = row</span> - bottom:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, bottom:offset - bottom:address:number/deref<span class="Special"> <- </span>copy row:number <span class="Comment"># is cursor to the right of the last line? move to end</span> <span class="Delimiter">{</span> at-cursor-row?:boolean<span class="Special"> <- </span>equal row:number, cursor-row:address:number/deref @@ -319,12 +281,8 @@ container editor-data [ above-cursor-row?:boolean<span class="Special"> <- </span>lesser-than row:number, cursor-row:address:number/deref before-cursor?:boolean<span class="Special"> <- </span>or before-cursor-on-same-line?:boolean, above-cursor-row?:boolean <span class="muControl">break-unless</span> before-cursor?:boolean -<span class="CommentedCode">#? $print [pointed after all text</span> -<span class="CommentedCode">#? ] #? 1</span> cursor-row:address:number/deref<span class="Special"> <- </span>copy row:number cursor-column:address:number/deref<span class="Special"> <- </span>copy column:number -<span class="CommentedCode">#? $print [render: cursor moved to ], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [ </span> -<span class="CommentedCode">#? ] #? 1</span> <span class="Comment"># line not wrapped but cursor outside bounds? wrap cursor</span> <span class="Delimiter">{</span> too-far-right?:boolean<span class="Special"> <- </span>greater-than cursor-column:address:number/deref, right:number @@ -334,62 +292,106 @@ container editor-data [ above-screen-bottom?:boolean<span class="Special"> <- </span>lesser-than cursor-row:address:number/deref, screen-height:number assert above-screen-bottom?:boolean, <span class="Constant">[unimplemented: wrapping cursor past bottom of screen]</span> <span class="Delimiter">}</span> -<span class="CommentedCode">#? $print [now ], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [ </span> -<span class="CommentedCode">#? ] #? 1</span> before-cursor:address:address:duplex-list/deref<span class="Special"> <- </span>copy prev:address:duplex-list -<span class="CommentedCode">#? new-prev:character <- get before-cursor:address:address:duplex-list/deref/deref, value:offset #? 1</span> -<span class="CommentedCode">#? $print [render Ω: cursor adjusted to after ], new-prev:character, [(], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [)</span> -<span class="CommentedCode">#? ] #? 1</span> <span class="Delimiter">}</span> -<span class="CommentedCode">#? $print [clearing ], row:number, [ ], column:number, [ ], right:number, [ </span> -<span class="CommentedCode">#? ] #? 2</span> + <span class="Comment"># clear rest of current line</span> + clear-line-delimited screen:address, column:number, right:number + <span class="muControl">reply</span> row:number, screen:address/same-as-ingredient:0 +] + +<span class="Comment"># row:number, screen:address <- render-string screen:address, s:address:array:character, left:number, right:number, color:number, row:number</span> +<span class="Comment"># print a string 's' to 'editor' in 'color' starting at 'row'</span> +<span class="Comment"># leave cursor at start of next line</span> +<span class="muRecipe">recipe</span> render-string [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">40:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + s:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + left:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + right:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + color:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + row:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> + <span class="muControl">reply-unless</span> s:address:array:character, row:number/same-as-ingredient:5, screen:address/same-as-ingredient:0 + column:number<span class="Special"> <- </span>copy left:number + move-cursor screen:address, row:number, column:number + screen-height:number<span class="Special"> <- </span>screen-height screen:address + i:number<span class="Special"> <- </span>copy <span class="Constant">0:literal</span> + len:number<span class="Special"> <- </span>length s:address:array:character/deref <span class="Delimiter">{</span> - <span class="Comment"># clear rest of current line</span> +<span class="Constant"> +next-character</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal i:number, len:number + <span class="muControl">break-if</span> done?:boolean done?:boolean<span class="Special"> <- </span>greater-or-equal row:number, screen-height:number <span class="muControl">break-if</span> done?:boolean + c:character<span class="Special"> <- </span>index s:address:array:character/deref, i:number <span class="Delimiter">{</span> - line-done?:boolean<span class="Special"> <- </span>greater-than column:number, right:number - <span class="muControl">break-if</span> line-done?:boolean - print-character screen:address, <span class="Constant">32:literal/space</span> - column:number<span class="Special"> <- </span>add column:number, <span class="Constant">1:literal</span> - <span class="muControl">loop</span> + <span class="Comment"># at right? wrap.</span> + at-right?:boolean<span class="Special"> <- </span>equal column:number, right:number + <span class="muControl">break-unless</span> at-right?:boolean + <span class="Comment"># print wrap icon</span> + print-character screen:address, <span class="Constant">8617:literal/loop-back-to-left</span>, <span class="Constant">245:literal/grey</span> + column:number<span class="Special"> <- </span>copy left:number + row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> + move-cursor screen:address, row:number, column:number + <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> <span class="Comment"># retry i</span> <span class="Delimiter">}</span> - <span class="Comment"># clear one more line just in case we just backspaced out of it</span> - row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> - column:number<span class="Special"> <- </span>copy left:number - done?:boolean<span class="Special"> <- </span>greater-or-equal row:number, screen-height:number - <span class="muControl">break-if</span> done?:boolean - move-cursor screen:address, row:number, column:number + i:number<span class="Special"> <- </span>add i:number, <span class="Constant">1:literal</span> <span class="Delimiter">{</span> - line-done?:boolean<span class="Special"> <- </span>greater-or-equal column:number, right:number - <span class="muControl">break-if</span> line-done?:boolean - print-character screen:address, <span class="Constant">32:literal/space</span> - column:number<span class="Special"> <- </span>add column:number, <span class="Constant">1:literal</span> - <span class="muControl">loop</span> + <span class="Comment"># newline? move to left rather than 0</span> + newline?:boolean<span class="Special"> <- </span>equal c:character, <span class="Constant">10:literal/newline</span> + <span class="muControl">break-unless</span> newline?:boolean + <span class="Comment"># clear rest of line in this window</span> + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-than column:number, right:number + <span class="muControl">break-if</span> done?:boolean + print-character screen:address, <span class="Constant">32:literal/space</span> + column:number<span class="Special"> <- </span>add column:number, <span class="Constant">1:literal</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> + column:number<span class="Special"> <- </span>copy left:number + move-cursor screen:address, row:number, column:number + <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> <span class="Delimiter">}</span> + print-character screen:address, c:character, color:number + column:number<span class="Special"> <- </span>add column:number, <span class="Constant">1:literal</span> + <span class="muControl">loop</span> <span class="Delimiter">}</span> - <span class="Comment"># update cursor</span> <span class="Delimiter">{</span> - in-focus?:boolean<span class="Special"> <- </span>get editor:address:editor-data/deref, in-focus?:offset - <span class="muControl">break-unless</span> in-focus?:boolean - cursor-inside-right-margin?:boolean<span class="Special"> <- </span>lesser-or-equal cursor-column:address:number/deref, right:number - assert cursor-inside-right-margin?:boolean, <span class="Constant">[cursor outside right margin]</span> - cursor-inside-left-margin?:boolean<span class="Special"> <- </span>greater-or-equal cursor-column:address:number/deref, left:number - assert cursor-inside-left-margin?:boolean, <span class="Constant">[cursor outside left margin]</span> - move-cursor screen:address, cursor-row:address:number/deref, cursor-column:address:number/deref + <span class="Comment"># clear rest of current line</span> + line-done?:boolean<span class="Special"> <- </span>greater-than column:number, right:number + <span class="muControl">break-if</span> line-done?:boolean + print-character screen:address, <span class="Constant">32:literal/space</span> + column:number<span class="Special"> <- </span>add column:number, <span class="Constant">1:literal</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <span class="muControl">reply</span> row:number/same-as-ingredient:5, screen:address/same-as-ingredient:0 +] + +<span class="muRecipe">recipe</span> clear-line-delimited [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">40:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + left:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + right:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + column:number<span class="Special"> <- </span>copy left:number + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-than column:number, right:number + <span class="muControl">break-if</span> done?:boolean + print-character screen:address, <span class="Constant">32:literal/space</span> + column:number<span class="Special"> <- </span>add column:number, <span class="Constant">1:literal</span> + <span class="muControl">loop</span> <span class="Delimiter">}</span> - show-screen screen:address - <span class="muControl">reply</span> editor:address:editor-data/same-as-ingredient:0 ] <span class="muScenario">scenario</span> editor-initially-prints-multiple-lines [ - assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span> + assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">5:literal/height</span> run [ s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> .def .</span> <span class="Constant"> . .</span> @@ -397,26 +399,27 @@ container editor-data [ ] <span class="muScenario">scenario</span> editor-initially-handles-offsets [ - assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span> + assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">5:literal/height</span> run [ s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">1:literal/left</span>, <span class="Constant">5:literal/right</span> + new-editor s:address:array:character, screen:address, <span class="Constant">1:literal/left</span>, <span class="Constant">5:literal/right</span> ] screen-should-contain [ - <span class="Constant"> . abc .</span> <span class="Constant"> . .</span> + <span class="Constant"> . abc .</span> <span class="Constant"> . .</span> ] ] <span class="muScenario">scenario</span> editor-initially-prints-multiple-lines-at-offset [ - assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span> + assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">5:literal/height</span> run [ s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">1:literal/left</span>, <span class="Constant">5:literal/right</span> + new-editor s:address:array:character, screen:address, <span class="Constant">1:literal/left</span>, <span class="Constant">5:literal/right</span> ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> . abc .</span> <span class="Constant"> . def .</span> <span class="Constant"> . .</span> @@ -424,17 +427,41 @@ container editor-data [ ] <span class="muScenario">scenario</span> editor-initially-wraps-long-lines [ - assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span> + assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">5:literal/height</span> run [ s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc def]</span> - new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc ↩.</span> <span class="Constant"> .def .</span> <span class="Constant"> . .</span> ] screen-should-contain-in-color, <span class="Constant">245:literal/grey</span> [ + <span class="Constant"> . .</span> + <span class="Constant"> . ↩.</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + ] +] + +<span class="muScenario">scenario</span> editor-initially-wraps-barely-long-lines [ + assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">5:literal/height</span> + run [ + s:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + ] + <span class="Comment"># still wrap, even though the line would fit. We need room to click on the</span> + <span class="Comment"># end of the line</span> + screen-should-contain [ + <span class="Constant"> . .</span> +<span class="Constant"> .abcd↩.</span> + <span class="Constant"> .e .</span> + <span class="Constant"> . .</span> + ] + screen-should-contain-in-color, <span class="Constant">245:literal/grey</span> [ + <span class="Constant"> . .</span> <span class="Constant"> . ↩.</span> <span class="Constant"> . .</span> <span class="Constant"> . .</span> @@ -442,10 +469,10 @@ container editor-data [ ] <span class="muScenario">scenario</span> editor-initializes-empty-text [ - assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span> + assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">5:literal/height</span> run [ 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] @@ -455,86 +482,112 @@ container editor-data [ <span class="Constant"> . .</span> ] memory-should-contain [ - 3<span class="Special"> <- </span>0 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> 4<span class="Special"> <- </span>0 <span class="Comment"># cursor column</span> ] ] <span class="SalientComment">## handling events from the keyboard, mouse, touch screen, ...</span> -<span class="Comment"># Takes a chain of editors (chained using editor-data.next-editor), sends each</span> -<span class="Comment"># event from the console to each editor.</span> <span class="muRecipe">recipe</span> event-loop [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> console:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - editor:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + env:address:programming-environment-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + recipes:address:editor-data<span class="Special"> <- </span>get env:address:programming-environment-data/deref, recipes:offset + current-sandbox:address:editor-data<span class="Special"> <- </span>get env:address:programming-environment-data/deref, current-sandbox:offset + sandbox-in-focus?:address:boolean<span class="Special"> <- </span>get-address env:address:programming-environment-data/deref, sandbox-in-focus?:offset <span class="Delimiter">{</span> - <span class="Comment"># send each event to each editor</span> + <span class="Comment"># looping over each (keyboard or touch) event as it occurs</span> +<span class="Constant"> +next-event</span> e:event, console:address, found?:boolean, quit?:boolean<span class="Special"> <- </span>read-event console:address <span class="muControl">loop-unless</span> found?:boolean <span class="muControl">break-if</span> quit?:boolean <span class="Comment"># only in tests</span> trace <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span> -<span class="CommentedCode">#? $print [--- new event</span> -<span class="CommentedCode">#? ] #? 1</span> - curr:address:editor-data<span class="Special"> <- </span>copy editor:address:editor-data + <span class="Comment"># check for global events that will trigger regardless of which editor has focus</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> curr:address:editor-data - handle-event screen:address, console:address, curr:address:editor-data, e:event - curr:address:editor-data<span class="Special"> <- </span>get curr:address:editor-data/deref, next-editor:offset - <span class="muControl">loop</span> + k:address:number<span class="Special"> <- </span>maybe-convert e:event, keycode:variant + <span class="muControl">break-unless</span> k:address:number + <span class="Comment"># F10? load all code and run all sandboxes.</span> + <span class="Delimiter">{</span> + do-run?:boolean<span class="Special"> <- </span>equal k:address:number/deref, <span class="Constant">65526:literal/F10</span> + <span class="muControl">break-unless</span> do-run?:boolean + run-sandboxes env:address:programming-environment-data + <span class="muControl">jump</span> <span class="Constant">+continue:label</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> - <span class="Comment"># after each non-trivial event, render all editors</span> - curr:address:editor-data<span class="Special"> <- </span>copy editor:address:editor-data + <span class="Comment"># 'touch' event - send to both editors</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> curr:address:editor-data - render curr:address:editor-data - curr:address:editor-data<span class="Special"> <- </span>get curr:address:editor-data/deref, next-editor:offset - <span class="muControl">loop</span> + t:address:touch-event<span class="Special"> <- </span>maybe-convert e:event, touch:variant + <span class="muControl">break-unless</span> t:address:touch-event + _<span class="Special"> <- </span>move-cursor-in-editor screen:address, recipes:address:editor-data, t:address:touch-event/deref + sandbox-in-focus?:address:boolean/deref<span class="Special"> <- </span>move-cursor-in-editor screen:address, current-sandbox:address:editor-data, t:address:touch-event/deref + <span class="muControl">jump</span> <span class="Constant">+continue:label</span> <span class="Delimiter">}</span> - <span class="Comment"># ..and position the cursor</span> - curr:address:editor-data<span class="Special"> <- </span>copy editor:address:editor-data + <span class="Comment"># if it's not global, send to appropriate editor</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> curr:address:editor-data <span class="Delimiter">{</span> - in-focus?:boolean<span class="Special"> <- </span>get curr:address:editor-data/deref, in-focus?:offset - <span class="muControl">break-unless</span> in-focus?:boolean - cursor-row:number<span class="Special"> <- </span>get curr:address:editor-data/deref, cursor-row:offset - cursor-column:number<span class="Special"> <- </span>get curr:address:editor-data/deref, cursor-column:offset - move-cursor screen:address, cursor-row:number, cursor-column:number + <span class="muControl">break-if</span> sandbox-in-focus?:address:boolean/deref + handle-event screen:address, console:address, recipes:address:editor-data, e:event <span class="Delimiter">}</span> - curr:address:editor-data<span class="Special"> <- </span>get curr:address:editor-data/deref, next-editor:offset - <span class="muControl">loop</span> + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> sandbox-in-focus?:address:boolean/deref + handle-event screen:address, console:address, current-sandbox:address:editor-data, e:event + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Constant"> +continue</span> + <span class="Comment"># if no more events currently left to process, render</span> + <span class="Comment"># todo: test this</span> + <span class="Delimiter">{</span> + more-events?:boolean<span class="Special"> <- </span>has-more-events? console:address + <span class="muControl">break-if</span> more-events?:boolean + render-all screen:address, env:address:programming-environment-data <span class="Delimiter">}</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] +<span class="Comment"># helper for testing a single editor</span> +<span class="muRecipe">recipe</span> editor-event-loop [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + console:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + editor:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="Delimiter">{</span> + <span class="Comment"># looping over each (keyboard or touch) event as it occurs</span> +<span class="Constant"> +next-event</span> + e:event, console:address, found?:boolean, quit?:boolean<span class="Special"> <- </span>read-event console:address + <span class="muControl">loop-unless</span> found?:boolean + <span class="muControl">break-if</span> quit?:boolean <span class="Comment"># only in tests</span> + trace <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span> + <span class="Comment"># 'touch' event - send to both editors</span> + <span class="Delimiter">{</span> + t:address:touch-event<span class="Special"> <- </span>maybe-convert e:event, touch:variant + <span class="muControl">break-unless</span> t:address:touch-event + move-cursor-in-editor screen:address, editor:address:editor-data, t:address:touch-event/deref + <span class="muControl">jump</span> <span class="Constant">+continue:label</span> + <span class="Delimiter">}</span> + <span class="Comment"># other events - send to appropriate editor</span> + handle-event screen:address, console:address, editor:address:editor-data, e:event +<span class="Constant"> +continue</span> + row:number, screen:address<span class="Special"> <- </span>render screen:address, editor:address:editor-data + <span class="Comment"># clear next line, in case we just processed a backspace</span> + left:number<span class="Special"> <- </span>get editor:address:editor-data/deref, left:offset + right:number<span class="Special"> <- </span>get editor:address:editor-data/deref, right:offset + row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> + move-cursor screen:address, row:number, left:number + clear-line-delimited screen:address, left:number, right:number + <span class="muControl">loop</span> + <span class="Delimiter">}</span> +] + <span class="muRecipe">recipe</span> handle-event [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">50:literal</span> screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> console:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> editor:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> e:event<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Comment"># 'touch' event</span> - <span class="Delimiter">{</span> - t:address:touch-event<span class="Special"> <- </span>maybe-convert e:event, touch:variant - <span class="muControl">break-unless</span> t:address:touch-event - move-cursor-in-editor editor:address:editor-data, t:address:touch-event/deref - <span class="muControl">reply</span> - <span class="Delimiter">}</span> - <span class="Comment"># other events trigger only if this editor is in focus</span> -<span class="CommentedCode">#? $print [checking ], editor:address:editor-data, [ </span> -<span class="CommentedCode">#? ] #? 1</span> -<span class="CommentedCode">#? x:address:boolean <- get-address editor:address:editor-data/deref, in-focus?:offset #? 1</span> -<span class="CommentedCode">#? $print [address of focus: ], x:address:boolean, [ </span> -<span class="CommentedCode">#? ] #? 1</span> - in-focus?:address:boolean<span class="Special"> <- </span>get-address editor:address:editor-data/deref, in-focus?:offset -<span class="CommentedCode">#? $print [ at ], in-focus?:address:boolean, [ </span> -<span class="CommentedCode">#? ] #? 1</span> - <span class="muControl">reply-unless</span> in-focus?:address:boolean/deref -<span class="CommentedCode">#? $print [in focus: ], editor:address:editor-data, [ </span> -<span class="CommentedCode">#? ] #? 1</span> + <span class="muControl">reply-unless</span> editor:address:editor-data <span class="Comment"># typing a character</span> <span class="Delimiter">{</span> c:address:character<span class="Special"> <- </span>maybe-convert e:event, text:variant @@ -546,7 +599,7 @@ container editor-data [ delete-before-cursor editor:address:editor-data <span class="muControl">reply</span> <span class="Delimiter">}</span> - insert-at-cursor editor:address:editor-data, c:address:character/deref + insert-at-cursor editor:address:editor-data, c:address:character/deref, screen:address <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Comment"># otherwise it's a special key to control the editor</span> @@ -557,7 +610,8 @@ container editor-data [ cursor-row:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, cursor-row:offset cursor-column:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, cursor-column:offset screen-height:number<span class="Special"> <- </span>screen-height screen:address - top:number<span class="Special"> <- </span>get editor:address:editor-data/deref, top:offset + left:number<span class="Special"> <- </span>get editor:address:editor-data/deref, left:offset + right:number<span class="Special"> <- </span>get editor:address:editor-data/deref, right:offset <span class="Comment"># arrows; update cursor-row and cursor-column, leave before-cursor to 'render'.</span> <span class="Comment"># right arrow</span> <span class="Delimiter">{</span> @@ -574,7 +628,7 @@ container editor-data [ was-at-newline?:boolean<span class="Special"> <- </span>equal old-cursor-character:character, <span class="Constant">10:literal/newline</span> <span class="muControl">break-unless</span> was-at-newline?:boolean cursor-row:address:number/deref<span class="Special"> <- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span> - cursor-column:address:number/deref<span class="Special"> <- </span>copy <span class="Constant">0:literal</span> + cursor-column:address:number/deref<span class="Special"> <- </span>copy left:number <span class="Comment"># todo: what happens when cursor is too far down?</span> screen-height:number<span class="Special"> <- </span>screen-height screen:address above-screen-bottom?:boolean<span class="Special"> <- </span>lesser-than cursor-row:address:number/deref, screen-height:number @@ -584,21 +638,17 @@ container editor-data [ <span class="Comment"># if the line wraps, move cursor to start of next row</span> <span class="Delimiter">{</span> <span class="Comment"># if we're at the column just before the wrap indicator</span> - right:number<span class="Special"> <- </span>get editor:address:editor-data/deref, right:offset wrap-column:number<span class="Special"> <- </span>subtract right:number, <span class="Constant">1:literal</span> at-wrap?:boolean<span class="Special"> <- </span>equal cursor-column:address:number/deref, wrap-column:number <span class="muControl">break-unless</span> at-wrap?:boolean - <span class="Comment"># and if character after next isn't newline</span> -<span class="CommentedCode">#? $print [aaa] #? 1</span> + <span class="Comment"># and if next character isn't newline</span> new-cursor:address:duplex-list<span class="Special"> <- </span>next-duplex old-cursor:address:duplex-list <span class="muControl">break-unless</span> new-cursor:address:duplex-list - next:address:duplex-list<span class="Special"> <- </span>next-duplex new-cursor:address:duplex-list - <span class="muControl">break-unless</span> next:address:duplex-list - next-character:character<span class="Special"> <- </span>get next:address:duplex-list/deref, value:offset + next-character:character<span class="Special"> <- </span>get new-cursor:address:duplex-list/deref, value:offset newline?:boolean<span class="Special"> <- </span>equal next-character:character, <span class="Constant">10:literal/newline</span> <span class="muControl">break-if</span> newline?:boolean cursor-row:address:number/deref<span class="Special"> <- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span> - cursor-column:address:number/deref<span class="Special"> <- </span>copy <span class="Constant">0:literal</span> + cursor-column:address:number/deref<span class="Special"> <- </span>copy left:number <span class="Comment"># todo: what happens when cursor is too far down?</span> above-screen-bottom?:boolean<span class="Special"> <- </span>lesser-than cursor-row:address:number/deref, screen-height:number assert above-screen-bottom?:boolean, <span class="Constant">[unimplemented: moving past bottom of screen]</span> @@ -611,6 +661,7 @@ container editor-data [ <span class="Delimiter">{</span> move-to-previous-character?:boolean<span class="Special"> <- </span>equal k:address:number/deref, <span class="Constant">65515:literal/left-arrow</span> <span class="muControl">break-unless</span> move-to-previous-character?:boolean +<span class="CommentedCode">#? trace [app], [left arrow] #? 1</span> <span class="Comment"># if not at start of text (before-cursor at § sentinel)</span> prev:address:duplex-list<span class="Special"> <- </span>prev-duplex before-cursor:address:address:duplex-list/deref <span class="muControl">break-unless</span> prev:address:duplex-list @@ -618,6 +669,7 @@ container editor-data [ <span class="Delimiter">{</span> at-left-margin?:boolean<span class="Special"> <- </span>equal cursor-column:address:number/deref, <span class="Constant">0:literal</span> <span class="muControl">break-if</span> at-left-margin?:boolean +<span class="CommentedCode">#? trace [app], [decrementing] #? 1</span> cursor-column:address:number/deref<span class="Special"> <- </span>subtract cursor-column:address:number/deref, <span class="Constant">1:literal</span> <span class="muControl">reply</span> <span class="Delimiter">}</span> @@ -628,6 +680,7 @@ container editor-data [ prevc:character<span class="Special"> <- </span>get before-cursor:address:address:duplex-list/deref/deref, value:offset previous-character-is-newline?:boolean<span class="Special"> <- </span>equal prevc:character, <span class="Constant">10:literal/newline</span> <span class="muControl">break-unless</span> previous-character-is-newline?:boolean +<span class="CommentedCode">#? trace [app], [previous line] #? 1</span> <span class="Comment"># compute length of previous line</span> end-of-line:number<span class="Special"> <- </span>previous-line-length before-cursor:address:address:duplex-list/deref, d:address:duplex-list cursor-row:address:number/deref<span class="Special"> <- </span>subtract cursor-row:address:number/deref, <span class="Constant">1:literal</span> @@ -637,7 +690,6 @@ container editor-data [ <span class="Comment"># if before-cursor is not at newline, we're just at a wrapped line</span> assert cursor-row:address:number/deref, <span class="Constant">[unimplemented: moving cursor above top of screen]</span> cursor-row:address:number/deref<span class="Special"> <- </span>subtract cursor-row:address:number/deref, <span class="Constant">1:literal</span> - right:number<span class="Special"> <- </span>get editor:address:editor-data/deref, right:offset cursor-column:address:number/deref<span class="Special"> <- </span>subtract right:number, <span class="Constant">1:literal</span> <span class="Comment"># leave room for wrap icon</span> <span class="Delimiter">}</span> <span class="Comment"># down arrow</span> @@ -657,7 +709,7 @@ container editor-data [ move-to-previous-line?:boolean<span class="Special"> <- </span>equal k:address:number/deref, <span class="Constant">65517:literal/up-arrow</span> <span class="muControl">break-unless</span> move-to-previous-line?:boolean <span class="Comment"># todo: support scrolling</span> - already-at-top?:boolean<span class="Special"> <- </span>lesser-or-equal cursor-row:address:number/deref, top:number + already-at-top?:boolean<span class="Special"> <- </span>lesser-or-equal cursor-row:address:number/deref, <span class="Constant">1:literal/top</span> <span class="muControl">break-if</span> already-at-top?:boolean <span class="CommentedCode">#? $print [moving up</span> <span class="CommentedCode">#? ] #? 1</span> @@ -666,58 +718,58 @@ container editor-data [ <span class="Delimiter">}</span> ] +<span class="Comment"># process click, return if it was on current editor</span> +<span class="Comment"># todo: ignores menu bar (for now just displays shortcuts)</span> <span class="muRecipe">recipe</span> move-cursor-in-editor [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> editor:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> t:touch-event<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Comment"># always reset focus to start</span> - in-focus?:address:boolean<span class="Special"> <- </span>get-address editor:address:editor-data/deref, in-focus?:offset - in-focus?:address:boolean/deref<span class="Special"> <- </span>copy <span class="Constant">0:literal/true</span> + <span class="muControl">reply-unless</span> editor:address:editor-data, <span class="Constant">0:literal/false</span> click-column:number<span class="Special"> <- </span>get t:touch-event, column:offset left:number<span class="Special"> <- </span>get editor:address:editor-data/deref, left:offset too-far-left?:boolean<span class="Special"> <- </span>lesser-than click-column:number, left:number - <span class="muControl">reply-if</span> too-far-left?:boolean + <span class="muControl">reply-if</span> too-far-left?:boolean, <span class="Constant">0:literal/false</span> right:number<span class="Special"> <- </span>get editor:address:editor-data/deref, right:offset too-far-right?:boolean<span class="Special"> <- </span>greater-than click-column:number, right:number - <span class="muControl">reply-if</span> too-far-right?:boolean -<span class="CommentedCode">#? $print [focus now at ], editor:address:editor-data, [ </span> -<span class="CommentedCode">#? ] #? 2</span> - <span class="Comment"># click on this window; gain focus</span> - in-focus?:address:boolean/deref<span class="Special"> <- </span>copy <span class="Constant">1:literal/true</span> + <span class="muControl">reply-if</span> too-far-right?:boolean, <span class="Constant">0:literal/false</span> <span class="Comment"># update cursor</span> cursor-row:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, cursor-row:offset cursor-row:address:number/deref<span class="Special"> <- </span>get t:touch-event, row:offset cursor-column:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, cursor-column:offset cursor-column:address:number/deref<span class="Special"> <- </span>get t:touch-event, column:offset -<span class="CommentedCode">#? $print [column is at: ], cursor-column:address:number, [ </span> -<span class="CommentedCode">#? ] #? 1</span> + render screen:address, editor:address:editor-data + <span class="Comment"># gain focus</span> + <span class="muControl">reply</span> <span class="Constant">1:literal/true</span> ] <span class="muRecipe">recipe</span> insert-at-cursor [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> editor:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> c:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="CommentedCode">#? $print [insert ], c:character, [ </span> <span class="CommentedCode">#? ] #? 1</span> before-cursor:address:address:duplex-list<span class="Special"> <- </span>get-address editor:address:editor-data/deref, before-cursor:offset d:address:duplex-list<span class="Special"> <- </span>get editor:address:editor-data/deref, data:offset insert-duplex c:character, before-cursor:address:address:duplex-list/deref - screen:address<span class="Special"> <- </span>get editor:address:editor-data/deref, screen:offset + before-cursor:address:address:duplex-list/deref<span class="Special"> <- </span>next-duplex before-cursor:address:address:duplex-list/deref cursor-row:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, cursor-row:offset cursor-column:address:number<span class="Special"> <- </span>get-address editor:address:editor-data/deref, cursor-column:offset + left:number<span class="Special"> <- </span>get editor:address:editor-data/deref, left:offset + right:number<span class="Special"> <- </span>get editor:address:editor-data/deref, right:offset <span class="Comment"># update cursor: if newline, move cursor to start of next line</span> <span class="Comment"># todo: bottom of screen</span> <span class="Delimiter">{</span> newline?:boolean<span class="Special"> <- </span>equal c:character, <span class="Constant">10:literal/newline</span> <span class="muControl">break-unless</span> newline?:boolean cursor-row:address:number/deref<span class="Special"> <- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span> - cursor-column:address:number/deref<span class="Special"> <- </span>copy <span class="Constant">0:literal</span> + cursor-column:address:number/deref<span class="Special"> <- </span>copy left:number <span class="muControl">reply</span> <span class="Delimiter">}</span> <span class="Comment"># if the line wraps at the cursor, move cursor to start of next row</span> <span class="Delimiter">{</span> <span class="Comment"># if we're at the column just before the wrap indicator</span> - right:number<span class="Special"> <- </span>get editor:address:editor-data/deref, right:offset wrap-column:number<span class="Special"> <- </span>subtract right:number, <span class="Constant">1:literal</span> <span class="CommentedCode">#? $print [wrap? ], cursor-column:address:number/deref, [ vs ], wrap-column:number, [ </span> <span class="CommentedCode">#? ] #? 1</span> @@ -782,24 +834,116 @@ container editor-data [ <span class="muControl">reply</span> result:number ] +<span class="muRecipe">recipe</span> render-all [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">40:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + env:address:programming-environment-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + recipes:address:editor-data<span class="Special"> <- </span>get env:address:programming-environment-data/deref, recipes:offset + current-sandbox:address:editor-data<span class="Special"> <- </span>get env:address:programming-environment-data/deref, current-sandbox:offset + sandbox-in-focus?:boolean<span class="Special"> <- </span>get env:address:programming-environment-data/deref, sandbox-in-focus?:offset + <span class="Comment"># render recipes, along with any warnings</span> + left:number<span class="Special"> <- </span>get recipes:address:editor-data/deref, left:offset + right:number<span class="Special"> <- </span>get recipes:address:editor-data/deref, right:offset + row:number, screen:address<span class="Special"> <- </span>render screen:address, recipes:address:editor-data + recipe-warnings:address:array:character<span class="Special"> <- </span>get env:address:programming-environment-data/deref, recipe-warnings:offset + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> recipe-warnings:address:array:character + row:number, screen:address<span class="Special"> <- </span>render-string screen:address, recipe-warnings:address:array:character, left:number, right:number, <span class="Constant">1:literal/red</span>, row:number + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="Comment"># no warnings? move to next lin</span> + <span class="muControl">break-if</span> recipe-warnings:address:array:character + row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> + <span class="Delimiter">}</span> + <span class="Comment"># draw dotted line after recipes</span> + draw-horizontal screen:address, row:number, left:number, right:number, <span class="Constant">9480:literal/horizontal-dotted</span> + <span class="Comment"># clear next line, in case we just processed a backspace</span> + row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> + move-cursor screen:address, row:number, left:number + clear-line-delimited screen:address, left:number, right:number + <span class="Comment"># render sandboxes along with warnings for each</span> + left:number<span class="Special"> <- </span>get current-sandbox:address:editor-data/deref, left:offset + right:number<span class="Special"> <- </span>get current-sandbox:address:editor-data/deref, right:offset + row:number, screen:address<span class="Special"> <- </span>render screen:address, current-sandbox:address:editor-data + row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> + draw-horizontal screen:address, row:number, left:number, right:number, <span class="Constant">9473:literal/horizontal-double</span> + sandbox:address:sandbox-data<span class="Special"> <- </span>get env:address:programming-environment-data/deref, sandbox:offset + row:number, screen:address<span class="Special"> <- </span>render-sandboxes screen:address, sandbox:address:sandbox-data, left:number, right:number, row:number + <span class="Comment"># clear next line, in case we just processed a backspace</span> + row:number<span class="Special"> <- </span>add row:number, <span class="Constant">1:literal</span> + move-cursor screen:address, row:number, left:number + clear-line-delimited screen:address, left:number, right:number + update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:boolean + show-screen screen:address + <span class="muControl">reply</span> screen:address/same-as-ingredient:0 +] + +<span class="muRecipe">recipe</span> render-sandboxes [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">40:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + sandbox:address:sandbox-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + left:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + right:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + row:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="muControl">reply-unless</span> sandbox:address:sandbox-data, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0 + screen-height:number<span class="Special"> <- </span>screen-width screen:address + at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal row:number screen-height:number + <span class="muControl">reply-if</span> at-bottom?:boolean, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0 + <span class="Comment"># render sandbox contents</span> + sandbox-data:address:array:character<span class="Special"> <- </span>get sandbox:address:sandbox-data/deref, data:offset + row:number, screen:address<span class="Special"> <- </span>render-string screen:address, sandbox-data:address:array:character, left:number, right:number, <span class="Constant">7:literal/white</span>, row:number + <span class="Comment"># render sandbox warnings or response, in that order</span> + sandbox-response:address:array:character<span class="Special"> <- </span>get sandbox:address:sandbox-data/deref, response:offset + sandbox-warnings:address:array:character<span class="Special"> <- </span>get sandbox:address:sandbox-data/deref, warnings:offset + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> sandbox-warnings:address:array:character + row:number, screen:address<span class="Special"> <- </span>render-string screen:address, sandbox-warnings:address:array:character, left:number, right:number, <span class="Constant">1:literal/red</span>, row:number + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> sandbox-warnings:address:array:character + row:number, screen:address<span class="Special"> <- </span>render-string screen:address, sandbox-response:address:array:character, left:number, right:number, <span class="Constant">245:literal/grey</span>, row:number + <span class="Delimiter">}</span> + <span class="Comment"># draw solid line after sandbox</span> + draw-horizontal screen:address, row:number, left:number, right:number, <span class="Constant">9473:literal/horizontal-double</span> + <span class="Comment"># draw next sandbox</span> + next-sandbox:address:sandbox-data<span class="Special"> <- </span>get sandbox:address:sandbox-data/deref, next-sandbox:offset + row:number, screen:address<span class="Special"> <- </span>render-sandboxes screen:address, next-sandbox:address:sandbox-data, left:number, right:number, row:number + <span class="muControl">reply</span> row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0 +] + +<span class="muRecipe">recipe</span> update-cursor [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">40:literal</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + recipes:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + current-sandbox:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + sandbox-in-focus?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> sandbox-in-focus?:boolean +<span class="CommentedCode">#? $print [recipes in focus</span> +<span class="CommentedCode">#? ] #? 1</span> + cursor-row:number<span class="Special"> <- </span>get recipes:address:editor-data/deref, cursor-row:offset + cursor-column:number<span class="Special"> <- </span>get recipes:address:editor-data/deref, cursor-column:offset + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> sandbox-in-focus?:boolean +<span class="CommentedCode">#? $print [sandboxes in focus</span> +<span class="CommentedCode">#? ] #? 1</span> + cursor-row:number<span class="Special"> <- </span>get current-sandbox:address:editor-data/deref, cursor-row:offset + cursor-column:number<span class="Special"> <- </span>get current-sandbox:address:editor-data/deref, cursor-column:offset + <span class="Delimiter">}</span> + move-cursor screen:address, cursor-row:number, cursor-column:number +] + <span class="muScenario">scenario</span> editor-handles-empty-event-queue [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> -<span class="CommentedCode">#? 3:number <- get screen:address/deref, num-rows:offset #? 1</span> -<span class="CommentedCode">#? $print [0: ], screen:address, [: ], 3:number, [ </span> -<span class="CommentedCode">#? ] #? 1</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> -<span class="CommentedCode">#? $print [1: ], screen:address, [ </span> -<span class="CommentedCode">#? ] #? 1</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console <span class="Constant">[]</span> -<span class="CommentedCode">#? $print [8: ], screen:address, [ </span> -<span class="CommentedCode">#? ] #? 1</span> run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] -<span class="CommentedCode">#? $print [9: ], screen:address, [ </span> -<span class="CommentedCode">#? ] #? 1</span> screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> . .</span> ] @@ -808,21 +952,22 @@ container editor-data [ <span class="muScenario">scenario</span> editor-handles-mouse-clicks [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 0, 1 <span class="Comment"># on the 'b'</span> + left-click 1, 1 <span class="Comment"># on the 'b'</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> . .</span> ] memory-should-contain [ - 3<span class="Special"> <- </span>0 <span class="Comment"># cursor is at row 0..</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># cursor is at row 0..</span> 4<span class="Special"> <- </span>1 <span class="Comment"># ..and column 1</span> ] ] @@ -830,17 +975,17 @@ container editor-data [ <span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 0, 7 <span class="Comment"># last line, to the right of text</span> + left-click 1, 7 <span class="Comment"># last line, to the right of text</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ - 3<span class="Special"> <- </span>0 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> 4<span class="Special"> <- </span>3 <span class="Comment"># cursor column</span> ] ] @@ -849,17 +994,17 @@ container editor-data [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 0, 7 <span class="Comment"># interior line, to the right of text</span> + left-click 1, 7 <span class="Comment"># interior line, to the right of text</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ - 3<span class="Special"> <- </span>0 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> 4<span class="Special"> <- </span>3 <span class="Comment"># cursor column</span> ] ] @@ -868,17 +1013,17 @@ container editor-data [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 2, 7 <span class="Comment"># below text</span> + left-click 3, 7 <span class="Comment"># below text</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ - 3<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>2 <span class="Comment"># cursor row</span> 4<span class="Special"> <- </span>3 <span class="Comment"># cursor column</span> ] ] @@ -887,22 +1032,23 @@ container editor-data [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> <span class="Comment"># editor occupies only left half of screen</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> assume-console [ <span class="Comment"># click on right half of screen</span> left-click 3, 8 ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> . .</span> ] memory-should-contain [ - 3<span class="Special"> <- </span>0 <span class="Comment"># no change to cursor row</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># no change to cursor row</span> 4<span class="Special"> <- </span>0 <span class="Comment"># ..or column</span> ] ] @@ -910,14 +1056,15 @@ container editor-data [ <span class="muScenario">scenario</span> editor-inserts-characters-into-empty-editor [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> assume-console [ type <span class="Constant">[abc]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> . .</span> ] @@ -926,16 +1073,17 @@ container editor-data [ <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ type <span class="Constant">[0]</span> - left-click 0, 2 + left-click 1, 2 type <span class="Constant">[d]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .0adbc .</span> <span class="Constant"> . .</span> ] @@ -944,15 +1092,16 @@ container editor-data [ <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-2 [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 0, 5 <span class="Comment"># right of last line</span> + left-click 1, 5 <span class="Comment"># right of last line</span> type <span class="Constant">[d]</span> <span class="Comment"># should append</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abcd .</span> <span class="Constant"> . .</span> ] @@ -961,15 +1110,16 @@ container editor-data [ <span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-3 [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ left-click 3, 5 <span class="Comment"># below all text</span> type <span class="Constant">[d]</span> <span class="Comment"># should append</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abcd .</span> <span class="Constant"> . .</span> ] @@ -979,15 +1129,16 @@ container editor-data [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ left-click 3, 5 <span class="Comment"># below all text</span> type <span class="Constant">[e]</span> <span class="Comment"># should append</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> .de .</span> <span class="Constant"> . .</span> @@ -998,61 +1149,38 @@ container editor-data [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ left-click 3, 5 <span class="Comment"># below all text</span> type <span class="Constant">[ef]</span> <span class="Comment"># should append multiple characters in order</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> .def .</span> <span class="Constant"> . .</span> ] ] -<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-6 [ - assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> - <span class="Comment"># text fills line</span> - 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> - <span class="Comment"># position cursor at end</span> - assume-console [ - left-click 3, 0 - ] - run [ - event-loop screen:address, console:address, 2:address:editor-data - 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset - 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset - ] - <span class="Comment"># text shouldn't wrap</span> - screen-should-contain [ - <span class="Constant"> .abcde .</span> - <span class="Constant"> . .</span> - ] - <span class="Comment"># cursor should wrap</span> - memory-should-contain [ - 3<span class="Special"> <- </span>1 - 4<span class="Special"> <- </span>0 - ] -] - <span class="muScenario">scenario</span> editor-wraps-line-on-insert [ - assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span> - 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcd]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">5:literal/height</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> <span class="Comment"># type a letter</span> assume-console [ type <span class="Constant">[e]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] <span class="Comment"># no wrap yet</span> screen-should-contain [ -<span class="Constant"> .eabcd.</span> + <span class="Constant"> . .</span> + <span class="Constant"> .eabc .</span> + <span class="Constant"> . .</span> <span class="Constant"> . .</span> ] <span class="Comment"># type a second letter</span> @@ -1060,28 +1188,30 @@ container editor-data [ type <span class="Constant">[f]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] <span class="Comment"># now wrap</span> screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .efab↩.</span> - <span class="Constant"> .cd .</span> + <span class="Constant"> .c .</span> <span class="Constant"> . .</span> ] ] <span class="muScenario">scenario</span> editor-moves-cursor-after-inserting-characters [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> - 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab]</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> assume-console [ type <span class="Constant">[01]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ - <span class="Constant"> .01abc .</span> + <span class="Constant"> . .</span> + <span class="Constant"> .01ab .</span> <span class="Constant"> . .</span> ] ] @@ -1089,23 +1219,24 @@ container editor-data [ <span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> assume-console [ - left-click 0, 4 <span class="Comment"># line is full; no wrap icon yet</span> + left-click 1, 4 <span class="Comment"># line is full; no wrap icon yet</span> type <span class="Constant">[f]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abcd↩ .</span> <span class="Constant"> .fe .</span> <span class="Constant"> . .</span> ] memory-should-contain [ - 3<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>2 <span class="Comment"># cursor row</span> 4<span class="Special"> <- </span>1 <span class="Comment"># cursor column</span> ] ] @@ -1113,23 +1244,24 @@ container editor-data [ <span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-2 [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> assume-console [ - left-click 0, 3 <span class="Comment"># right before the wrap icon</span> + left-click 1, 3 <span class="Comment"># right before the wrap icon</span> type <span class="Constant">[f]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abcf↩ .</span> <span class="Constant"> .de .</span> <span class="Constant"> . .</span> ] memory-should-contain [ - 3<span class="Special"> <- </span>1 <span class="Comment"># cursor row</span> + 3<span class="Special"> <- </span>2 <span class="Comment"># cursor row</span> 4<span class="Special"> <- </span>0 <span class="Comment"># cursor column</span> ] ] @@ -1137,66 +1269,92 @@ container editor-data [ <span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ type <span class="Constant">[0</span> <span class="Constant">1]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .0 .</span> <span class="Constant"> .1abc .</span> <span class="Constant"> . .</span> ] ] +<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline-2 [ + assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">1:literal/left</span>, <span class="Constant">10:literal/right</span> + assume-console [ + type <span class="Constant">[0</span> +<span class="Constant">1]</span> + ] + run [ + editor-event-loop screen:address, console:address, 2:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> . 0 .</span> + <span class="Constant"> . 1abc .</span> + <span class="Constant"> . .</span> + ] +] + <span class="muScenario">scenario</span> editor-clears-previous-line-completely-after-inserting-newline [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> <span class="Comment"># press just a 'newline'</span> assume-console [ type [ ] ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abcd↩ .</span> + <span class="Constant"> .e .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] <span class="Comment"># line should be fully cleared</span> screen-should-contain [ <span class="Constant"> . .</span> - <span class="Constant"> .abcde .</span> + <span class="Constant"> . .</span> + <span class="Constant"> .abcd↩ .</span> + <span class="Constant"> .e .</span> <span class="Constant"> . .</span> ] ] <span class="muScenario">scenario</span> editor-handles-backspace-key [ -<span class="CommentedCode">#? $print [=== new test</span> -<span class="CommentedCode">#? ] #? 1</span> assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> -<span class="CommentedCode">#? $print [editor: ], 2:address:editor-data, [ </span> -<span class="CommentedCode">#? ] #? 1</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 0, 1 + left-click 1, 1 type <span class="Constant">[«]</span> ] 3:event/backspace<span class="Special"> <- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">8:literal/backspace</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span> replace-in-console <span class="Constant">171:literal/«</span>, 3:event/backspace run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 5:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .bc .</span> <span class="Constant"> . .</span> ] memory-should-contain [ - 4<span class="Special"> <- </span>0 + 4<span class="Special"> <- </span>1 5<span class="Special"> <- </span>0 ] ] @@ -1204,87 +1362,71 @@ container editor-data [ <span class="muScenario">scenario</span> editor-clears-last-line-on-backspace [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> <span class="Comment"># just one character in final line</span> - 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> -<span class="Constant">d]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> +<span class="Constant">cd]</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> assume-console [ - left-click 1, 0 <span class="Comment"># cursor at only character in final line</span> + left-click 2, 0 <span class="Comment"># cursor at only character in final line</span> type <span class="Constant">[«]</span> ] 3:event/backspace<span class="Special"> <- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">8:literal/backspace</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span> replace-in-console <span class="Constant">171:literal/«</span>, 3:event/backspace run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abcd .</span> <span class="Constant"> . .</span> ] ] -<span class="muScenario">scenario</span> editor-handles-backspace-key-at-right-margin [ +<span class="muScenario">scenario</span> editor-moves-cursor-right-with-key [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> - <span class="Comment"># fill a line with text</span> - 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> - <span class="Comment"># position cursor at end</span> - assume-console [ - left-click 1, 3 <span class="Comment"># at end of text</span> - ] - run [ - event-loop screen:address, console:address, 2:address:editor-data - 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset - 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset - ] - <span class="Comment"># check that cursor wraps to next line</span> - memory-should-contain [ - 3<span class="Special"> <- </span>1 - 4<span class="Special"> <- </span>0 - ] - <span class="Comment"># now hit a backspace key</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - type <span class="Constant">[«]</span> + press 65514 <span class="Comment"># right arrow</span> + type <span class="Constant">[0]</span> ] - 5:event/backspace<span class="Special"> <- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">8:literal/backspace</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span> - replace-in-console <span class="Constant">171:literal/«</span>, 5:event/backspace run [ - event-loop screen:address, console:address, 2:address:editor-data - 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset - 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset - ] - <span class="Comment"># cursor unwraps</span> - memory-should-contain [ - 3<span class="Special"> <- </span>0 - 4<span class="Special"> <- </span>4 + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ - <span class="Constant"> .abcd .</span> + <span class="Constant"> . .</span> + <span class="Constant"> .a0bc .</span> <span class="Constant"> . .</span> ] ] -<span class="muScenario">scenario</span> editor-moves-cursor-right-with-key [ +<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> - 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> +<span class="Constant">d]</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ press 65514 <span class="Comment"># right arrow</span> + press 65514 <span class="Comment"># right arrow</span> + press 65514 <span class="Comment"># right arrow</span> + press 65514 <span class="Comment"># right arrow - next line</span> type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ - <span class="Constant"> .a0bc .</span> + <span class="Constant"> . .</span> + <span class="Constant"> .abc .</span> + <span class="Constant"> .0d .</span> <span class="Constant"> . .</span> ] ] -<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow [ +<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow-2 [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">1:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ press 65514 <span class="Comment"># right arrow</span> press 65514 <span class="Comment"># right arrow</span> @@ -1293,11 +1435,12 @@ container editor-data [ type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ - <span class="Constant"> .abc .</span> - <span class="Constant"> .0d .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . abc .</span> + <span class="Constant"> . 0d .</span> <span class="Constant"> . .</span> ] ] @@ -1305,63 +1448,84 @@ container editor-data [ <span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> assume-console [ - left-click 0, 3 + left-click 1, 3 press 65514 <span class="Comment"># right arrow</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abcd↩ .</span> <span class="Constant"> .ef .</span> <span class="Constant"> . .</span> ] memory-should-contain [ - 3<span class="Special"> <- </span>1 + 3<span class="Special"> <- </span>2 4<span class="Special"> <- </span>0 ] ] -<span class="muScenario">scenario</span> editor-does-not-wrap-cursor-when-line-does-not-wrap [ +<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow-2 [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> + <span class="Comment"># line just barely wrapping</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + <span class="Comment"># position cursor at last character before wrap and hit right-arrow</span> assume-console [ - left-click 0, 3 <span class="Comment"># one before right, in the last line</span> + left-click 1, 3 press 65514 <span class="Comment"># right arrow</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data + 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset + 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset + ] + memory-should-contain [ + 3<span class="Special"> <- </span>2 + 4<span class="Special"> <- </span>0 + ] + <span class="Comment"># now hit right arrow again</span> + assume-console [ + press 65514 + ] + run [ + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ - 3<span class="Special"> <- </span>0 - 4<span class="Special"> <- </span>4 + 3<span class="Special"> <- </span>2 + 4<span class="Special"> <- </span>1 ] ] -<span class="muScenario">scenario</span> editor-does-not-wrap-cursor-when-line-does-not-wrap-2 [ +<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow-3 [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> - 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde</span> -<span class="Constant">f]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">1:literal/left</span>, <span class="Constant">6:literal/right</span> assume-console [ - left-click 0, 3 <span class="Comment"># one before right, not the last line</span> + left-click 1, 4 press 65514 <span class="Comment"># right arrow</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> . abcd↩ .</span> + <span class="Constant"> . ef .</span> + <span class="Constant"> . .</span> + ] memory-should-contain [ - 3<span class="Special"> <- </span>0 - 4<span class="Special"> <- </span>4 + 3<span class="Special"> <- </span>2 + 4<span class="Special"> <- </span>1 ] ] @@ -1369,16 +1533,17 @@ container editor-data [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 0, 3 + left-click 1, 3 press 65514 <span class="Comment"># right arrow - next line</span> type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> .0d .</span> <span class="Constant"> . .</span> @@ -1388,16 +1553,17 @@ container editor-data [ <span class="muScenario">scenario</span> editor-moves-cursor-left-with-key [ assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 0, 2 + left-click 1, 2 press 65515 <span class="Comment"># left arrow</span> type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .a0bc .</span> <span class="Constant"> . .</span> ] @@ -1408,20 +1574,20 @@ container editor-data [ <span class="Comment"># initialize editor with two lines</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">d]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> <span class="Comment"># position cursor at start of second line (so there's no previous newline)</span> assume-console [ - left-click 1, 0 + left-click 2, 0 press 65515 <span class="Comment"># left arrow</span> - type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data + 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset + 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] - screen-should-contain [ - <span class="Constant"> .abc0 .</span> - <span class="Constant"> .d .</span> - <span class="Constant"> . .</span> + memory-should-contain [ + 3<span class="Special"> <- </span>1 + 4<span class="Special"> <- </span>3 ] ] @@ -1431,18 +1597,19 @@ container editor-data [ 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">g]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> <span class="Comment"># position cursor further down (so there's a newline before the character at</span> <span class="Comment"># the cursor)</span> assume-console [ - left-click 2, 0 + left-click 3, 0 press 65515 <span class="Comment"># left arrow</span> type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> .def0 .</span> <span class="Constant"> .g .</span> @@ -1455,17 +1622,18 @@ container editor-data [ 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def</span> <span class="Constant">g]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> <span class="Comment"># position cursor at start of text</span> assume-console [ - left-click 0, 0 + left-click 1, 0 press 65515 <span class="Comment"># left arrow should have no effect</span> type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .0abc .</span> <span class="Constant"> .def .</span> <span class="Constant"> .g .</span> @@ -1479,17 +1647,18 @@ container editor-data [ 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> d] - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> <span class="Comment"># position cursor right after empty line</span> assume-console [ - left-click 2, 0 + left-click 3, 0 press 65515 <span class="Comment"># left arrow</span> type <span class="Constant">[0]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data ] screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abc .</span> <span class="Constant"> .0 .</span> <span class="Constant"> .d .</span> @@ -1501,24 +1670,25 @@ d] assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> <span class="Comment"># initialize editor with text containing an empty line</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdef]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> screen-should-contain [ + <span class="Constant"> . .</span> <span class="Constant"> .abcd↩ .</span> <span class="Constant"> .ef .</span> <span class="Constant"> . .</span> ] <span class="Comment"># position cursor right after empty line</span> assume-console [ - left-click 1, 0 + left-click 2, 0 press 65515 <span class="Comment"># left arrow</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ - 3<span class="Special"> <- </span>0 <span class="Comment"># previous row</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># previous row</span> 4<span class="Special"> <- </span>3 <span class="Comment"># end of wrapped line</span> ] ] @@ -1527,18 +1697,18 @@ d] assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 1, 1 + left-click 2, 1 press 65517 <span class="Comment"># up arrow</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ - 3<span class="Special"> <- </span>0 + 3<span class="Special"> <- </span>1 4<span class="Special"> <- </span>1 ] ] @@ -1547,19 +1717,19 @@ d] assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> - <span class="Comment"># cursor starts out at (0, 0)</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + <span class="Comment"># cursor starts out at (1, 0)</span> assume-console [ press 65516 <span class="Comment"># down arrow</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] - <span class="Comment"># ..and ends at (1, 0)</span> + <span class="Comment"># ..and ends at (2, 0)</span> memory-should-contain [ - 3<span class="Special"> <- </span>1 + 3<span class="Special"> <- </span>2 4<span class="Special"> <- </span>0 ] ] @@ -1568,18 +1738,18 @@ d] assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> <span class="Constant">def]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 1, 3 + left-click 2, 3 press 65517 <span class="Comment"># up arrow</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ - 3<span class="Special"> <- </span>0 + 3<span class="Special"> <- </span>1 4<span class="Special"> <- </span>2 ] ] @@ -1588,164 +1758,402 @@ d] assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">de]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> assume-console [ - left-click 0, 3 + left-click 1, 3 press 65516 <span class="Comment"># down arrow</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + editor-event-loop screen:address, console:address, 2:address:editor-data 3:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset 4:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ - 3<span class="Special"> <- </span>1 + 3<span class="Special"> <- </span>2 4<span class="Special"> <- </span>2 ] ] <span class="muScenario">scenario</span> point-at-multiple-editors [ - assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> - <span class="Comment"># initialize an editor covering left half of screen</span> + assume-screen <span class="Constant">30:literal/width</span>, <span class="Constant">5:literal/height</span> + <span class="Comment"># initialize both halves of screen</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> - 3:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - <span class="Comment"># chain new editor to it, covering the right half of the screen</span> - 4:address:address:editor-data<span class="Special"> <- </span>get-address 2:address:editor-data/deref, next-editor:offset - 4:address:address:editor-data/deref<span class="Special"> <- </span>new-editor 3:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">5:literal/left</span>, <span class="Constant">10:literal/right</span> - <span class="Comment"># type one letter in each of them</span> + 2:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> + 3:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + <span class="Comment"># focus on both sides</span> assume-console [ - left-click 0, 1 - left-click 0, 8 + left-click 1, 1 + left-click 1, 17 ] + <span class="Comment"># check cursor column in each</span> run [ - event-loop screen:address, console:address, 2:address:editor-data - 5:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset - 6:number<span class="Special"> <- </span>get 4:address:address:editor-data/deref/deref, cursor-column:offset + event-loop screen:address, console:address, 3:address:programming-environment-data + 4:address:editor-data<span class="Special"> <- </span>get 3:address:programming-environment-data/deref, recipes:offset + 5:number<span class="Special"> <- </span>get 4:address:editor-data/deref, cursor-column:offset + 6:address:editor-data<span class="Special"> <- </span>get 3:address:programming-environment-data/deref, current-sandbox:offset + 7:number<span class="Special"> <- </span>get 6:address:editor-data/deref, cursor-column:offset ] memory-should-contain [ 5<span class="Special"> <- </span>1 - 6<span class="Special"> <- </span>8 + 7<span class="Special"> <- </span>17 ] ] -<span class="muScenario">scenario</span> editors-chain-to-cover-multiple-columns [ - assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> - <span class="Comment"># initialize an editor covering left half of screen</span> +<span class="muScenario">scenario</span> edit-multiple-editors [ + assume-screen <span class="Constant">30:literal/width</span>, <span class="Constant">5:literal/height</span> + <span class="Comment"># initialize both halves of screen</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> - 3:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - <span class="Comment"># chain new editor to it, covering the right half of the screen</span> - 4:address:address:editor-data<span class="Special"> <- </span>get-address 2:address:editor-data/deref, next-editor:offset - 4:address:address:editor-data/deref<span class="Special"> <- </span>new-editor 3:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">5:literal/left</span>, <span class="Constant">10:literal/right</span> - reset-focus 2:address:editor-data + 2:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> + 3:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character <span class="Comment"># type one letter in each of them</span> assume-console [ - left-click 0, 1 + left-click 1, 1 type <span class="Constant">[0]</span> - left-click 0, 6 + left-click 1, 17 type <span class="Constant">[1]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data - 5:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset - 6:number<span class="Special"> <- </span>get 4:address:address:editor-data/deref/deref, cursor-column:offset + event-loop screen:address, console:address, 3:address:programming-environment-data + 4:address:editor-data<span class="Special"> <- </span>get 3:address:programming-environment-data/deref, recipes:offset + 5:number<span class="Special"> <- </span>get 4:address:editor-data/deref, cursor-column:offset + 6:address:editor-data<span class="Special"> <- </span>get 3:address:programming-environment-data/deref, current-sandbox:offset + 7:number<span class="Special"> <- </span>get 6:address:editor-data/deref, cursor-column:offset ] screen-should-contain [ - <span class="Constant"> .a0bc d1ef .</span> - <span class="Constant"> . .</span> + <span class="Constant"> . run (F10) . # this line has a different background, but we don't test that yet</span> + <span class="Constant"> .a0bc ┊d1ef .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> ] memory-should-contain [ - 5<span class="Special"> <- </span>2 - 6<span class="Special"> <- </span>7 + 5<span class="Special"> <- </span>2 <span class="Comment"># cursor column of recipe editor</span> + 7<span class="Special"> <- </span>18 <span class="Comment"># cursor column of sandbox editor</span> ] <span class="Comment"># show the cursor at the right window</span> run [ screen:address<span class="Special"> <- </span>print-character screen:address, <span class="Constant">9251:literal/␣</span> ] screen-should-contain [ - <span class="Constant"> .a0bc d1␣f .</span> - <span class="Constant"> . .</span> + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> .a0bc ┊d1␣f .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> multiple-editors-cover-only-their-own-areas [ - assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> + assume-screen <span class="Constant">60:literal/width</span>, <span class="Constant">10:literal/height</span> run [ - <span class="Comment"># draw a divider</span> - draw-vertical screen:address, <span class="Constant">5:literal/divider</span>, <span class="Constant">0:literal/top</span>, <span class="Constant">5:literal/height</span> - <span class="Comment"># initialize editors on both sides of it and chain the two</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> - 3:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - 4:address:address:editor-data<span class="Special"> <- </span>get-address 2:address:editor-data/deref, next-editor:offset - 4:address:address:editor-data/deref<span class="Special"> <- </span>new-editor 3:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">6:literal/left</span>, <span class="Constant">10:literal/right</span> + 2:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> + 3:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character ] <span class="Comment"># divider isn't messed up</span> screen-should-contain [ - <span class="Constant"> .abc │def .</span> - <span class="Constant"> . │ .</span> - <span class="Constant"> . │ .</span> - <span class="Constant"> . │ .</span> - <span class="Constant"> . │ .</span> + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> .abc ┊def .</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> editor-in-focus-keeps-cursor [ - assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> - <span class="Comment"># initialize an editor covering left half of screen</span> + assume-screen <span class="Constant">30:literal/width</span>, <span class="Constant">5:literal/height</span> 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> - 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> - 3:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> - <span class="Comment"># chain new editor to it, covering the right half of the screen</span> - 4:address:address:editor-data<span class="Special"> <- </span>get-address 2:address:editor-data/deref, next-editor:offset - 4:address:address:editor-data/deref<span class="Special"> <- </span>new-editor 3:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">5:literal/left</span>, <span class="Constant">10:literal/right</span> - <span class="Comment"># initialize cursor</span> + 2:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> + <span class="Comment"># initialize programming environment and highlight cursor</span> + assume-console <span class="Constant">[]</span> run [ - reset-focus 2:address:editor-data - 5:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-row:offset - 6:number<span class="Special"> <- </span>get 2:address:editor-data/deref, cursor-column:offset - move-cursor screen:address, 5:number, 6:number + 3:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + event-loop screen:address, console:address, 3:address:programming-environment-data screen:address<span class="Special"> <- </span>print-character screen:address, <span class="Constant">9251:literal/␣</span> ] - <span class="Comment"># is it at the right place?</span> + <span class="Comment"># is cursor at the right place?</span> screen-should-contain [ - <span class="Constant"> .␣bc def .</span> - <span class="Constant"> . .</span> + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> .␣bc ┊def .</span> +<span class="Comment"># artifact of fake console: no events = no render</span> +<span class="Comment"># .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> ] <span class="Comment"># now try typing a letter</span> assume-console [ type <span class="Constant">[z]</span> ] run [ - event-loop screen:address, console:address, 2:address:editor-data + 3:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + event-loop screen:address, console:address, 3:address:programming-environment-data screen:address<span class="Special"> <- </span>print-character screen:address, <span class="Constant">9251:literal/␣</span> ] <span class="Comment"># cursor should still be right</span> screen-should-contain [ - <span class="Constant"> .z␣bc def .</span> - <span class="Constant"> . .</span> + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> .z␣bc ┊def .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] +] + +<span class="SalientComment">## Running code from the editors</span> + +container sandbox-data [ + data:address:array:character + response:address:array:character + warnings:address:array:character + next-sandbox:address:sandbox-data +] + +<span class="muScenario">scenario</span> run-and-show-results [ + $close-trace <span class="Comment"># trace too long for github</span> + assume-screen <span class="Constant">100:literal/width</span>, <span class="Constant">12:literal/height</span> + <span class="Comment"># recipe editor is empty</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Comment"># sandbox editor contains an instruction without storing outputs</span> + 2:address:array:character<span class="Special"> <- </span>new <span class="Constant">[divide-with-remainder 11:literal, 3:literal]</span> + 3:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + <span class="Comment"># run the code in the editors</span> + assume-console [ + press 65526 <span class="Comment"># F10</span> + ] + run [ + event-loop screen:address, console:address, 3:address:programming-environment-data + ] + <span class="Comment"># check that screen prints the results</span> + screen-should-contain [ + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> . ┊ .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊divide-with-remainder 11:literal, 3:literal .</span> + <span class="Constant"> . ┊3 .</span> + <span class="Constant"> . ┊2 .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] + screen-should-contain-in-color <span class="Constant">7:literal/white</span>, [ + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . divide-with-remainder 11:literal, 3:literal .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + ] + screen-should-contain-in-color, <span class="Constant">245:literal/grey</span>, [ + <span class="Constant"> . .</span> + <span class="Constant"> . ┊ .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> . ┊3 .</span> + <span class="Constant"> . ┊2 .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] + <span class="Comment"># run another command</span> + assume-console [ + left-click 1, 80 + type <span class="Constant">[add 2:literal, 2:literal]</span> + press 65526 <span class="Comment"># F10</span> + ] + run [ + event-loop screen:address, console:address, 3:address:programming-environment-data + ] + <span class="Comment"># check that screen prints the results</span> + screen-should-contain [ + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> . ┊ .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊add 2:literal, 2:literal .</span> + <span class="Constant"> . ┊4 .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊divide-with-remainder 11:literal, 3:literal .</span> + <span class="Constant"> . ┊3 .</span> + <span class="Constant"> . ┊2 .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] +] + +<span class="muRecipe">recipe</span> run-sandboxes [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> + env:address:programming-environment-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + recipes:address:editor-data<span class="Special"> <- </span>get env:address:programming-environment-data/deref, recipes:offset + current-sandbox:address:editor-data<span class="Special"> <- </span>get env:address:programming-environment-data/deref, current-sandbox:offset + <span class="Comment"># load code from recipe editor, save any warnings</span> + in:address:array:character<span class="Special"> <- </span>editor-contents recipes:address:editor-data + recipe-warnings:address:address:array:character<span class="Special"> <- </span>get-address env:address:programming-environment-data/deref, recipe-warnings:offset + recipe-warnings:address:address:array:character/deref<span class="Special"> <- </span>reload in:address:array:character + <span class="Comment"># check contents of right editor (sandbox)</span> + <span class="Delimiter">{</span> + sandbox-contents:address:array:character<span class="Special"> <- </span>editor-contents current-sandbox:address:editor-data + <span class="muControl">break-unless</span> sandbox-contents:address:array:character + <span class="Comment"># if contents exist, run them and turn them into a new sandbox-data</span> + new-sandbox:address:sandbox-data<span class="Special"> <- </span>new sandbox-data:type + data:address:address:array:character<span class="Special"> <- </span>get-address new-sandbox:address:sandbox-data/deref, data:offset + data:address:address:array:character/deref<span class="Special"> <- </span>copy sandbox-contents:address:array:character + <span class="Comment"># push to head of sandbox list</span> + dest:address:address:sandbox-data<span class="Special"> <- </span>get-address env:address:programming-environment-data/deref, sandbox:offset + next:address:address:sandbox-data<span class="Special"> <- </span>get-address new-sandbox:address:sandbox-data/deref, next-sandbox:offset + next:address:address:sandbox-data/deref<span class="Special"> <- </span>copy dest:address:address:sandbox-data/deref + dest:address:address:sandbox-data/deref<span class="Special"> <- </span>copy new-sandbox:address:sandbox-data + <span class="Comment"># clear sandbox editor</span> + init:address:address:duplex-list<span class="Special"> <- </span>get-address current-sandbox:address:editor-data/deref, data:offset + init:address:address:duplex-list/deref<span class="Special"> <- </span>push-duplex <span class="Constant">167:literal/§</span>, <span class="Constant">0:literal/tail</span> + <span class="Delimiter">}</span> + <span class="Comment"># rerun other sandboxes</span> + curr:address:sandbox-data<span class="Special"> <- </span>get env:address:programming-environment-data/deref, sandbox:offset + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> curr:address:sandbox-data + data:address:address:array:character<span class="Special"> <- </span>get-address curr:address:sandbox-data/deref, data:offset + response:address:address:array:character<span class="Special"> <- </span>get-address curr:address:sandbox-data/deref, response:offset + warnings:address:address:array:character<span class="Special"> <- </span>get-address curr:address:sandbox-data/deref, warnings:offset + response:address:address:array:character/deref, warnings:address:address:array:character/deref<span class="Special"> <- </span>run-interactive data:address:address:array:character/deref + curr:address:sandbox-data<span class="Special"> <- </span>get curr:address:sandbox-data/deref, next-sandbox:offset + <span class="muControl">loop</span> + <span class="Delimiter">}</span> +] + +<span class="muScenario">scenario</span> run-updates-results [ + $close-trace <span class="Comment"># trace too long for github</span> + assume-screen <span class="Constant">100:literal/width</span>, <span class="Constant">12:literal/height</span> + <span class="Comment"># define a recipe (no indent for the 'add' line below so column numbers are more obvious)</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ </span> +<span class="Constant">recipe foo [</span> +<span class="Constant">z:number <- add 2:literal, 2:literal</span> +<span class="Constant">]</span>] + <span class="Comment"># sandbox editor contains an instruction without storing outputs</span> + 2:address:array:character<span class="Special"> <- </span>new <span class="Constant">[foo]</span> + 3:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + <span class="Comment"># run the code in the editors</span> + assume-console [ + press 65526 <span class="Comment"># F10</span> + ] + run [ + event-loop screen:address, console:address, 3:address:programming-environment-data + ] + <span class="Comment"># check that screen prints the results</span> + screen-should-contain [ + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .z:number <- add 2:literal, 2:literal ┊foo .</span> + <span class="Constant"> .] ┊4 .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] + <span class="Comment"># make a change (incrementing one of the args to 'add'), then rerun</span> + assume-console [ + left-click 3, 28 <span class="Comment"># one past the value of the second arg</span> + type <span class="Constant">[«3]</span> <span class="Comment"># replace</span> + press 65526 <span class="Comment"># F10</span> + ] + 4:event/backspace<span class="Special"> <- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">8:literal/backspace</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span> + replace-in-console <span class="Constant">171:literal/«</span>, 4:event/backspace + run [ + event-loop screen:address, console:address, 3:address:programming-environment-data + ] + <span class="Comment"># check that screen updates the result on the right</span> + screen-should-contain [ + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .z:number <- add 2:literal, 3:literal ┊foo .</span> + <span class="Constant"> .] ┊5 .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> ] ] -<span class="Comment"># set focus to first editor, reset it in later ones</span> -<span class="muRecipe">recipe</span> reset-focus [ +<span class="muScenario">scenario</span> run-instruction-and-print-warnings [ + $close-trace <span class="Comment"># trace too long for github</span> + assume-screen <span class="Constant">100:literal/width</span>, <span class="Constant">10:literal/height</span> + <span class="Comment"># left editor is empty</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Comment"># right editor contains an illegal instruction</span> + 2:address:array:character<span class="Special"> <- </span>new <span class="Constant">[get 1234:number, foo:offset]</span> + 3:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + <span class="Comment"># run the code in the editors</span> + assume-console [ + press 65526 <span class="Comment"># F10</span> + ] + run [ + event-loop screen:address, console:address, 3:address:programming-environment-data + ] + <span class="Comment"># check that screen prints error message in red</span> + screen-should-contain [ + <span class="Constant"> . run (F10) .</span> + <span class="Constant"> . ┊ .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊get 1234:number, foo:offset .</span> + <span class="Constant"> . ┊unknown element foo in container number .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] + screen-should-contain-in-color <span class="Constant">7:literal/white</span>, [ + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . get 1234:number, foo:offset .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + ] + screen-should-contain-in-color, <span class="Constant">1:literal/red</span>, [ + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + <span class="Constant"> . unknown element foo in container number .</span> + <span class="Constant"> . .</span> + ] + screen-should-contain-in-color, <span class="Constant">245:literal/grey</span>, [ + <span class="Constant"> . .</span> + <span class="Constant"> . ┊ .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] +] + +<span class="muRecipe">recipe</span> editor-contents [ <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> editor:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - in-focus:address:boolean<span class="Special"> <- </span>get-address editor:address:editor-data/deref, in-focus?:offset - in-focus:address:boolean/deref<span class="Special"> <- </span>copy <span class="Constant">1:literal/true</span> - e:address:editor-data<span class="Special"> <- </span>get editor:address:editor-data/deref, next-editor:offset + buf:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80:literal</span> + curr:address:duplex-list<span class="Special"> <- </span>get editor:address:editor-data/deref, data:offset + <span class="Comment"># skip § sentinel</span> + assert curr:address:duplex-list, <span class="Constant">[editor without data is illegal; must have at least a sentinel]</span> + curr:address:duplex-list<span class="Special"> <- </span>next-duplex curr:address:duplex-list + <span class="muControl">reply-unless</span> curr:address:duplex-list, <span class="Constant">0:literal</span> <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> e:address:editor-data -<span class="CommentedCode">#? $print [resetting focus in ], e:address:editor-data, [ </span> -<span class="CommentedCode">#? ] #? 1</span> - x:address:boolean<span class="Special"> <- </span>get-address e:address:editor-data/deref, in-focus?:offset -<span class="CommentedCode">#? $print [ at ], x:address:boolean, [ </span> -<span class="CommentedCode">#? ] #? 1</span> - x:address:boolean/deref<span class="Special"> <- </span>copy <span class="Constant">0:literal/false</span> - e:address:editor-data<span class="Special"> <- </span>get e:address:editor-data/deref, next-editor:offset + <span class="muControl">break-unless</span> curr:address:duplex-list + c:character<span class="Special"> <- </span>get curr:address:duplex-list/deref, value:offset + buffer-append buf:address:buffer, c:character + curr:address:duplex-list<span class="Special"> <- </span>next-duplex curr:address:duplex-list <span class="muControl">loop</span> <span class="Delimiter">}</span> + result:address:array:character<span class="Special"> <- </span>buffer-to-array buf:address:buffer + <span class="muControl">reply</span> result:address:array:character +] + +<span class="muScenario">scenario</span> editor-provides-edited-contents [ + assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span> + 1:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + 2:address:editor-data<span class="Special"> <- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span> + assume-console [ + left-click 1, 2 + type <span class="Constant">[def]</span> + ] + run [ + editor-event-loop screen:address, console:address, 2:address:editor-data + 3:address:array:character<span class="Special"> <- </span>editor-contents 2:address:editor-data + 4:array:character<span class="Special"> <- </span>copy 3:address:array:character/deref + ] + memory-should-contain [ + 4:string<span class="Special"> <- </span><span class="Constant">[abdefc]</span> + ] ] <span class="SalientComment">## helpers for drawing editor borders</span> @@ -1784,17 +2192,27 @@ d] row:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> x:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> right:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + style:character, style-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> style-found?:boolean + style:character<span class="Special"> <- </span>copy <span class="Constant">9472:literal/horizontal</span> + <span class="Delimiter">}</span> color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> <span class="Comment"># default color to white</span> <span class="muControl">break-if</span> color-found?:boolean color:number<span class="Special"> <- </span>copy <span class="Constant">245:literal/grey</span> <span class="Delimiter">}</span> + bg-color:number, bg-color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> bg-color-found?:boolean + bg-color:number<span class="Special"> <- </span>copy <span class="Constant">0:literal/black</span> + <span class="Delimiter">}</span> move-cursor screen:address, row:number, x:number <span class="Delimiter">{</span> - continue?:boolean<span class="Special"> <- </span>lesser-than x:number, right:number + continue?:boolean<span class="Special"> <- </span>lesser-or-equal x:number, right:number <span class="Comment"># right is inclusive, to match editor-data semantics</span> <span class="muControl">break-unless</span> continue?:boolean - print-character screen:address, <span class="Constant">9472:literal/horizontal</span>, color:number + print-character screen:address, style:character, color:number, bg-color:number x:number<span class="Special"> <- </span>add x:number, <span class="Constant">1:literal</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> @@ -1806,6 +2224,11 @@ d] col:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> x:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> bottom:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + style:character, style-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> style-found?:boolean + style:character<span class="Special"> <- </span>copy <span class="Constant">9474:literal/vertical</span> + <span class="Delimiter">}</span> color:number, color-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> <span class="Delimiter">{</span> <span class="Comment"># default color to white</span> @@ -1816,7 +2239,7 @@ d] continue?:boolean<span class="Special"> <- </span>lesser-than x:number, bottom:number <span class="muControl">break-unless</span> continue?:boolean move-cursor screen:address, x:number, col:number - print-character screen:address, <span class="Constant">9474:literal/vertical</span>, color:number + print-character screen:address, style:character, color:number x:number<span class="Special"> <- </span>add x:number, <span class="Constant">1:literal</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> @@ -1881,6 +2304,37 @@ d] move-cursor screen:address, bottom:number, right:number print-character screen:address, <span class="Constant">9496:literal/up-left</span>, color:number ] + +<span class="muRecipe">recipe</span> print-string-with-gradient-background [ + <span class="Constant">default-space</span>:address:array:location<span class="Special"> <- </span>new location:type, <span class="Constant">30:literal</span> + x:address:screen<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + s:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + color:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + bg-color1:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + bg-color2:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + len:number<span class="Special"> <- </span>length s:address:array:character/deref + color-range:number<span class="Special"> <- </span>subtract bg-color2:number, bg-color1:number + color-quantum:number<span class="Special"> <- </span>divide color-range:number, len:number +<span class="CommentedCode">#? close-console #? 2</span> +<span class="CommentedCode">#? $print len:number, [, ], color-range:number, [, ], color-quantum:number, [ </span> +<span class="CommentedCode">#? ] #? 2</span> +<span class="CommentedCode">#? #? $exit #? 3</span> + bg-color:number<span class="Special"> <- </span>copy bg-color1:number + i:number<span class="Special"> <- </span>copy <span class="Constant">0:literal</span> + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal i:number, len:number + <span class="muControl">break-if</span> done?:boolean + c:character<span class="Special"> <- </span>index s:address:array:character/deref, i:number + print-character x:address:screen, c:character, color:number, bg-color:number + i:number<span class="Special"> <- </span>add i:number, <span class="Constant">1:literal</span> + bg-color:number<span class="Special"> <- </span>add bg-color:number, color-quantum:number +<span class="CommentedCode">#? $print [=> ], bg-color:number, [ </span> +<span class="CommentedCode">#? ] #? 1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> +<span class="CommentedCode">#? $exit #? 1</span> + <span class="muControl">reply</span> x:address:screen/same-as-ingredient:0 +] </pre> </body> </html> |