]> git.mdlowis.com Git - projs/tide.git/commitdiff
Reworked unit tests to have one test executable per real executable and one catch...
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 3 Feb 2017 19:01:38 +0000 (14:01 -0500)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 3 Feb 2017 19:01:38 +0000 (14:01 -0500)
14 files changed:
Makefile
TODO.md
inc/atf.h [changed mode: 0755->0644]
inc/edit.h
inc/win.h
lib/win.c
tests/lib/buf.c [moved from tests/buf.c with 100% similarity]
tests/lib/utf8.c [moved from tests/utf8.c with 100% similarity]
tests/libedit.c [moved from unittests.c with 91% similarity]
tests/xedit.c
tests/xpick.c [new file with mode: 0644]
tools/term.c [new file with mode: 0644]
xedit.c
xpick.c

index f69808a7cda8f1b174998e7a11cae1b043358597..31a3bbcdee7ab245843c583213bf085f8ed2d61a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,22 +10,19 @@ LIBEDIT_OBJS =     \
        lib/x11.o      \
        lib/win.o
 
-TEST_OBJS =      \
-       unittests.o  \
-       tests/buf.o  \
-       tests/utf8.o \
-       tests/xedit.o
+TEST_BINS = \
+       tests/xedit \
+       tests/xpick \
+       tests/libedit
 
 include config.mk
 
-all: xedit xpick term
+all: xedit xpick term test
 
 clean:
