From: Michael D. Lowis Date: Thu, 22 Jun 2017 14:40:16 +0000 (-0400) Subject: Added unit tests for buf.c and tweaked xresources sample file X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=4374d1687fae234fe99e54bc7ac01984d90bbf09;p=projs%2Ftide.git Added unit tests for buf.c and tweaked xresources sample file --- diff --git a/Makefile b/Makefile index 4f2da71..a83c4a1 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ docs: clean: find . -name '*.[oad]' -delete + find . \( -name '*.gcno' -o -name '*.gcda' \) -delete $(RM) pick tide xcpd term tests/libedit $(RM) $(TEST_BINS) diff --git a/TODO.md b/TODO.md index 6e9c2ee..62d1e62 100644 --- a/TODO.md +++ b/TODO.md @@ -2,16 +2,16 @@ Up Next: +* implement transaction control in buf.c * highlight all matches of search term * highlight classes of identifiers -* implement transaction control in buf.c * Add a way to CD using a builtin (buffers will track original dir) * shortcut to jump to previous edit * add command line flags to toggle options (Tabs, Indent, etc..) * move by words is inconsistent. Example: var infoId = 'readerinfo'+reader.id; * ignore the menu key or map it to control - + The Future: * Ctrl+/ shortcut to comment/uncomment based on syntax diff --git a/XResources b/XResources index 29dda56..343cc70 100644 --- a/XResources +++ b/XResources @@ -5,7 +5,7 @@ tide.ui.font: Monaco:size=10:antialias=true:autohint=true tide.ui.line_spacing: 0 #else tide.ui.font: Liberation Mono:pixelsize=14:antialias=true:autohint=true -tide.ui.line_spacing: 2 +tide.ui.line_spacing: 1 #endif tide.ui.tags: 'Quit Save Undo Redo Cut Copy Paste | Find ' tide.ui.width: 640 @@ -23,32 +23,50 @@ tide.input.scroll_lines: 4 tide.input.click_time: 500 tide.input.max_scan_dist: 8192 -! Color Palette Definition -tide.palette.00: 0xff002b36 -tide.palette.01: 0xff073642 -tide.palette.02: 0xff586e75 -tide.palette.03: 0xff657b83 -tide.palette.04: 0xff839496 -tide.palette.05: 0xff93a1a1 -tide.palette.06: 0xffeee8d5 -tide.palette.07: 0xfffdf6e3 -tide.palette.08: 0xffb58900 -tide.palette.09: 0xffcb4b16 -tide.palette.10: 0xffdc322f -tide.palette.11: 0xffd33682 -tide.palette.12: 0xff6c71c4 -tide.palette.13: 0xff268bd2 -tide.palette.14: 0xff2aa198 -tide.palette.15: 0xff859900 +! Color Palette Definition (Solarized Dark) +tide.palette.00: 0xff002b36 ! 00 (0) - Base03 +tide.palette.01: 0xff073642 ! 01 (1) - Base02 +tide.palette.02: 0xff586e75 ! 02 (2) - Base01 +tide.palette.03: 0xff657b83 ! 03 (3) - Base00 +tide.palette.04: 0xff839496 ! 04 (4) - Base0 +tide.palette.05: 0xff93a1a1 ! 05 (5) - Base1 +tide.palette.06: 0xffeee8d5 ! 06 (6) - Base2 +tide.palette.07: 0xfffdf6e3 ! 07 (7) - Base3 +tide.palette.08: 0xffb58900 ! 08 (8) - Yellow +tide.palette.09: 0xffcb4b16 ! 09 (9) - Orange +tide.palette.10: 0xffdc322f ! 10 (A) - Red +tide.palette.11: 0xffd33682 ! 11 (B) - Magenta +tide.palette.12: 0xff6c71c4 ! 12 (C) - Violet +tide.palette.13: 0xff268bd2 ! 13 (D) - Blue +tide.palette.14: 0xff2aa198 ! 14 (E) - Cyan +tide.palette.15: 0xff859900 ! 15 (F) - Green + +!! Color Palette Definition (Solarized Light) +!tide.palette.00: 0xfffdf6e3 ! 00 (0) - Base03 +!tide.palette.01: 0xffeee8d5 ! 01 (1) - Base02 +!tide.palette.02: 0xff93a1a1 ! 02 (2) - Base01 +!tide.palette.03: 0xff839496 ! 03 (3) - Base00 +!tide.palette.04: 0xff657b83 ! 04 (4) - Base0 +!tide.palette.05: 0xff586e75 ! 05 (5) - Base1 +!tide.palette.06: 0xff073642 ! 06 (6) - Base2 +!tide.palette.07: 0xff002b36 ! 07 (7) - Base3 +!tide.palette.08: 0xffb58900 ! 08 (8) - Yellow +!tide.palette.09: 0xffcb4b16 ! 09 (9) - Orange +!tide.palette.10: 0xffdc322f ! 10 (A) - Red +!tide.palette.11: 0xffd33682 ! 11 (B) - Magenta +!tide.palette.12: 0xff6c71c4 ! 12 (C) - Violet +!tide.palette.13: 0xff268bd2 ! 13 (D) - Blue +!tide.palette.14: 0xff2aa198 ! 14 (E) - Cyan +!tide.palette.15: 0xff859900 ! 15 (F) - Green ! Background and UI Colors -tide.colors.ruler: 0x01 -tide.colors.gutter: 0x01 -tide.colors.bkg_tags: 0x01 -tide.colors.bkg_edit: 0x00 -tide.colors.bkg_scroll: 0x03 -tide.colors.bkg_thumb: 0x00 -tide.colors.border: 0x03 +tide.colors.ruler: 0x1 +tide.colors.gutter: 0x1 +tide.colors.bkg_tags: 0x1 +tide.colors.bkg_edit: 0x0 +tide.colors.bkg_scroll: 0x3 +tide.colors.bkg_thumb: 0x0 +tide.colors.border: 0x3 ! Base Text Colors tide.colors.text.cursor: 0x0007 @@ -57,7 +75,7 @@ tide.colors.text.selected: 0x0400 tide.colors.text.gutter: 0x0003 tide.colors.text.currline: 0x0D07 -! Syntax Colors +! Syntax Highlighting Colors tide.colors.syntax.normal: 0x0004 tide.colors.syntax.comment: 0x0002 tide.colors.syntax.constant: 0x000E diff --git a/inc/edit.h b/inc/edit.h index 4853ab3..ceaf0d6 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -94,7 +94,6 @@ void buf_getblock(Buf* buf, Rune beg, Rune end, Sel* sel); size_t buf_byrune(Buf* buf, size_t pos, int count); size_t buf_byword(Buf* buf, size_t pos, int count); size_t buf_byline(Buf* buf, size_t pos, int count); -void buf_find(Buf* buf, int dir, size_t* beg, size_t* end); void buf_findstr(Buf* buf, int dir, char* str, size_t* beg, size_t* end); void buf_lastins(Buf* buf, size_t* beg, size_t* end); size_t buf_setln(Buf* buf, size_t line); @@ -236,7 +235,7 @@ char* cmdwriteread(char** cmd, char* text, char** err); /* Configuration Data *****************************************************************************/ -enum { +enum { /* Configuration Variables */ FontString = 0, TagString, WinWidth, WinHeight, LineSpacing, LineNumbers, RulerColumn, EventTimeout, CopyIndent, TrimOnSave, ExpandTabs, TabWidth, ScrollLines, DblClickTime, MaxScanDist, diff --git a/lib/buf.c b/lib/buf.c index d5b8df1..4b13134 100644 --- a/lib/buf.c +++ b/lib/buf.c @@ -345,25 +345,6 @@ size_t buf_byline(Buf* buf, size_t pos, int count) { return pos; } -void buf_find(Buf* buf, int dir, size_t* beg, size_t* end) { - size_t dbeg = *beg, dend = *end; - size_t mbeg = dbeg+dir, mend = dend+dir; - size_t mlen = dend - dbeg; - while (true) { - if ((buf_get(buf, mbeg) == buf_get(buf, dbeg)) && - (buf_get(buf, mend-1) == buf_get(buf, dend-1)) && - (0 == range_match(buf, dbeg, dend, mbeg, mend))) - { - *beg = mbeg; - *end = mend; - break; - } - mbeg += dir, mend += dir; - if (mend > buf_end(buf)) - mbeg = (dir < 0 ? buf_end(buf)-mlen : 0), mend = mbeg+mlen; - } -} - void buf_findstr(Buf* buf, int dir, char* str, size_t* beg, size_t* end) { if (!str) return; Rune* runes = charstorunes(str); diff --git a/lib/config.c b/lib/config.c index fb77201..270e70d 100644 --- a/lib/config.c +++ b/lib/config.c @@ -24,7 +24,7 @@ struct { #else [FontString] = { "tide.ui.font", STRING, { .str = "Liberation Mono:pixelsize=14:antialias=true:autohint=true" } }, - [LineSpacing] = { "tide.ui.line_spacing", INTEGER, { .num = 2 } }, + [LineSpacing] = { "tide.ui.line_spacing", INTEGER, { .num = 1 } }, #endif /* user interface related options */ diff --git a/tests/lib/buf.c b/tests/lib/buf.c index 80eb600..f9555ac 100644 --- a/tests/lib/buf.c +++ b/tests/lib/buf.c @@ -20,19 +20,205 @@ static void set_buffer_text(char* str) { static bool buf_text_eq(char* str) { for (unsigned i = 0; i < buf_end(&TestBuf); i++) { - if ((Rune)*(str++) != buf_get(&TestBuf, i)) + printf("'%c'", buf_get(&TestBuf, i)); + if ((Rune)*(str++) != buf_get(&TestBuf, i)) { + printf("\n"); return false; + } } + printf("\n"); return true; } TEST_SUITE(BufferTests) { /* Initializing *************************************************************************/ + TEST(buf_init should initialize an empty buffer) { + Buf buf = {0}; + buf_init(&buf, (void*)0x12345678); + CHECK(buf.modified == false); + CHECK(buf.expand_tabs == config_get_bool(ExpandTabs)); + CHECK(buf.copy_indent == config_get_bool(CopyIndent)); + CHECK(buf.charset == UTF_8); + CHECK(buf.crlf == 0); + CHECK(buf.bufsize == 8192); + CHECK(buf.bufstart != NULL); + CHECK(buf.bufend == buf.bufstart + buf.bufsize); + CHECK(buf.gapstart == buf.bufstart); + CHECK(buf.gapend == buf.bufend); + CHECK(buf.undo == NULL); + CHECK(buf.redo == NULL); + CHECK(buf.errfn == (void*)0x12345678); + CHECK(buf.nlines == 0); + } + + TEST(buf_init shoud free old buffer and reinitialize) { + Buf buf = {0}; + buf_init(&buf, onerror); + buf_insert(&buf, false, 0, 'a'); + buf_init(&buf, (void*)0x12345678); + CHECK(buf.modified == false); + CHECK(buf.expand_tabs == config_get_bool(ExpandTabs)); + CHECK(buf.copy_indent == config_get_bool(CopyIndent)); + CHECK(buf.charset == UTF_8); + CHECK(buf.crlf == 0); + CHECK(buf.bufsize == 8192); + CHECK(buf.bufstart != NULL); + CHECK(buf.bufend == buf.bufstart + buf.bufsize); + CHECK(buf.gapstart == buf.bufstart); + CHECK(buf.gapend == buf.bufend); + CHECK(buf.undo == NULL); + CHECK(buf.redo == NULL); + CHECK(buf.errfn == (void*)0x12345678); + CHECK(buf.nlines == 0); + } + /* Loading *************************************************************************/ + TEST(buf_load should load a UTF-8 file from disk) { + buf_init(&TestBuf, NULL); + size_t pos = buf_load(&TestBuf, "testdocs/lorem.txt"); + CHECK(pos == 0); + CHECK(TestBuf.modified == false); + CHECK(TestBuf.expand_tabs == true); + CHECK(TestBuf.copy_indent == config_get_bool(CopyIndent)); + CHECK(TestBuf.charset == UTF_8); + CHECK(TestBuf.crlf == 0); + CHECK(TestBuf.bufsize == 65536); + CHECK(TestBuf.undo == NULL); + CHECK(TestBuf.redo == NULL); + CHECK(TestBuf.errfn == NULL); + CHECK(TestBuf.nlines == 998); + CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt")); + } + + TEST(buf_load should load a non UTF-8 file from disk) { + buf_init(&TestBuf, NULL); + size_t pos = buf_load(&TestBuf, "testdocs/waf"); + CHECK(pos == 0); + CHECK(TestBuf.modified == false); + CHECK(TestBuf.expand_tabs == false); + CHECK(TestBuf.copy_indent == config_get_bool(CopyIndent)); + CHECK(TestBuf.charset == BINARY); + CHECK(TestBuf.crlf == 0); + CHECK(TestBuf.bufsize == 131072); + CHECK(TestBuf.undo == NULL); + CHECK(TestBuf.redo == NULL); + CHECK(TestBuf.errfn == NULL); + CHECK(TestBuf.nlines == 169); + CHECK(!strcmp(TestBuf.path, "testdocs/waf")); + } + + TEST(buf_load should load a file from disk and jump to a specific line) { + buf_init(&TestBuf, NULL); + size_t pos = buf_load(&TestBuf, "testdocs/lorem.txt:2"); + CHECK(pos == 70); + CHECK(TestBuf.modified == false); + CHECK(TestBuf.expand_tabs == true); + CHECK(TestBuf.copy_indent == config_get_bool(CopyIndent)); + CHECK(TestBuf.charset == UTF_8); + CHECK(TestBuf.crlf == 0); + CHECK(TestBuf.bufsize == 65536); + CHECK(TestBuf.undo == NULL); + CHECK(TestBuf.redo == NULL); + CHECK(TestBuf.errfn == NULL); + CHECK(TestBuf.nlines == 998); + CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt")); + } + + TEST(buf_load should remove ./ from file path) { + buf_init(&TestBuf, NULL); + size_t pos = buf_load(&TestBuf, "./testdocs/lorem.txt"); + CHECK(pos == 0); + CHECK(TestBuf.modified == false); + CHECK(TestBuf.expand_tabs == true); + CHECK(TestBuf.copy_indent == config_get_bool(CopyIndent)); + CHECK(TestBuf.charset == UTF_8); + CHECK(TestBuf.crlf == 0); + CHECK(TestBuf.bufsize == 65536); + CHECK(TestBuf.undo == NULL); + CHECK(TestBuf.redo == NULL); + CHECK(TestBuf.errfn == NULL); + CHECK(TestBuf.nlines == 998); + CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt")); + } + + TEST(buf_reload should reload the file from disk) { + buf_init(&TestBuf, NULL); + buf_load(&TestBuf, "testdocs/waf"); + TestBuf.path = "testdocs/lorem.txt"; + buf_reload(&TestBuf); + CHECK(TestBuf.modified == false); + CHECK(TestBuf.expand_tabs == true); + CHECK(TestBuf.copy_indent == config_get_bool(CopyIndent)); + CHECK(TestBuf.charset == UTF_8); + CHECK(TestBuf.crlf == 0); + CHECK(TestBuf.bufsize == 65536); + CHECK(TestBuf.undo == NULL); + CHECK(TestBuf.redo == NULL); + CHECK(TestBuf.errfn == NULL); + CHECK(TestBuf.nlines == 998); + CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt")); + } + /* Saving *************************************************************************/ + TEST(buf_save should save a UTF-8 file to disk) { + buf_init(&TestBuf, NULL); + buf_load(&TestBuf, "testdocs/lorem.txt"); + TestBuf.modified = true; + buf_save(&TestBuf); + CHECK(TestBuf.modified == false); + } + + TEST(buf_save should save a non UTF-8 file to disk) { + buf_init(&TestBuf, NULL); + buf_load(&TestBuf, "testdocs/waf"); + TestBuf.modified = true; + buf_save(&TestBuf); + CHECK(TestBuf.modified == false); + } + + TEST(buf_save should save a file to disk with unix line endings) { + buf_init(&TestBuf, NULL); + buf_load(&TestBuf, "testdocs/lf.txt"); + TestBuf.modified = true; + buf_save(&TestBuf); + CHECK(TestBuf.modified == false); + } + + TEST(buf_save should save a file to disk with dos line endings) { + buf_init(&TestBuf, NULL); + buf_load(&TestBuf, "testdocs/crlf.txt"); + TestBuf.modified = true; + buf_save(&TestBuf); + CHECK(TestBuf.modified == false); + } + + TEST(buf_save should make sure unix file ends witn newline) { + buf_init(&TestBuf, NULL); + buf_load(&TestBuf, "testdocs/lf.txt"); + TestBuf.modified = true; + size_t end = buf_end(&TestBuf); + buf_delete(&TestBuf, end-1, end); + CHECK(end-1 == buf_end(&TestBuf)); + buf_save(&TestBuf); + CHECK(end == buf_end(&TestBuf)); + CHECK(TestBuf.modified == false); + } + + TEST(buf_save should make sure dos file ends witn newline) { + buf_init(&TestBuf, NULL); + buf_load(&TestBuf, "testdocs/crlf.txt"); + TestBuf.modified = true; + size_t end = buf_end(&TestBuf); + buf_delete(&TestBuf, end-1, end); + CHECK(end-1 == buf_end(&TestBuf)); + buf_save(&TestBuf); + CHECK(end == buf_end(&TestBuf)); + CHECK(TestBuf.modified == false); + } + /* Resizing *************************************************************************/ /* Insertions @@ -41,6 +227,8 @@ TEST_SUITE(BufferTests) { buf_init(&TestBuf, onerror); buf_insert(&TestBuf, false, 0, 'a'); CHECK(buf_text_eq("a")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); } TEST(buf_insert should insert at 0) { @@ -48,6 +236,8 @@ TEST_SUITE(BufferTests) { buf_insert(&TestBuf, false, 0, 'b'); buf_insert(&TestBuf, false, 0, 'a'); CHECK(buf_text_eq("ab")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); } TEST(buf_insert should insert at 1) { @@ -55,6 +245,8 @@ TEST_SUITE(BufferTests) { buf_insert(&TestBuf, false, 0, 'a'); buf_insert(&TestBuf, false, 1, 'b'); CHECK(buf_text_eq("ab")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); } TEST(buf_insert should insert at 1) { @@ -63,25 +255,102 @@ TEST_SUITE(BufferTests) { buf_insert(&TestBuf, false, 1, 'c'); buf_insert(&TestBuf, false, 1, 'b'); CHECK(buf_text_eq("abc")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); } TEST(buf_insert should sentence in larger text) { set_buffer_text( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - ); - + "Lorem ipsum dolor sit amet, consectetur adipiscing elit." ); buf_insert(&TestBuf, false, 5, ' '); buf_insert(&TestBuf, false, 6, 'a'); - CHECK(buf_text_eq( - "Lorem a ipsum dolor sit amet, consectetur adipiscing elit." - )); + "Lorem a ipsum dolor sit amet, consectetur adipiscing elit." )); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); + } + + TEST(buf_insert should expand tabs) { + set_buffer_text(""); + TestBuf.expand_tabs = true; + buf_insert(&TestBuf, true, 0, '\t'); + CHECK(buf_text_eq(" ")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); + } + + TEST(buf_insert should copy indent) { + set_buffer_text(" "); + TestBuf.copy_indent = true; + TestBuf.crlf = 0; + buf_insert(&TestBuf, true, 4, '\n'); + CHECK(buf_text_eq(" \n ")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); } /* Deletions *************************************************************************/ + TEST(buf_delete should delete first char) { + set_buffer_text("abc"); + buf_delete(&TestBuf, 0, 1); + CHECK(buf_text_eq("bc")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); + } + + TEST(buf_delete should delete second char) { + set_buffer_text("abc"); + buf_delete(&TestBuf, 1, 2); + CHECK(buf_text_eq("ac")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); + } + + TEST(buf_delete should delete third char) { + set_buffer_text("abc"); + buf_delete(&TestBuf, 2, 3); + CHECK(buf_text_eq("ab")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); + } + + TEST(buf_delete should delete more than one char) { + set_buffer_text("abcdef"); + buf_delete(&TestBuf, 1, 5); + CHECK(buf_text_eq("af")); + CHECK(TestBuf.modified == true); + CHECK(TestBuf.redo == NULL); + } + /* Undo/Redo *************************************************************************/ + TEST(buf_undo should undo an insert) { + Sel sel; + set_buffer_text(""); + buf_insert(&TestBuf, true, 0, 'a'); + CHECK(buf_text_eq("a")); + CHECK(TestBuf.redo == NULL); + CHECK(TestBuf.undo != NULL); + buf_undo(&TestBuf, &sel); + CHECK(buf_text_eq("")); + CHECK(TestBuf.redo != NULL); + CHECK(TestBuf.undo == NULL); + } + + TEST(buf_undo should undo a delete) { + Sel sel; + set_buffer_text("a"); + buf_delete(&TestBuf, 0, 1); + CHECK(buf_text_eq("")); + CHECK(TestBuf.redo == NULL); + CHECK(TestBuf.undo != NULL); + buf_undo(&TestBuf, &sel); + CHECK(buf_text_eq("a")); + CHECK(TestBuf.redo != NULL); + CHECK(TestBuf.undo != NULL); + } + /* Accessors *************************************************************************/ // buf_get