about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--081print.mu108
-rw-r--r--edit/001-editor.mu4
-rw-r--r--edit/002-typing.mu18
-rw-r--r--edit/004-programming-environment.mu4
-rw-r--r--edit/005-sandbox.mu10
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)           .
     .                                                  ┊                                                 .