]> git.mdlowis.com Git - projs/tide.git/commitdiff
added tests and refactored selection handling
authorMichael D. Lowis <mike.lowis@gentex.com>
Wed, 23 Oct 2019 14:58:29 +0000 (10:58 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Wed, 23 Oct 2019 14:58:29 +0000 (10:58 -0400)
TODO.md
src/lib/buf.c
tests/lib/buf.c

diff --git a/TODO.md b/TODO.md
index e3525b2e020eb0c8e9fdd832d7ef24cf1a5c6425..adcead51065395c8e3b9b1cfaabf20e50d82dab9 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -4,6 +4,9 @@
 
 ## STAGING
 
+* tide: assert fails in mouse handling code for invalid mouse button
+* tide: filter commands don't always select the output like they should
+* tide: move looping of cursor movements into selmoveby
 * all: eliminate multiple return statements and other lint
 * tide: byrune, byword, byline functions should be hidden in buf.c
 * tide: column tracking should be hidden in buf.c
index 774feb90273878a53e83028e27178d8fdae1af08..486f7affde11816a126d4ee3fac8c17058637d90 100644 (file)
@@ -627,29 +627,32 @@ static size_t byword(Buf* buf, size_t off, int count)
 {
     require(buf != NULL);
     int move = (count < 0 ? -1 : 1);
+    count *= move; // remove the sign if there is one
 
-    while (nextrune(buf, off, move, risblank))
-    {
-        off = buf_byrune(buf, off, move);
-    }
-
-    if (nextrune(buf, off, move, risword))
+    for (; count > 0; count--)
     {
-        while (nextrune(buf, off, move, risword))
+        while (nextrune(buf, off, move, risblank))
         {
             off = buf_byrune(buf, off, move);
         }
 
-        if (move > 0)
+        if (nextrune(buf, off, move, risword))
+        {
+            while (nextrune(buf, off, move, risword))
+            {
+                off = buf_byrune(buf, off, move);
+            }
+
+            if (move > 0)
+            {
+                off = buf_byrune(buf, off, move);
+            }
+        }
+        else
         {
             off = buf_byrune(buf, off, move);
         }
     }
-    else
-    {
-        off = buf_byrune(buf, off, move);
-    }
-
     return off;
 }
 
@@ -883,15 +886,10 @@ void buf_selmove(Buf* buf, bool extsel, int move, int bything)
 
 void buf_selmoveto(Buf* buf, bool extsel, size_t off)
 {
-    off = (off > buf_end(buf) ? buf_end(buf) : off);
-    int dir = (off < buf->selection.end ? LEFT : RIGHT);
-    buf->selection.end = off;
+    buf->selection.end = (off > buf_end(buf) ? buf_end(buf) : off);
     if (!extsel)
     {
-        buf_selclr(buf, dir);
-    }
-    else
-    {
-        getcol(buf);
+        buf->selection.beg = buf->selection.end;
     }
+    getcol(buf);
 }
index ea6254411a4c29386e8afd8ced9bf102711a936f..cc822b4d1521383490913e7a34238facfe24484d 100644 (file)
@@ -13,6 +13,7 @@ static Buf TestBuf = {0};
 
 static void set_buffer_text(char* str)
 {
+    DosLineFeed = Off;
     /* cleanup old data if there is any */
     if (TestBuf.contents.bufstart)
     {
@@ -307,68 +308,6 @@ TEST_SUITE(BufferTests)
         CHECK(3 == buf_bol(&TestBuf, 3));
     }
 
-//    /* Cursor Column Tracking
-//     *************************************************************************/
-//    TEST(buf_getcol should return the column associated with the position)
-//    {
-//        set_buffer_text("abcdef");
-//        TestBuf.selection = (Sel){ .end = 4 };
-//        buf_getcol(&TestBuf);
-//        CHECK(4 == TestBuf.selection.col);
-//    }
-//
-//    TEST(buf_getcol should return the column associated with the position on second line)
-//    {
-//        set_buffer_text("abcdef\nabcdef");
-//        TestBuf.selection = (Sel){ .end = 7 };
-//        buf_getcol(&TestBuf);
-//        CHECK(0 == TestBuf.selection.col);
-//    }
-//
-//    TEST(buf_getcol should handle tab characters)
-//    {
-//        set_buffer_text("\tabcdef");
-//        TestBuf.selection = (Sel){ .end = 1 };
-//        buf_getcol(&TestBuf);
-//        CHECK(4 == TestBuf.selection.col);
-//    }
-//
-//    TEST(buf_setcol should set the column to column 1 of second line)
-//    {
-//        set_buffer_text("abc\ndef");
-//        TestBuf.selection = (Sel){ .end = 4, .col = 0 };
-//        buf_setcol(&TestBuf);
-//        CHECK(0 == TestBuf.selection.col);
-//        CHECK(4 == TestBuf.selection.end);
-//    }
-//
-////    TEST(buf_setcol should set the column to column 2 of second line) {
-////        set_buffer_text("abc\ndef");
-////        TestBuf.selection = (Sel){ .end = 4, .col = 1 };
-////        buf_setcol(&TestBuf);
-////        CHECK(1 == TestBuf.selection.col);
-////        printf("%lu\n", TestBuf.selection.end);
-////        CHECK(5 == TestBuf.selection.end);
-////    }
-////
-////    TEST(buf_setcol should handle tabs) {
-////        set_buffer_text("abc\n\tdef");
-////        TestBuf.selection = (Sel){ .end = 4, .col = 4 };
-////        buf_setcol(&TestBuf);
-////        CHECK(4 == TestBuf.selection.col);
-////        printf("%lu\n", TestBuf.selection.end);
-////        CHECK(5 == TestBuf.selection.end);
-////    }
-////
-////    TEST(buf_setcol should not set column past the last rune) {
-////        set_buffer_text("abc\n\tdef");
-////        TestBuf.selection = (Sel){ .end = 4, .col = 100 };
-////        buf_setcol(&TestBuf);
-////        CHECK(100 == TestBuf.selection.col);
-////        printf("%lu\n", TestBuf.selection.end);
-////        CHECK(8 == TestBuf.selection.end);
-////    }
-
     /* Context-Sensitive Selection
      *************************************************************************/
     TEST(buf_selctx should select from ( to ))
@@ -525,10 +464,10 @@ TEST_SUITE(BufferTests)
     TEST(buf_selctx should select line on bol)
     {
         set_buffer_text("\n...\n");
-        TestBuf.selection = (Sel){ .beg = 2, .end = 2 };
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1 };
         buf_selctx(&TestBuf, risword);
-        CHECK(2 == buf_selbeg(&TestBuf));
-        CHECK(7 == buf_selend(&TestBuf));
+        CHECK(1 == buf_selbeg(&TestBuf));
+        CHECK(5 == buf_selend(&TestBuf));
     }
 
     TEST(buf_selctx should select line on eol)
@@ -536,7 +475,7 @@ TEST_SUITE(BufferTests)
         set_buffer_text("\n...\n");
         TestBuf.selection = (Sel){ .beg = 4, .end = 4 };
         buf_selctx(&TestBuf, risword);
-        CHECK(2 == buf_selbeg(&TestBuf));
+        CHECK(1 == buf_selbeg(&TestBuf));
         CHECK(5 == buf_selend(&TestBuf));
     }
 
