about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-05-29 01:47:54 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-05-29 02:13:43 -0700
commit284e5576495a946d60603b026bb5e27de356b9fd (patch)
treebf2f1c193e2976c0fe20ef13c6c734cac510b664
parentaf4bf7ed2287e051b0d9efdd1918c0812af388e6 (diff)
downloadmu-284e5576495a946d60603b026bb5e27de356b9fd.tar.gz
3894 - comment/uncomment lines in edit app
-rw-r--r--065duplex_list.mu45
-rw-r--r--085scenario_console.cc1
-rw-r--r--edit/003-shortcuts.mu114
-rw-r--r--sandbox/003-shortcuts.mu114
4 files changed, 268 insertions, 6 deletions
diff --git a/065duplex_list.mu b/065duplex_list.mu
index 3e43cebc..97541f33 100644
--- a/065duplex_list.mu
+++ b/065duplex_list.mu
@@ -585,6 +585,51 @@ def last in:&:duplex-list:_elem -> result:&:duplex-list:_elem [
   }
 ]
 
+# does a duplex list start with a certain sequence of elements?
+def match x:&:duplex-list:_elem, y:&:@:_elem -> result:bool [
+  local-scope
+  load-ingredients
+  i:num <- copy 0
+  max:num <- length *y
+  {
+    done?:bool <- greater-or-equal i, max
+    break-if done?
+    expected:_elem <- index *y, i
+    return-unless x, 0/no-match
+    curr:_elem <- first x
+    curr-matches?:bool <- equal curr, expected
+    return-unless curr-matches?, 0/no-match
+    x <- next x
+    i <- add i, 1
+    loop
+  }
+  return 1/successful-match
+]
+
+scenario duplex-list-match [
+  local-scope
+  list:&:duplex-list:char <- push 97/a, 0
+  list <- push 98/b, list
+  list <- push 99/c, list
+  list <- push 100/d, list
+  run [
+    10:bool/raw <- match list, []
+    11:bool/raw <- match list, [d]
+    12:bool/raw <- match list, [dc]
+    13:bool/raw <- match list, [dcba]
+    14:bool/raw <- match list, [dd]
+    15:bool/raw <- match list, [dcbax]
+  ]
+  memory-should-contain [
+    10 <- 1  # matches []
+    11 <- 1  # matches [d]
+    12 <- 1  # matches [dc]
+    13 <- 1  # matches [dcba]
+    14 <- 0  # does not match [dd]
+    15 <- 0  # does not match [dcbax]
+  ]
+]
+
 # helper for debugging
 def dump-from x:&:duplex-list:_elem [
   local-scope
diff --git a/085scenario_console.cc b/085scenario_console.cc
index 2b6c7e8a..496769ab 100644
--- a/085scenario_console.cc
+++ b/085scenario_console.cc
@@ -185,6 +185,7 @@ void initialize_key_names() {
   Key["ctrl-y"] = TB_KEY_CTRL_Y;
   Key["ctrl-z"] = TB_KEY_CTRL_Z;
   Key["escape"] = TB_KEY_ESC;
+  Key["ctrl-slash"] = TB_KEY_CTRL_SLASH;
 }
 
 :(after "Begin check_or_set_invalid_types(r)")
diff --git a/edit/003-shortcuts.mu b/edit/003-shortcuts.mu
index 5444b740..f2cc26af 100644
--- a/edit/003-shortcuts.mu
+++ b/edit/003-shortcuts.mu
@@ -7,7 +7,6 @@
 scenario editor-inserts-two-spaces-on-tab [
   local-scope
   assume-screen 10/width, 5/height
-  # just one character in final line
   s:text <- new [ab
 cd]
   e:&:editor <- new-editor s, 0/left, 5/right
@@ -213,12 +212,11 @@ def previous-line-length curr:&:duplex-list:char, start:&:duplex-list:char -> re
 scenario editor-clears-last-line-on-backspace [
   local-scope
   assume-screen 10/width, 5/height
-  # just one character in final line
   s:text <- new [ab
 cd]
   e:&:editor <- new-editor s, 0/left, 10/right
   assume-console [
-    left-click 2, 0  # cursor at only character in final line
+    left-click 2, 0
     press backspace
   ]
   run [
@@ -3571,3 +3569,113 @@ after <handle-special-character> [
     return go-render?
   }
 ]
+
+# ctrl-/ - comment/uncomment current line
+# todo: scenarios
+
+after <handle-special-character> [
+  {
+    comment-toggle?:bool <- equal c, 31/ctrl-slash
+    break-unless comment-toggle?
+    cursor-column:num <- get *editor, cursor-column:offset
+    data:&:duplex-list:char <- get *editor, data:offset
+    <insert-character-begin>
+    cursor:&:duplex-list:char <- get *editor, before-cursor:offset
+    {
+      next:&:duplex-list:char <- next cursor
+      break-unless next
+      cursor <- copy next
+    }
+    before-line-start:&:duplex-list:char <- before-previous-line cursor, editor
+    line-start:&:duplex-list:char <- next before-line-start
+    commented-out?:bool <- match line-start, [#? ]  # comment prefix
+    {
+      break-unless commented-out?
+      # uncomment
+      data <- remove line-start, 3/length-comment-prefix, data
+      cursor-column <- subtract cursor-column, 3/length-comment-prefix
+    }
+    {
+      break-if commented-out?
+      # comment
+      insert before-line-start, [#? ]
+      cursor-column <- add cursor-column, 3/length-comment-prefix
+    }
+    *editor <- put *editor, cursor-column:offset, cursor-column
+    <insert-character-end>
+    return 1/do-render
+  }
+]
+
+scenario editor-comments-empty-line [
+  local-scope
+  assume-screen 10/width, 5/height
+  e:&:editor <- new-editor [], 0/left, 5/right
+  assume-console [
+    press ctrl-slash
+  ]
+  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 [
+    .          .
+    .#?        .
+    .┈┈┈┈┈     .
+    .          .
+  ]
+  memory-should-contain [
+    4 <- 1
+    5 <- 3
+  ]
+]
+
+scenario editor-comments-at-start-of-contents [
+  local-scope
+  assume-screen 10/width, 5/height
+  e:&:editor <- new-editor [ab], 0/left, 10/right
+  assume-console [
+    press ctrl-slash
+  ]
+  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 [
+    .          .
+    .#? ab     .
+    .┈┈┈┈┈┈┈┈┈┈.
+    .          .
+  ]
+  memory-should-contain [
+    4 <- 1
+    5 <- 3
+  ]
+]
+
+scenario editor-comments-at-end-of-contents [
+  local-scope
+  assume-screen 10/width, 5/height
+  e:&:editor <- new-editor [ab], 0/left, 10/right
+  assume-console [
+    left-click 1, 7
+    press ctrl-slash
+  ]
+  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 [
+    .          .
+    .#? ab     .
+    .┈┈┈┈┈┈┈┈┈┈.
+    .          .
+  ]
+  memory-should-contain [
+    4 <- 1
+    5 <- 5
+  ]
+]
diff --git a/sandbox/003-shortcuts.mu b/sandbox/003-shortcuts.mu
index 65dc4d24..3eaf4413 100644
--- a/sandbox/003-shortcuts.mu
+++ b/sandbox/003-shortcuts.mu
@@ -7,7 +7,6 @@
 scenario editor-inserts-two-spaces-on-tab [
   local-scope
   assume-screen 10/width, 5/height
-  # just one character in final line
   s:text <- new [ab
 cd]
   e:&:editor <- new-editor s, 0/left, 5/right
@@ -210,12 +209,11 @@ def previous-line-length curr:&:duplex-list:char, start:&:duplex-list:char -> re
 scenario editor-clears-last-line-on-backspace [
   local-scope
   assume-screen 10/width, 5/height
-  # just one character in final line
   s:text <- new [ab
 cd]
   e:&:editor <- new-editor s, 0/left, 10/right
   assume-console [
-    left-click 2, 0  # cursor at only character in final line
+    left-click 2, 0
     press backspace
   ]
   run [
@@ -2174,3 +2172,113 @@ def before-previous-line in:&:duplex-list:char, editor:&:editor -> out:&:duplex-
   }
   return curr
 ]
+
+# ctrl-/ - comment/uncomment current line
+# todo: scenarios
+
+after <handle-special-character> [
+  {
+    comment-toggle?:bool <- equal c, 31/ctrl-slash
+    break-unless comment-toggle?
+    cursor-column:num <- get *editor, cursor-column:offset
+    data:&:duplex-list:char <- get *editor, data:offset
+    <insert-character-begin>
+    cursor:&:duplex-list:char <- get *editor, before-cursor:offset
+    {
+      next:&:duplex-list:char <- next cursor
+      break-unless next
+      cursor <- copy next
+    }
+    before-line-start:&:duplex-list:char <- before-previous-line cursor, editor
+    line-start:&:duplex-list:char <- next before-line-start
+    commented-out?:bool <- match line-start, [#? ]  # comment prefix
+    {
+      break-unless commented-out?
+      # uncomment
+      data <- remove line-start, 3/length-comment-prefix, data
+      cursor-column <- subtract cursor-column, 3/length-comment-prefix
+    }
+    {
+      break-if commented-out?
+      # comment
+      insert before-line-start, [#? ]
+      cursor-column <- add cursor-column, 3/length-comment-prefix
+    }
+    *editor <- put *editor, cursor-column:offset, cursor-column
+    <insert-character-end>
+    return 1/do-render
+  }
+]
+
+scenario editor-comments-empty-line [
+  local-scope
+  assume-screen 10/width, 5/height
+  e:&:editor <- new-editor [], 0/left, 5/right
+  assume-console [
+    press ctrl-slash
+  ]
+  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 [
+    .          .
+    .#?        .
+    .┈┈┈┈┈     .
+    .          .
+  ]
+  memory-should-contain [
+    4 <- 1
+    5 <- 3
+  ]
+]
+
+scenario editor-comments-at-start-of-contents [
+  local-scope
+  assume-screen 10/width, 5/height
+  e:&:editor <- new-editor [ab], 0/left, 10/right
+  assume-console [
+    press ctrl-slash
+  ]
+  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 [
+    .          .
+    .#? ab     .
+    .┈┈┈┈┈┈┈┈┈┈.
+    .          .
+  ]
+  memory-should-contain [
+    4 <- 1
+    5 <- 3
+  ]
+]
+
+scenario editor-comments-at-end-of-contents [
+  local-scope
+  assume-screen 10/width, 5/height
+  e:&:editor <- new-editor [ab], 0/left, 10/right
+  assume-console [
+    left-click 1, 7
+    press ctrl-slash
+  ]
+  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 [
+    .          .
+    .#? ab     .
+    .┈┈┈┈┈┈┈┈┈┈.
+    .          .
+  ]
+  memory-should-contain [
+    4 <- 1
+    5 <- 5
+  ]
+]