diff options
author | jack <[email protected]> | 2023-11-28 11:49:42 -0700 |
---|---|---|
committer | jack <[email protected]> | 2023-11-28 11:49:42 -0700 |
commit | 8ce4a74ed37bea15e4dc1464a9dec04ff329fb42 (patch) | |
tree | 68a3ac1512fb223f9d7b2839417eb46b495b7307 | |
parent | d7d1f3fbf52f916807f06b88fbb2f732cc5b5b80 (diff) | |
download | st-8ce4a74ed37bea15e4dc1464a9dec04ff329fb42.tar.gz st-8ce4a74ed37bea15e4dc1464a9dec04ff329fb42.zip |
further cleanup
-rw-r--r-- | config.h | 19 | ||||
-rw-r--r-- | normalMode.c | 428 | ||||
-rw-r--r-- | normalMode.h | 14 | ||||
-rw-r--r-- | utils.h | 43 |
4 files changed, 9 insertions, 495 deletions
@@ -57,16 +57,15 @@ static KeySym mappedkeys[] = {-1}; static uint ignoremod = Mod2Mask | XK_SWITCH_MOD; static uint forceselmod = ShiftMask; -static Key key[] = { - {XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - {XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - {XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - {XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - {XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - {XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - {XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - {XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - {XK_BackSpace, XK_NO_MOD, "\177", 0, 0}}; +static Key key[] = {{XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + {XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + {XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + {XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + {XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + {XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + {XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + {XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + {XK_BackSpace, XK_NO_MOD, "\177", 0, 0}}; static uint selmasks[] = { [SEL_RECTANGULAR] = Mod1Mask, diff --git a/normalMode.c b/normalMode.c deleted file mode 100644 index 026e02b..0000000 --- a/normalMode.c +++ /dev/null @@ -1,428 +0,0 @@ -#include <X11/XKBlib.h> -#include <X11/keysym.h> - -#include "normalMode.h" -#include "utils.h" - -extern Glyph const styleSearch, style[]; -extern char const wDelS[], wDelL[], *nmKeys[]; -extern unsigned int bg[], fg, currentBg, highlightBg, highlightFg, amountNmKeys; - -typedef struct { - int p[3]; -} Pos; - -typedef enum { visual = 'v', visualLine = 'V', yank = 'y' } Op; -typedef enum { infix_none = 0, infix_i = 'i', infix_a = 'a' } Infix; -typedef enum { fw = '/', bw = '?' } Search; -struct NormalModeState { - struct OperationState { - Op op; - Infix infix; - } cmd; - struct MotionState { - uint32_t c; - int active; - Pos searchPos; - Search search; - } m; -} defaultNormalMode, state; - -DynamicArray searchStr = UTF8_ARRAY, cCmd = UTF8_ARRAY, lCmd = UTF8_ARRAY; -Glyph styleCmd; -char posBuffer[10], - braces[6][3] = {{"()"}, {"<>"}, {"{}"}, {"[]"}, {"\"\""}, {"''"}}; -int exited = 1, overlay = 1; -static inline Rune cChar() { return term.line[term.c.y][term.c.x].u; } -static inline int pos(int p, int h) { - return IS_SET(MODE_ALTSCREEN) ? p : rangeY(p + h * histOff - insertOff); -} -static inline int contains(Rune l, char const *values, size_t const memSize) { - for (uint32_t i = 0; i < memSize; ++i) - if (l == values[i]) - return 1; - return 0; -} -static inline void decodeTo(char const *cs, size_t len, DynamicArray *arr) { - char *var = expand(arr); - if (!var) - empty(arr); - else - utf8decode(cs, (Rune *)(var), len); -} -static inline void applyPos(Pos p) { - term.c.x = p.p[0], term.c.y = p.p[1]; - if (!IS_SET(MODE_ALTSCREEN) && histOp) - term.line = &buf[histOff = p.p[2]]; -} -/// Find string in history buffer, and provide string-match-lookup for -/// highlighting matches -static int highlighted(int x, int y) { - int const s = term.row * term.col, i = y * term.col + x, - sz = size(&searchStr); - return sz && i < s && mark[i] != sz && i + mark[i] < s && !mark[i + mark[i]]; -} -static void markSearchMatches(int all) { - int sz = size(&searchStr), ox = 0, oy = 0, oi = 0; - for (int y = 0; sz && all && y < term.row; ++y) - for (int x = 0; x < term.col; ++x) - term.dirty[y] |= highlighted(x, y); - for (int y = 0, wi = 0, owi = 0, i = 0; sz && y < term.row; ++y) - for (int x = 0; x < term.col; ++x, wi %= sz, ++i, owi = wi) - if (all || term.dirty[y]) { - mark[i] = - sz - (wi = (getU32(&searchStr, wi, 1) == term.line[y][x].u ? wi + 1 - : 0)); - if (wi == 1) - ox = x, oy = y, oi = i; - else if (!wi && owi) - x = ox, y = oy, i = oi; - } - for (int y = 0; sz && all && y < term.row; ++y) - for (int x = 0; x < term.col; ++x) - term.dirty[y] |= highlighted(x, y); -} -static int findString(int s, int all) { - Pos p = - (Pos){.p = {term.c.x, term.c.y, IS_SET(MODE_ALTSCREEN) ? 0 : histOff}}; - historyMove(s, 0, 0); - uint32_t strSz = size(&searchStr), maxIter = rows() * term.col + strSz, - wIdx = 0; - for (uint32_t i = 0, wi = 0; wIdx < strSz && ++i <= maxIter; - historyMove(s, 0, 0), wi = wIdx) { - wIdx = (getU32(&searchStr, wIdx, s > 0) == cChar()) ? wIdx + 1 : 0; - if (wi && !wIdx) - historyMove(-(int)(s * wi), 0, 0); - } - if (wIdx == strSz && wIdx) - historyMove(-(int)(s * strSz), 0, 0); - else - applyPos(p); - markSearchMatches(all); - return wIdx == strSz; -} -/// Execute series of normal-mode commands from char array / decoded from -/// dynamic array -ExitState pressKeys(char const *s, size_t e) { - ExitState x = success; - for (size_t i = 0; i < e && (x = (!s[i] ? x : kPressHist(&s[i], 1, 0, NULL))); - ++i) - ; - return x; -} -static ExitState executeCommand(uint32_t *cs, size_t z) { - ExitState x = success; - char dc[32]; - for (size_t i = 0; - i < z && (x = kPressHist(dc, utf8encode(cs[i], dc), 0, NULL)); ++i) - ; - return x; -} -/// Get character for overlay, if the overlay (st) has something to show, else -/// normal char. -static void getChar(DynamicArray *st, Glyph *glyphChange, int y, int xEnd, - int width, int x) { - if (x < xEnd - min(min(width, xEnd), size(st))) - *glyphChange = term.line[y][x]; - else if (x < xEnd) - glyphChange->u = - *((Rune *)(st->content + (size(st) + x - xEnd) * st->elSize)); -} -/// Expand "infix" expression: for instance (w =>) l b | | v e -/// | | y -static ExitState expandExpression( - char l) { // ({ =>) l ? { \n | l | v / } \n | h | y - int a = state.cmd.infix == infix_a, yank = state.cmd.op == 'y', - lc = tolower(l), found = 1; - state.cmd.infix = infix_none; - if (!yank && state.cmd.op != visual && state.cmd.op != visualLine) - return failed; - char mot[11] = {'l', 0, 'b', 0, 0, 'v', 0, 'e', 0, 0, (char)(yank ? 'y' : 0)}; - if (lc == 'w') - mot[2] = (char)('b' - lc + l), mot[7] = (char)((a ? 'w' : 'e') - lc + l), - mot[9] = (char)(a ? 'h' : 0); - else { - mot[1] = '?', mot[3] = mot[8] = '\n', mot[6] = '/', - mot[4] = (char)(a ? 0 : 'l'), mot[9] = (char)(a ? 0 : 'h'); - for (int i = found = 0; !found && i < 6; ++i) - if ((found = contains(l, braces[i], 2))) - mot[2] = braces[i][0], mot[7] = braces[i][1]; - } - if (!found) - return failed; - assign(&lCmd, &cCmd); - empty(&cCmd); - state.cmd = defaultNormalMode.cmd; - return pressKeys(mot, 11); -} - -ExitState executeMotion(char const cs, KeySym const *const ks) { - state.m.c = state.m.c < 1u ? 1u : state.m.c; - if (ks && *ks == XK_d) - historyMove(0, 0, term.row / 2); - else if (ks && *ks == XK_u) - historyMove(0, 0, -term.row / 2); - else if (ks && *ks == XK_f) - historyMove(0, 0, term.row - 1 + (term.c.y = 0)); - else if (ks && *ks == XK_b) - historyMove(0, 0, -(term.c.y = term.row - 1)); - else if (ks && *ks == XK_h) - overlay = !overlay; - else if (cs == 'K') - historyMove(0, 0, -(int)state.m.c); - else if (cs == 'J') - historyMove(0, 0, (int)state.m.c); - else if (cs == 'k') - historyMove(0, -(int)state.m.c, 0); - else if (cs == 'j') - historyMove(0, (int)state.m.c, 0); - else if (cs == 'h') - historyMove(-(int)state.m.c, 0, 0); - else if (cs == 'l') - historyMove((int)state.m.c, 0, 0); - else if (cs == 'H') - term.c.y = 0; - else if (cs == 'M') - term.c.y = term.bot / 2; - else if (cs == 'L') - term.c.y = term.bot; - else if (cs == 's' || cs == 'S') - altToggle = cs == 's' ? !altToggle : 1; - else if (cs == 'G' || cs == 'g') { - if (cs == 'G') - term.c = c[0] = c[IS_SET(MODE_ALTSCREEN) + 1]; - if (!IS_SET(MODE_ALTSCREEN)) - term.line = &buf[histOff = insertOff]; - } else if (cs == '0') - term.c.x = 0; - else if (cs == '$') - term.c.x = term.col - 1; - else if (cs == 't') - sel.type = sel.type == SEL_REGULAR ? SEL_RECTANGULAR : SEL_REGULAR; - else if (cs == 'n' || cs == 'N') { - int const d = ((cs == 'N') != (state.m.search == bw)) ? -1 : 1; - for (uint32_t i = state.m.c; i && findString(d, 0); --i) - ; - } else if (contains(cs, "wWeEbB", 6)) { - int const low = cs <= 90, off = tolower(cs) != 'w', - sgn = (tolower(cs) == 'b') ? -1 : 1; - size_t const l = strlen(wDelL), s = strlen(wDelS), - maxIt = rows() * term.col; - for (int it = 0, on = 0; state.m.c > 0 && it < maxIt; ++it) { - // If an offset is to be performed in beginning or not in beginning, move - // in history. - if ((off || it) && historyMove(sgn, 0, 0)) - break; - // Determine if the category of the current letter changed since last - // iteration. - int n = 1 << (contains(cChar(), wDelS, s) ? (2 - low) - : !contains(cChar(), wDelL, l)), - found = (on |= n) ^ n && ((off ? on ^ n : n) != 1); - // If a reverse offset is to be performed and this is the last letter: - if (found && off) - historyMove(-sgn, 0, 0); - // Terminate iteration: reset #it and old n value #on and decrease - // operation count: - if (found) - it = -1, on = 0, --state.m.c; - } - } else - return failed; - state.m.c = 0; - return state.cmd.op == yank ? exitMotion : success; -} - -ExitState kPressHist(char const *cs, size_t len, int ctrl, KeySym const *kSym) { - historyOpToggle(1, 1); - int const prevYOff = IS_SET(MODE_ALTSCREEN) ? 0 : histOff, - search = state.m.search && state.m.active, - prevAltToggle = altToggle, prevOverlay = overlay; - int const noOp = !state.cmd.op && !state.cmd.infix, - num = len == 1 && BETWEEN(cs[0], 48, 57), - esc = kSym && *kSym == XK_Escape, - ret = (kSym && *kSym == XK_Return) || (len == 1 && cs[0] == '\n'), - quantifier = num && (cs[0] != '0' || state.m.c), - ins = !search && noOp && len && cs[0] == 'i'; - exited = 0; - ExitState result = success; - if (esc || ret || ins) { - result = exitMotion, len = 0; - } else if (kSym && *kSym == XK_BackSpace) { - if ((search || state.m.c) && size(&cCmd)) - pop(&cCmd); - if (search) { - if (size(&searchStr)) - pop(&searchStr); - else - result = exitMotion; - if (!size(&searchStr)) - tfulldirt(); - applyPos(state.m.searchPos); - findString(state.m.search == fw ? 1 : -1, 1); - } else if (state.m.c) - state.m.c /= 10; - len = 0; - } else if (search) { - if (len >= 1) - decodeTo(cs, len, &searchStr); - applyPos(state.m.searchPos); - findString(state.m.search == fw ? 1 : -1, 1); - } else if (len == 0) { - result = failed; - } else if (quantifier) { - state.m.c = min(SHRT_MAX, (int)state.m.c * 10 + cs[0] - 48); - } else if (state.cmd.infix && state.cmd.op && - (result = expandExpression(cs[0]), len = 0)) { - } else if (cs[0] == 'd') { - state = defaultNormalMode; - result = exitMotion; - state.m.active = 1; - } else if (cs[0] == '.') { - if (size(&cCmd)) - assign(&lCmd, &cCmd); - empty(&cCmd); - executeCommand((uint32_t *)lCmd.content, size(&lCmd)); - empty(&cCmd); - len = 0; - } else if (cs[0] == 'r') { - tfulldirt(); - } else if (cs[0] == 'c') { - empty(&lCmd); - empty(&cCmd); - empty(&searchStr); - tfulldirt(); - len = 0; - } else if (cs[0] == fw || cs[0] == bw) { - empty(&searchStr); - state.m.search = (Search)cs[0]; - state.m.searchPos = (Pos){.p = {term.c.x, term.c.y, prevYOff}}; - state.m.active = 1; - } else if (cs[0] == infix_i || cs[0] == infix_a) { - state.cmd.infix = (Infix)cs[0]; - } else if (cs[0] == 'y') { - if (state.cmd.op) { - result = (state.cmd.op == yank || state.cmd.op == visualLine) - ? exitOp - : exitMotion; - if (state.cmd.op == yank) - selstart(0, term.c.y, 0); - } else - selstart(term.c.x, term.c.y, 0); - state.cmd.op = yank; - } else if (cs[0] == visual || cs[0] == visualLine) { - if (state.cmd.op != (Op)cs[0]) { - state.cmd = defaultNormalMode.cmd; - state.cmd.op = (Op)cs[0]; - selstart(cs[0] == visualLine ? 0 : term.c.x, term.c.y, 0); - } else - result = exitOp; - } else if (!(result = executeMotion((char)(len ? cs[0] : 0), - ctrl ? kSym : NULL))) { - result = failed; - for (size_t i = 0; !ctrl && i < amountNmKeys; ++i) - if (cs[0] == nmKeys[i][0] && - failed != (result = pressKeys(&nmKeys[i][1], strlen(nmKeys[i]) - 1))) - goto end; - } // Operation/Motion finished if valid: update cmd string, extend selection, - // update search - if (result != failed) { - if (len == 1 && !ctrl) - decodeTo(cs, len, &cCmd); - if ((state.cmd.op == visualLine) || - ((state.cmd.op == yank) && (result == exitOp))) { - int const off = term.c.y + (IS_SET(MODE_ALTSCREEN) ? 0 : histOff) < - sel.ob.y; //< Selection start below end. - sel.ob.x = off ? term.col - 1 : 0; - selextend(off ? 0 : term.col - 1, term.c.y, sel.type, 0); - } else if (sel.oe.x != -1) { - selextend(term.c.x, term.c.y, sel.type, 0); - } - } // Set repaint for motion or status bar - if (!IS_SET(MODE_ALTSCREEN) && prevYOff != histOff) - tfulldirt(); - // Terminate Motion / operation if thus indicated - if (result == exitMotion) { - if (!state.m.active) - result = (exited = noOp) ? finish : exitOp; - state.m.active = (int)(state.m.c = 0u); - } - if (result == exitOp || result == finish) { - if (state.cmd.op == yank) { - xsetsel(getsel()); - xclipcopy(); - } - state = defaultNormalMode; - selclear(); - if (!esc) - assign(&lCmd, &cCmd); - empty(&cCmd); - } // Update the content displayed in the history overlay - styleCmd = style[state.cmd.op == yank - ? 1 - : (state.cmd.op == visual - ? 2 - : (state.cmd.op == visualLine ? 3 : 0))]; - int const posLin = !IS_SET(MODE_ALTSCREEN) ? rangeY(insertOff - histOff) : 0, - h = rows() - term.row; - if (!posLin || posLin == h || !h) - strcpy(posBuffer, posLin ? " [BOT] " : " [TOP] "); - else - sprintf(posBuffer, " % 3d%c ", - min(100, max(0, (int)(.5 + posLin * 100. / h))), '%'); - if ((overlay || overlay != prevOverlay) && term.col > 9 && term.row > 4) { - if (!term.dirty[term.row - 1]) - xdrawline(term.line[term.row - 1], term.col * 2 / 3, term.row - 1, - term.col - 1); - if (!term.dirty[term.row - 2]) - xdrawline(term.line[term.row - 2], term.col * 2 / 3, term.row - 2, - term.col - 1); - } - if (result == finish) - altToggle = 0; - if (altToggle != prevAltToggle) - tswapscreen(); -end: - historyOpToggle(-1, 1); - return result; -} - -void historyOverlay(int x, int y, Glyph *g) { - if (!histMode) - return; - TCursor const *cHist = histOp ? &term.c : &c[0]; - if (overlay && term.col > 9 && term.row > 4 && (x > (2 * term.col / 3)) && - (y >= (term.row - 2))) { - *g = (y == term.row - 2) ? styleSearch : styleCmd; - if (y == term.row - 2) - getChar(&searchStr, g, term.row - 2, term.col - 2, term.col / 3, x); - else if (x > term.col - 7) - g->u = (Rune)(posBuffer[x - term.col + 7]); - else - getChar(size(&cCmd) ? &cCmd : &lCmd, g, term.row - 1, term.col - 7, - term.col / 3 - 6, x); - } else if (highlighted(x, y)) - g->bg = highlightBg, g->fg = highlightFg; - else if ((x == cHist->x) ^ (y == cHist->y)) - g->bg = currentBg; - else if (x == cHist->x) - g->mode ^= ATTR_REVERSE; -} -void historyPreDraw() { - static Pos op = {.p = {0, 0, 0}}; - historyOpToggle(1, 0); - // Draw the cursor cross if changed - if (term.c.y >= term.row || op.p[1] >= term.row) - tfulldirt(); - else if (exited || (op.p[1] != term.c.y)) - term.dirty[term.c.y] = term.dirty[op.p[1]] = 1; - for (int i = 0; (exited || term.c.x != op.p[0]) && i < term.row; ++i) - if (!term.dirty[i]) { - xdrawline(term.line[i], term.c.x, i, term.c.x + 1); - xdrawline(term.line[i], op.p[0], i, op.p[0] + 1); - } - // Update search results either only for lines with new content or all results - // if exiting - markSearchMatches(exited); - op = (Pos){.p = {term.c.x, term.c.y, 0}}; - historyOpToggle(-1, 0); -} diff --git a/normalMode.h b/normalMode.h deleted file mode 100644 index e9534f6..0000000 --- a/normalMode.h +++ /dev/null @@ -1,14 +0,0 @@ -void normalMode(); -void historyPreDraw(); -void historyOverlay(int x, int y, Glyph *g); -void historyModeToggle(int start); -void historyOpToggle(int, int); -typedef enum { - failed = 0, - success = 1, - exitMotion = 2, - exitOp = 3, - finish = 4 -} ExitState; -ExitState kPressHist(char const *txt, size_t len, int ctrl, KeySym const *kSym); -ExitState pressKeys(char const *s, size_t e); diff --git a/utils.h b/utils.h deleted file mode 100644 index 331988f..0000000 --- a/utils.h +++ /dev/null @@ -1,43 +0,0 @@ -/// Dynamic memory-chunk, with (1) datatype size, (2/3) initialized / allocated -/// chunk, (4) content -typedef struct { - uint8_t const elSize; - uint32_t init, alloc; - char *content; -} DynamicArray; -#define UTF8_ARRAY \ - { 4, 0, 0, NULL } - -static inline int p_alloc(DynamicArray *s, uint32_t amount) { - uint32_t const diff = s->init + s->elSize * amount - s->alloc, - nas = s->alloc + max(diff, 15) * s->elSize; - if (s->alloc < s->init + s->elSize * amount) { - char *tmp = realloc(s->content, nas); - if (!tmp) - return 0; - s->alloc = nas, s->content = tmp; - } - return 1; -} -static inline char *view(DynamicArray *s, uint32_t i) { - return s->content + i * s->elSize; -} -static inline char *end(DynamicArray *s, uint32_t i) { - return s->content + s->init - (i + 1) * s->elSize; -} -static inline uint32_t getU32(DynamicArray *s, uint32_t i, int b) { - return *((uint32_t *)(b ? view(s, i) : end(s, i))); -} -static char *expand(DynamicArray *s) { - if (!p_alloc(s, 1)) - return NULL; - s->init += s->elSize; - return end(s, 0); -} -static inline void pop(DynamicArray *s) { s->init -= s->elSize; } -static inline void empty(DynamicArray *s) { s->init = 0; } -static inline int size(DynamicArray const *s) { return s->init / s->elSize; } -static inline void assign(DynamicArray *s, DynamicArray const *o) { - if (p_alloc(s, size(o))) - memcpy(s->content, o->content, (s->init = o->init)); -} |