about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-07-27 15:49:28 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-07-27 15:49:28 -0700
commiteecab21816fad9ff82cfbf670ff645e807394fe3 (patch)
tree7c1cc756321074b11ed2812dcc6dec26c8535a5b
parente0935feec50556803a4e4ba54864bb92b2bc8849 (diff)
downloadmu-eecab21816fad9ff82cfbf670ff645e807394fe3.tar.gz
1857 - editor supports autoindent
-rw-r--r--edit.mu84
1 files changed, 80 insertions, 4 deletions
diff --git a/edit.mu b/edit.mu
index 06dcb553..9dd32324 100644
--- a/edit.mu
+++ b/edit.mu
@@ -749,8 +749,8 @@ recipe handle-event [
   {
     c:address:character <- maybe-convert e:event, text:variant
     break-unless c:address:character
-    # check for special characters
-    # unless it's a backspace
+    ## check for special characters
+    # backspace - delete character before cursor
     {
       backspace?:boolean <- equal c:address:character/deref, 8:literal/backspace
       break-unless backspace?:boolean
@@ -956,9 +956,8 @@ recipe insert-at-cursor [
   editor:address:editor-data <- next-ingredient
   c:character <- next-ingredient
   screen:address <- next-ingredient
-#?   $print [insert ], c:character, 10:literal/newline
+#?   $print [insert ], c:character, 10:literal/newline #? 1
   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
   cursor-row:address:number <- get-address editor:address:editor-data/deref, cursor-row:offset
@@ -972,6 +971,20 @@ recipe insert-at-cursor [
     break-unless newline?:boolean
     cursor-row:address:number/deref <- add cursor-row:address:number/deref, 1:literal
     cursor-column:address:number/deref <- copy left:number
+    # indent if necessary
+#?     $print [computing indent], 10:literal/newline #? 1
+    d:address:duplex-list <- get editor:address:editor-data/deref, data:offset
+    end-of-previous-line:address:duplex-list <- prev-duplex before-cursor:address:address:duplex-list/deref
+    indent:number <- line-indent end-of-previous-line:address:duplex-list, d:address:duplex-list
+#?     $print indent:number, 10:literal/newline #? 1
+    i:number <- copy 0:literal
+    {
+      indent-done?:boolean <- greater-or-equal i:number, indent:number
+      break-if indent-done?:boolean
+      insert-at-cursor editor:address:editor-data, 32:literal/space, screen:address
+      i:number <- add i:number, 1:literal
+      loop
+    }
     reply
   }
   # if the line wraps at the cursor, move cursor to start of next row
@@ -1039,6 +1052,45 @@ recipe previous-line-length [
   reply result:number
 ]
 
+# takes a pointer 'curr' into the doubly-linked list and its sentinel, counts
+# the number of spaces at the start of the line containing 'curr'.
+recipe line-indent [
+  local-scope
+  curr:address:duplex-list <- next-ingredient
+  start:address:duplex-list <- next-ingredient
+  result:number <- copy 0:literal
+  reply-unless curr:address:duplex-list, result:number
+#?   $print [a0], 10:literal/newline #? 1
+  at-start?:boolean <- equal curr:address:duplex-list, start:address:duplex-list
+  reply-if at-start?:boolean, result:number
+#?   $print [a1], 10:literal/newline #? 1
+  {
+    curr:address:duplex-list <- prev-duplex curr:address:duplex-list
+    break-unless curr:address:duplex-list
+#?   $print [a2], 10:literal/newline #? 1
+    at-start?:boolean <- equal curr:address:duplex-list, start:address:duplex-list
+    break-if at-start?:boolean
+#?   $print [a3], 10:literal/newline #? 1
+    c:character <- get curr:address:duplex-list/deref, value:offset
+    at-newline?:boolean <- equal c:character, 10:literal/newline
+    break-if at-newline?:boolean
+#?   $print [a4], 10:literal/newline #? 1
+    # if c is a space, increment result
+    is-space?:boolean <- equal c:character, 32:literal/space
+    {
+      break-unless is-space?:boolean
+      result:number <- add result:number, 1:literal
+    }
+    # if c is not a space, reset result
+    {
+      break-if is-space?:boolean
+      result:number <- copy 0:literal
+    }
+    loop
+  }
+  reply result:number
+]
+
 recipe move-to-start-of-line [
   local-scope
   editor:address:editor-data <- next-ingredient
@@ -1638,6 +1690,30 @@ scenario editor-clears-previous-line-completely-after-inserting-newline [
   ]
 ]
 
+scenario editor-inserts-indent-after-newline [
+  assume-screen 10:literal/width, 10:literal/height
+  1:address:array:character <- new [ab
+  cd
+ef]
+  2:address:editor-data <- new-editor 1:address:array:character, screen:address, 0:literal/left, 10:literal/right
+  # position cursor after 'cd' and hit 'newline'
+  assume-console [
+    left-click 2, 8
+    type [
+]
+  ]
+  run [
+    editor-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
+  ]
+  # cursor should be below start of previous line
+  memory-should-contain [
+    3 <- 3  # cursor row
+    4 <- 2  # cursor column (indented)
+  ]
+]
+
 scenario editor-handles-backspace-key [
   assume-screen 10:literal/width, 5:literal/height
   1:address:array:character <- new [abc]