about summary refs log tree commit diff stats
path: root/edit
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-06-18 10:51:29 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-06-18 10:51:29 -0700
commit17a68d800407f8b6ab3de89909147b73ab7e33e9 (patch)
treeb4dda888e6997fba46e898a11a30e060497fdc5c /edit
parent8fce01c15050a8c565e1d195a3b3a4ac7872db07 (diff)
downloadmu-17a68d800407f8b6ab3de89909147b73ab7e33e9.tar.gz
3923
Bugfix: ctrl-a leaves things consistent in the presence of wrapped
lines.
Diffstat (limited to 'edit')
-rw-r--r--edit/003-shortcuts.mu106
1 files changed, 91 insertions, 15 deletions
diff --git a/edit/003-shortcuts.mu b/edit/003-shortcuts.mu
index 87a6f784..4627c3b7 100644
--- a/edit/003-shortcuts.mu
+++ b/edit/003-shortcuts.mu
@@ -1435,7 +1435,7 @@ after <handle-special-character> [
     move-to-start-of-line?:bool <- equal c, 1/ctrl-a
     break-unless move-to-start-of-line?
     <move-cursor-begin>
-    move-to-start-of-line editor
+    move-to-start-of-screen-line editor
     undo-coalesce-tag:num <- copy 0/never
     <move-cursor-end>
     return 0/don't-render
@@ -1447,35 +1447,34 @@ after <handle-special-key> [
     move-to-start-of-line?:bool <- equal k, 65521/home
     break-unless move-to-start-of-line?
     <move-cursor-begin>
-    move-to-start-of-line editor
+    move-to-start-of-screen-line editor
     undo-coalesce-tag:num <- copy 0/never
     <move-cursor-end>
     return 0/don't-render
   }
 ]
 
-def move-to-start-of-line editor:&:editor -> editor:&:editor [
+# handles wrapped lines
+# precondition: cursor-column should be in a consistent state
+def move-to-start-of-screen-line editor:&:editor -> editor:&:editor [
   local-scope
   load-ingredients
   # update cursor column
   left:num <- get *editor, left:offset
-  cursor-column:num <- copy left
-  *editor <- put *editor, cursor-column:offset, cursor-column
+  col:num <- get *editor, cursor-column:offset
   # update before-cursor
-  before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
-  init:&:duplex-list:char <- get *editor, data:offset
+  curr:&:duplex-list:char <- get *editor, before-cursor:offset
   # while not at start of line, move
   {
-    at-start-of-text?:bool <- equal before-cursor, init
-    break-if at-start-of-text?
-    prev:char <- get *before-cursor, value:offset
-    at-start-of-line?:bool <- equal prev, 10/newline
-    break-if at-start-of-line?
-    before-cursor <- prev before-cursor
-    *editor <- put *editor, before-cursor:offset, before-cursor
-    assert before-cursor, [move-to-start-of-line tried to move before start of text]
+    done?:bool <- equal col, left
+    break-if done?
+    assert curr, [move-to-start-of-line tried to move before start of text]
+    curr <- prev curr
+    col <- subtract col, 1
     loop
   }
+  *editor <- put *editor, cursor-column:offset, col
+  *editor <- put *editor, before-cursor:offset, curr
 ]
 
 scenario editor-moves-to-start-of-line-with-ctrl-a-2 [
@@ -1555,6 +1554,58 @@ scenario editor-moves-to-start-of-line-with-home-2 [
   check-trace-count-for-label 0, [print-character]
 ]
 
+scenario editor-moves-to-start-of-screen-line-with-ctrl-a [
+  local-scope
+  assume-screen 10/width, 5/height
+  e:&:editor <- new-editor [123456], 0/left, 5/right
+  editor-render screen, e
+  screen-should-contain [
+    .          .
+    .1234↩     .
+    .56        .
+    .┈┈┈┈┈     .
+    .          .
+  ]
+  $clear-trace
+  # start on second line, press ctrl-a then up
+  assume-console [
+    left-click 2, 1
+    press ctrl-a
+    press up-arrow
+  ]
+  run [
+    editor-event-loop screen, console, e
+    4:num/raw <- get *e, cursor-row:offset
+    5:num/raw <- get *e, cursor-column:offset
+  ]
+  # cursor moves to start of first line
+  memory-should-contain [
+    4 <- 1  # cursor-row
+    5 <- 0  # cursor-column
+  ]
+  check-trace-count-for-label 0, [print-character]
+  # make sure before-cursor is in sync
+  assume-console [
+    type [a]
+  ]
+  run [
+    editor-event-loop screen, console, e
+    4:num/raw <- get *e, cursor-row:offset
+    5:num/raw <- get *e, cursor-column:offset
+  ]
+  screen-should-contain [
+    .          .
+    .a123↩     .
+    .456       .
+    .┈┈┈┈┈     .
+    .          .
+  ]
+  memory-should-contain [
+    4 <- 1  # cursor-row
+    5 <- 1  # cursor-column
+  ]
+]
+
 # ctrl-e/end - move cursor to end of line
 
 scenario editor-moves-to-end-of-line-with-ctrl-e [
@@ -3178,6 +3229,31 @@ def page-down editor:&:editor -> editor:&:editor [
   *editor <- put *editor, top-of-screen:offset, before-cursor
 ]
 
+# jump to previous newline
+def move-to-start-of-line editor:&:editor -> editor:&:editor [
+  local-scope
+  load-ingredients
+  # update cursor column
+  left:num <- get *editor, left:offset
+  cursor-column:num <- copy left
+  *editor <- put *editor, cursor-column:offset, cursor-column
+  # update before-cursor
+  before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
+  init:&:duplex-list:char <- get *editor, data:offset
+  # while not at start of line, move
+  {
+    at-start-of-text?:bool <- equal before-cursor, init
+    break-if at-start-of-text?
+    prev:char <- get *before-cursor, value:offset
+    at-start-of-line?:bool <- equal prev, 10/newline
+    break-if at-start-of-line?
+    before-cursor <- prev before-cursor
+    *editor <- put *editor, before-cursor:offset, before-cursor
+    assert before-cursor, [move-to-start-of-line tried to move before start of text]
+    loop
+  }
+]
+
 scenario editor-does-not-scroll-past-end [
   local-scope
   assume-screen 10/width, 4/height