From: Michael D. Lowis Date: Tue, 10 Jan 2017 13:25:52 +0000 (-0500) Subject: Added brace balancing to the block selection X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=18673f0476467708a33d5d6677cb3440ca27b9fe;p=projs%2Ftide.git Added brace balancing to the block selection --- diff --git a/TODO.md b/TODO.md index a07c6c4..66c9754 100644 --- a/TODO.md +++ b/TODO.md @@ -2,11 +2,10 @@ Up Next: -* invalid memory accesses while viewing docs/waf -* Tag line count should account for wrapped lines -* block selection should handle brace-balancing * context sensitive selection of words, commands, line numbers, or filenames. +* Tag line count should account for wrapped lines * ctrl+alt+f should find next occurence of previous search term +* invalid memory accesses while viewing docs/waf * check for file changes on save * check for file changes when window regains focus @@ -19,10 +18,8 @@ The Rest: * Add a tools dir to namespace utility scripts only useful inside the editor * implement command diffing logic to optimize the undo/redo log * add command line flags to toggle options (Tabs, Indent, etc..) -* backspace should delete indent if preceded by whitespace * Add a ctrl+space shortcut to autocomplete ctag * off by one error on scrolling up with wrapped lines -* Auto-save on focus change or quit # Auxillary Programs diff --git a/inc/edit.h b/inc/edit.h index bd0aa6a..37bd478 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -78,6 +78,7 @@ 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_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); diff --git a/lib/buf.c b/lib/buf.c index e0b1bfe..555f0a8 100644 --- a/lib/buf.c +++ b/lib/buf.c @@ -380,6 +380,39 @@ unsigned buf_rscan(Buf* buf, unsigned pos, Rune r) { return (buf_get(buf, off) == r ? off : pos); } +void buf_getblock(Buf* buf, Rune first, Rune last, Sel* sel) { + int balance = 0, dir; + unsigned beg = sel->end, end = sel->end, off; + + /* figure out which end of the block we're starting at */ + if (buf_get(buf, end) == first) + dir = +1, balance++, beg = end++; + else if (buf_get(buf, end) == last) + dir = -1, balance--, beg = end--; + else + return; + + /* scan for a blanced set of braces */ + while (true) { + if (buf_get(buf, end) == first) + balance++; + else if (buf_get(buf, end) == last) + balance--; + + if (balance == 0 || end >= buf_end(buf) || end == 0) + break; + else + end += dir; + } + + /* bail if we failed to find a block */ + if (balance != 0) return; + + /* update the passed in selection */ + if (end > beg) beg++, end--; + sel->beg = beg, sel->end = end; +} + /*****************************************************************************/ unsigned buf_byrune(Buf* buf, unsigned pos, int count) { diff --git a/lib/view.c b/lib/view.c index bd1e029..b4ba8bc 100644 --- a/lib/view.c +++ b/lib/view.c @@ -319,17 +319,11 @@ static void selcontext(View* view, Sel* sel) { sel->beg = buf_bow(buf, sel->end); sel->end = buf_eow(buf, sel->end++); } else if (r == '(' || r == ')') { - sel->beg = buf_lscan(buf, sel->end, '('); - sel->end = buf_rscan(buf, sel->end++, ')'); - sel->beg++, sel->end--; + buf_getblock(buf, '(', ')', sel); } else if (r == '[' || r == ']') { - sel->beg = buf_lscan(buf, sel->end, '['); - sel->end = buf_rscan(buf, sel->end++, ']'); - sel->beg++, sel->end--; + buf_getblock(buf, '[', ']', sel); } else if (r == '{' || r == '}') { - sel->beg = buf_lscan(buf, sel->end, '{'); - sel->end = buf_rscan(buf, sel->end++, '}'); - sel->beg++, sel->end--; + buf_getblock(buf, '{', '}', sel); } else { selbigword(view, sel); }