diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-09-07 10:37:27 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-09-07 10:37:27 -0700 |
commit | f5465e1220d73e237c51897b7d1211ec53b0dc04 (patch) | |
tree | 939ee8e57241b8515aede8106c6420e330ace75a /html/edit/002-typing.mu.html | |
parent | 5ccf2653fb7d31b013f77df4e92e964e45c54f8a (diff) | |
download | mu-f5465e1220d73e237c51897b7d1211ec53b0dc04.tar.gz |
2177
Diffstat (limited to 'html/edit/002-typing.mu.html')
-rw-r--r-- | html/edit/002-typing.mu.html | 1092 |
1 files changed, 1092 insertions, 0 deletions
diff --git a/html/edit/002-typing.mu.html b/html/edit/002-typing.mu.html new file mode 100644 index 00000000..787e3a4e --- /dev/null +++ b/html/edit/002-typing.mu.html @@ -0,0 +1,1092 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<title>Mu - edit/002-typing.mu</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> +<meta name="colorscheme" content="minimal"> +<style type="text/css"> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } +body { font-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 1.05em; } +.muRecipe { color: #ff8700; } +.muData { color: #ffff00; } +.Special { color: #ff6060; } +.muScenario { color: #00af00; } +.Comment { color: #9090ff; } +.Constant { color: #00a0a0; } +.SalientComment { color: #00ffff; } +.Delimiter { color: #a04060; } +.muControl { color: #c0a020; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="SalientComment">## handling events from the keyboard, mouse, touch screen, ...</span> + +<span class="Comment"># temporary main: interactive editor</span> +<span class="Comment"># hit ctrl-c to exit</span> +<span class="muRecipe">recipe!</span> main [ + <span class="Constant">local-scope</span> + text:address:array:character<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + open-console + editor:address:editor-data<span class="Special"> <- </span>new-editor text, <span class="Constant">0/screen</span>, <span class="Constant">5/left</span>, <span class="Constant">45/right</span> + editor-event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, editor + close-console +] + +<span class="muRecipe">recipe</span> editor-event-loop [ + <span class="Constant">local-scope</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> + cursor-row:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:number<span class="Special"> <- </span>get *editor, <span class="Constant">cursor-column:offset</span> + screen<span class="Special"> <- </span>move-cursor screen, cursor-row, cursor-column + e:event, console:address, found?:boolean, quit?:boolean<span class="Special"> <- </span>read-event console + <span class="muControl">loop-unless</span> found? + <span class="muControl">break-if</span> quit? <span class="Comment"># only in tests</span> + trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span> + <span class="Comment"># 'touch' event</span> + t:address:touch-event<span class="Special"> <- </span>maybe-convert e, <span class="Constant">touch:variant</span> + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> t + move-cursor-in-editor screen, editor, *t + <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> + <span class="Delimiter">}</span> + <span class="Comment"># keyboard events</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> t + screen, editor, go-render?:boolean<span class="Special"> <- </span>handle-keyboard-event screen, editor, e + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> go-render? + screen<span class="Special"> <- </span>editor-render screen, editor + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> +] + +<span class="Comment"># process click, return if it was on current editor</span> +<span class="muRecipe">recipe</span> move-cursor-in-editor [ + <span class="Constant">local-scope</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="muControl">reply-unless</span> editor, <span class="Constant">0/false</span> + click-row:number<span class="Special"> <- </span>get t, <span class="Constant">row:offset</span> + <span class="muControl">reply-unless</span> click-row, <span class="Constant">0/false</span> <span class="Comment"># ignore clicks on 'menu'</span> + click-column:number<span class="Special"> <- </span>get t, <span class="Constant">column:offset</span> + left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> + too-far-left?:boolean<span class="Special"> <- </span>lesser-than click-column, left + <span class="muControl">reply-if</span> too-far-left?, <span class="Constant">0/false</span> + right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> + too-far-right?:boolean<span class="Special"> <- </span>greater-than click-column, right + <span class="muControl">reply-if</span> too-far-right?, <span class="Constant">0/false</span> + <span class="Comment"># position cursor</span> +<span class="Constant"> <move-cursor-begin></span> + editor<span class="Special"> <- </span>snap-cursor screen, editor, click-row, click-column + undo-coalesce-tag:number<span class="Special"> <- </span>copy <span class="Constant">0/never</span> +<span class="Constant"> <move-cursor-end></span> + <span class="Comment"># gain focus</span> + <span class="muControl">reply</span> <span class="Constant">1/true</span> +] + +<span class="Comment"># editor <- snap-cursor screen:address, editor:address:editor-data, target-row:number, target-column:number</span> +<span class="Comment">#</span> +<span class="Comment"># Variant of 'render' that only moves the cursor (coordinates and</span> +<span class="Comment"># before-cursor). If it's past the end of a line, it 'slides' it left. If it's</span> +<span class="Comment"># past the last line it positions at end of last line.</span> +<span class="muRecipe">recipe</span> snap-cursor [ + <span class="Constant">local-scope</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> + target-row:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + target-column:number<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="muControl">reply-unless</span> editor, <span class="Constant">1/top</span>, editor/same-as-ingredient:<span class="Constant">1</span> + left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> + right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> + screen-height:number<span class="Special"> <- </span>screen-height screen + <span class="Comment"># count newlines until screen row</span> + curr:address:duplex-list<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + prev:address:duplex-list<span class="Special"> <- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev-duplex</span> + curr<span class="Special"> <- </span>next-duplex curr + row:number<span class="Special"> <- </span>copy <span class="Constant">1/top</span> + column:number<span class="Special"> <- </span>copy left + cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> + *cursor-row<span class="Special"> <- </span>copy target-row + cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> + *cursor-column<span class="Special"> <- </span>copy target-column + before-cursor:address:address:duplex-list<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + <span class="Delimiter">{</span> +<span class="Constant"> +next-character</span> + <span class="muControl">break-unless</span> curr + off-screen?:boolean<span class="Special"> <- </span>greater-or-equal row, screen-height + <span class="muControl">break-if</span> off-screen? + <span class="Comment"># update editor-data.before-cursor</span> + <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span> + <span class="Comment"># the current character.</span> + <span class="Delimiter">{</span> + at-cursor-row?:boolean<span class="Special"> <- </span>equal row, *cursor-row + <span class="muControl">break-unless</span> at-cursor-row? + at-cursor?:boolean<span class="Special"> <- </span>equal column, *cursor-column + <span class="muControl">break-unless</span> at-cursor? + *before-cursor<span class="Special"> <- </span>copy prev + <span class="Delimiter">}</span> + c:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> + <span class="Delimiter">{</span> + <span class="Comment"># newline? move to left rather than 0</span> + newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> + <span class="muControl">break-unless</span> newline? + <span class="Comment"># adjust cursor if necessary</span> + <span class="Delimiter">{</span> + at-cursor-row?:boolean<span class="Special"> <- </span>equal row, *cursor-row + <span class="muControl">break-unless</span> at-cursor-row? + left-of-cursor?:boolean<span class="Special"> <- </span>lesser-than column, *cursor-column + <span class="muControl">break-unless</span> left-of-cursor? + *cursor-column<span class="Special"> <- </span>copy column + *before-cursor<span class="Special"> <- </span>copy prev + <span class="Delimiter">}</span> + <span class="Comment"># skip to next line</span> + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + column<span class="Special"> <- </span>copy left + curr<span class="Special"> <- </span>next-duplex curr + prev<span class="Special"> <- </span>next-duplex prev + <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? 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, right + <span class="muControl">break-unless</span> at-right? + column<span class="Special"> <- </span>copy left + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + <span class="Comment"># don't increment curr/prev</span> + <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> + <span class="Delimiter">}</span> + curr<span class="Special"> <- </span>next-duplex curr + prev<span class="Special"> <- </span>next-duplex prev + column<span class="Special"> <- </span>add column, <span class="Constant">1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <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, *cursor-row + cursor-outside-line?:boolean<span class="Special"> <- </span>lesser-or-equal column, *cursor-column + before-cursor-on-same-line?:boolean<span class="Special"> <- </span>and at-cursor-row?, cursor-outside-line? + above-cursor-row?:boolean<span class="Special"> <- </span>lesser-than row, *cursor-row + before-cursor?:boolean<span class="Special"> <- </span>or before-cursor-on-same-line?, above-cursor-row? + <span class="muControl">break-unless</span> before-cursor? + *cursor-row<span class="Special"> <- </span>copy row + *cursor-column<span class="Special"> <- </span>copy column + *before-cursor<span class="Special"> <- </span>copy prev + <span class="Delimiter">}</span> + <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">1</span> +] + +<span class="Comment"># screen, editor, go-render?:boolean <- handle-keyboard-event screen:address, editor:address:editor-data, e:event</span> +<span class="Comment"># Process an event 'e' and try to minimally update the screen.</span> +<span class="Comment"># Set 'go-render?' to true to indicate the caller must perform a non-minimal update.</span> +<span class="muRecipe">recipe</span> handle-keyboard-event [ + <span class="Constant">local-scope</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> + e:event<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="muControl">reply-unless</span> editor, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + screen-width:number<span class="Special"> <- </span>screen-width screen + screen-height:number<span class="Special"> <- </span>screen-height screen + left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> + right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> + before-cursor:address:address:duplex-list<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> + save-row:number<span class="Special"> <- </span>copy *cursor-row + save-column:number<span class="Special"> <- </span>copy *cursor-column + <span class="Comment"># character</span> + <span class="Delimiter">{</span> + c:address:character<span class="Special"> <- </span>maybe-convert e, <span class="Constant">text:variant</span> + <span class="muControl">break-unless</span> c + trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[handle-keyboard-event: special character]</span> + <span class="Comment"># exceptions for special characters go here</span> +<span class="Constant"> <handle-special-character></span> + <span class="Comment"># ignore any other special characters</span> + regular-character?:boolean<span class="Special"> <- </span>greater-or-equal *c, <span class="Constant">32/space</span> + <span class="muControl">reply-unless</span> regular-character?, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">0/no-more-render</span> + <span class="Comment"># otherwise type it in</span> +<span class="Constant"> <insert-character-begin></span> + editor, screen, go-render?:boolean<span class="Special"> <- </span>insert-at-cursor editor, *c, screen +<span class="Constant"> <insert-character-end></span> + <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, go-render? + <span class="Delimiter">}</span> + <span class="Comment"># special key to modify the text or move the cursor</span> + k:address:number<span class="Special"> <- </span>maybe-convert e:event, <span class="Constant">keycode:variant</span> + assert k, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span> + <span class="Comment"># handlers for each special key will go here</span> +<span class="Constant"> <handle-special-key></span> + <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> +] + +<span class="muRecipe">recipe</span> insert-at-cursor [ + <span class="Constant">local-scope</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> + before-cursor:address:address:duplex-list<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + insert-duplex c, *before-cursor + *before-cursor<span class="Special"> <- </span>next-duplex *before-cursor + cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> + left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> + right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> + save-row:number<span class="Special"> <- </span>copy *cursor-row + save-column:number<span class="Special"> <- </span>copy *cursor-column + screen-width:number<span class="Special"> <- </span>screen-width screen + screen-height:number<span class="Special"> <- </span>screen-height screen + <span class="Comment"># occasionally we'll need to mess with the cursor</span> +<span class="Constant"> <insert-character-special-case></span> + <span class="Comment"># but mostly we'll just move the cursor right</span> + *cursor-column<span class="Special"> <- </span>add *cursor-column, <span class="Constant">1</span> + next:address:duplex-list<span class="Special"> <- </span>next-duplex *before-cursor + <span class="Delimiter">{</span> + <span class="Comment"># at end of all text? no need to scroll? just print the character and leave</span> + at-end?:boolean<span class="Special"> <- </span>equal next, <span class="Constant">0/null</span> + <span class="muControl">break-unless</span> at-end? + bottom:number<span class="Special"> <- </span>subtract screen-height, <span class="Constant">1</span> + at-bottom?:boolean<span class="Special"> <- </span>equal save-row, bottom + at-right?:boolean<span class="Special"> <- </span>equal save-column, right + overflow?:boolean<span class="Special"> <- </span>and at-bottom?, at-right? + <span class="muControl">break-if</span> overflow? + move-cursor screen, save-row, save-column + print-character screen, c + <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">0/no-more-render</span> + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="Comment"># not at right margin? print the character and rest of line</span> + <span class="muControl">break-unless</span> next + at-right?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-column, screen-width + <span class="muControl">break-if</span> at-right? + curr:address:duplex-list<span class="Special"> <- </span>copy *before-cursor + move-cursor screen, save-row, save-column + curr-column:number<span class="Special"> <- </span>copy save-column + <span class="Delimiter">{</span> + <span class="Comment"># hit right margin? give up and let caller render</span> + at-right?:boolean<span class="Special"> <- </span>greater-than curr-column, right + <span class="muControl">reply-if</span> at-right?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span> + <span class="muControl">break-unless</span> curr + <span class="Comment"># newline? done.</span> + currc:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> + at-newline?:boolean<span class="Special"> <- </span>equal currc, <span class="Constant">10/newline</span> + <span class="muControl">break-if</span> at-newline? + print-character screen, currc + curr-column<span class="Special"> <- </span>add curr-column, <span class="Constant">1</span> + curr<span class="Special"> <- </span>next-duplex curr + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">0/no-more-render</span> + <span class="Delimiter">}</span> + <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span> +] + +<span class="Comment"># helper for tests</span> +<span class="muRecipe">recipe</span> editor-render [ + <span class="Constant">local-scope</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> + left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> + right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> + row:number, column:number<span class="Special"> <- </span>render screen, editor + clear-line-delimited screen, column, right + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + draw-horizontal screen, row, left, right, <span class="Constant">9480/horizontal-dotted</span> + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + clear-screen-from screen, row, left, left, right +] + +<span class="muScenario">scenario</span> editor-handles-empty-event-queue [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data + assume-console <span class="Constant">[]</span> + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] +] + +<span class="muScenario">scenario</span> editor-handles-mouse-clicks [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">1</span> <span class="Comment"># on the 'b'</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor is at row 0..</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># ..and column 1</span> + ] + check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">7</span> <span class="Comment"># last line, to the right of text</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># cursor column</span> + ] + check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-2 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> +<span class="Constant">def]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">7</span> <span class="Comment"># interior line, to the right of text</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># cursor column</span> + ] + check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-3 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> +<span class="Constant">def]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">3</span>, <span class="Constant">7</span> <span class="Comment"># below text</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># cursor column</span> + ] + check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-column [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Comment"># editor occupies only left half of screen</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + <span class="Comment"># click on right half of screen</span> + left-click <span class="Constant">3</span>, <span class="Constant">8</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc .</span> + <span class="Constant"> .┈┈┈┈┈ .</span> + <span class="Constant"> . .</span> + ] + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># no change to cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># ..or column</span> + ] + check-trace-count-for-label <span class="Constant">0</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-handles-mouse-clicks-in-menu-area [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + <span class="Comment"># click on first, 'menu' row</span> + left-click <span class="Constant">0</span>, <span class="Constant">3</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># no change to cursor</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">1</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> + ] +] + +<span class="muScenario">scenario</span> editor-inserts-characters-into-empty-editor [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + type <span class="Constant">[abc]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc .</span> + <span class="Constant"> .┈┈┈┈┈ .</span> + <span class="Constant"> . .</span> + ] + check-trace-count-for-label <span class="Constant">3</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + <span class="Comment"># type two letters at different places</span> + assume-console [ + type <span class="Constant">[0]</span> + left-click <span class="Constant">1</span>, <span class="Constant">2</span> + type <span class="Constant">[d]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .0adbc .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] + check-trace-count-for-label <span class="Constant">7</span>, <span class="Constant">[print-character]</span> <span class="Comment"># 4 for first letter, 3 for second</span> +] + +<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-2 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">5</span> <span class="Comment"># right of last line</span> + type <span class="Constant">[d]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abcd .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] + check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-5 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> +<span class="Constant">d]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">5</span> <span class="Comment"># right of non-last line</span> + type <span class="Constant">[e]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abce .</span> + <span class="Constant"> .d .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] + check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-3 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">3</span>, <span class="Constant">5</span> <span class="Comment"># below all text</span> + type <span class="Constant">[d]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abcd .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] + check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-4 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> +<span class="Constant">d]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">3</span>, <span class="Constant">5</span> <span class="Comment"># below all text</span> + type <span class="Constant">[e]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc .</span> + <span class="Constant"> .de .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] + check-trace-count-for-label <span class="Constant">1</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-6 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> +<span class="Constant">d]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data +<span class="Constant"> $clear-trace</span> + assume-console [ + left-click <span class="Constant">3</span>, <span class="Constant">5</span> <span class="Comment"># below all text</span> + type <span class="Constant">[ef]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>: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="Constant"> . .</span> + ] + check-trace-count-for-label <span class="Constant">2</span>, <span class="Constant">[print-character]</span> +] + +<span class="muScenario">scenario</span> editor-moves-cursor-after-inserting-characters [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data + assume-console [ + type <span class="Constant">[01]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .01ab .</span> + <span class="Constant"> .┈┈┈┈┈ .</span> + <span class="Constant"> . .</span> + ] +] + +<span class="Comment"># if the cursor reaches the right margin, wrap the line</span> + +<span class="muScenario">scenario</span> editor-wraps-line-on-insert [ + assume-screen <span class="Constant">5/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data + <span class="Comment"># type a letter</span> + assume-console [ + type <span class="Constant">[e]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + <span class="Comment"># no wrap yet</span> + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .eabc .</span> +<span class="Constant"> .┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + <span class="Constant"> . .</span> + ] + <span class="Comment"># type a second letter</span> + assume-console [ + type <span class="Constant">[f]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + <span class="Comment"># now wrap</span> + screen-should-contain [ + <span class="Constant"> . .</span> +<span class="Constant"> .efab↩.</span> + <span class="Constant"> .c .</span> +<span class="Constant"> .┈┈┈┈┈.</span> + <span class="Constant"> . .</span> + ] +] + +<span class="muScenario">scenario</span> editor-wraps-line-on-insert-2 [ + <span class="Comment"># create an editor with some text</span> + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcdefg</span> +<span class="Constant">defg]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + editor-render screen, <span class="Constant">2</span>:address:editor-data + <span class="Comment"># type more text at the start</span> + assume-console [ + left-click <span class="Constant">3</span>, <span class="Constant">0</span> + type <span class="Constant">[abc]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># cursor is not wrapped</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">3</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> + ] + <span class="Comment"># but line is wrapped</span> + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abcd↩ .</span> + <span class="Constant"> .efg .</span> + <span class="Constant"> .abcd↩ .</span> + <span class="Constant"> .efg .</span> + ] +] + +<span class="muRecipe">after</span> <span class="Constant"><insert-character-special-case></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> + wrap-column:number<span class="Special"> <- </span>subtract right, <span class="Constant">1</span> + at-wrap?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-column, wrap-column + <span class="muControl">break-unless</span> at-wrap? + *cursor-column<span class="Special"> <- </span>subtract *cursor-column, wrap-column + *cursor-column<span class="Special"> <- </span>add *cursor-column, left + *cursor-row<span class="Special"> <- </span>add *cursor-row, <span class="Constant">1</span> + <span class="Comment"># if we're out of the screen, scroll down</span> + <span class="Delimiter">{</span> + below-screen?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-row, screen-height + <span class="muControl">break-unless</span> below-screen? +<span class="Constant"> <scroll-down></span> + <span class="Delimiter">}</span> + <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">2</span>, <span class="Constant">1/go-render</span> + <span class="Delimiter">}</span> +] + +<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">4</span> <span class="Comment"># line is full; no wrap icon yet</span> + type <span class="Constant">[f]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abcd↩ .</span> + <span class="Constant"> .fe .</span> + <span class="Constant"> .┈┈┈┈┈ .</span> + <span class="Constant"> . .</span> + ] + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor column</span> + ] +] + +<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-2 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">3</span> <span class="Comment"># right before the wrap icon</span> + type <span class="Constant">[f]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abcf↩ .</span> + <span class="Constant"> .de .</span> + <span class="Constant"> .┈┈┈┈┈ .</span> + <span class="Constant"> . .</span> + ] + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># cursor column</span> + ] +] + +<span class="muScenario">scenario</span> editor-wraps-cursor-to-left-margin [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">2/left</span>, <span class="Constant">7/right</span> + assume-console [ + left-click <span class="Constant">1</span>, <span class="Constant">5</span> <span class="Comment"># line is full; no wrap icon yet</span> + type <span class="Constant">[01]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> . abc0↩ .</span> + <span class="Constant"> . 1de .</span> + <span class="Constant"> . ┈┈┈┈┈ .</span> + <span class="Constant"> . .</span> + ] + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># cursor column</span> + ] +] + +<span class="Comment"># if newline, move cursor to start of next line, and maybe align indent with previous line</span> + +<span class="muData">container</span> editor-data [ + indent?:boolean +] + +<span class="muRecipe">after</span> <span class="Constant"><editor-initialization></span> [ + indent?:address:boolean<span class="Special"> <- </span>get-address *result, <span class="Constant">indent?:offset</span> + *indent?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> +] + +<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + assume-console [ + type <span class="Constant">[0</span> +<span class="Constant">1]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>: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="Constant"> . .</span> + ] +] + +<span class="muRecipe">after</span> <span class="Constant"><handle-special-character></span> [ + <span class="Delimiter">{</span> + newline?:boolean<span class="Special"> <- </span>equal *c, <span class="Constant">10/newline</span> + <span class="muControl">break-unless</span> newline? +<span class="Constant"> <insert-enter-begin></span> + editor<span class="Special"> <- </span>insert-new-line-and-indent editor, screen +<span class="Constant"> <insert-enter-end></span> + <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + <span class="Delimiter">}</span> +] + +<span class="muRecipe">recipe</span> insert-new-line-and-indent [ + <span class="Constant">local-scope</span> + editor:address:editor-data<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + cursor-row:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-row:offset</span> + cursor-column:address:number<span class="Special"> <- </span>get-address *editor, <span class="Constant">cursor-column:offset</span> + before-cursor:address:address:duplex-list<span class="Special"> <- </span>get-address *editor, <span class="Constant">before-cursor:offset</span> + left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> + right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> + screen-height:number<span class="Special"> <- </span>screen-height screen + <span class="Comment"># insert newline</span> + insert-duplex <span class="Constant">10/newline</span>, *before-cursor + *before-cursor<span class="Special"> <- </span>next-duplex *before-cursor + *cursor-row<span class="Special"> <- </span>add *cursor-row, <span class="Constant">1</span> + *cursor-column<span class="Special"> <- </span>copy left + <span class="Comment"># maybe scroll</span> + <span class="Delimiter">{</span> + below-screen?:boolean<span class="Special"> <- </span>greater-or-equal *cursor-row, screen-height <span class="Comment"># must be equal, never greater</span> + <span class="muControl">break-unless</span> below-screen? +<span class="Constant"> <scroll-down></span> + *cursor-row<span class="Special"> <- </span>subtract *cursor-row, <span class="Constant">1</span> <span class="Comment"># bring back into screen range</span> + <span class="Delimiter">}</span> + <span class="Comment"># indent if necessary</span> + indent?:boolean<span class="Special"> <- </span>get *editor, <span class="Constant">indent?:offset</span> + <span class="muControl">reply-unless</span> indent?, editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> + d:address:duplex-list<span class="Special"> <- </span>get *editor, <span class="Constant">data:offset</span> + end-of-previous-line:address:duplex-list<span class="Special"> <- </span>prev-duplex *before-cursor + indent:number<span class="Special"> <- </span>line-indent end-of-previous-line, d + i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Delimiter">{</span> + indent-done?:boolean<span class="Special"> <- </span>greater-or-equal i, indent + <span class="muControl">break-if</span> indent-done? + editor, screen, go-render?:boolean<span class="Special"> <- </span>insert-at-cursor editor, <span class="Constant">32/space</span>, screen + i<span class="Special"> <- </span>add i, <span class="Constant">1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <span class="muControl">reply</span> editor/same-as-ingredient:<span class="Constant">0</span>, screen/same-as-ingredient:<span class="Constant">1</span> +] + +<span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span> +<span class="Comment"># the number of spaces at the start of the line containing 'curr'.</span> +<span class="muRecipe">recipe</span> line-indent [ + <span class="Constant">local-scope</span> + curr:address:duplex-list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + start:address:duplex-list<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + result:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="muControl">reply-unless</span> curr, result + at-start?:boolean<span class="Special"> <- </span>equal curr, start + <span class="muControl">reply-if</span> at-start?, result + <span class="Delimiter">{</span> + curr<span class="Special"> <- </span>prev-duplex curr + <span class="muControl">break-unless</span> curr + at-start?:boolean<span class="Special"> <- </span>equal curr, start + <span class="muControl">break-if</span> at-start? + c:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> + at-newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> + <span class="muControl">break-if</span> at-newline? + <span class="Comment"># if c is a space, increment result</span> + is-space?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">32/space</span> + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> is-space? + result<span class="Special"> <- </span>add result, <span class="Constant">1</span> + <span class="Delimiter">}</span> + <span class="Comment"># if c is not a space, reset result</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> is-space? + result<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Delimiter">}</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <span class="muControl">reply</span> result +] + +<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline-2 [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">1/left</span>, <span class="Constant">10/right</span> + assume-console [ + type <span class="Constant">[0</span> +<span class="Constant">1]</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>: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="Constant"> . .</span> + ] +] + +<span class="muScenario">scenario</span> editor-clears-previous-line-completely-after-inserting-newline [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + assume-console [ + press enter + ] + 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 [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + ] + <span class="Comment"># line should be fully cleared</span> + screen-should-contain [ + <span class="Constant"> . .</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-inserts-indent-after-newline [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> +<span class="Constant"> cd</span> +<span class="Constant">ef]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Comment"># position cursor after 'cd' and hit 'newline'</span> + assume-console [ + left-click <span class="Constant">2</span>, <span class="Constant">8</span> + type [ +] + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># cursor should be below start of previous line</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># cursor column (indented)</span> + ] +] + +<span class="muScenario">scenario</span> editor-skips-indent-around-paste [ + assume-screen <span class="Constant">10/width</span>, <span class="Constant">10/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[ab</span> +<span class="Constant"> cd</span> +<span class="Constant">ef]</span> + <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address, <span class="Constant">0/left</span>, <span class="Constant">10/right</span> + <span class="Comment"># position cursor after 'cd' and hit 'newline' surrounded by paste markers</span> + assume-console [ + left-click <span class="Constant">2</span>, <span class="Constant">8</span> + press <span class="Constant">65507</span> <span class="Comment"># start paste</span> + press enter + press <span class="Constant">65506</span> <span class="Comment"># end paste</span> + ] + run [ + editor-event-loop screen:address, console:address, <span class="Constant">2</span>:address:editor-data + <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> + <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + ] + <span class="Comment"># cursor should be below start of previous line</span> + memory-should-contain [ + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">3</span> <span class="Comment"># cursor row</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># cursor column (not indented)</span> + ] +] + +<span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ + <span class="Delimiter">{</span> + paste-start?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65507/paste-start</span> + <span class="muControl">break-unless</span> paste-start? + indent?:address:boolean<span class="Special"> <- </span>get-address *editor, <span class="Constant">indent?:offset</span> + *indent?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> + <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + <span class="Delimiter">}</span> +] + +<span class="muRecipe">after</span> <span class="Constant"><handle-special-key></span> [ + <span class="Delimiter">{</span> + paste-end?:boolean<span class="Special"> <- </span>equal *k, <span class="Constant">65506/paste-end</span> + <span class="muControl">break-unless</span> paste-end? + indent?:address:boolean<span class="Special"> <- </span>get-address *editor, <span class="Constant">indent?:offset</span> + *indent?<span class="Special"> <- </span>copy <span class="Constant">1/true</span> + <span class="muControl">reply</span> screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span>, <span class="Constant">1/go-render</span> + <span class="Delimiter">}</span> +] + +<span class="SalientComment">## helpers</span> + +<span class="muRecipe">recipe</span> draw-horizontal [ + <span class="Constant">local-scope</span> + screen:address<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + 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? + style<span class="Special"> <- </span>copy <span class="Constant">9472/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? + color<span class="Special"> <- </span>copy <span class="Constant">245/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? + bg-color<span class="Special"> <- </span>copy <span class="Constant">0/black</span> + <span class="Delimiter">}</span> + screen<span class="Special"> <- </span>move-cursor screen, row, x + <span class="Delimiter">{</span> + continue?:boolean<span class="Special"> <- </span>lesser-or-equal x, right <span class="Comment"># right is inclusive, to match editor-data semantics</span> + <span class="muControl">break-unless</span> continue? + print-character screen, style, color, bg-color + x<span class="Special"> <- </span>add x, <span class="Constant">1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> +] +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> |