about summary refs log tree commit diff stats
path: root/twtio.nim
diff options
context:
space:
mode:
Diffstat (limited to 'twtio.nim')
-rw-r--r--twtio.nim213
1 files changed, 174 insertions, 39 deletions
diff --git a/twtio.nim b/twtio.nim
index 0a19bfbf..acb4add7 100644
--- a/twtio.nim
+++ b/twtio.nim
@@ -40,23 +40,188 @@ proc getLinedAction*(s: string): TwtAction =
     return linedActionRemap[s]
   return NO_ACTION
 
-proc readLine*(prompt: string, current: var string): bool =
+const breakWord = [
+  Rune('\n'), Rune('/'), Rune('\\'), Rune(' '), Rune('&'), Rune('=')
+]
+
+#proc readLine*(prompt: string, current: var string, termwidth: int): bool =
+#  var new = current
+#  print(prompt)
+#  let maxlen = termwidth - prompt.len
+#  printesc(new)
+#  var s = ""
+#  var feedNext = false
+#  var escNext = false
+#  var cursor = new.runeLen
+#  var shift = 0
+#  while true:
+#    var rl = new.runeLen()
+#
+#    if cursor < shift:
+#      shift = cursor
+#    elif cursor - shift > maxlen:
+#      shift += cursor - maxlen
+#
+#    if not feedNext:
+#      s = ""
+#    else:
+#      feedNext = false
+#    let c = getch()
+#    s &= c
+#    var action = getLinedAction(s)
+#    if escNext:
+#      action = NO_ACTION
+#    case action
+#    of ACTION_LINED_CANCEL:
+#      return false
+#    of ACTION_LINED_SUBMIT:
+#      current = new
+#      return true
+#    of ACTION_LINED_BACKSPACE:
+#      if cursor > 0:
+#        print(' '.repeat(rl - cursor + 1))
+#        print('\b'.repeat(rl - cursor + 1))
+#        print("\b \b")
+#        new = new.runeSubstr(0, cursor - 1) & new.runeSubstr(cursor)
+#        rl = new.runeLen()
+#        cursor -= 1
+#        printesc(new.runeSubstr(cursor))
+#        print('\b'.repeat(rl - cursor))
+#    of ACTION_LINED_ESC:
+#      escNext = true
+#    of ACTION_LINED_CLEAR:
+#      print('\r')
+#      print(' '.repeat(termwidth))
+#      print('\r')
+#      new = new.runeSubstr(cursor)
+#      rl = new.runeLen()
+#      printesc(prompt)
+#      printesc(new.maxString(maxlen + 1))
+#      print('\r')
+#      printesc(prompt)
+#      cursor = 0
+#    of ACTION_LINED_KILL:
+#      print(' '.repeat(rl - cursor + 1))
+#      print('\b'.repeat(rl - cursor + 1))
+#      new = new.runeSubstr(0, cursor)
+#    of ACTION_LINED_BACK:
+#      if cursor > 0:
+#        if cursor < maxlen:
+#          print('\b')
+#        dec cursor
+#    of ACTION_LINED_FORWARD:
+#      if cursor < rl:
+#        if cursor + 1 < maxlen:
+#          var rune: Rune
+#          new.fastRuneAt(cursor, rune, false)
+#          printesc($rune)
+#        elif cursor + 1 == maxlen:
+#          print('$')
+#        inc cursor
+#    of ACTION_LINED_PREV_WORD:
+#      while cursor > 0:
+#        print('\b')
+#        cursor -= 1
+#        var rune: Rune
+#        new.fastRuneAt(cursor, rune, false)
+#        if rune in breakWord:
+#          break
+#    of ACTION_LINED_NEXT_WORD:
+#      while cursor < rl:
+#        var rune: Rune
+#        new.fastRuneAt(cursor, rune, false)
+#        printesc($rune)
+#        inc cursor
+#        if cursor < rl:
+#          new.fastRuneAt(cursor, rune, false)
+#          if rune in breakWord:
+#            break
+#    of ACTION_LINED_KILL_WORD:
+#      var chars = 0
+#      while cursor > chars:
+#        inc chars
+#        var rune: Rune
+#        new.fastRuneAt(cursor - chars, rune, false)
+#        if rune in breakWord:
+#          break
+#      if chars > 0:
+#        print(' '.repeat(rl - cursor + 1))
+#        print('\b'.repeat(rl - cursor + 1))
+#        print("\b \b".repeat(chars))
+#        new = new.runeSubstr(0, cursor - chars) & new.runeSubstr(cursor)
+#        rl = new.runeLen()
+#        cursor -= chars
+#        printesc(new.runeSubstr(cursor))
+#        print('\b'.repeat(rl - cursor))
+#    of ACTION_FEED_NEXT:
+#      feedNext = true
+#    elif validateUtf8(s) == -1:
+#      var cs = ""
+#      for c in s:
+#        if not c.isControlChar():
+#          cs &= c
+#        elif escNext:
+#          cs &= c
+#          escNext = false
+#      escNext = false
+#      if cs.len == 0:
+#        continue
+#      if rl + 1 < maxlen:
+#        print(' '.repeat(rl - cursor + 1))
+#        print('\b'.repeat(rl - cursor + 1))
+#      new = new.runeSubstr(0, cursor) & cs & new.runeSubstr(cursor)
+#      rl = new.runeLen()
+#      if cursor - shift > maxlen:
+#        shift += maxlen - cursor
+#      if shift == 0:
+#        printesc(new.runeSubstr(cursor, min(maxlen - cursor - 1, rl)))
+#        print('\b'.repeat(max(min(maxlen - cursor - 2, rl - cursor - 1), 0)))
+#      else:
+#        print('\r')
+#        print(' '.repeat(termwidth))
+#        print('\r')
+#        print(prompt)
+#        print(new.runeSubstr(shift, min(maxlen - 1, rl - shift)))
+#        if maxlen < rl - shift:
+#          print(new.runeSubstr(shift, maxlen - 1))
+#          print('\b'.repeat(maxlen - cursor + shift))
+#        else:
+#          print(new.runeSubstr(shift, rl - shift))
+#          print('\b'.repeat(rl + shift - cursor))
+#      inc cursor
+#    else:
+#      feedNext = true
+
+proc readLine*(prompt: string, current: var string, termwidth: int): bool =
   var new = current
   print(prompt)
