about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-07-01 13:28:09 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-07-01 13:32:07 -0700
commit61a42dc1c23f02e889eb6116d5a602dcefde7b24 (patch)
tree2a6565fdd4f1dc7f610574d9ab07716e472a73de
parent8529e532499027ac37318b001700fe5a9629d2e8 (diff)
downloadmu-61a42dc1c23f02e889eb6116d5a602dcefde7b24.tar.gz
1694
I started fixing scenario editor-inserts-character-at-wrapped-cursor,
but as I work further I notice there's an irreconcilable ambiguity in
the approach of letting the cursor wrap in a non-wrapped line: if a
cursor is at column 0 and the previous line occupies the entire width,
should the next character you insert go before (assuming a wrapped
cursor) or after the newline (assuming you're at the start of the next
line)? No way to distinguish the two cases.

One approach would be to delete the newline and have the cursor replace
it with whatever you type. Then you have to hit a newline again to
separate.

But the simpler way is to simply wrap the moment the line grows to
width-1, always leaving room for the cursor. Yeah, let's switch to that
approach.
-rw-r--r--edit.mu163
1 files changed, 160 insertions, 3 deletions
diff --git a/edit.mu b/edit.mu
index 677fccfd..07bac50c 100644
--- a/edit.mu
+++ b/edit.mu
@@ -22,9 +22,9 @@ recipe main [
   draw-horizontal 0:literal/screen, 35:literal, column2:number, width:number, 9473:literal/horizontal-double
   # editor on the left
   left:address:array:character <- new [abcde]
-  left-editor:address:editor-data <- new-editor left:address:array:character, 0:literal/screen, 0:literal/top, 0:literal/left, divider:number/right
+  left-editor:address:editor-data <- new-editor left:address:array:character, 0:literal/screen, 0:literal/top, 0:literal/left, 5:literal/right  #divider:number/right
   # editor on the right
-  right:address:array:character <- new [def]
+  right:address:array:character <- new [defgh]
   new-left:number <- add divider:number, 1:literal
   new-right:number <- add new-left:number, 5:literal
   right-editor:address:editor-data <- new-editor right:address:array:character, 0:literal/screen, 4:literal/top, new-left:number, new-right:number #width:number
@@ -272,7 +272,7 @@ recipe render [
       next:character <- get next-node:address:duplex-list/deref, value:offset
       next-character-is-newline?:boolean <- equal next:character, 10:literal/newline
       break-if next-character-is-newline?:boolean
-      # wrap
+      # print wrap icon
       print-character screen:address, 8617:literal/loop-back-to-left, 245:literal/grey
       column:number <- copy left:number
       row:number <- add row:number, 1:literal
@@ -680,6 +680,7 @@ recipe insert-at-cursor [
   before-cursor:address:address:duplex-list <- get-address editor:address:editor-data/deref, before-cursor:offset
   d:address:duplex-list <- get editor:address:editor-data/deref, data:offset
   insert-duplex c:character, before-cursor:address:address:duplex-list/deref
+  before-cursor:address:address:duplex-list/deref <- next-duplex before-cursor:address:address:duplex-list/deref
   screen:address <- get editor:address:editor-data/deref, screen:offset
   cursor-row:address:number <- get-address editor:address:editor-data/deref, cursor-row:offset
   cursor-column:address:number <- get-address editor:address:editor-data/deref, cursor-column:offset
@@ -714,6 +715,43 @@ recipe insert-at-cursor [
 #? ] #? 1
     reply
   }
+  # was cursor wrapped?
+  {
+    at-left-margin?:boolean <- equal cursor-column:address:number/deref, left:number
+    break-unless at-left-margin?:boolean
+    $print [wrapped cursor check: 1
+]
+    previous:address:duplex-list <- prev-duplex before-cursor:address:address:duplex-list/deref
+    at-start-of-text?:boolean <- not previous:address:duplex-list
+    after-newline?:boolean <- copy 0:literal/false
+    {
+      break-if at-start-of-text?:boolean
+      previous-character:character <- get before-cursor:address:address:duplex-list/deref/deref, value:offset
+      after-newline?:boolean <- equal previous-character:character, 10:literal/newline
+    }
+    at-start-of-line?:boolean <- or at-start-of-text?:boolean, after-newline?:boolean
+    break-if at-start-of-line?:boolean  # i.e. not at wrapped line
+    $print [wrapped cursor check: 2
+]
+    current:address:duplex-list <- next-duplex before-cursor:address:address:duplex-list/deref
+    at-end-of-text?:boolean <- not current:address:duplex-list
+    $print [at end of text? ], at-end-of-text?:boolean, [ 
+]
+    at-newline?:boolean <- copy 0:literal/false
+    {
+      break-if at-end-of-text?:boolean
+      current-character:character <- get current:address:duplex-list/deref, value:offset
+      $print [current character: ], current-character:character, [ 
+]
+      at-newline?:boolean <- equal current-character:character, 10:literal/newline
+    }
+    at-end-of-line?:boolean <- or at-end-of-text?:boolean, at-newline?:boolean
+    break-unless at-end-of-line?:boolean
+    $print [wrapped cursor check: 3
+]
+    cursor-column:address:number/deref <- copy 2:literal  # add 2 rather than 1 to account for wrap icon
+    reply
+  }
   # otherwise move cursor right
   cursor-column:address:number/deref <- add cursor-column:address:number/deref, 1:literal
 ]
@@ -1018,6 +1056,99 @@ scenario editor-inserts-characters-at-cursor-6 [
   ]
 ]
 
+scenario editor-inserts-character-at-wrapped-cursor [
+  assume-screen 10:literal/width, 5:literal/height
+  # text fills line
+  1:address:array:character <- new [abcde]
+  2:address:editor-data <- new-editor 1:address:array:character, screen:address, 0:literal/top, 0:literal/left, 5:literal/right
+  # make cursor wrap at end of text
+  assume-console [
+    left-click 4, 3
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number <- get 2:address:editor-data/deref, cursor-row:offset
+    4:number <- get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3 <- 1
+    4 <- 0  # cursor wrapped
+  ]
+  # but line doesn't wrap
+  screen-should-contain [
+    .abcde     .
+    .          .
+  ]
+  # now insert a character
+  assume-console [
+    type [f]
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number <- get 2:address:editor-data/deref, cursor-row:offset
+    4:number <- get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  # line now wraps
+  screen-should-contain [
+    .abcd↩     .
+    .ef        .
+  ]
+  # and wrapped cursor remains at the same *logical* point
+  memory-should-contain [
+    3 <- 1
+    4 <- 2  # not 1
+  ]
+]
+
+scenario editor-inserts-character-at-wrapped-cursor-2 [
+  assume-screen 10:literal/width, 5:literal/height
+  # text fills line
+  1:address:array:character <- new [abcde
+z]
+  2:address:editor-data <- new-editor 1:address:array:character, screen:address, 0:literal/top, 0:literal/left, 5:literal/right
+  # make cursor wrap at end of an internal line
+  assume-console [
+    left-click 0, 4
+    press 65514  # right arrow
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number <- get 2:address:editor-data/deref, cursor-row:offset
+    4:number <- get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3 <- 1
+    4 <- 0  # cursor wrapped
+  ]
+  # but line doesn't wrap
+  screen-should-contain [
+    .abcde     .
+    .z         .
+    .          .
+  ]
+  # now insert a character
+  assume-console [
+    type [f]
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number <- get 2:address:editor-data/deref, cursor-row:offset
+    4:number <- get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  # line now wraps
+  screen-should-contain [
+    .abcd↩     .
+    .ef        .
+    .z         .
+    .          .
+  ]
+  # and wrapped cursor remains at the same *logical* point
+  memory-should-contain [
+    3 <- 1
+    4 <- 2  # not 1
+  ]
+]
+
 scenario editor-wraps-line-on-insert [
   assume-screen 5:literal/width, 3:literal/height
   1:address:array:character <- new [abcd]
@@ -1428,6 +1559,32 @@ d]
   ]
 ]
 
+scenario editor-wraps-just-cursor-with-right-arrow [
+  assume-screen 10:literal/width, 5:literal/height
+  # first line occupies entire width
+  1:address:array:character <- new [abcde
+z]
+  2:address:editor-data <- new-editor 1:address:array:character, screen:address, 0:literal/top, 0:literal/left, 5:literal/right
+  assume-console [
+    left-click 0, 4
+    press 65514  # right arrow - next line
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number <- get 2:address:editor-data/deref, cursor-row:offset
+    4:number <- get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  screen-should-contain [
+    .abcde     .
+    .z         .
+    .          .
+  ]
+  memory-should-contain [
+    3 <- 1
+    4 <- 0
+  ]
+]
+
 scenario editor-moves-cursor-left-with-key [
   assume-screen 10:literal/width, 5:literal/height
   1:address:array:character <- new [abc]