]> git.mdlowis.com Git - projs/tide.git/commitdiff
Changed ctrl+h to highlight the thing under cursor rather than backspace
authorMichael D. Lowis <mike@mdlowis.com>
Wed, 3 May 2017 00:09:42 +0000 (20:09 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Wed, 3 May 2017 00:09:42 +0000 (20:09 -0400)
TODO.md
inc/edit.h
inc/win.h
lib/view.c
lib/win.c
lib/x11.c
tests/xedit.c
xedit.c

diff --git a/TODO.md b/TODO.md
index 320bc0ea4f0c4bdbfe4ae0026ef738db1ceb2c8c..a098bd2315f68d537d41efe1b4d61a8f004bede5 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -3,7 +3,6 @@
 Up Next:
 
 * refactor x11.c and win.c
-* Add keyboard shortcut to highlight the thing under the cursor
 * Make Fn keys execute nth command in the tags buffers
 * Run commands in the background and don't block the main thread.
 * check for file changes on save
index 5d0e9521ea493f62abb68c593f205475c7597c06..fc39bc7042c031fac7cf1eea4aed7d6c86a902f6 100644 (file)
@@ -157,6 +157,7 @@ void view_append(View* view, char* str);
 char* view_getstr(View* view, Sel* sel);
 char* view_getcmd(View* view);
 char* view_getctx(View* view);
+void view_selctx(View* view);
 void view_scroll(View* view, int move);
 void view_scrollpage(View* view, int move);
 void view_setln(View* view, size_t line);
index 2272e56e9b35a7cec1dfc3d5b8268793ef6cd461..a3f8d06672e4a1c8828da73d9f114f544a103008 100644 (file)
--- a/inc/win.h
+++ b/inc/win.h
@@ -48,7 +48,7 @@ WinRegion win_getregion(void);
 bool win_setregion(WinRegion id);
 void win_setscroll(double offset, double visible);
 
-/* These functions must be implemented by any appliation that wishes 
+/* These functions must be implemented by any appliation that wishes
    to use this module */
 void onshutdown(void);
 void onupdate(void);
index 042298296eb2e936b683d63a7629c47b9e987c43..9567baeab6adb06cfc00c3eb6f3b8617e15420b5 100644 (file)
@@ -517,11 +517,16 @@ char* view_getcmd(View* view) {
     return view_getstr(view, &sel);
 }
 
-char* view_getctx(View* view) {
+void view_selctx(View* view) {
     if (!num_selected(view->selection)) {
         selcontext(view, &(view->selection));
-        view->selection.end++;
+        view->selection.end = buf_byrune(
+            &(view->buffer), view->selection.end, RIGHT);
     }
+}
+
+char* view_getctx(View* view) {
+    view_selctx(view);
     return view_getstr(view, NULL);
 }
 
index 33278f925eefc28669521dad524d2112df4f8e88..d7d4b36dfac9b99b3ba3fa3b9060eb29d13814ae 100644 (file)
--- a/lib/win.c
+++ b/lib/win.c
@@ -152,7 +152,7 @@ static void layout(int width, int height) {
     View* statview = win_view(STATUS);
     View* tagview  = win_view(TAGS);
     View* editview = win_view(EDIT);
-    
+
     /* update the text views and region positions and sizes */
     for (int i = 0; i < SCROLL; i++) {
         Regions[i].x      = 2;
@@ -162,10 +162,10 @@ static void layout(int width, int height) {
         Regions[i].width  = (width - 4);
         Regions[i].height = fheight;
     }
-    
+
     /* place the status region */
     view_resize(statview, 1, Regions[STATUS].width / fwidth);
-    
+
     /* Place the tag region relative to status */
     Regions[TAGS].y = 5 + Regions[STATUS].y + Regions[STATUS].height;
     size_t maxtagrows = ((height - Regions[TAGS].y - 5) / 4) / fheight;
@@ -173,35 +173,35 @@ static void layout(int width, int height) {
     size_t tagrows    = view_limitrows(tagview, maxtagrows, tagcols);
     Regions[TAGS].height = tagrows * fheight;
     view_resize(tagview, tagrows, tagcols);
-    
+
     /* Place the scroll region relative to tags */
     Regions[SCROLL].x      = 0;
     Regions[SCROLL].y      = 5 + Regions[TAGS].y + Regions[TAGS].height;
     Regions[SCROLL].height = (height - Regions[EDIT].y - 5);
     Regions[SCROLL].width  = 5 + fwidth;
-    
+
     /* Place the edit region relative to tags */
     Regions[EDIT].x      = 3 + Regions[SCROLL].width;
     Regions[EDIT].y      = 5 + Regions[TAGS].y + Regions[TAGS].height;
     Regions[EDIT].height = (height - Regions[EDIT].y - 5);
-    Regions[EDIT].width  = width - Regions[SCROLL].width - 5; 
+    Regions[EDIT].width  = width - Regions[SCROLL].width - 5;
     view_resize(editview, Regions[EDIT].height / fheight, Regions[EDIT].width / fwidth);
 }
 
 static void onredraw(int width, int height) {
     size_t fheight = x11_font_height(Font);
     size_t fwidth  = x11_font_width(Font);
-    
+
     layout(width, height);
     onupdate(); // Let the user program update the status and other content
     view_update(win_view(STATUS), &(Regions[STATUS].csrx), &(Regions[STATUS].csry));
     view_update(win_view(TAGS), &(Regions[TAGS].csrx), &(Regions[TAGS].csry));
     view_update(win_view(EDIT), &(Regions[EDIT].csrx), &(Regions[EDIT].csry));
     onlayout(); // Let the user program update the scroll bar
-    
+
     for (int i = 0; i < SCROLL; i++) {
         View* view = win_view(i);
-        x11_draw_rect((i == TAGS ? CLR_BASE02 : CLR_BASE03), 
+        x11_draw_rect((i == TAGS ? CLR_BASE02 : CLR_BASE03),
             0, Regions[i].y - 3, width, Regions[i].height + 8);
         x11_draw_rect(CLR_BASE01, 0, Regions[i].y - 3, width, 1);
         if ((i == EDIT) && (Ruler != 0))
@@ -211,7 +211,7 @@ static void onredraw(int width, int height) {
             draw_glyphs(Regions[i].x, Regions[i].y + ((y+1) * fheight), row->cols, row->rlen, row->len);
         }
     }
-    
+
     /* draw the scroll region */
     size_t thumbreg = (Regions[SCROLL].height - Regions[SCROLL].y + 9);
     size_t thumboff = (size_t)((thumbreg * ScrollOffset) + (Regions[SCROLL].y - 2));
@@ -220,15 +220,15 @@ static void onredraw(int width, int height) {
     x11_draw_rect(CLR_BASE01, Regions[SCROLL].width, Regions[SCROLL].y - 2, 1, Regions[SCROLL].height);
     x11_draw_rect(CLR_BASE00, 0, Regions[SCROLL].y - 2, Regions[SCROLL].width, thumbreg);
     x11_draw_rect(CLR_BASE03, 0, thumboff, Regions[SCROLL].width, thumbsz);
-    
+
     /* place the cursor on screen */
     if (Regions[Focused].csrx != SIZE_MAX && Regions[Focused].csry != SIZE_MAX) {
-        x11_draw_rect(CLR_BASE3, 
-            Regions[Focused].x + (Regions[Focused].csrx * fwidth), 
-            Regions[Focused].y + (Regions[Focused].csry * fheight), 
+        x11_draw_rect(CLR_BASE3,
+            Regions[Focused].x + (Regions[Focused].csrx * fwidth),
+            Regions[Focused].y + (Regions[Focused].csry * fheight),
             1, fheight);
     }
-    
+
     /* adjust the mouse location */
     if (Regions[Focused].warp_ptr) {
         Regions[Focused].warp_ptr = false;
@@ -251,11 +251,11 @@ static void oninput(int mods, Rune key) {
             return;
         }
     }
-    
+
     /* fallback to just inserting the rune if it doesn't fall in the private use area.
      * the private use area is used to encode special keys */
     if (key < 0xE000 || key > 0xF8FF) {
-        if (key == '\n' && win_view(FOCUSED)->buffer.crlf) 
+        if (key == '\n' && win_view(FOCUSED)->buffer.crlf)
             key = RUNE_CRLF;
         view_insert(win_view(FOCUSED), true, key);
     }
@@ -271,12 +271,12 @@ static void onclick(MouseAct act, MouseBtn btn, int x, int y) {
             case MOUSE_BTN_LEFT:
                 view_scroll(win_view(EDIT), -row);
                 break;
-            case MOUSE_BTN_MIDDLE: 
+            case MOUSE_BTN_MIDDLE:
                 onscroll((double)(y - Regions[SCROLL].y) /
                          (double)(Regions[SCROLL].height - Regions[SCROLL].y));
                 break;
             case MOUSE_BTN_RIGHT:
-                view_scroll(win_view(EDIT), +row); 
+                view_scroll(win_view(EDIT), +row);
                 break;
             case MOUSE_BTN_WHEELUP:
                 view_scroll(win_view(id), -ScrollLines);
index 69c720aa1304e660ac41f7e582105f647f70d945..d3bc4de3dda3fddaad71705561568b0ba643e2a5 100644 (file)
--- a/lib/x11.c
+++ b/lib/x11.c
@@ -119,11 +119,11 @@ void x11_window(char* name, int width, int height) {
         X.height,
         0, X.depth,
         Config->palette[0]);
-    
+
     /* register interest in the delete window message */
     Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
     XSetWMProtocols(X.display, X.window, &wmDeleteMessage, 1);
-    
+
     /* setup window attributes and events */
     XSetWindowAttributes swa;
     swa.backing_store = WhenMapped;
@@ -137,15 +137,15 @@ void x11_window(char* name, int width, int height) {
         | ButtonMotionMask
         | KeyPressMask
     );
-    
+
     /* set input methods */
     if ((X.xim = XOpenIM(X.display, 0, 0, 0)))
         X.xic = XCreateIC(X.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, X.window, XNFocusWindow, X.window, NULL);
-    
+
     /* initialize pixmap and drawing context */
     X.pixmap = XCreatePixmap(X.display, X.window, width, height, X.depth);
     X.xft    = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap);
-    
+
     /* initialize the graphics context */
     XGCValues gcv;
     gcv.foreground = WhitePixel(X.display, X.screen);
@@ -572,7 +572,7 @@ static void selrequest(XEvent* evnt) {
     s.xselection.selection = evnt->xselectionrequest.selection;
     s.xselection.target    = evnt->xselectionrequest.target;
     s.xselection.time      = evnt->xselectionrequest.time;
-    
+
     Atom target    = evnt->xselectionrequest.target;
     Atom xatargets = XInternAtom(X.display, "TARGETS", 0);
     Atom xastring  = XInternAtom(X.display, "STRING", 0);
@@ -580,16 +580,16 @@ static void selrequest(XEvent* evnt) {
         /* respond with the supported type */
         XChangeProperty(
             X.display,
-            s.xselection.requestor, 
+            s.xselection.requestor,
             s.xselection.property,
             XA_ATOM, 32, PropModeReplace,
             (unsigned char*)&SelTarget, 1);
     } else if (target == SelTarget || target == xastring) {
         XChangeProperty(
-            X.display, 
+            X.display,
             s.xselection.requestor,
             s.xselection.property,
-            SelTarget, 8, PropModeReplace, 
+            SelTarget, 8, PropModeReplace,
             (unsigned char*)sel->text, strlen(sel->text));
     }
     XSendEvent(X.display, s.xselection.requestor, True, 0, &s);
@@ -602,7 +602,7 @@ bool x11_sel_get(int selid, void(*cbfn)(char*)) {
     if (owner == X.window) {
         cbfn(sel->text);
     } else if (owner != None){
-        sel->callback = cbfn;    
+        sel->callback = cbfn;
         XConvertSelection(X.display, sel->atom, SelTarget, sel->atom, X.window, CurrentTime);
     }
     return true;
index 89fc8348897a1919de047c76da8a1bdc9cf61257..0dac7eded92a65829e52eec2545ded142356d6b8 100644 (file)
@@ -371,21 +371,6 @@ TEST_SUITE(UnitTests) {
         CHECK(buf_end(win_buf(EDIT)) == 3);
     }
 
-    TEST(ctrl+h should do nothing for empty buffer) {
-        setup_view(EDIT, "", CRLF, 0);
-        send_keys(ModCtrl, XK_h);
-        CHECK(win_sel(EDIT)->beg == 0);
-        CHECK(win_sel(EDIT)->end == 0);
-    }
-
-    TEST(ctrl+h should delete previous character) {
-        setup_view(EDIT, "AB", CRLF, 1);
-        send_keys(ModCtrl, XK_h);
-        CHECK(win_sel(EDIT)->beg == 0);
-        CHECK(win_sel(EDIT)->end == 0);
-        CHECK(buf_end(win_buf(EDIT)) == 1);
-    }
-
     TEST(ctrl+a should do nothing for empty buffer) {
         setup_view(EDIT, "", CRLF, 0);
         send_keys(ModCtrl, XK_a);
@@ -622,6 +607,83 @@ TEST_SUITE(UnitTests) {
         CHECK(win_view(EDIT)->selection.beg == 0);
         CHECK(win_view(EDIT)->selection.end == 3);
     }
+    
+    TEST(ctrl+h should nothing for empty buffer) {
+        setup_view(EDIT, "", CRLF, 0);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 0);
+        CHECK(win_sel(EDIT)->end == 0);
+    }
+    
+    TEST(ctrl+h should highlight content in parens from left paren) {
+        setup_view(EDIT, " (foo bar) ", CRLF, 1);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 2);
+        CHECK(win_sel(EDIT)->end == 9);
+    }
+    
+    TEST(ctrl+h should highlight content in parens from right paren) {
+        setup_view(EDIT, " (foo bar) ", CRLF, 9);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 9);
+        CHECK(win_sel(EDIT)->end == 2);
+    }
+    
+    TEST(ctrl+h should highlight content in parens from left bracket) {
+        setup_view(EDIT, " [foo bar] ", CRLF, 1);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 2);
+        CHECK(win_sel(EDIT)->end == 9);
+    }
+    
+    TEST(ctrl+h should highlight content in parens from right bracket) {
+        setup_view(EDIT, " [foo bar] ", CRLF, 9);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 9);
+        CHECK(win_sel(EDIT)->end == 2);
+    }
+    
+    TEST(ctrl+h should highlight content in parens from left brace) {
+        setup_view(EDIT, " {foo bar} ", CRLF, 1);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 2);
+        CHECK(win_sel(EDIT)->end == 9);
+    }
+    
+    TEST(ctrl+h should highlight content in parens from right brace) {
+        setup_view(EDIT, " {foo bar} ", CRLF, 9);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 9);
+        CHECK(win_sel(EDIT)->end == 2);
+    }
+    
+    TEST(ctrl+h should highlight whole line from bol) {
+        setup_view(EDIT, "foo bar\n", CRLF, 0);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 0);
+        CHECK(win_sel(EDIT)->end == 8);
+    }
+    
+    TEST(ctrl+h should highlight whole line from eol) {
+        setup_view(EDIT, "foo bar\n", CRLF, 7);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 0);
+        CHECK(win_sel(EDIT)->end == 8);
+    }
+    
+    TEST(ctrl+h should highlight word under cursor) {
+        setup_view(EDIT, " foo.bar \n", CRLF, 1);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 1);
+        CHECK(win_sel(EDIT)->end == 4);
+    }
+    
+    TEST(ctrl+h should highlight word under cursor) {
+        setup_view(EDIT, " foo.bar \n", CRLF, 4);
+        send_keys(ModCtrl, XK_h);
+        CHECK(win_sel(EDIT)->beg == 1);
+        CHECK(win_sel(EDIT)->end == 8);
+    }
 
     /* Mouse Input Handling
      *************************************************************************/
diff --git a/xedit.c b/xedit.c
index e349f47c180f1f3f2a986758f122af675a8985c4..82e31957511044a85c0e6ea94103ffc5f8900e20 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -72,10 +72,10 @@ static void cmd_exec(char* cmd) {
         if (op != '<') dest = win_getregion();
         output = cmdread(ShellCmd, &error);
     }
-    
+
     if (error)
         view_append(win_view(TAGS), chomp(error));
-    
+
     if (output) {
         if (op == '>')
             view_append(win_view(dest), chomp(output));
@@ -192,19 +192,19 @@ void onmouseright(WinRegion id, size_t count, size_t row, size_t col) {
  ******************************************************************************/
 static void del_to_bol(void) {
     view_bol(win_view(FOCUSED), true);
-    if (view_selsize(win_view(FOCUSED)) > 0) 
+    if (view_selsize(win_view(FOCUSED)) > 0)
         delete();
 }
 
 static void del_to_eol(void) {
     view_eol(win_view(FOCUSED), true);
-    if (view_selsize(win_view(FOCUSED)) > 0) 
+    if (view_selsize(win_view(FOCUSED)) > 0)
         delete();
 }
 
 static void del_to_bow(void) {
     view_byword(win_view(FOCUSED), LEFT, true);
-    if (view_selsize(win_view(FOCUSED)) > 0) 
+    if (view_selsize(win_view(FOCUSED)) > 0)
         delete();
 }
 
@@ -445,6 +445,10 @@ static void newline(void) {
     view_insert(view, true, '\n');
 }
 
+void highlight(void) {
+    view_selctx(win_view(FOCUSED));
+}
+
 /* Main Routine
  ******************************************************************************/
 static Tag Builtins[] = {
@@ -462,7 +466,7 @@ static Tag Builtins[] = {
     { .tag = "Indent", .action.noarg = indent   },
     { .tag = "Eol",    .action.noarg = eol_mode },
     { .tag = NULL,     .action.noarg = NULL     }
-}; 
+};
 
 static KeyBinding Bindings[] = {
     /* Cursor Movements */
@@ -472,12 +476,11 @@ static KeyBinding Bindings[] = {
     { ModAny, KEY_DOWN,  cursor_dn    },
     { ModAny, KEY_LEFT,  cursor_left  },
     { ModAny, KEY_RIGHT, cursor_right },
-    
+
     /* Standard Unix Shortcuts */
     { ModCtrl, 'u', del_to_bol  },
     { ModCtrl, 'k', del_to_eol  },
     { ModCtrl, 'w', del_to_bow  },
-    { ModCtrl, 'h', backspace   },
     { ModCtrl, 'a', cursor_bol  },
     { ModCtrl, 'e', cursor_eol  },
 
@@ -488,7 +491,7 @@ static KeyBinding Bindings[] = {
     { ModCtrl, 'x', cut   },
     { ModCtrl, 'c', copy  },
     { ModCtrl, 'v', paste },
-    
+
     /* Block Indent */
     { ModCtrl, '[', del_indent },
     { ModCtrl, ']', add_indent },
@@ -503,6 +506,7 @@ static KeyBinding Bindings[] = {
     { ModNone,                 KEY_ESCAPE, select_prev  },
     { ModCtrl,                 't',        change_focus },
     { ModCtrl,                 'q',        quit         },
+    { ModCtrl,                 'h',        highlight    },
     { ModCtrl,                 'f',        search       },
     { ModCtrl|ModShift,        'f',        search       },
     { ModCtrl|ModAlt,          'f',        search       },
@@ -521,7 +525,7 @@ static KeyBinding Bindings[] = {
 void onscroll(double percent) {
     size_t bend = buf_end(win_buf(EDIT));
     size_t off  = (size_t)((double)bend * percent);
-    view_scrollto(win_view(EDIT), (off >= bend ? bend : off));    
+    view_scrollto(win_view(EDIT), (off >= bend ? bend : off));
 }
 
 void onupdate(void) {
@@ -543,7 +547,7 @@ void onupdate(void) {
     win_view(STATUS)->selection = (Sel){0,0,0};
 }
 
-void onlayout(void) {    
+void onlayout(void) {
     /* calculate and update scroll region */
     View* view = win_view(EDIT);
     size_t bend = buf_end(win_buf(EDIT));