From: Michael D. Lowis Date: Fri, 9 Dec 2016 21:06:23 +0000 (-0500) Subject: Added more unit tests for cut, copy, and paste X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=b66912c579f42d8578ddb0ad75e828039aeab768;p=projs%2Ftide.git Added more unit tests for cut, copy, and paste --- diff --git a/config.mk b/config.mk index 1002217..85d96ed 100644 --- a/config.mk +++ b/config.mk @@ -24,5 +24,5 @@ LIBS += -L/usr/X11/lib INCS += -I/usr/include/freetype2 # Gcov Coverage -CFLAGS += --coverage -LDFLAGS += --coverage +#CFLAGS += --coverage +#LDFLAGS += --coverage diff --git a/coverage.sh b/coverage.sh new file mode 100755 index 0000000..8375cc2 --- /dev/null +++ b/coverage.sh @@ -0,0 +1,2 @@ +#!/bin/bash +gcov -fabc "$@" | pcregrep -vM '\nLines executed:100.00%(.*\n){3}' \ No newline at end of file diff --git a/libedit/buf.c b/libedit/buf.c index 94267be..a01d1e7 100644 --- a/libedit/buf.c +++ b/libedit/buf.c @@ -158,12 +158,18 @@ static void log_delete(Log** list, unsigned off, Rune* r, size_t len) { } } -static void insert(Buf* buf, unsigned off, Rune rune) { +static unsigned insert(Buf* buf, unsigned off, Rune rune) { + unsigned rcount = 1; syncgap(buf, off); - if (buf->crlf && rune == '\n' && buf_get(buf, off-1) == '\r') + if (buf->crlf && rune == '\n' && buf_get(buf, off-1) == '\r') { + rcount = 0; *(buf->gapstart-1) = RUNE_CRLF; - else + } else if (buf->crlf && rune == '\n') { + *(buf->gapstart++) = RUNE_CRLF; + } else { *(buf->gapstart++) = rune; + } + return rcount; } static void clear_redo(Buf* buf) { @@ -189,10 +195,11 @@ unsigned buf_ins(Buf* buf, bool fmt, unsigned off, Rune rune) { if (fmt && buf->expand_tabs && rune == '\t') { size_t n = (TabWidth - ((off - buf_bol(buf, off)) % TabWidth)); log_insert(&(buf->undo), off, off+n); - for(; n > 0; n--) insert(buf, off++, ' '); + for(; n > 0; n--) off += insert(buf, off, ' '); } else { - log_insert(&(buf->undo), off, off+1); - insert(buf, off++, rune); + size_t n = insert(buf, off, rune); + log_insert(&(buf->undo), off, off+n); + off += n; } if (fmt && buf->copy_indent && (rune == '\n' || rune == RUNE_CRLF)) { unsigned indent = getindent(buf, off-1); @@ -238,9 +245,10 @@ unsigned swaplog(Buf* buf, Log** from, Log** to, unsigned pos) { } else { newlog->insert = true; newlog->data.ins.beg = log->data.del.off; - newlog->data.ins.end = log->data.del.off + log->data.del.len; + newlog->data.ins.end = newlog->data.ins.beg; + //newlog->data.ins.end = log->data.del.off + log->data.del.len; for (size_t i = log->data.del.len; i > 0; i--) { - insert(buf, newlog->data.ins.beg, log->data.del.runes[i-1]); + newlog->data.ins.end += insert(buf, newlog->data.ins.beg, log->data.del.runes[i-1]); } pos = newlog->data.ins.end; } diff --git a/libedit/view.c b/libedit/view.c index c2da611..61b93e1 100644 --- a/libedit/view.c +++ b/libedit/view.c @@ -525,8 +525,8 @@ char* view_getstr(View* view, Sel* range) { Rune rune = buf_get(buf, sel.beg); if (rune == RUNE_CRLF) { str = realloc(str, len + 2); - str[len + 1] = '\r'; - str[len + 2] = '\n'; + str[len + 0] = '\r'; + str[len + 1] = '\n'; len += 2; } else { size_t n = utf8encode(utf, rune); @@ -580,6 +580,7 @@ void view_indent(View* view, int dir) { view->selection.beg = buf_bol(buf, view->selection.beg); view->selection.end = buf_eol(buf, view->selection.end); unsigned off = buf_bol(buf, view->selection.end); + if (num_selected(view->selection) == 0) return; while (off >= view->selection.beg) { if (dir == RIGHT) { buf_ins(buf, true, off, '\t'); diff --git a/tests/buf.c b/tests/buf.c index 62e9f31..fc351e3 100644 --- a/tests/buf.c +++ b/tests/buf.c @@ -5,21 +5,9 @@ static Buf TestBuf; -static void buf_clr(Buf* buf) { - while (buf->undo) { - Log* deadite = buf->undo; - buf->undo = deadite->next; - if (!deadite->insert) - free(deadite->data.del.runes); - free(deadite); - } - free(buf->bufstart); - buf_init(buf); -} - static void set_buffer_text(char* str) { int i = 0; - buf_clr(&TestBuf); + buf_init(&TestBuf); TestBuf.crlf = 1; for (Rune* curr = TestBuf.bufstart; curr < TestBuf.bufend; curr++) *curr = '-'; @@ -36,7 +24,6 @@ static bool buf_text_eq(char* str) { } TEST_SUITE(BufferTests) { -#if 0 /* Initializing *************************************************************************/ /* Loading @@ -48,27 +35,27 @@ TEST_SUITE(BufferTests) { /* Insertions *************************************************************************/ TEST(buf_ins should insert at 0 in empty buf) { - buf_clr(&TestBuf); + buf_init(&TestBuf); buf_ins(&TestBuf, false, 0, 'a'); CHECK(buf_text_eq("a")); } TEST(buf_ins should insert at 0) { - buf_clr(&TestBuf); + buf_init(&TestBuf); buf_ins(&TestBuf, false, 0, 'b'); buf_ins(&TestBuf, false, 0, 'a'); CHECK(buf_text_eq("ab")); } TEST(buf_ins should insert at 1) { - buf_clr(&TestBuf); + buf_init(&TestBuf); buf_ins(&TestBuf, false, 0, 'a'); buf_ins(&TestBuf, false, 1, 'b'); CHECK(buf_text_eq("ab")); } TEST(buf_ins should insert at 1) { - buf_clr(&TestBuf); + buf_init(&TestBuf); buf_ins(&TestBuf, false, 0, 'a'); buf_ins(&TestBuf, false, 1, 'c'); buf_ins(&TestBuf, false, 1, 'b'); @@ -389,5 +376,4 @@ TEST_SUITE(BufferTests) { set_buffer_text("abc\n\tdef"); CHECK(8 == buf_setcol(&TestBuf, 4, 100)); } -#endif } diff --git a/tests/xedit.c b/tests/xedit.c index 068f13f..2f87a1e 100644 --- a/tests/xedit.c +++ b/tests/xedit.c @@ -19,6 +19,15 @@ void send_keys(int mods, Rune key) { key_handler(mods, key); } +bool verify_text(enum RegionId id, char* text) { + Sel sel = { .beg = 0, .end = buf_end(getbuf(id)) }; + char* buftext = view_getstr(getview(id), &sel); + bool result = (0 == strcmp(buftext, text)); + printf("'%s'\n", buftext); + free(buftext); + return result; +} + /* Stubbed Functions *****************************************************************************/ bool x11_keymodsset(int mask) { @@ -40,6 +49,15 @@ static void redraw(int width, int height) { /* Unit Tests *****************************************************************************/ TEST_SUITE(XeditTests) { + /* Key Handling - Normal Input + *************************************************************************/ + TEST(input not matching a shortcut should be inserted as text) { + setup_view(EDIT, "", 0); + send_keys(ModNone, 'e'); + CHECK(getsel(EDIT)->beg == 1); + CHECK(getsel(EDIT)->end == 1); + } + /* Key Handling - Cursor Movement - Basic *************************************************************************/ TEST(left should do nothing for empty buffer) { @@ -245,7 +263,7 @@ TEST_SUITE(XeditTests) { CHECK(getsel(EDIT)->end == 2); } - /* Key Handling - Unix Standard Shortcuts + /* Key Handling - Unix Editing Shortcuts *************************************************************************/ TEST(ctrl+u should do nothing for empty buffer) { setup_view(EDIT, "", 0); @@ -374,15 +392,66 @@ TEST_SUITE(XeditTests) { CHECK(getsel(EDIT)->end == 2); } - /* Key Handling - Normal Input + /* Key Handling - Standard Text Editing Shortcuts *************************************************************************/ - TEST(input not matching a shortcut should be inserted as text) { + TEST(cut and paste should delete selection and transfer it to+from the system clipboard) { + setup_view(EDIT, "foo\nbar\nbaz\n", 0); + CHECK(RUNE_CRLF == buf_get(getbuf(EDIT), 3)); + getview(EDIT)->selection = (Sel){ 0, 8, 0 }; + send_keys(ModCtrl, 'x'); + getview(EDIT)->selection = (Sel){ 4, 4, 0 }; + send_keys(ModCtrl, 'v'); + CHECK(getsel(EDIT)->beg == 12); + CHECK(getsel(EDIT)->end == 12); + CHECK(verify_text(EDIT, "baz\r\nfoo\r\nbar\r\n")); + } + + TEST(copy and paste should copy selection and transfer it to+from the system clipboard) { + getbuf(EDIT)->crlf = 1; + setup_view(EDIT, "foo\nbar\nbaz\n", 0); + CHECK(RUNE_CRLF == buf_get(getbuf(EDIT), 3)); + getview(EDIT)->selection = (Sel){ 0, 8, 0 }; + send_keys(ModCtrl, 'c'); + getview(EDIT)->selection = (Sel){ 12, 12, 0 }; + send_keys(ModCtrl, 'v'); + CHECK(getsel(EDIT)->beg == 20); + CHECK(getsel(EDIT)->end == 20); + CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n")); + } + + /* Key Handling - Block Indent + *************************************************************************/ + TEST(ctrl+[ should do nothing on empty buffer) { setup_view(EDIT, "", 0); - send_keys(ModNone, 'e'); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); + send_keys(ModCtrl, '['); + CHECK(getsel(EDIT)->beg == 0); + CHECK(getsel(EDIT)->end == 0); + } + + //TEST(ctrl+[ should do nothing on empty buffer) { + // setup_view(EDIT, "a", 0); + // send_keys(ModCtrl, '['); + // CHECK(getsel(EDIT)->beg == 0); + // CHECK(getsel(EDIT)->end == 0); + //} + + TEST(ctrl+] should do nothing on empty buffer) { + setup_view(EDIT, "", 0); + send_keys(ModCtrl, ']'); + CHECK(getsel(EDIT)->beg == 0); + CHECK(getsel(EDIT)->end == 0); } + //TEST(ctrl+] should indent the current line) { + // setup_view(EDIT, "a", 0); + // send_keys(ModCtrl, ']'); + // CHECK(getsel(EDIT)->beg == 0); + // CHECK(getsel(EDIT)->end == 0); + //} + + /* Key Handling - Special Keys + *************************************************************************/ + /* Key Handling - Implementation Specific *************************************************************************/ TEST(ctrl+t should switch focus to EDIT view) {