about summary refs log tree commit diff stats
path: root/edit
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-05-18 09:44:37 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-05-18 09:57:57 -0700
commitee1a18f050a5458ade460720091e20ce6b335011 (patch)
treece16273f91254d3d966a1f5427bf9af04b4f136a /edit
parent7f67383400216732166ff8c845829b93b217ff30 (diff)
downloadmu-ee1a18f050a5458ade460720091e20ce6b335011.tar.gz
3860 - stop buffering the screen in termbox
To achieve this we have to switch to a model of the screen in termbox that
is closer to the underlying terminal.

Before:
  a screen is a grid of characters
  writing out of bounds does nothing

After:
  a screen is a scrolling raster of characters
  writing out of bounds wraps to next line and scrolls if necessary

To move to the new model, it was essential that I migrate my fake screen
at the same time to mimic it. This is why the first attempt (commit 3824)
failed (commit 3858). This is also why this commit can't be split into
smaller pieces.

The fake screen now 'scrolls' by rotating screen lines from top to bottom.
There's still no notion of a scrollback buffer.

The newer model is richer; it permits repl-like apps that upstream termbox
can't do easily. It also permits us to simply use `printf` or `cout` to
write to the screen, and everything mostly works as you would expect. Exceptions:

  a) '\n' won't do what you expect. You need to explicitly print both '\n'
  and '\r'.

  b) backspace won't do what you expect. It only moves the cursor back,
  without erasing the previous character. It does not wrap.

  Both behaviors exactly mimic my existing terminal's emulation of vt100.

The catch: it's easy to accidentally scroll in apps. Out-of-bounds prints
didn't matter before, but they're bugs now. To help track them down, use
the `save-top-idx`, `assert-no-scroll` pair of helpers.

  An important trick is to wrap the cursor before rather after printing
  a character. Otherwise we end up scrolling every time we print to the
  bottom-right character. This means that the cursor position can be invalid
  at the start of a print, and we need to handle that.

In the process we also lose the ability to hide and show the screen. We
have to show the prints happening. Seems apt for a "white-box" platform
like Mu.
Diffstat (limited to 'edit')
-rw-r--r--edit/001-editor.mu2
-rw-r--r--edit/002-typing.mu5
-rw-r--r--edit/004-programming-environment.mu8
-rw-r--r--edit/005-sandbox.mu4
-rw-r--r--edit/006-sandbox-copy.mu2
-rw-r--r--edit/007-sandbox-delete.mu2
-rw-r--r--edit/008-sandbox-edit.mu2
-rw-r--r--edit/009-sandbox-test.mu2
-rw-r--r--edit/010-sandbox-trace.mu2
9 files changed, 8 insertions, 21 deletions
diff --git a/edit/001-editor.mu b/edit/001-editor.mu
index d81278ae..a6dde85b 100644
--- a/edit/001-editor.mu
+++ b/edit/001-editor.mu
@@ -6,10 +6,8 @@ def main text:text [
   local-scope
   load-ingredients
   open-console
-  hide-screen 0/screen
   e:&:editor <- new-editor text, 0/left, 5/right
   render 0/screen, e
-  show-screen 0/screen
   wait-for-event 0/console
   close-console
 ]
