diff options
-rw-r--r-- | 081print.mu | 108 | ||||
-rw-r--r-- | edit/001-editor.mu | 4 | ||||
-rw-r--r-- | edit/002-typing.mu | 18 | ||||
-rw-r--r-- | edit/004-programming-environment.mu | 4 | ||||
-rw-r--r-- | edit/005-sandbox.mu | 10 |
5 files changed, 106 insertions, 38 deletions
diff --git a/081print.mu b/081print.mu index ff6cf5c0..465d228a 100644 --- a/081print.mu +++ b/081print.mu @@ -1,5 +1,16 @@ # Wrappers around print primitives that take a 'screen' object and are thus # easier to test. +# +# Screen objects are intended to exactly mimic the behavior of traditional +# terminals. Moving a cursor too far write wraps it to the next line, +# scrolling if necessary. The details are subtle: +# +# a) Rows can take unbounded values, and such values are preserved rather than +# clamped or wrapped around. +# +# b) If you print to a square (row, right) on the right margin, the cursor +# position depends on whether 'row' is in range. If it is, the new cursor +# position is (row+1, 0). If it isn't, the new cursor position is (row, 0). container screen [ num-rows:num @@ -7,6 +18,7 @@ container screen [ cursor-row:num cursor-column:num data:&:@:screen-cell # capacity num-rows*num-columns + pending-scroll?:bool top-idx:num # index inside data that corresponds to top-left of screen # modified on scroll, wrapping around to the top of data ] @@ -16,6 +28,32 @@ container screen-cell [ color:num ] +def main [ + local-scope + open-console + clear-screen + print 0/screen [a] +#? a:char <- copy 97 +#? i:num <- copy 0 +#? { +#? done?:bool <- greater-or-equal i, 6 +#? break-if done? +#? move-cursor 0/screen i, 2527 +#? print 0/screen a +#? a <- add a, 1 +#? i <- add i, 1 +#? loop +#? } + move-cursor 0/screen 5, 2527 + a:num b:num <- cursor-position 0/screen + print 0/screen [f] + c:num d:num <- cursor-position 0/screen + wait-for-some-interaction + close-console + $print a [ ] b 10/newline + $print c [ ] d 10/newline +] + def new-fake-screen w:num, h:num -> result:&:screen [ local-scope load-ingredients @@ -26,14 +64,14 @@ def new-fake-screen w:num, h:num -> result:&:screen [ assert non-zero-height?, [screen can't have zero height] bufsize:num <- multiply w, h data:&:@:screen-cell <- new screen-cell:type, bufsize - *result <- merge h/num-rows, w/num-columns, 0/cursor-row, 0/cursor-column, data, 0/top-idx + *result <- merge h/num-rows, w/num-columns, 0/cursor-row, 0/cursor-column, data, 0/pending-scroll?, 0/top-idx result <- clear-screen result ] def clear-screen screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [clear-screen] +#? stash [clear-screen] { break-if screen # real screen @@ -61,7 +99,7 @@ def clear-screen screen:&:screen -> screen:&:screen [ def fake-screen-is-empty? screen:&:screen -> result:bool [ local-scope load-ingredients - stash [fake-screen-is-empty?] +#? stash [fake-screen-is-empty?] return-unless screen, 1/true # do nothing for real screens buf:&:@:screen-cell <- get *screen, data:offset i:num <- copy 0 @@ -150,9 +188,13 @@ def print screen:&:screen, c:char -> screen:&:screen [ { at-bottom?:bool <- equal row, height break-unless at-bottom? + $dump-screen + $print [scroll1] 10/newline scroll-fake-screen screen row <- subtract height, 1 *screen <- put *screen, cursor-row:offset, row + *screen <- put *screen, pending-scroll?:offset, 0/false + $dump-screen } # if row is below bottom margin (error), reset to bottom margin { @@ -162,6 +204,17 @@ def print screen:&:screen, c:char -> screen:&:screen [ *screen <- put *screen, cursor-row:offset, row } # } + # if there's a pending scroll, perform it + { + pending-scroll?:bool <- get *screen, pending-scroll?:offset +#? $print pending-scroll? 10/newline + break-unless pending-scroll? + $print [scroll2] 10/newline + $dump-screen + scroll-fake-screen screen + *screen <- put *screen, pending-scroll?:offset, 0/false + $dump-screen + } #? stash [print] row column #? $print [print-character (], row, [, ], column, [): ], c, 10/newline # special-case: newline @@ -195,16 +248,30 @@ def print screen:&:screen, c:char -> screen:&:screen [ index:num <- data-index row, column, width, height, top-idx cursor:screen-cell <- merge c, color *buf <- put-index *buf, index, cursor - # move cursor to next character + # move cursor to next character, wrapping as necessary + # however, don't scroll just yet # (but don't bother making it valid; we'll do that before the next print) column <- add column, 1 + { + past-right?:bool <- greater-or-equal column, width + break-unless past-right? + column <- copy 0 + row <- add row, 1 + past-bottom?:bool <- greater-or-equal row, height + break-unless past-bottom? + # queue up a scroll + $print [pending scroll] 10/newline + *screen <- put *screen, pending-scroll?:offset, 1/true + row <- subtract row, 1 # update cursor as if scroll already happened + } + *screen <- put *screen, cursor-row:offset, row *screen <- put *screen, cursor-column:offset, column ] def cursor-down-on-fake-screen screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [cursor-down] +#? stash [cursor-down] row:num <- get *screen, cursor-row:offset height:num <- get *screen, num-rows:offset bottom:num <- subtract height, 1 @@ -223,7 +290,7 @@ def cursor-down-on-fake-screen screen:&:screen -> screen:&:screen [ def scroll-fake-screen screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [scroll-fake-screen] +#? stash [scroll-fake-screen] width:num <- get *screen, num-columns:offset height:num <- get *screen, num-rows:offset buf:&:@:screen-cell <- get *screen, data:offset @@ -515,7 +582,7 @@ def assert-no-scroll screen:&:screen, old-top-idx:num [ def clear-line screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [clear-line] +#? stash [clear-line] space:char <- copy 0/nul { break-if screen @@ -545,7 +612,7 @@ def clear-line-until screen:&:screen, right:num/inclusive -> screen:&:screen [ local-scope load-ingredients row:num, column:num <- cursor-position screen - stash [clear-line-until] row column +#? stash [clear-line-until] row column height:num <- screen-height screen past-bottom?:bool <- greater-or-equal row, height return-if past-bottom? @@ -582,7 +649,7 @@ def cursor-position screen:&:screen -> row:num, column:num [ def move-cursor screen:&:screen, new-row:num, new-column:num -> screen:&:screen [ local-scope load-ingredients - stash [move-cursor] +#? stash [move-cursor] { break-if screen # real screen @@ -592,6 +659,8 @@ def move-cursor screen:&:screen, new-row:num, new-column:num -> screen:&:screen # fake screen *screen <- put *screen, cursor-row:offset, new-row *screen <- put *screen, cursor-column:offset, new-column + $print [move cursor ] new-row [ ] new-column 10/newline + *screen <- put *screen, pending-scroll?:offset, 0/false ] scenario clear-line-erases-printed-characters [ @@ -628,7 +697,7 @@ scenario clear-line-erases-printed-characters [ def cursor-down screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [cursor-down] +#? stash [cursor-down] { break-if screen # real screen @@ -671,7 +740,7 @@ scenario cursor-down-scrolls [ def cursor-up screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [cursor-up] +#? stash [cursor-up] { break-if screen # real screen @@ -689,7 +758,7 @@ def cursor-up screen:&:screen -> screen:&:screen [ def cursor-right screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [cursor-right] +#? stash [cursor-right] { break-if screen # real screen @@ -709,7 +778,7 @@ def cursor-right screen:&:screen -> screen:&:screen [ def cursor-left screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [cursor-left] +#? stash [cursor-left] { break-if screen # real screen @@ -727,16 +796,15 @@ def cursor-left screen:&:screen -> screen:&:screen [ def cursor-to-start-of-line screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [cursor-to-start-of-line] +#? stash [cursor-to-start-of-line] row:num <- cursor-position screen - column:num <- copy 0 - screen <- move-cursor screen, row, column + screen <- move-cursor screen, row, 0/column ] def cursor-to-next-line screen:&:screen -> screen:&:screen [ local-scope load-ingredients - stash [cursor-to-next-line] +#? stash [cursor-to-next-line] screen <- cursor-down screen screen <- cursor-to-start-of-line screen ] @@ -745,14 +813,14 @@ def move-cursor-to-column screen:&:screen, column:num -> screen:&:screen [ local-scope load-ingredients row:num, _ <- cursor-position screen - stash [move-cursor-to-column] row +#? stash [move-cursor-to-column] row move-cursor screen, row, column ] def screen-width screen:&:screen -> width:num [ local-scope load-ingredients - stash [screen-width] +#? stash [screen-width] { break-unless screen # fake screen @@ -766,7 +834,7 @@ def screen-width screen:&:screen -> width:num [ def screen-height screen:&:screen -> height:num [ local-scope load-ingredients - stash [screen-height] +#? stash [screen-height] { break-unless screen # fake screen diff --git a/edit/001-editor.mu b/edit/001-editor.mu index f7b7fb89..d4e0a479 100644 --- a/edit/001-editor.mu +++ b/edit/001-editor.mu @@ -207,7 +207,7 @@ def render screen:&:screen, editor:&:editor -> last-row:num, last-column:num, sc def clear-screen-from screen:&:screen, row:num, column:num, left:num, right:num -> screen:&:screen [ local-scope load-ingredients - stash [clear-screen-from] row column [between] left [and] right +#? stash [clear-screen-from] row column [between] left [and] right # if it's the real screen, use the optimized primitive { break-if screen @@ -218,7 +218,7 @@ def clear-screen-from screen:&:screen, row:num, column:num, left:num, right:num screen <- move-cursor screen, row, column clear-line-until screen, right clear-rest-of-screen screen, row, left, right - screen <- move-cursor screen, row, column +#? screen <- move-cursor screen, row, column ] def clear-rest-of-screen screen:&:screen, row:num, left:num, right:num -> screen:&:screen [ diff --git a/edit/002-typing.mu b/edit/002-typing.mu index 05ace7c5..acb0a53c 100644 --- a/edit/002-typing.mu +++ b/edit/002-typing.mu @@ -1116,11 +1116,11 @@ after <handle-special-key> [ def draw-horizontal screen:&:screen, row:num, x:num, right:num -> screen:&:screen [ local-scope load-ingredients - a:num, b:num <- cursor-position screen - stash [draw-horizontal] row [--] a b +#? a:num, b:num <- cursor-position screen +#? stash [draw-horizontal] row [--] a b height:num <- screen-height screen past-bottom?:bool <- greater-or-equal row, height - stash [ past-bottom?] past-bottom? +#? stash [ past-bottom?] past-bottom? return-if past-bottom? style:char, style-found?:bool <- next-ingredient { @@ -1138,18 +1138,18 @@ def draw-horizontal screen:&:screen, row:num, x:num, right:num -> screen:&:scree break-if bg-color-found? bg-color <- copy 0/black } - stash [aa] x +#? stash [aa] x screen <- move-cursor screen, row, x { continue?:bool <- lesser-or-equal x, right # right is inclusive, to match editor semantics break-unless continue? - a b <- cursor-position screen - stash [bb] x [--] a b +#? a b <- cursor-position screen +#? stash [bb] x [--] a b print screen, style, color, bg-color - a b <- cursor-position screen - stash [cc] x [--] a b +#? a b <- cursor-position screen +#? stash [cc] x [--] a b x <- add x, 1 loop } - stash [draw-horizontal done] +#? stash [draw-horizontal done] ] diff --git a/edit/004-programming-environment.mu b/edit/004-programming-environment.mu index bcd3b524..021d9d73 100644 --- a/edit/004-programming-environment.mu +++ b/edit/004-programming-environment.mu @@ -447,7 +447,7 @@ def render-recipes screen:&:screen, env:&:environment, render-editor:render-reci clear-screen-from screen, row, left, left, right # assert-no-scroll screen, old-top-idx - stash [render recipes done] +#? stash [render recipes done] ] # replaced in a later layer @@ -468,7 +468,7 @@ def render-sandbox-side screen:&:screen, env:&:environment, render-editor:render clear-screen-from screen, row, left, left, right # assert-no-scroll screen, old-top-idx - stash [render sandbox side0 done] +#? stash [render sandbox side0 done] ] def update-cursor screen:&:screen, recipes:&:editor, current-sandbox:&:editor, sandbox-in-focus?:bool, env:&:environment -> screen:&:screen [ diff --git a/edit/005-sandbox.mu b/edit/005-sandbox.mu index 2b17ecc2..f27c1a2c 100644 --- a/edit/005-sandbox.mu +++ b/edit/005-sandbox.mu @@ -270,15 +270,15 @@ def! render-sandbox-side screen:&:screen, env:&:environment, render-editor:rende clear-rest-of-screen screen, row, left, right # assert-no-scroll screen, old-top-idx - stash [render sandbox side done] +#? stash [render sandbox side done] ] def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, row:num, render-from:num, idx:num -> row:num, screen:&:screen, sandbox:&:sandbox [ local-scope load-ingredients return-unless sandbox - a:num b:num <- cursor-position screen - stash [render-sandboxes] idx [:] row [--] a b +#? a:num b:num <- cursor-position screen +#? stash [render-sandboxes] idx [:] row [--] a b screen-height:num <- screen-height screen at-bottom?:bool <- greater-or-equal row, screen-height return-if at-bottom? @@ -361,11 +361,11 @@ scenario skip-rendering-sandbox-menu-past-bottom-row [ # create two sandboxes such that the top one just barely fills the screen env:&:environment <- new-programming-environment resources, screen, [] env <- restore-sandboxes env, resources - $clear-trace +#? $clear-trace run [ render-all screen, env, render ] - $dump-trace [app] +#? $dump-trace [app] screen-should-contain [ . run (F4) . . ┊ . |