@@ -565,4 +504,267 @@ TEST_SUITE(BufferTests)
         free(str);
         CHECK(result);
     }
+
+    /* Cursor/Selection Movement
+    *************************************************************************/
+    TEST(buf_selmove should move cursor left by one rune)
+    {
+        set_buffer_text(" abc ");
+        TestBuf.selection = (Sel){ .beg = 2, .end = 2, .col = 2 };
+        buf_selmove(&TestBuf, false, LEFT, BY_RUNE);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor left by two runes)
+    {
+        set_buffer_text(" abc ");
+        TestBuf.selection = (Sel){ .beg = 2, .end = 2, .col = 2 };
+        buf_selmove(&TestBuf, false, 2*LEFT, BY_RUNE);
+        CHECK(0 == TestBuf.selection.beg);
+        CHECK(0 == TestBuf.selection.end);
+        CHECK(0 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection left by one rune)
+    {
+        set_buffer_text(" abc ");
+        TestBuf.selection = (Sel){ .beg = 2, .end = 2, .col = 2 };
+        buf_selmove(&TestBuf, true, LEFT, BY_RUNE);
+        CHECK(2 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection left by two runes)
+    {
+        set_buffer_text(" abc ");
+        TestBuf.selection = (Sel){ .beg = 2, .end = 2, .col = 2 };
+        buf_selmove(&TestBuf, true, 2*LEFT, BY_RUNE);
+        CHECK(2 == TestBuf.selection.beg);
+        CHECK(0 == TestBuf.selection.end);
+        CHECK(0 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor left by one word)
+    {
+        set_buffer_text(" a b c ");
+        TestBuf.selection = (Sel){ .beg = 3, .end = 3, .col = 3 };
+        buf_selmove(&TestBuf, false, LEFT, BY_WORD);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor left by two words)
+    {
+        set_buffer_text(" a b c ");
+        TestBuf.selection = (Sel){ .beg = 5, .end = 5, .col = 5 };
+        buf_selmove(&TestBuf, false, 2*LEFT, BY_WORD);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection left by one word)
+    {
+        set_buffer_text(" a b c ");
+        TestBuf.selection = (Sel){ .beg = 3, .end = 3, .col = 3  };
+        buf_selmove(&TestBuf, true, LEFT, BY_WORD);
+        CHECK(3 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection left by two words)
+    {
+        set_buffer_text(" a b c ");
+        TestBuf.selection = (Sel){ .beg = 5, .end = 5, .col = 5 };
+        buf_selmove(&TestBuf, true, 2*LEFT, BY_WORD);
+        CHECK(5 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor right by one rune)
+    {
+        set_buffer_text(" abc ");
+        TestBuf.selection = (Sel){ .beg = 2, .end = 2, .col = 2 };
+        buf_selmove(&TestBuf, false, RIGHT, BY_RUNE);
+        CHECK(3 == TestBuf.selection.beg);
+        CHECK(3 == TestBuf.selection.end);
+        CHECK(3 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor right by two runes)
+    {
+        set_buffer_text(" abc ");
+        TestBuf.selection = (Sel){ .beg = 2, .end = 2, .col = 2 };
+        buf_selmove(&TestBuf, false, 2*RIGHT, BY_RUNE);
+        CHECK(4 == TestBuf.selection.beg);
+        CHECK(4 == TestBuf.selection.end);
+        CHECK(4 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection right by one rune)
+    {
+        set_buffer_text(" abc ");
+        TestBuf.selection = (Sel){ .beg = 2, .end = 2, .col = 2 };
+        buf_selmove(&TestBuf, true, RIGHT, BY_RUNE);
+        CHECK(2 == TestBuf.selection.beg);
+        CHECK(3 == TestBuf.selection.end);
+        CHECK(3 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection right by two runes)
+    {
+        set_buffer_text(" abc ");
+        TestBuf.selection = (Sel){ .beg = 2, .end = 2, .col = 2 };
+        buf_selmove(&TestBuf, true, 2*RIGHT, BY_RUNE);
+        CHECK(2 == TestBuf.selection.beg);
+        CHECK(4 == TestBuf.selection.end);
+        CHECK(4 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor right by one word)
+    {
+        set_buffer_text(" a b c ");
+        TestBuf.selection = (Sel){ .beg = 3, .end = 3, .col = 3 };
+        buf_selmove(&TestBuf, false, RIGHT, BY_WORD);
+        CHECK(6 == TestBuf.selection.beg);
+        CHECK(6 == TestBuf.selection.end);
+        CHECK(6 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor right by two words)
+    {
+        set_buffer_text(" a b c ");
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1, .col = 1 };
+        buf_selmove(&TestBuf, false, 2*RIGHT, BY_WORD);
+        CHECK(6 == TestBuf.selection.beg);
+        CHECK(6 == TestBuf.selection.end);
+        CHECK(6 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection right by one word)
+    {
+        set_buffer_text(" a b c ");
+        TestBuf.selection = (Sel){ .beg = 3, .end = 3, .col = 3  };
+        buf_selmove(&TestBuf, true, RIGHT, BY_WORD);
+        CHECK(3 == TestBuf.selection.beg);
+        CHECK(6 == TestBuf.selection.end);
+        CHECK(6 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection right by two words)
+    {
+        set_buffer_text(" a b c ");
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1, .col = 1 };
+        buf_selmove(&TestBuf, true, 2*RIGHT, BY_WORD);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(6 == TestBuf.selection.end);
+        CHECK(6 == TestBuf.selection.col);
+    }
+
+
+    TEST(buf_selmove should move cursor up one line)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 4, .end = 4, .col = 1 };
+        buf_selmove(&TestBuf, false, UP, BY_LINE);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor up two lines)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 7, .end = 7, .col = 1 };
+        buf_selmove(&TestBuf, false, 2*UP, BY_LINE);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection up one line)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 4, .end = 4, .col = 1 };
+        buf_selmove(&TestBuf, true, UP, BY_LINE);
+        CHECK(4 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection up two lines)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 7, .end = 7, .col = 1 };
+        buf_selmove(&TestBuf, true, 2*UP, BY_LINE);
+        CHECK(7 == TestBuf.selection.beg);
+        CHECK(1 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor down one line)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1, .col = 1 };
+        buf_selmove(&TestBuf, false, DOWN, BY_LINE);
+        CHECK(4 == TestBuf.selection.beg);
+        CHECK(4 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should move cursor down two lines)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1, .col = 1 };
+        buf_selmove(&TestBuf, false, 2*DOWN, BY_LINE);
+        CHECK(7 == TestBuf.selection.beg);
+        CHECK(7 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection down one line)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1, .col = 1 };
+        buf_selmove(&TestBuf, true, DOWN, BY_LINE);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(4 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should expand selection down two lines)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1, .col = 1 };
+        buf_selmove(&TestBuf, true, 2*DOWN, BY_LINE);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(7 == TestBuf.selection.end);
+        CHECK(1 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should leave column unchanged when moving by lines)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1, .col = 10 };
+        buf_selmove(&TestBuf, false, DOWN, BY_LINE);
+        CHECK(5 == TestBuf.selection.beg);
+        CHECK(5 == TestBuf.selection.end);
+        CHECK(10 == TestBuf.selection.col);
+    }
+
+    TEST(buf_selmove should leave column unchanged when selecting by lines)
+    {
+        set_buffer_text("aa\nbb\ncc\ndd\n");
+        TestBuf.selection = (Sel){ .beg = 1, .end = 1, .col = 10 };
+        buf_selmove(&TestBuf, true, DOWN, BY_LINE);
+        CHECK(1 == TestBuf.selection.beg);
+        CHECK(5 == TestBuf.selection.end);
+        CHECK(10 == TestBuf.selection.col);
+    }
 }