]> git.mdlowis.com Git - projs/tide.git/commitdiff
implemented find tag
authorMichael D. Lowis <mike@mdlowis.com>
Wed, 23 Nov 2016 00:27:19 +0000 (19:27 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Wed, 23 Nov 2016 00:27:19 +0000 (19:27 -0500)
TODO.md
inc/edit.h
libedit/buf.c
libedit/view.c
xedit.c

diff --git a/TODO.md b/TODO.md
index 9834e162e1434c9a9806f93e9d3238728b7b6ff2..feec8e51c77fc8746306fbe9877c494acf51730c 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -1,8 +1,8 @@
 # Implementation Tweaks and Bug Fixes
 
+* Arbitrary command execution (<|> operators)
 * Add tag for ctags lookup
 * Implement minimal regex search (per Kernighan article)
-* Arbitrary command execution (<|> operators)
 
 * off by one error on scrolling wrapped lines
 * block selection should handle brace-balancing
index 79a59aea8707668194ff68e654d6120ea8314a2c..848c8ebe1b19bb7eb4f775c7a22624030ee7f629 100644 (file)
@@ -69,6 +69,7 @@ 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_find(Buf* buf, size_t* beg, size_t* end);
+void buf_findstr(Buf* buf, char* str, size_t* beg, size_t* end);
 unsigned buf_end(Buf* buf);
 unsigned buf_byrune(Buf* buf, unsigned pos, int count);
 unsigned buf_byline(Buf* buf, unsigned pos, int count);
@@ -158,6 +159,7 @@ void view_selword(View* view, size_t row, size_t col);
 void view_select(View* view, size_t row, size_t col);
 char* view_fetch(View* view, size_t row, size_t col);
 void view_find(View* view, size_t row, size_t col);
+void view_findstr(View* view, char* str);
 void view_insert(View* view, Rune rune);
 void view_delete(View* view);
 void view_bol(View* view);
@@ -231,7 +233,10 @@ typedef struct {
 
 typedef struct {
     char* tag;
-    void (*action)(void);
+    union {
+        void (*noarg)(void);
+        void (*arg)(char* arg);
+    } action;
 } Tag;
 
 
index ee4694bbecf7e84cf7cb2593d2ef6a19d966fed6..6b4ddfc160b9f1ec8eab7f10899f4d8eaeed5178 100644 (file)
@@ -272,6 +272,60 @@ void buf_find(Buf* buf, size_t* beg, size_t* end) {
     }
 }
 
+static Rune* charstorunes(char* str) {
+    size_t len = 0;
+    Rune* runes = NULL;
+    while (str && *str) {
+        Rune rune = 0;
+        size_t length = 0;
+        while (!utf8decode(&rune, &length, *str++));
+        runes = realloc(runes, (len + 1) * sizeof(Rune));
+        runes[len++] = rune;
+    }
+    if (runes) {
+        runes = realloc(runes, (len + 1) * sizeof(Rune));
+        runes[len++] = '\0';
+    }
+    return runes;
+}
+
+static size_t runelen(Rune* runes) {
+    size_t len = 0;
+    for (; runes[len]; len++);
+    return len;
+}
+
+static int rune_match(Buf* buf, unsigned mbeg, unsigned mend, Rune* runes) {
+    for (; *runes; runes++, mbeg++) {
+        int cmp = *runes - buf_get(buf, mbeg);
+        if (cmp != 0) return cmp;
+    }
+    return 0;
+}
+
+void buf_findstr(Buf* buf, char* str, size_t* beg, size_t* end) {
+    if (!str) return;
+    Rune* runes = charstorunes(str);
+    size_t rlen = runelen(runes);
+    unsigned start = *beg, mbeg = start+1, mend = mbeg + rlen;
+
+    while (mbeg != start) {
+        if ((buf_get(buf, mbeg) == runes[0]) &&
+            (buf_get(buf, mend-1) == runes[rlen-1]) &&
+            (0 == rune_match(buf, mbeg, mend, runes)))
+        {
+            *beg = mbeg;
+            *end = mend;
+            break;
+        }
+        mbeg++, mend++;
+        if (mend >= buf_end(buf))
+            mbeg = 0, mend = rlen;
+    }
+
+    free(runes);
+}
+
 unsigned buf_end(Buf* buf) {
     size_t bufsz = buf->bufend - buf->bufstart;
     size_t gapsz = buf->gapend - buf->gapstart;
index 6823a7f62619f4ccf87c2015f07b64a9ddf39b18..634cef4f69697faf897e30958346bc1e97093fd0 100644 (file)
@@ -341,6 +341,13 @@ void view_find(View* view, size_t row, size_t col) {
     }
 }
 
+void view_findstr(View* view, char* str) {
+    Sel sel = view->selection;
+    buf_findstr(&(view->buffer), str, &sel.beg, &sel.end);
+    view->selection = sel;
+    view->sync_needed = true;
+}
+
 void view_insert(View* view, Rune rune) {
     if (rune == '\b') {
         if (num_selected(view->selection))
@@ -425,8 +432,10 @@ char* view_getstr(View* view, Sel* range) {
             len += n;
         }
     }
-    str = realloc(str, len+1);
-    if (str) str[len] = '\0';
+    if (str) {
+        str = realloc(str, len+1);
+        str[len] = '\0';
+    }
     return str;
 }
 
diff --git a/xedit.c b/xedit.c
index 0db251705f1fabe97f4316957a4cc98de352995d..54a785e286a66380181e18e61d1ab1a70a49bc7f 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -13,7 +13,7 @@ enum RegionId {
 
 // Input Handlers
 static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y);
-static void tag_handler(char* cmd);
+static void tag_handler(char* cmd, char* arg);
 static void key_handler(Rune key);
 
 // Drawing Routines
@@ -42,6 +42,7 @@ static void redo(void);
 static void cut(void);
 static void copy(void);
 static void paste(void);
+static void find(char* arg);
 
 // Mouse Handling
 static void mouse_left(enum RegionId id, size_t count, size_t row, size_t col);
@@ -61,7 +62,6 @@ static enum RegionId getregion(size_t x, size_t y);
  *****************************************************************************/
 static enum RegionId Focused = EDIT;
 static Region Regions[NREGIONS] = { 0 };
-static bool TagWinExpanded = false;
 static ButtonState MouseBtns[MOUSE_BTN_COUNT] = { 0 };
 static XFont Font;
 static XConfig Config = {
@@ -72,15 +72,15 @@ static XConfig Config = {
 };
 
 Tag Builtins[] = {
-    { "Quit",  quit  },
-    { "Save",  save  },
-    { "Cut",   cut   },
-    { "Copy",  copy  },
-    { "Paste", paste },
-    { "Undo",  undo  },
-    { "Redo",  redo  },
-    //{ "Find",  NULL  },
-    { NULL,    NULL  }
+    { .tag = "Quit",  .action.noarg = quit  },
+    { .tag = "Save",  .action.noarg = save  },
+    { .tag = "Cut",   .action.noarg = cut   },
+    { .tag = "Copy",  .action.noarg = copy  },
+    { .tag = "Paste", .action.noarg = paste },
+    { .tag = "Undo",  .action.noarg = undo  },
+    { .tag = "Redo",  .action.noarg = redo  },
+    { .tag = "Find",  .action.arg   = find  },
+    { .tag = NULL,    .action.noarg = NULL  }
 };
 
 void (*MouseActs[MOUSE_BTN_COUNT])(enum RegionId id, size_t count, size_t row, size_t col) = {
@@ -175,12 +175,12 @@ static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y) {
     }
 }
 
-static void tag_handler(char* cmd) {
+static void tag_handler(char* cmd, char* arg) {
     Tag* tags = Builtins;
     while (tags->tag) {
         if (!strcmp(tags->tag, cmd)) {
             Focused = EDIT;
-            tags->action();
+            tags->action.arg(arg);
             break;
         }
         tags++;
@@ -408,6 +408,10 @@ static void paste(void) {
     free(str);
 }
 
+static void find(char* arg) {
+    view_findstr(getview(EDIT), arg);
+}
+
 /* Mouse Handling
  *****************************************************************************/
 static void mouse_left(enum RegionId id, size_t count, size_t row, size_t col) {
@@ -424,8 +428,22 @@ static void mouse_middle(enum RegionId id, size_t count, size_t row, size_t col)
         cut();
     } else {
         char* str = view_fetch(getview(id), row, col);
-        tag_handler(str);
+        char* arg = str;
+        if (!str) { return; }
+        /* first check if the arg is in the same selection as the tag/cmd */
+        while (*arg && !isspace(*arg++));
+        if (*arg) {
+            char* temp = stringdup(arg);
+            *arg = '\0', arg = temp;
+        } else {
+            /* if it isn't then check the tags buffer selection */
+            arg = view_getstr(getview(TAGS), NULL);
+        }
+        /* if we still haven't found it, check the edit buffer selection */
+        if (!arg) arg = view_getstr(getview(EDIT), NULL);
+        tag_handler(str, arg);
         free(str);
+        free(arg);
     }
 }