-  print(' ')
+  let maxlen = termwidth - prompt.len
   printesc(new)
   var s = ""
   var feedNext = false
   var escNext = false
   var cursor = new.runeLen
+  var shift = 0
   while true:
+    var rl = new.runeLen()
+    print('\r')
+    print(' '.repeat(termwidth))
+    print('\r')
+    printesc(prompt & new)
+    print('\r')
+    cursorForward(prompt.len + cursor)
+
+    if cursor < shift:
+      shift = cursor
+    elif cursor - shift > maxlen:
+      shift += cursor - maxlen
+
     if not feedNext:
       s = ""
     else:
       feedNext = false
     let c = getch()
     s &= c
-    var rl = new.runeLen()
     var action = getLinedAction(s)
     if escNext:
       action = NO_ACTION
@@ -68,58 +233,37 @@ proc readLine*(prompt: string, current: var string): bool =
       return true
     of ACTION_LINED_BACKSPACE:
       if cursor > 0:
-        print(' '.repeat(rl - cursor + 1))
-        print('\b'.repeat(rl - cursor + 1))
-        print("\b \b")
         new = new.runeSubstr(0, cursor - 1) & new.runeSubstr(cursor)
         rl = new.runeLen()
-        cursor -= 1
-        printesc(new.runeSubstr(cursor))
-        print('\b'.repeat(rl - cursor))
+        dec cursor
     of ACTION_LINED_ESC:
       escNext = true
     of ACTION_LINED_CLEAR:
-      print(' '.repeat(rl - cursor + 1))
-      print('\b'.repeat(rl - cursor + 1))
-      print('\b'.repeat(cursor))
-      print(' '.repeat(cursor))
-      print('\b'.repeat(cursor))
       new = new.runeSubstr(cursor)
       rl = new.runeLen()
-      printesc(new)
-      print('\b'.repeat(rl))
       cursor = 0
     of ACTION_LINED_KILL:
-      print(' '.repeat(rl - cursor + 1))
-      print('\b'.repeat(rl - cursor + 1))
       new = new.runeSubstr(0, cursor)
     of ACTION_LINED_BACK:
       if cursor > 0:
-        cursor -= 1
-        print("\b")
+        dec cursor
     of ACTION_LINED_FORWARD:
       if cursor < rl:
-        var rune: Rune
-        new.fastRuneAt(cursor, rune, false)
-        printesc($rune)
         inc cursor
     of ACTION_LINED_PREV_WORD:
       while cursor > 0:
-        print('\b')
-        cursor -= 1
+        dec cursor
         var rune: Rune
         new.fastRuneAt(cursor, rune, false)
-        if rune == Rune(' '):
+        if rune in breakWord:
           break
     of ACTION_LINED_NEXT_WORD:
       while cursor < rl:
         var rune: Rune
-        new.fastRuneAt(cursor, rune, false)
-        printesc($rune)
         inc cursor
         if cursor < rl:
           new.fastRuneAt(cursor, rune, false)
-          if rune == Rune(' '):
+          if rune in breakWord:
             break
     of ACTION_LINED_KILL_WORD:
       var chars = 0
@@ -127,17 +271,12 @@ proc readLine*(prompt: string, current: var string): bool =
         inc chars
         var rune: Rune
         new.fastRuneAt(cursor - chars, rune, false)
-        if rune == Rune(' '):
+        if rune in breakWord:
           break
       if chars > 0:
-        print(' '.repeat(rl - cursor + 1))
-        print('\b'.repeat(rl - cursor + 1))
-        print("\b \b".repeat(chars))
         new = new.runeSubstr(0, cursor - chars) & new.runeSubstr(cursor)
         rl = new.runeLen()
         cursor -= chars
-        printesc(new.runeSubstr(cursor))
-        print('\b'.repeat(rl - cursor))
     of ACTION_FEED_NEXT:
       feedNext = true
     elif validateUtf8(s) == -1:
@@ -151,12 +290,8 @@ proc readLine*(prompt: string, current: var string): bool =
       escNext = false
       if cs.len == 0:
         continue
-      print(' '.repeat(rl - cursor + 1))
-      print('\b'.repeat(rl - cursor + 1))
       new = new.runeSubstr(0, cursor) & cs & new.runeSubstr(cursor)
       rl = new.runeLen()
-      printesc(new.runeSubstr(cursor))
-      print('\b'.repeat(rl - cursor - 1))
       inc cursor
     else:
       feedNext = true