From: Michael D. Lowis Date: Wed, 23 Oct 2019 14:58:29 +0000 (-0400) Subject: added tests and refactored selection handling X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=4d2fa32abdf985c1a7c922877630c1dc063d05de;p=projs%2Ftide.git added tests and refactored selection handling --- diff --git a/TODO.md b/TODO.md index e3525b2..adcead5 100644 --- 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 diff --git a/src/lib/buf.c b/src/lib/buf.c index 774feb9..486f7af 100644 --- a/src/lib/buf.c +++ b/src/lib/buf.c @@ -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); } diff --git a/tests/lib/buf.c b/tests/lib/buf.c index ea62544..cc822b4 100644 --- a/tests/lib/buf.c +++ b/tests/lib/buf.c @@ -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); + } }