-       $(RM) *.o lib*/*.o tests/*.o *.a xpick xedit term unittests
-       $(RM) *.d lib*/*.d tests/*.d
-       $(RM) *.gcno lib*/*.gcno tests/*.gcno
-       $(RM) *.gcda lib*/*.gcda tests/*.gcda
-       $(RM) *.gcov lib*/*.gcov tests/*.gcov
+       find . -name '*.[oad]' -delete
+       $(RM) xpick xedit term tests/libedit
+       $(RM) $(TEST_BINS)
 
 install: all
        mkdir -p $(PREFIX)/bin
@@ -44,8 +41,8 @@ uninstall:
        rm -f $(PREFIX)/bin/xman
        rm -f $(PREFIX)/bin/edit
 
-test: unittests
-       ./unittests
+test: $(TEST_BINS)
+       for t in $(TEST_BINS); do ./$$t; done
 
 xedit: xedit.o libedit.a
        $(LD) -o $@ $^ $(LDFLAGS)
@@ -59,7 +56,11 @@ term: term.o libedit.a
 libedit.a: $(LIBEDIT_OBJS)
        $(AR) $(ARFLAGS) $@ $^
 
-unittests: $(TEST_OBJS) libedit.a
+#unittests: $(TEST_OBJS) libedit.a
+
+tests/libedit: tests/lib/buf.o tests/lib/utf8.o libedit.a
+tests/xedit: tests/xedit.o libedit.a
+tests/xpick: tests/xpick.o libedit.a
 
 -include *.d lib/*.d tests/*.d
 
diff --git a/TODO.md b/TODO.md
index 2d6e7ba6e06eca2d86e616bf61e69e53871a5913..f2da0168bdad219084d1f6435829622df93cdc9f 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -10,7 +10,7 @@ Up Next:
 * ctrl+alt+f should find next occurence of previous search term
 * Add keyboard shortcut to highlight the thing under the cursor
 
-The Rest:
+Tomorrow-ish:
 
 * Selection bug when selecting text with tabs
 * off by one error on scrolling up with wrapped lines
old mode 100755 (executable)
new mode 100644 (file)
index ec851e4754be412ac00d87ab8de315961f4dcb4c..3240ab90841d7262bd0609ca077a273670ce7397 100644 (file)
@@ -58,19 +58,15 @@ typedef struct {
 void buf_init(Buf* buf);
 unsigned buf_load(Buf* buf, char* path);
 void buf_save(Buf* buf);
-
 Rune buf_get(Buf* buf, unsigned pos);
 unsigned buf_end(Buf* buf);
-
 unsigned buf_insert(Buf* buf, bool indent, unsigned off, Rune rune);
 unsigned buf_delete(Buf* buf, unsigned beg, unsigned end);
 unsigned buf_change(Buf* buf, unsigned beg, unsigned end);
-
 void buf_undo(Buf* buf, Sel* sel);
 void buf_redo(Buf* buf, Sel* sel);
 void buf_loglock(Buf* buf);
 void buf_logclear(Buf* buf);
-
 bool buf_iseol(Buf* buf, unsigned pos);
 unsigned buf_bol(Buf* buf, unsigned pos);
 unsigned buf_eol(Buf* buf, unsigned pos);
@@ -78,17 +74,13 @@ unsigned buf_bow(Buf* buf, unsigned pos);
 unsigned buf_eow(Buf* buf, unsigned pos);
 unsigned buf_lscan(Buf* buf, unsigned pos, Rune r);
 unsigned buf_rscan(Buf* buf, unsigned pos, Rune r);
-
 void buf_getword(Buf* buf, bool (*isword)(Rune), Sel* sel);
 void buf_getblock(Buf* buf, Rune beg, Rune end, Sel* sel);
-
 unsigned buf_byrune(Buf* buf, unsigned pos, int count);
 unsigned buf_byword(Buf* buf, unsigned pos, int count);
 unsigned buf_byline(Buf* buf, unsigned 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);
-
 unsigned buf_setln(Buf* buf, unsigned line);
 unsigned buf_getcol(Buf* buf, unsigned pos);
 unsigned buf_setcol(Buf* buf, unsigned pos, unsigned col);
@@ -150,7 +142,6 @@ Row* view_getrow(View* view, size_t row);
 void view_byrune(View* view, int move, bool extsel);
 void view_byword(View* view, int move, bool extsel);
 void view_byline(View* view, int move, bool extsel);
-
 char* view_fetchcmd(View* view, size_t row, size_t col);
 void view_find(View* view, int dir, size_t row, size_t col);
 void view_findstr(View* view, int dir, char* str);
@@ -171,7 +162,6 @@ void view_scroll(View* view, int move);
 void view_scrollpage(View* view, int move);
 void view_setln(View* view, size_t line);
 void view_indent(View* view, int dir);
-
 size_t view_selsize(View* view);
 void view_selprev(View* view);
 void view_setcursor(View* view, size_t row, size_t col);
@@ -211,40 +201,6 @@ enum ColorId {
     CLR_COUNT   = 16
 };
 
-/* Global State
- *****************************************************************************/
-typedef struct {
-    int mods;
-    Rune key;
-    void (*action)(void);
-} KeyBinding;
-
-typedef struct {
-    uint64_t time;
-    uint8_t count;
-    bool pressed;
-    int region;
-} ButtonState;
-
-typedef struct {
-    size_t x;
-    size_t y;
-    size_t height;
-    size_t width;
-    size_t csrx;
-    size_t csry;
-    bool warp_ptr;
-    View view;
-} Region;
-
-typedef struct {
-    char* tag;
-    union {
-        void (*noarg)(void);
-        void (*arg)(char* arg);
-    } action;
-} Tag;
-
 /* Configuration
  *****************************************************************************/
 enum {
index 684cbf0ddf98d67b56646262f595cdb2aebde115..5139d77068e5836158d84cd9fefff517fd71cead 100644 (file)
--- a/inc/win.h
+++ b/inc/win.h
@@ -7,7 +7,12 @@ typedef enum {
     FOCUSED  = 4\r
 } WinRegion;\r
 \r
-#if 0\r
+typedef struct {\r
+    int mods;\r
+    Rune key;\r
+    void (*action)(void);\r
+} KeyBinding;\r
+\r
 typedef struct {\r
     size_t x;\r
     size_t y;\r
@@ -18,7 +23,6 @@ typedef struct {
     bool warp_ptr;\r
     View view;\r
 } Region;\r
-#endif\r
 \r
 typedef void (*MouseFunc)(WinRegion id, size_t count, size_t row, size_t col);\r
 \r
index 24309b7af99e074863c28305bb71953ef90ecd7c..2d0170f124188185c755122531c7ad5690e133ee 100644 (file)
--- a/lib/win.c
+++ b/lib/win.c
@@ -3,6 +3,14 @@
 #include <edit.h>\r
 #include <x11.h>\r
 #include <win.h>\r
+#include <ctype.h>\r
+\r
+typedef struct {\r
+    uint64_t time;\r
+    uint8_t count;\r
+    bool pressed;\r
+    int region;\r
+} ButtonState;\r
 \r
 static void draw_glyphs(size_t x, size_t y, UGlyph* glyphs, size_t rlen, size_t ncols);\r
 static WinRegion getregion(size_t x, size_t y);\r
similarity index 100%
rename from tests/buf.c
rename to tests/lib/buf.c
similarity index 100%
rename from tests/utf8.c
rename to tests/lib/utf8.c
similarity index 91%
rename from unittests.c
rename to tests/libedit.c
index 06c6dfd57cb4bcbacef8362e5add52d10a36809b..bbe0552af7a980de023649f955817a226095a28f 100644 (file)
@@ -17,7 +17,6 @@ void move_pointer(unsigned x, unsigned y) {
 
 int main(int argc, char** argv) {
     atf_init(argc,argv);
-    RUN_EXTERN_TEST_SUITE(XeditTests);
     RUN_EXTERN_TEST_SUITE(BufferTests);
     RUN_EXTERN_TEST_SUITE(Utf8Tests);
     return atf_print_results();
index 13d67fff58347671a99c9b7b17fa86e62eca085d..4158741713cc7274d8aa8c07990f6a9f1f1f83dc 100644 (file)
@@ -1,3 +1,4 @@
+#define INCLUDE_DEFS
 #include <atf.h>
 #include <time.h>
 
@@ -22,880 +23,886 @@ void mockexit(int code) {
 
 /* Helper Functions
  *****************************************************************************/
-void setup_view(enum RegionId id, char* text, int crlf, unsigned cursor) {
-    ShellCmd[0] = "/bin/sh";
-    Focused = id;
-    view_init(getview(id), NULL);
-    getbuf(id)->crlf = crlf;
-    view_putstr(getview(id), text);
-    getsel(id)->beg = cursor;
-    getsel(id)->end = cursor;
-    getsel(id)->col = buf_getcol(getbuf(id), getsel(id)->end);
-}
-
-void send_keys(int mods, Rune key) {
-    Mods = mods;
-    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);
-    //printf("buftext: '%s'\n", buftext);
-    bool result;
-    if (buftext == NULL)
-        result = (*text == '\0');
-    else
-        result = (0 == strcmp(buftext, text));
-    free(buftext);
-    return result;
-}
+//void setup_view(enum RegionId id, char* text, int crlf, unsigned cursor) {
+//    ShellCmd[0] = "/bin/sh";
+//    Focused = id;
+//    view_init(getview(id), NULL);
+//    getbuf(id)->crlf = crlf;
+//    view_putstr(getview(id), text);
+//    getsel(id)->beg = cursor;
+//    getsel(id)->end = cursor;
+//    getsel(id)->col = buf_getcol(getbuf(id), getsel(id)->end);
+//}
+//
+//void send_keys(int mods, Rune key) {
+//    Mods = mods;
+//    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);
+//    //printf("buftext: '%s'\n", buftext);
+//    bool result;
+//    if (buftext == NULL)
+//        result = (*text == '\0');
+//    else
+//        result = (0 == strcmp(buftext, text));
+//    free(buftext);
+//    return result;
+//}
 
 /* Stubbed Functions
  *****************************************************************************/
-bool x11_keymodsset(int mask) {
-    return ((Mods & mask) == mask);
-}
-
-size_t x11_font_height(XFont fnt) {
-    return 10;
-}
-
-size_t x11_font_width(XFont fnt) {
-    return 10;
-}
-
-static void redraw(int width, int height) {
-    /* do nothing for unit testing */
-}
-
-void x11_deinit(void) {
-    mockexit(0);
-}
-
-bool x11_getsel(int selid, void(*cbfn)(char*)) {
-    cbfn(selid == PRIMARY ? PrimaryText : ClipboardText);
-    return true;
-}
-
-bool x11_setsel(int selid, char* str) {
-    if (selid == PRIMARY) {
-        free(PrimaryText);
-        PrimaryText = str;
-    } else {
-        free(ClipboardText);
-        ClipboardText = str;
-    }   
-    return true;
-}
+//bool x11_keymodsset(int mask) {
+//    return ((Mods & mask) == mask);
+//}
+//
+//size_t x11_font_height(XFont fnt) {
+//    return 10;
+//}
+//
+//size_t x11_font_width(XFont fnt) {
+//    return 10;
+//}
+//
+//static void redraw(int width, int height) {
+//    /* do nothing for unit testing */
+//}
+//
+//void x11_deinit(void) {
+//    mockexit(0);
+//}
+//
+//bool x11_getsel(int selid, void(*cbfn)(char*)) {
+//    cbfn(selid == PRIMARY ? PrimaryText : ClipboardText);
+//    return true;
+//}
+//
+//bool x11_setsel(int selid, char* str) {
+//    if (selid == PRIMARY) {
+//        free(PrimaryText);
+//        PrimaryText = str;
+//    } else {
+//        free(ClipboardText);
+//        ClipboardText = str;
+//    }   
+//    return true;
+//}
 
 /* Unit Tests
  *****************************************************************************/
-TEST_SUITE(XeditTests) {
-    /* Key Handling - Normal Input
-     *************************************************************************/
-    TEST(input not matching a shortcut should be inserted as text) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, 'e');
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-    }
-
-    TEST(input \n chould result in RUNE_CRLF if in crlf mode) {
-        setup_view(EDIT, "", CRLF, 0);
-        getbuf(EDIT)->crlf = 1;
-        send_keys(ModNone, '\n');
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-        CHECK(RUNE_CRLF == buf_get(getbuf(EDIT), 0));
-    }
-    
-    TEST(input \n chould result in \n if not in crlf mode) {
-        setup_view(EDIT, "", CRLF, 0);
-        getbuf(EDIT)->crlf = 0;
-        send_keys(ModNone, '\n');
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-        CHECK('\n' == buf_get(getbuf(EDIT), 0));
-    }
-
-    /* Key Handling - Cursor Movement - Basic
-     *************************************************************************/
-    TEST(left should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, KEY_LEFT);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+left should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, KEY_LEFT);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(left should do nothing at beginning of buffer) {
-        setup_view(EDIT, "AB", CRLF, 0);
-        send_keys(ModNone, KEY_LEFT);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+left should do nothing at beginning of buffer) {
-        setup_view(EDIT, "AB", CRLF, 0);
-        send_keys(ModCtrl, KEY_LEFT);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+left should move left by one word) {
-        setup_view(EDIT, "AB CD", CRLF, 3);
-        send_keys(ModCtrl, KEY_LEFT);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(left should move left by one rune) {
-        setup_view(EDIT, "AB", CRLF, 1);
-        send_keys(ModNone, KEY_LEFT);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(right should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, KEY_RIGHT);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(right should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, KEY_RIGHT);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+right should do nothing at end of buffer) {
-        setup_view(EDIT, "AB", CRLF, 2);
-        send_keys(ModNone, KEY_RIGHT);
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-    }
-    
-    TEST(ctrl+right should do nothing at end of buffer) {
-        setup_view(EDIT, "AB", CRLF, 2);
-        send_keys(ModCtrl, KEY_RIGHT);
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-    }
-    
-    TEST(ctrl+right should move right by one word) {
-        setup_view(EDIT, "AB CD", CRLF, 0);
-        send_keys(ModCtrl, KEY_RIGHT);
-        CHECK(getsel(EDIT)->beg == 3);
-        CHECK(getsel(EDIT)->end == 3);
-    }
-    
-    TEST(right should move right by one rune) {
-        setup_view(EDIT, "AB", CRLF, 1);
-        send_keys(ModNone, KEY_RIGHT);
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-    }
-    
-    TEST(up should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, KEY_UP);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(up should move cursor up one line) {
-        setup_view(EDIT, "AB\nCD", CRLF, 4);
-        send_keys(ModNone, KEY_UP);
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-    }
-    
-    TEST(up should do nothing for first line) {
-        setup_view(EDIT, "AB\nCD", CRLF, 1);
-        send_keys(ModNone, KEY_UP);
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-    }
-    
-    TEST(down should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, KEY_DOWN);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }    
-    
-    TEST(down should move down one line) {
-        setup_view(EDIT, "AB\nCD", CRLF, 1);
-        send_keys(ModNone, KEY_DOWN);
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(down should do nothing on last line) {
-        setup_view(EDIT, "AB\nCD", CRLF, 4);
-        send_keys(ModNone, KEY_DOWN);
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(home should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, KEY_HOME);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+home should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, KEY_HOME);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+home should move to beginning of buffer) {
-        setup_view(EDIT, "ABCD", CRLF, 4);
-        send_keys(ModCtrl, KEY_HOME);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(home should move to beginning of indented content) {
-        setup_view(EDIT, "    ABCD", CRLF, 7);
-        send_keys(ModNone, KEY_HOME);
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(home should move to beginning of line if at beginning of indented content) {
-        setup_view(EDIT, "    ABCD", CRLF, 7);
-        send_keys(ModNone, KEY_HOME);
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(home should move to beginning of indented content when at beginning of line) {
-        setup_view(EDIT, "    ABCD", CRLF, 0);
-        send_keys(ModNone, KEY_HOME);
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(end should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, KEY_END);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+end should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, KEY_END);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+end should move to end of buffer) {
-        setup_view(EDIT, "ABCD", CRLF, 0);
-        send_keys(ModCtrl, KEY_END);
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(end should do nothing at end of line) {
-        setup_view(EDIT, "AB\nCD", CRLF, 2);
-        send_keys(ModNone, KEY_END);
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-    }
-    
-    TEST(end should move to end of line) {
-        setup_view(EDIT, "AB\nCD", CRLF, 0);
-        send_keys(ModNone, KEY_END);
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-    }
-
-    /* Key Handling - Unix Editing Shortcuts
-     *************************************************************************/
-    TEST(ctrl+u should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, 'u');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+u should delete to beginning of line) {
-        setup_view(EDIT, "\nABC\n", CRLF, 2);
-        send_keys(ModCtrl, 'u');
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-        CHECK(buf_end(getbuf(EDIT)) == 4);
-    }
-    
-    TEST(ctrl+u should delete entire lines contents) {
-        setup_view(EDIT, "\nABC\n", CRLF, 3);
-        send_keys(ModCtrl, 'u');
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-        CHECK(buf_end(getbuf(EDIT)) == 3);
-    }
-    
-    TEST(ctrl+k should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, 'k');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-        CHECK(buf_end(getbuf(EDIT)) == 0);
-    }
-    
-    TEST(ctrl+k should delete to end of line) {
-        setup_view(EDIT, "\nABC\n", CRLF, 2);
-        send_keys(ModCtrl, 'k');
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-        CHECK(buf_end(getbuf(EDIT)) == 3);
-    }
-    
-    TEST(ctrl+k should delete entire lines contents) {
-        setup_view(EDIT, "\nABC\n", CRLF, 1);
-        send_keys(ModCtrl, 'k');
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-        CHECK(buf_end(getbuf(EDIT)) == 2);
-    }
-    
-    TEST(ctrl+w should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, 'w');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-        CHECK(buf_end(getbuf(EDIT)) == 0);
-    }
-    
-    TEST(ctrl+w should delete previous word) {
-        setup_view(EDIT, "abc def", CRLF, 4);
-        send_keys(ModCtrl, 'w');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-        CHECK(buf_end(getbuf(EDIT)) == 3);
-    }
-    
-    TEST(ctrl+h should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, 'h');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+h should delete previous character) {
-        setup_view(EDIT, "AB", CRLF, 1);
-        send_keys(ModCtrl, 'h');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-        CHECK(buf_end(getbuf(EDIT)) == 1);
-    }
-    
-    TEST(ctrl+a should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, 'a');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+a should move to beginning of indented content) {
-        setup_view(EDIT, "    ABCD", CRLF, 7);
-        send_keys(ModCtrl, 'a');
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(ctrl+a should move to beginning of line if at beginning of indented content) {
-        setup_view(EDIT, "    ABCD", CRLF, 7);
-        send_keys(ModCtrl, 'a');
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(ctrl+a should move to beginning of indented content when at beginning of line) {
-        setup_view(EDIT, "    ABCD", CRLF, 0);
-        send_keys(ModCtrl, 'a');
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 4);
-    }
-    
-    TEST(ctrl+e should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, 'e');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+e should do nothing at end of line) {
-        setup_view(EDIT, "AB\nCD", CRLF, 2);
-        send_keys(ModCtrl, 'e');
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-    }
-    
-    TEST(ctrl+e should move to end of line) {
-        setup_view(EDIT, "AB\nCD", CRLF, 0);
-        send_keys(ModCtrl, 'e');
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-    }
-    
-    TEST(esc should select previously inserted text) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        send_keys(ModNone, KEY_ESCAPE);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 3);
-    }
-    
-    TEST(esc should select previously edited text) {
-        setup_view(EDIT, "foob", CRLF, 4);
-        send_keys(ModNone, KEY_BACKSPACE);
-        send_keys(ModNone, KEY_ESCAPE);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 3);
-    }
-    
-    /* Key Handling - Standard Text Editing Shortcuts
-     *************************************************************************/
-    TEST(cut and paste should delete selection and transfer it to+from the system clipboard) {
-        setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0);
-        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 == 4);
-        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", CRLF, 0);
-        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 == 12);
-        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, "", CRLF, 0);
-        send_keys(ModCtrl, '[');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+[ should do nothing at beginning of buffer) {
-        setup_view(EDIT, "a", CRLF, 0);
-        send_keys(ModCtrl, '[');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 1);
-    }
-    
-    TEST(ctrl+] should do nothing on empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, ']');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-    }
-    
-    TEST(ctrl+] should indent the first line) {
-        setup_view(EDIT, "a", CRLF, 0);
-        send_keys(ModCtrl, ']');
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 5);
-        CHECK(verify_text(EDIT, "    a"));
-    }
-    
-    /* Key Handling - Special 
-     *************************************************************************/
-    TEST(backspace should do nothing on empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, KEY_BACKSPACE);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-        CHECK(verify_text(EDIT, ""));
-    }
-
-    TEST(backspace should do nothing at beginning of buffer) {
-        setup_view(EDIT, "abc", CRLF, 0);
-        send_keys(ModNone, KEY_BACKSPACE);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-        CHECK(verify_text(EDIT, "abc"));
-    }
-    
-    TEST(backspace should delete previous character) {
-        setup_view(EDIT, "abc", CRLF, 1);
-        send_keys(ModNone, KEY_BACKSPACE);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-        CHECK(verify_text(EDIT, "bc"));
-    }
-    
-    TEST(backspace should delete selection) {
-        setup_view(EDIT, "abcde", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ .beg = 1, .end = 4 };
-        send_keys(ModNone, KEY_BACKSPACE);
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-        CHECK(verify_text(EDIT, "ae"));
-    }
-    
-    TEST(delete should do nothing on empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModNone, KEY_DELETE);
-        CHECK(getsel(EDIT)->beg == 0);
-        CHECK(getsel(EDIT)->end == 0);
-        CHECK(verify_text(EDIT, ""));
-    }
-
-    TEST(delete should do nothing at end of buffer) {
-        setup_view(EDIT, "abc", CRLF, 3);
-        send_keys(ModNone, KEY_DELETE);
-        CHECK(getsel(EDIT)->beg == 3);
-        CHECK(getsel(EDIT)->end == 3);
-        CHECK(verify_text(EDIT, "abc"));
-    }
-    
-    TEST(delete should delete next character) {
-        setup_view(EDIT, "abc", CRLF, 2);
-        send_keys(ModNone, KEY_DELETE);
-        CHECK(getsel(EDIT)->beg == 2);
-        CHECK(getsel(EDIT)->end == 2);
-        CHECK(verify_text(EDIT, "ab"));
-    }
-    
-    TEST(delete should delete selection) {
-        setup_view(EDIT, "abcde", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ .beg = 1, .end = 4 };
-        send_keys(ModNone, KEY_DELETE);
-        CHECK(getsel(EDIT)->beg == 1);
-        CHECK(getsel(EDIT)->end == 1);
-        CHECK(verify_text(EDIT, "ae"));
-    }
-    
-    /* Key Handling - Implementation Specific
-     *************************************************************************/
-    TEST(ctrl+t should switch focus to EDIT view) {
-        Focused = TAGS;
-        send_keys(ModCtrl, 't');
-        CHECK(Focused == EDIT);
-    }
-    
-    TEST(ctrl+t should switch focus to TAGs view) {
-        Focused = EDIT;
-        send_keys(ModCtrl, 't');
-        CHECK(Focused == TAGS);
-    }
-    
-    TEST(ctrl+q should quit) {
-        setup_view(TAGS, "", CRLF, 0);
-        setup_view(EDIT, "", CRLF, 0);
-        getbuf(EDIT)->modified = false;
-        ExitCode = 42;
-        send_keys(ModCtrl, 'q');
-        CHECK(ExitCode == 0);
-        CHECK(verify_text(TAGS, ""));
-    }
-    
-    TEST(ctrl+f should find next occurrence of selected text) {
-        setup_view(EDIT, "foobarfoo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 0, 3, 0 };
-        send_keys(ModCtrl, 'f');
-        CHECK(getview(EDIT)->selection.beg == 6);
-        CHECK(getview(EDIT)->selection.end == 9);
-    }
-    
-    TEST(ctrl+f should wrap around to beginning of buffer) {
-        setup_view(EDIT, "foobarbazfoo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 9, 12, 0 };
-        send_keys(ModCtrl, 'f');
-        CHECK(getview(EDIT)->selection.beg == 0);
-        CHECK(getview(EDIT)->selection.end == 3);
-    }
-    
-    /* Mouse Input Handling
-     *************************************************************************/
-    
-    /* Command Execution
-     *************************************************************************/
-    TEST(Commands starting with : should be executed as sed scripts) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
-        setup_view(TAGS, ":s/foo/bar/", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 11 };
-        send_keys(ModCtrl, 'd');
-        #ifdef __MACH__
-        CHECK(verify_text(EDIT, "bar\r\n"));
-        #else
-        CHECK(verify_text(EDIT, "bar"));
-        #endif
-    }
-    
-    TEST(Commands starting with | should be take selection as input and replace it with output) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
-        setup_view(TAGS, "|sed -e 's/foo/bar/'", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 20 };
-        send_keys(ModCtrl, 'd');
-        #ifdef __MACH__
-        CHECK(verify_text(EDIT, "bar\r\n"));
-        #else
-        CHECK(verify_text(EDIT, "bar"));
-        #endif
-    }
-    
-    TEST(Commands starting with ! should execute in the background with no input or output) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
-        setup_view(TAGS, "!ls", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 3 };
-        send_keys(ModCtrl, 'd');
-        CHECK(verify_text(EDIT, "foo"));        
-    }
-
-#if 0
-    TEST(Commands starting with > should execute in the background with selection as input) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
-        setup_view(TAGS, ">cat", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 4 };
-        send_keys(ModCtrl, 'd');
-        CHECK(verify_text(EDIT, "foo"));        
-    }
-#endif
-
-    TEST(Commands starting with < should replace selection with output) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
-        setup_view(TAGS, "<echo bar", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 9 };
-        send_keys(ModCtrl, 'd');
-        CHECK(verify_text(EDIT, "bar\r\n"));        
-    }
-    
-    TEST(Commands not starting with a sigil should replace themselves with their output) {
-        setup_view(EDIT, "echo foo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 8 };
-        send_keys(ModCtrl, 'd');
-        CHECK(verify_text(EDIT, "foo\r\n"));        
-    }
-    
-    /* Tag Handling
-     *************************************************************************/
-    TEST(Quit should  quit immediately if buffer is unmodified) {
-        setup_view(TAGS, "", CRLF, 0);
-        setup_view(EDIT, "", CRLF, 0);
-        getbuf(EDIT)->modified = false;
-        ExitCode = 42;
-        exec("Quit");
-        CHECK(ExitCode == 0);
-        CHECK(verify_text(TAGS, ""));
-    }
-    
-    TEST(Quit should display error message when quit called with unsaved changes) {
-        setup_view(TAGS, "", CRLF, 0);
-        setup_view(EDIT, "", CRLF, 0);
-        getbuf(EDIT)->modified = true;
-        ExitCode = 42;
-        usleep(251 * 1000);
-        exec("Quit");
-        CHECK(ExitCode == 42);
-        CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
-    }
-    
-    TEST(Quit should discard changes if quit executed twice in less than 250 ms) {
-        setup_view(TAGS, "", CRLF, 0);
-        setup_view(EDIT, "", CRLF, 0);
-        getbuf(EDIT)->modified = true;
-        ExitCode = 42;
-        usleep(251 * 1000);
-        exec("Quit");
-        CHECK(ExitCode == 42);
-        CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
-        exec("Quit");
-        CHECK(ExitCode == 0);
-        CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
-    }
-
-    TEST(Save should save changes to disk with crlf line endings) {
-        setup_view(TAGS, "", CRLF, 0);
-        view_init(getview(EDIT), "docs/crlf.txt");
-        CHECK(verify_text(EDIT, "this file\r\nuses\r\ndos\r\nline\r\nendings\r\n"));
-        exec("Save");
-        view_init(getview(EDIT), "docs/crlf.txt");
-        CHECK(verify_text(EDIT, "this file\r\nuses\r\ndos\r\nline\r\nendings\r\n"));
-    }
-    
-    TEST(Save should save changes to disk with lf line endings) {
-        setup_view(TAGS, "", CRLF, 0);
-        view_init(getview(EDIT), "docs/lf.txt");
-        CHECK(verify_text(EDIT, "this file\nuses\nunix\nline\nendings\n"));
-        exec("Save");
-        view_init(getview(EDIT), "docs/lf.txt");
-        CHECK(verify_text(EDIT, "this file\nuses\nunix\nline\nendings\n"));
-    }
-
-    TEST(Cut and Paste tags should move selection to new location) {
-        setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 0, 8, 0 };
-        exec("Cut");
-        getview(EDIT)->selection = (Sel){ 4, 4, 0 };
-        exec("Paste");
-        CHECK(getsel(EDIT)->beg == 4);
-        CHECK(getsel(EDIT)->end == 12);
-        CHECK(verify_text(EDIT, "baz\r\nfoo\r\nbar\r\n"));
-    }
-    
-    TEST(Copy and Paste tags should copy selection to new location) {
-        setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 0, 8, 0 };
-        exec("Copy");
-        getview(EDIT)->selection = (Sel){ 12, 12, 0 };
-        exec("Paste");
-        CHECK(getsel(EDIT)->beg == 12);
-        CHECK(getsel(EDIT)->end == 20);
-        CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n"));
-    }
-    
-    TEST(Undo+Redo should undo+redo the previous insert) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        exec("Undo");
-        CHECK(verify_text(EDIT, ""));
-        exec("Redo");
-        CHECK(verify_text(EDIT, "foo"));
-    }
-    
-    TEST(Undo+Redo should undo+redo the previous delete) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 0, 3, 0 };
-        send_keys(ModNone, KEY_DELETE);
-        exec("Undo");
-        CHECK(verify_text(EDIT, "foo"));
-        exec("Redo");
-        CHECK(verify_text(EDIT, ""));
-    }
-    
-    TEST(Undo+Redo should undo+redo the previous delete with two non-contiguous deletes logged) {
-        setup_view(EDIT, "foobarbaz", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 0, 3, 0 };
-        send_keys(ModNone, KEY_DELETE);
-        getview(EDIT)->selection = (Sel){ 3, 6, 0 };
-        send_keys(ModNone, KEY_DELETE);
-        CHECK(verify_text(EDIT, "bar"));
-        exec("Undo");
-        CHECK(verify_text(EDIT, "barbaz"));
-        exec("Redo");
-        CHECK(verify_text(EDIT, "bar"));
-    }
-    
-    TEST(Undo+Redo should undo+redo the previous delete performed with backspace) {
-        setup_view(EDIT, "foo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 3, 3, 0 };
-        for(int i = 0; i < 3; i++)
-            send_keys(ModNone, KEY_BACKSPACE);
-        CHECK(verify_text(EDIT, ""));
-        exec("Undo");
-        CHECK(verify_text(EDIT, "foo"));
-        exec("Redo");
-        CHECK(verify_text(EDIT, ""));
-    }
-
-    TEST(Find should find next occurrence of text selected in EDIT view) {
-        setup_view(EDIT, "foobarfoo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 0, 3, 0 };
-        exec("Find");
-        CHECK(getview(EDIT)->selection.beg == 6);
-        CHECK(getview(EDIT)->selection.end == 9);
-    }
-    
-    TEST(Find should find wrap around to beginning of EDIT buffer) {
-        setup_view(EDIT, "foobarbazfoo", CRLF, 0);
-        getview(EDIT)->selection = (Sel){ 9, 12, 0 };
-        exec("Find");
-        CHECK(getview(EDIT)->selection.beg == 0);
-        CHECK(getview(EDIT)->selection.end == 3);
-    }
-    
-    TEST(Find should find next occurrence of text selected in TAGS view) {
-        setup_view(TAGS, "foo", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ 0, 3, 0 };
-        setup_view(EDIT, "barfoo", CRLF, 0);
-        exec("Find");
-        CHECK(getview(EDIT)->selection.beg == 3);
-        CHECK(getview(EDIT)->selection.end == 6);
-    }
-    
-    TEST(Find should find next occurrence of text selected after tag) {
-        setup_view(EDIT, "barfoo", CRLF, 0);
-        exec("Find foo");
-        CHECK(getview(EDIT)->selection.beg == 3);
-        CHECK(getview(EDIT)->selection.end == 6);
-    }
-
-#if 0    
-    TEST(Find should do nothing if nothing selected) {
-        setup_view(TAGS, "Find", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ 0, 4, 0 };
-        send_keys(ModCtrl, 'f');
-    }
-#endif
+TEST_SUITE(UnitTests) {
+//    /* Key Handling - Normal Input
+//     *************************************************************************/
+//    TEST(input not matching a shortcut should be inserted as text) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, 'e');
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//    }
+//
+//    TEST(input \n chould result in RUNE_CRLF if in crlf mode) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        getbuf(EDIT)->crlf = 1;
+//        send_keys(ModNone, '\n');
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//        CHECK(RUNE_CRLF == buf_get(getbuf(EDIT), 0));
+//    }
+//    
+//    TEST(input \n chould result in \n if not in crlf mode) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        getbuf(EDIT)->crlf = 0;
+//        send_keys(ModNone, '\n');
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//        CHECK('\n' == buf_get(getbuf(EDIT), 0));
+//    }
+//
+//    /* Key Handling - Cursor Movement - Basic
+//     *************************************************************************/
+//    TEST(left should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, KEY_LEFT);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+left should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, KEY_LEFT);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(left should do nothing at beginning of buffer) {
+//        setup_view(EDIT, "AB", CRLF, 0);
+//        send_keys(ModNone, KEY_LEFT);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+left should do nothing at beginning of buffer) {
+//        setup_view(EDIT, "AB", CRLF, 0);
+//        send_keys(ModCtrl, KEY_LEFT);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+left should move left by one word) {
+//        setup_view(EDIT, "AB CD", CRLF, 3);
+//        send_keys(ModCtrl, KEY_LEFT);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(left should move left by one rune) {
+//        setup_view(EDIT, "AB", CRLF, 1);
+//        send_keys(ModNone, KEY_LEFT);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(right should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, KEY_RIGHT);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(right should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, KEY_RIGHT);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+right should do nothing at end of buffer) {
+//        setup_view(EDIT, "AB", CRLF, 2);
+//        send_keys(ModNone, KEY_RIGHT);
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//    }
+//    
+//    TEST(ctrl+right should do nothing at end of buffer) {
+//        setup_view(EDIT, "AB", CRLF, 2);
+//        send_keys(ModCtrl, KEY_RIGHT);
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//    }
+//    
+//    TEST(ctrl+right should move right by one word) {
+//        setup_view(EDIT, "AB CD", CRLF, 0);
+//        send_keys(ModCtrl, KEY_RIGHT);
+//        CHECK(getsel(EDIT)->beg == 3);
+//        CHECK(getsel(EDIT)->end == 3);
+//    }
+//    
+//    TEST(right should move right by one rune) {
+//        setup_view(EDIT, "AB", CRLF, 1);
+//        send_keys(ModNone, KEY_RIGHT);
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//    }
+//    
+//    TEST(up should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, KEY_UP);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(up should move cursor up one line) {
+//        setup_view(EDIT, "AB\nCD", CRLF, 4);
+//        send_keys(ModNone, KEY_UP);
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//    }
+//    
+//    TEST(up should do nothing for first line) {
+//        setup_view(EDIT, "AB\nCD", CRLF, 1);
+//        send_keys(ModNone, KEY_UP);
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//    }
+//    
+//    TEST(down should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, KEY_DOWN);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }    
+//    
+//    TEST(down should move down one line) {
+//        setup_view(EDIT, "AB\nCD", CRLF, 1);
+//        send_keys(ModNone, KEY_DOWN);
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(down should do nothing on last line) {
+//        setup_view(EDIT, "AB\nCD", CRLF, 4);
+//        send_keys(ModNone, KEY_DOWN);
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(home should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, KEY_HOME);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+home should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, KEY_HOME);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+home should move to beginning of buffer) {
+//        setup_view(EDIT, "ABCD", CRLF, 4);
+//        send_keys(ModCtrl, KEY_HOME);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(home should move to beginning of indented content) {
+//        setup_view(EDIT, "    ABCD", CRLF, 7);
+//        send_keys(ModNone, KEY_HOME);
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(home should move to beginning of line if at beginning of indented content) {
+//        setup_view(EDIT, "    ABCD", CRLF, 7);
+//        send_keys(ModNone, KEY_HOME);
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(home should move to beginning of indented content when at beginning of line) {
+//        setup_view(EDIT, "    ABCD", CRLF, 0);
+//        send_keys(ModNone, KEY_HOME);
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(end should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, KEY_END);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+end should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, KEY_END);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+end should move to end of buffer) {
+//        setup_view(EDIT, "ABCD", CRLF, 0);
+//        send_keys(ModCtrl, KEY_END);
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(end should do nothing at end of line) {
+//        setup_view(EDIT, "AB\nCD", CRLF, 2);
+//        send_keys(ModNone, KEY_END);
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//    }
+//    
+//    TEST(end should move to end of line) {
+//        setup_view(EDIT, "AB\nCD", CRLF, 0);
+//        send_keys(ModNone, KEY_END);
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//    }
+//
+//    /* Key Handling - Unix Editing Shortcuts
+//     *************************************************************************/
+//    TEST(ctrl+u should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, 'u');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+u should delete to beginning of line) {
+//        setup_view(EDIT, "\nABC\n", CRLF, 2);
+//        send_keys(ModCtrl, 'u');
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//        CHECK(buf_end(getbuf(EDIT)) == 4);
+//    }
+//    
+//    TEST(ctrl+u should delete entire lines contents) {
+//        setup_view(EDIT, "\nABC\n", CRLF, 3);
+//        send_keys(ModCtrl, 'u');
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//        CHECK(buf_end(getbuf(EDIT)) == 3);
+//    }
+//    
+//    TEST(ctrl+k should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, 'k');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//        CHECK(buf_end(getbuf(EDIT)) == 0);
+//    }
+//    
+//    TEST(ctrl+k should delete to end of line) {
+//        setup_view(EDIT, "\nABC\n", CRLF, 2);
+//        send_keys(ModCtrl, 'k');
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//        CHECK(buf_end(getbuf(EDIT)) == 3);
+//    }
+//    
+//    TEST(ctrl+k should delete entire lines contents) {
+//        setup_view(EDIT, "\nABC\n", CRLF, 1);
+//        send_keys(ModCtrl, 'k');
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//        CHECK(buf_end(getbuf(EDIT)) == 2);
+//    }
+//    
+//    TEST(ctrl+w should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, 'w');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//        CHECK(buf_end(getbuf(EDIT)) == 0);
+//    }
+//    
+//    TEST(ctrl+w should delete previous word) {
+//        setup_view(EDIT, "abc def", CRLF, 4);
+//        send_keys(ModCtrl, 'w');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//        CHECK(buf_end(getbuf(EDIT)) == 3);
+//    }
+//    
+//    TEST(ctrl+h should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, 'h');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+h should delete previous character) {
+//        setup_view(EDIT, "AB", CRLF, 1);
+//        send_keys(ModCtrl, 'h');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//        CHECK(buf_end(getbuf(EDIT)) == 1);
+//    }
+//    
+//    TEST(ctrl+a should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, 'a');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+a should move to beginning of indented content) {
+//        setup_view(EDIT, "    ABCD", CRLF, 7);
+//        send_keys(ModCtrl, 'a');
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(ctrl+a should move to beginning of line if at beginning of indented content) {
+//        setup_view(EDIT, "    ABCD", CRLF, 7);
+//        send_keys(ModCtrl, 'a');
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(ctrl+a should move to beginning of indented content when at beginning of line) {
+//        setup_view(EDIT, "    ABCD", CRLF, 0);
+//        send_keys(ModCtrl, 'a');
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 4);
+//    }
+//    
+//    TEST(ctrl+e should do nothing for empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, 'e');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+e should do nothing at end of line) {
+//        setup_view(EDIT, "AB\nCD", CRLF, 2);
+//        send_keys(ModCtrl, 'e');
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//    }
+//    
+//    TEST(ctrl+e should move to end of line) {
+//        setup_view(EDIT, "AB\nCD", CRLF, 0);
+//        send_keys(ModCtrl, 'e');
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//    }
+//    
+//    TEST(esc should select previously inserted text) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        send_keys(ModNone, KEY_ESCAPE);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 3);
+//    }
+//    
+//    TEST(esc should select previously edited text) {
+//        setup_view(EDIT, "foob", CRLF, 4);
+//        send_keys(ModNone, KEY_BACKSPACE);
+//        send_keys(ModNone, KEY_ESCAPE);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 3);
+//    }
+//    
+//    /* Key Handling - Standard Text Editing Shortcuts
+//     *************************************************************************/
+//    TEST(cut and paste should delete selection and transfer it to+from the system clipboard) {
+//        setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0);
+//        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 == 4);
+//        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", CRLF, 0);
+//        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 == 12);
+//        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, "", CRLF, 0);
+//        send_keys(ModCtrl, '[');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+[ should do nothing at beginning of buffer) {
+//        setup_view(EDIT, "a", CRLF, 0);
+//        send_keys(ModCtrl, '[');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 1);
+//    }
+//    
+//    TEST(ctrl+] should do nothing on empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModCtrl, ']');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//    }
+//    
+//    TEST(ctrl+] should indent the first line) {
+//        setup_view(EDIT, "a", CRLF, 0);
+//        send_keys(ModCtrl, ']');
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 5);
+//        CHECK(verify_text(EDIT, "    a"));
+//    }
+//    
+//    /* Key Handling - Special 
+//     *************************************************************************/
+//    TEST(backspace should do nothing on empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, KEY_BACKSPACE);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//        CHECK(verify_text(EDIT, ""));
+//    }
+//
+//    TEST(backspace should do nothing at beginning of buffer) {
+//        setup_view(EDIT, "abc", CRLF, 0);
+//        send_keys(ModNone, KEY_BACKSPACE);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//        CHECK(verify_text(EDIT, "abc"));
+//    }
+//    
+//    TEST(backspace should delete previous character) {
+//        setup_view(EDIT, "abc", CRLF, 1);
+//        send_keys(ModNone, KEY_BACKSPACE);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//        CHECK(verify_text(EDIT, "bc"));
+//    }
+//    
+//    TEST(backspace should delete selection) {
+//        setup_view(EDIT, "abcde", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ .beg = 1, .end = 4 };
+//        send_keys(ModNone, KEY_BACKSPACE);
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//        CHECK(verify_text(EDIT, "ae"));
+//    }
+//    
+//    TEST(delete should do nothing on empty buffer) {
+//        setup_view(EDIT, "", CRLF, 0);
+//        send_keys(ModNone, KEY_DELETE);
+//        CHECK(getsel(EDIT)->beg == 0);
+//        CHECK(getsel(EDIT)->end == 0);
+//        CHECK(verify_text(EDIT, ""));
+//    }
+//
+//    TEST(delete should do nothing at end of buffer) {
+//        setup_view(EDIT, "abc", CRLF, 3);
+//        send_keys(ModNone, KEY_DELETE);
+//        CHECK(getsel(EDIT)->beg == 3);
+//        CHECK(getsel(EDIT)->end == 3);
+//        CHECK(verify_text(EDIT, "abc"));
+//    }
+//    
+//    TEST(delete should delete next character) {
+//        setup_view(EDIT, "abc", CRLF, 2);
+//        send_keys(ModNone, KEY_DELETE);
+//        CHECK(getsel(EDIT)->beg == 2);
+//        CHECK(getsel(EDIT)->end == 2);
+//        CHECK(verify_text(EDIT, "ab"));
+//    }
+//    
+//    TEST(delete should delete selection) {
+//        setup_view(EDIT, "abcde", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ .beg = 1, .end = 4 };
+//        send_keys(ModNone, KEY_DELETE);
+//        CHECK(getsel(EDIT)->beg == 1);
+//        CHECK(getsel(EDIT)->end == 1);
+//        CHECK(verify_text(EDIT, "ae"));
+//    }
+//    
+//    /* Key Handling - Implementation Specific
+//     *************************************************************************/
+//    TEST(ctrl+t should switch focus to EDIT view) {
+//        Focused = TAGS;
+//        send_keys(ModCtrl, 't');
+//        CHECK(Focused == EDIT);
+//    }
+//    
+//    TEST(ctrl+t should switch focus to TAGs view) {
+//        Focused = EDIT;
+//        send_keys(ModCtrl, 't');
+//        CHECK(Focused == TAGS);
+//    }
+//    
+//    TEST(ctrl+q should quit) {
+//        setup_view(TAGS, "", CRLF, 0);
+//        setup_view(EDIT, "", CRLF, 0);
+//        getbuf(EDIT)->modified = false;
+//        ExitCode = 42;
+//        send_keys(ModCtrl, 'q');
+//        CHECK(ExitCode == 0);
+//        CHECK(verify_text(TAGS, ""));
+//    }
+//    
+//    TEST(ctrl+f should find next occurrence of selected text) {
+//        setup_view(EDIT, "foobarfoo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 0, 3, 0 };
+//        send_keys(ModCtrl, 'f');
+//        CHECK(getview(EDIT)->selection.beg == 6);
+//        CHECK(getview(EDIT)->selection.end == 9);
+//    }
+//    
+//    TEST(ctrl+f should wrap around to beginning of buffer) {
+//        setup_view(EDIT, "foobarbazfoo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 9, 12, 0 };
+//        send_keys(ModCtrl, 'f');
+//        CHECK(getview(EDIT)->selection.beg == 0);
+//        CHECK(getview(EDIT)->selection.end == 3);
+//    }
+//    
+//    /* Mouse Input Handling
+//     *************************************************************************/
+//    
+//    /* Command Execution
+//     *************************************************************************/
+//    TEST(Commands starting with : should be executed as sed scripts) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
+//        setup_view(TAGS, ":s/foo/bar/", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 11 };
+//        send_keys(ModCtrl, 'd');
+//        #ifdef __MACH__
+//        CHECK(verify_text(EDIT, "bar\r\n"));
+//        #else
+//        CHECK(verify_text(EDIT, "bar"));
+//        #endif
+//    }
+//    
+//    TEST(Commands starting with | should be take selection as input and replace it with output) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
+//        setup_view(TAGS, "|sed -e 's/foo/bar/'", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 20 };
+//        send_keys(ModCtrl, 'd');
+//        #ifdef __MACH__
+//        CHECK(verify_text(EDIT, "bar\r\n"));
+//        #else
+//        CHECK(verify_text(EDIT, "bar"));
+//        #endif
+//    }
+//    
+//    TEST(Commands starting with ! should execute in the background with no input or output) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
+//        setup_view(TAGS, "!ls", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 3 };
+//        send_keys(ModCtrl, 'd');
+//        CHECK(verify_text(EDIT, "foo"));        
+//    }
+//
+//#if 0
+//    TEST(Commands starting with > should execute in the background with selection as input) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
+//        setup_view(TAGS, ">cat", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 4 };
+//        send_keys(ModCtrl, 'd');
+//        CHECK(verify_text(EDIT, "foo"));        
+//    }
+//#endif
+//
+//    TEST(Commands starting with < should replace selection with output) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 };
+//        setup_view(TAGS, "<echo bar", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ .beg = 0, .end = 9 };
+//        send_keys(ModCtrl, 'd');
+//        CHECK(verify_text(EDIT, "bar\r\n"));        
+//    }
+//    
+//    TEST(Commands not starting with a sigil should replace themselves with their output) {
+//        setup_view(EDIT, "echo foo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ .beg = 0, .end = 8 };
+//        send_keys(ModCtrl, 'd');
+//        CHECK(verify_text(EDIT, "foo\r\n"));        
+//    }
+//    
+//    /* Tag Handling
+//     *************************************************************************/
+//    TEST(Quit should  quit immediately if buffer is unmodified) {
+//        setup_view(TAGS, "", CRLF, 0);
+//        setup_view(EDIT, "", CRLF, 0);
+//        getbuf(EDIT)->modified = false;
+//        ExitCode = 42;
+//        exec("Quit");
+//        CHECK(ExitCode == 0);
+//        CHECK(verify_text(TAGS, ""));
+//    }
+//    
+//    TEST(Quit should display error message when quit called with unsaved changes) {
+//        setup_view(TAGS, "", CRLF, 0);
+//        setup_view(EDIT, "", CRLF, 0);
+//        getbuf(EDIT)->modified = true;
+//        ExitCode = 42;
+//        usleep(251 * 1000);
+//        exec("Quit");
+//        CHECK(ExitCode == 42);
+//        CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
+//    }
+//    
+//    TEST(Quit should discard changes if quit executed twice in less than 250 ms) {
+//        setup_view(TAGS, "", CRLF, 0);
+//        setup_view(EDIT, "", CRLF, 0);
+//        getbuf(EDIT)->modified = true;
+//        ExitCode = 42;
+//        usleep(251 * 1000);
+//        exec("Quit");
+//        CHECK(ExitCode == 42);
+//        CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
+//        exec("Quit");
+//        CHECK(ExitCode == 0);
+//        CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
+//    }
+//
+//    TEST(Save should save changes to disk with crlf line endings) {
+//        setup_view(TAGS, "", CRLF, 0);
+//        view_init(getview(EDIT), "docs/crlf.txt");
+//        CHECK(verify_text(EDIT, "this file\r\nuses\r\ndos\r\nline\r\nendings\r\n"));
+//        exec("Save");
+//        view_init(getview(EDIT), "docs/crlf.txt");
+//        CHECK(verify_text(EDIT, "this file\r\nuses\r\ndos\r\nline\r\nendings\r\n"));
+//    }
+//    
+//    TEST(Save should save changes to disk with lf line endings) {
+//        setup_view(TAGS, "", CRLF, 0);
+//        view_init(getview(EDIT), "docs/lf.txt");
+//        CHECK(verify_text(EDIT, "this file\nuses\nunix\nline\nendings\n"));
+//        exec("Save");
+//        view_init(getview(EDIT), "docs/lf.txt");
+//        CHECK(verify_text(EDIT, "this file\nuses\nunix\nline\nendings\n"));
+//    }
+//
+//    TEST(Cut and Paste tags should move selection to new location) {
+//        setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 0, 8, 0 };
+//        exec("Cut");
+//        getview(EDIT)->selection = (Sel){ 4, 4, 0 };
+//        exec("Paste");
+//        CHECK(getsel(EDIT)->beg == 4);
+//        CHECK(getsel(EDIT)->end == 12);
+//        CHECK(verify_text(EDIT, "baz\r\nfoo\r\nbar\r\n"));
+//    }
+//    
+//    TEST(Copy and Paste tags should copy selection to new location) {
+//        setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 0, 8, 0 };
+//        exec("Copy");
+//        getview(EDIT)->selection = (Sel){ 12, 12, 0 };
+//        exec("Paste");
+//        CHECK(getsel(EDIT)->beg == 12);
+//        CHECK(getsel(EDIT)->end == 20);
+//        CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n"));
+//    }
+//    
+//    TEST(Undo+Redo should undo+redo the previous insert) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        exec("Undo");
+//        CHECK(verify_text(EDIT, ""));
+//        exec("Redo");
+//        CHECK(verify_text(EDIT, "foo"));
+//    }
+//    
+//    TEST(Undo+Redo should undo+redo the previous delete) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 0, 3, 0 };
+//        send_keys(ModNone, KEY_DELETE);
+//        exec("Undo");
+//        CHECK(verify_text(EDIT, "foo"));
+//        exec("Redo");
+//        CHECK(verify_text(EDIT, ""));
+//    }
+//    
+//    TEST(Undo+Redo should undo+redo the previous delete with two non-contiguous deletes logged) {
+//        setup_view(EDIT, "foobarbaz", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 0, 3, 0 };
+//        send_keys(ModNone, KEY_DELETE);
+//        getview(EDIT)->selection = (Sel){ 3, 6, 0 };
+//        send_keys(ModNone, KEY_DELETE);
+//        CHECK(verify_text(EDIT, "bar"));
+//        exec("Undo");
+//        CHECK(verify_text(EDIT, "barbaz"));
+//        exec("Redo");
+//        CHECK(verify_text(EDIT, "bar"));
+//    }
+//    
+//    TEST(Undo+Redo should undo+redo the previous delete performed with backspace) {
+//        setup_view(EDIT, "foo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 3, 3, 0 };
+//        for(int i = 0; i < 3; i++)
+//            send_keys(ModNone, KEY_BACKSPACE);
+//        CHECK(verify_text(EDIT, ""));
+//        exec("Undo");
+//        CHECK(verify_text(EDIT, "foo"));
+//        exec("Redo");
+//        CHECK(verify_text(EDIT, ""));
+//    }
+//
+//    TEST(Find should find next occurrence of text selected in EDIT view) {
+//        setup_view(EDIT, "foobarfoo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 0, 3, 0 };
+//        exec("Find");
+//        CHECK(getview(EDIT)->selection.beg == 6);
+//        CHECK(getview(EDIT)->selection.end == 9);
+//    }
+//    
+//    TEST(Find should find wrap around to beginning of EDIT buffer) {
+//        setup_view(EDIT, "foobarbazfoo", CRLF, 0);
+//        getview(EDIT)->selection = (Sel){ 9, 12, 0 };
+//        exec("Find");
+//        CHECK(getview(EDIT)->selection.beg == 0);
+//        CHECK(getview(EDIT)->selection.end == 3);
+//    }
+//    
+//    TEST(Find should find next occurrence of text selected in TAGS view) {
+//        setup_view(TAGS, "foo", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ 0, 3, 0 };
+//        setup_view(EDIT, "barfoo", CRLF, 0);
+//        exec("Find");
+//        CHECK(getview(EDIT)->selection.beg == 3);
+//        CHECK(getview(EDIT)->selection.end == 6);
+//    }
+//    
+//    TEST(Find should find next occurrence of text selected after tag) {
+//        setup_view(EDIT, "barfoo", CRLF, 0);
+//        exec("Find foo");
+//        CHECK(getview(EDIT)->selection.beg == 3);
+//        CHECK(getview(EDIT)->selection.end == 6);
+//    }
+//
+//#if 0    
+//    TEST(Find should do nothing if nothing selected) {
+//        setup_view(TAGS, "Find", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ 0, 4, 0 };
+//        send_keys(ModCtrl, 'f');
+//    }
+//#endif
+//
+//    TEST(Tabs should set indent style to tabs) {
+//        setup_view(TAGS, "Tabs", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ 0, 4, 0 };
+//        getbuf(EDIT)->expand_tabs = true;
+//        getbuf(TAGS)->expand_tabs = true;
+//        send_keys(ModCtrl, 'd');
+//        CHECK(getbuf(EDIT)->expand_tabs == false);
+//        CHECK(getbuf(TAGS)->expand_tabs == false);
+//    }
+//    
+//    TEST(Tabs should set indent style to spaces) {
+//        setup_view(TAGS, "Tabs", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ 0, 4, 0 };
+//        getbuf(EDIT)->expand_tabs = false;
+//        getbuf(TAGS)->expand_tabs = false;
+//        send_keys(ModCtrl, 'd');
+//        CHECK(getbuf(EDIT)->expand_tabs == true);
+//        CHECK(getbuf(TAGS)->expand_tabs == true);
+//    }
+//    
+//    TEST(Indent should disable copyindent) {
+//        setup_view(TAGS, "Indent", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ 0, 6, 0 };
+//        getbuf(EDIT)->copy_indent = true;
+//        getbuf(TAGS)->copy_indent = true;
+//        send_keys(ModCtrl, 'd');
+//        CHECK(getbuf(EDIT)->copy_indent == false);
+//        CHECK(getbuf(TAGS)->copy_indent == false);
+//    }
+//    
+//    TEST(Indent should enable copyindent) {
+//        setup_view(TAGS, "Indent", CRLF, 0);
+//        getview(TAGS)->selection = (Sel){ 0, 6, 0 };
+//        getbuf(EDIT)->copy_indent = false;
+//        getbuf(TAGS)->copy_indent = false;
+//        send_keys(ModCtrl, 'd');
+//        CHECK(getbuf(EDIT)->copy_indent == true);
+//        CHECK(getbuf(TAGS)->copy_indent == true);
+//    }
+}
 
-    TEST(Tabs should set indent style to tabs) {
-        setup_view(TAGS, "Tabs", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ 0, 4, 0 };
-        getbuf(EDIT)->expand_tabs = true;
-        getbuf(TAGS)->expand_tabs = true;
-        send_keys(ModCtrl, 'd');
-        CHECK(getbuf(EDIT)->expand_tabs == false);
-        CHECK(getbuf(TAGS)->expand_tabs == false);
-    }
-    
-    TEST(Tabs should set indent style to spaces) {
-        setup_view(TAGS, "Tabs", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ 0, 4, 0 };
-        getbuf(EDIT)->expand_tabs = false;
-        getbuf(TAGS)->expand_tabs = false;
-        send_keys(ModCtrl, 'd');
-        CHECK(getbuf(EDIT)->expand_tabs == true);
-        CHECK(getbuf(TAGS)->expand_tabs == true);
-    }
-    
-    TEST(Indent should disable copyindent) {
-        setup_view(TAGS, "Indent", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ 0, 6, 0 };
-        getbuf(EDIT)->copy_indent = true;
-        getbuf(TAGS)->copy_indent = true;
-        send_keys(ModCtrl, 'd');
-        CHECK(getbuf(EDIT)->copy_indent == false);
-        CHECK(getbuf(TAGS)->copy_indent == false);
-    }
-    
-    TEST(Indent should enable copyindent) {
-        setup_view(TAGS, "Indent", CRLF, 0);
-        getview(TAGS)->selection = (Sel){ 0, 6, 0 };
-        getbuf(EDIT)->copy_indent = false;
-        getbuf(TAGS)->copy_indent = false;
-        send_keys(ModCtrl, 'd');
-        CHECK(getbuf(EDIT)->copy_indent == true);
-        CHECK(getbuf(TAGS)->copy_indent == true);
-    }
+int main(int argc, char** argv) {
+    atf_init(argc,argv);
+    RUN_TEST_SUITE(UnitTests);
+    return atf_print_results();
 }
diff --git a/tests/xpick.c b/tests/xpick.c
new file mode 100644 (file)
index 0000000..82adc25
--- /dev/null
@@ -0,0 +1,15 @@
+#define INCLUDE_DEFS
+#include <atf.h>
+#include <time.h>
+
+// Inculd the source file so we can access everything 
+#include "../xpick.c"
+
+TEST_SUITE(UnitTests) {
+}
+
+int main(int argc, char** argv) {
+    atf_init(argc,argv);
+    RUN_TEST_SUITE(UnitTests);
+    return atf_print_results();
+}
diff --git a/tools/term.c b/tools/term.c
new file mode 100644 (file)
index 0000000..41ab59a
--- /dev/null
@@ -0,0 +1,72 @@
+#define _POSIX_C_SOURCE 200809L
+#include <stdc.h>
+#include <unistd.h>
+
+#define PIPE_READ 0
+#define PIPE_WRITE 1
+
+typedef struct {
+    int pid; /* process id of the child process */
+    int in;  /* file descriptor for the child process's standard input */
+    int out; /* file descriptor for the child process's standard output */
+} Process;
+
+static int execute(char** cmd, Process* proc) {
+    int inpipe[2], outpipe[2];
+    /* create the pipes */
+    if ((pipe(inpipe) < 0) || (pipe(outpipe) < 0))
+        return -1;
+    /* create the process */
+    proc->pid = fork();
+    if (proc->pid < 0) {
+        /* signal that we failed to fork */
+        proc->in  = -1;
+        proc->out = -1;
+    } else if (0 == proc->pid) {
+        /* redirect child process's io to the pipes */
+        if ((dup2(inpipe[PIPE_READ], STDIN_FILENO) < 0)    ||
+            (dup2(outpipe[PIPE_WRITE], STDOUT_FILENO) < 0)) {
+            perror("failed to pipe");
+            exit(1);
+        }
+        /* execute the process */
+        close(inpipe[PIPE_WRITE]);
+        close(outpipe[PIPE_READ]);
+        dup2(STDOUT_FILENO, STDERR_FILENO);
+        close(STDERR_FILENO);
+        exit(execvp(cmd[0], cmd));
+    } else {
+        close(inpipe[PIPE_READ]);
+        close(outpipe[PIPE_WRITE]);
+        proc->in   = inpipe[PIPE_WRITE];
+        proc->out  = outpipe[PIPE_READ];
+    }
+    return proc->pid;
+}
+
+int main(int argc, char** argv){
+    setenv("PS1", "$ ", 1);
+    Process proc;
+    execute((char*[]){"/bin/sh", "-i", NULL}, &proc);
+    
+    int nbytes = 0;
+    char buffer[8192];
+    while (true) {
+        puts("foo");
+        nbytes = read(STDIN_FILENO, buffer, sizeof(buffer));
+        if (nbytes < 0) break;
+        puts("bar");
+        write(proc.in, buffer, nbytes);
+        puts("baa");
+        while ((nbytes = read(proc.out, buffer, sizeof(buffer))) > 0) {
+            puts("boo");
+            write(1, buffer, nbytes);
+        }
+        puts("baz");
+        if (nbytes < 0) break;
+    }
+    close(proc.in);
+    close(proc.out);
+        
+    return 0;
+}
diff --git a/xedit.c b/xedit.c
index b8d57696e40f84544d6c2e9cb73d48bc010d2454..7e2311934a044a8ac5fcbf7f8e810acb973fb2ae 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -9,6 +9,14 @@
 #define exit mockexit
 #endif
 
+typedef struct {
+    char* tag;
+    union {
+        void (*noarg)(void);
+        void (*arg)(char* arg);
+    } action;
+} Tag;
+
 /* The shell: Filled in with $SHELL. Used to execute commands */
 static char* ShellCmd[] = { NULL, "-c", NULL, NULL };
 static char* SedCmd[] = { "sed", "-e", NULL, NULL };
diff --git a/xpick.c b/xpick.c
index 63367ed75a26a764757aa507be11ccb37f180412..181130dd300d5aa0639080df36d08218af4fed6b 100644 (file)
--- a/xpick.c
+++ b/xpick.c
@@ -194,6 +194,7 @@ static void keyboard_input(int mods, uint32_t key) {
     score();
 }
 
+#ifndef TEST
 int main(int argc, char** argv) {
     load_choices();
     if (vec_size(&Choices) > 1) {
@@ -213,3 +214,4 @@ int main(int argc, char** argv) {
     }
     return 0;
 }
+#endif