diff --git a/edit/002-typing.mu b/edit/002-typing.mu
index 8c48f147..16693429 100644
--- a/edit/002-typing.mu
+++ b/edit/002-typing.mu
@@ -264,6 +264,7 @@ def insert-at-cursor editor:&:editor, c:char, screen:&:screen -> go-render?:bool
 def editor-render screen:&:screen, editor:&:editor -> screen:&:screen, editor:&:editor [
   local-scope
   load-ingredients
+  old-top-idx:num <- save-top-idx screen
   left:num <- get *editor, left:offset
   right:num <- get *editor, right:offset
   row:num, column:num <- render screen, editor
@@ -272,6 +273,7 @@ def editor-render screen:&:screen, editor:&:editor -> screen:&:screen, editor:&:
   draw-horizontal screen, row, left, right, 9480/horizontal-dotted
   row <- add row, 1
   clear-screen-from screen, row, left, left, right
+  assert-no-scroll screen, old-top-idx
 ]
 
 scenario editor-handles-empty-event-queue [
@@ -1057,6 +1059,9 @@ after <handle-special-key> [
 def draw-horizontal screen:&:screen, row:num, x:num, right:num -> screen:&:screen [
   local-scope
   load-ingredients
+  height:num <- screen-height screen
+  past-bottom?:bool <- greater-or-equal row, height
+  return-if past-bottom?
   style:char, style-found?:bool <- next-ingredient
   {
     break-if style-found?
diff --git a/edit/004-programming-environment.mu b/edit/004-programming-environment.mu
index 0d4e907d..606cdfa2 100644
--- a/edit/004-programming-environment.mu
+++ b/edit/004-programming-environment.mu
@@ -96,7 +96,6 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources:
     }
     # if it's not global and not a touch event, send to appropriate editor
     {
-      hide-screen screen
       sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset
       {
         break-if sandbox-in-focus?
@@ -117,7 +116,6 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources:
         screen <- render-all screen, env, render
       }
       screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-      show-screen screen
     }
     loop
   }
@@ -396,7 +394,7 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr
   local-scope
   load-ingredients
   trace 10, [app], [render all]
-  hide-screen screen
+  old-top-idx:num <- save-top-idx screen
   # top menu
   trace 11, [app], [render top menu]
   width:num <- screen-width screen
@@ -414,14 +412,14 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr
   #
   screen <- render-recipes screen, env, render-editor
   screen <- render-sandbox-side screen, env, render-editor
-  <render-components-end>
+  <render-components-end>  # no early returns permitted
   #
   recipes:&:editor <- get *env, recipes:offset
   current-sandbox:&:editor <- get *env, current-sandbox:offset
   sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset
   screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
   #
-  show-screen screen
+  assert-no-scroll screen, old-top-idx
 ]
 
 def render-recipes screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [
diff --git a/edit/005-sandbox.mu b/edit/005-sandbox.mu
index 5f08554d..2e16e05b 100644
--- a/edit/005-sandbox.mu
+++ b/edit/005-sandbox.mu
@@ -971,10 +971,8 @@ after <global-keypress> [
       render-from <- add render-from, 1
       *env <- put *env, render-from:offset, render-from
     }
-    hide-screen screen
     screen <- render-sandbox-side screen, env, render
     screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-    show-screen screen
     loop +next-event
   }
 ]
@@ -1003,10 +1001,8 @@ after <global-keypress> [
     break-if at-beginning?
     render-from <- subtract render-from, 1
     *env <- put *env, render-from:offset, render-from
-    hide-screen screen
     screen <- render-sandbox-side screen, env, render
     screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/edit/006-sandbox-copy.mu b/edit/006-sandbox-copy.mu
index 9df5e625..d3f82e88 100644
--- a/edit/006-sandbox-copy.mu
+++ b/edit/006-sandbox-copy.mu
@@ -128,10 +128,8 @@ after <global-touch> [
     break-unless copy?
     copy?, env <- try-copy-sandbox click-row, env
     break-unless copy?
-    hide-screen screen
     screen <- render-sandbox-side screen, env, render
     screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/edit/007-sandbox-delete.mu b/edit/007-sandbox-delete.mu
index 4fa3c37d..5167b038 100644
--- a/edit/007-sandbox-delete.mu
+++ b/edit/007-sandbox-delete.mu
@@ -72,10 +72,8 @@ after <global-touch> [
     break-unless delete?
     delete?, env <- try-delete-sandbox click-row, env
     break-unless delete?
-    hide-screen screen
     screen <- render-sandbox-side screen, env, render
     screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/edit/008-sandbox-edit.mu b/edit/008-sandbox-edit.mu
index dd5c1bb9..2d591ad6 100644
--- a/edit/008-sandbox-edit.mu
+++ b/edit/008-sandbox-edit.mu
@@ -111,10 +111,8 @@ after <global-touch> [
     break-unless edit?
     edit?, env <- try-edit-sandbox click-row, env
     break-unless edit?
-    hide-screen screen
     screen <- render-sandbox-side screen, env, render
     screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/edit/009-sandbox-test.mu b/edit/009-sandbox-test.mu
index 023015ed..badd795b 100644
--- a/edit/009-sandbox-test.mu
+++ b/edit/009-sandbox-test.mu
@@ -130,10 +130,8 @@ after <global-touch> [
     # toggle its expected-response, and save session
     sandbox <- toggle-expected-response sandbox
     save-sandboxes env, resources
-    hide-screen screen
     screen <- render-sandbox-side screen, env, render
     screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/edit/010-sandbox-trace.mu b/edit/010-sandbox-trace.mu
index 66a321d6..8088577a 100644
--- a/edit/010-sandbox-trace.mu
+++ b/edit/010-sandbox-trace.mu
@@ -200,10 +200,8 @@ after <global-touch> [
     x:bool <- get *sandbox, display-trace?:offset
     x <- not x
     *sandbox <- put *sandbox, display-trace?:offset, x
-    hide-screen screen
     screen <- render-sandbox-side screen, env, render
     screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-    show-screen screen
     loop +next-event
   }
 ]