From: Michael D. Lowis Date: Wed, 23 Nov 2016 00:27:19 +0000 (-0500) Subject: implemented find tag X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=8494ba023021cc54ca21776b3f1a491d27719827;p=projs%2Ftide.git implemented find tag --- diff --git a/TODO.md b/TODO.md index 9834e16..feec8e5 100644 --- 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 diff --git a/inc/edit.h b/inc/edit.h index 79a59ae..848c8eb 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -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; diff --git a/libedit/buf.c b/libedit/buf.c index ee4694b..6b4ddfc 100644 --- a/libedit/buf.c +++ b/libedit/buf.c @@ -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; diff --git a/libedit/view.c b/libedit/view.c index 6823a7f..634cef4 100644 --- a/libedit/view.c +++ b/libedit/view.c @@ -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 0db2517..54a785e 100644 --- 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); } }