diff options
| author | Louis Burda <dev@sinitax.com> | 2025-12-04 01:10:59 +0100 |
|---|---|---|
| committer | Louis Burda <dev@sinitax.com> | 2025-12-04 01:10:59 +0100 |
| commit | e90ed4703ef8453f50c47b5acdc0d1486da17380 (patch) | |
| tree | 4ed69142eaf86de43de174c9ee88d4bb33981806 | |
| parent | 4f7b4022bfe76c4f8d38327cca695a595f00ca11 (diff) | |
| download | tmenu-e90ed4703ef8453f50c47b5acdc0d1486da17380.tar.gz tmenu-e90ed4703ef8453f50c47b5acdc0d1486da17380.zip | |
Add option for visual delim for entries
| -rw-r--r-- | tmenu.c | 126 |
1 files changed, 79 insertions, 47 deletions
@@ -72,6 +72,11 @@ struct searchmode { ssize_t (*match)(ssize_t, int, size_t, ssize_t, bool, bool); }; +struct entry { + size_t full; + size_t visible; +}; + static void browse_prompt(void); static bool browse_handlekey(int c); static void browse_cleanup(void); @@ -117,13 +122,13 @@ static char *input = NULL; static size_t input_len = 0; static size_t input_cap = 0; -static size_t *delims = NULL; -static size_t delims_cnt = 0; -static size_t delims_cap = 0; +static struct entry *entries = NULL; +static size_t entries_len = 0; +static size_t entries_cap = 0; +static size_t entries_cnt = 0; static ssize_t selected = -1; static const char *entry = NULL; -static size_t entry_max = 0; static size_t entry_off = 0; static char searchbuf[1024]; @@ -143,6 +148,7 @@ static bool show_prompt = true; static bool top_prompt = false; static char delim = '\n'; +static char vis_delim = '|'; static void die(const char *fmt, ...) @@ -203,15 +209,23 @@ lower(char c) } static size_t -entry_len(size_t index) +vis_entry_len(size_t index) +{ + if (index == entries_cnt-1) + return input_len - entries[index].visible; + return entries[index+1].visible-1 - entries[index].visible; +} + +static inline char * +vis_entry(size_t index) { - return delims[index] - (index > 0 ? delims[index-1] + 1 : 0); + return input + entries[index].visible; } static inline char * -get_entry(size_t index) +full_entry(size_t index) { - return input + (index > 0 ? delims[index-1] + 1 : 0); + return input + entries[index].full; } static int @@ -307,9 +321,9 @@ browse_prompt(void) linew = termw; } - if (selected >= 0 && i >= 0 && i < delims_cnt) { - entry = get_entry((size_t) i); - entlen = entry_len((size_t) i); + if (selected >= 0 && i >= 0 && i < entries_cnt) { + entry = vis_entry((size_t) i); + entlen = vis_entry_len((size_t) i); if (entlen > linew) { EPRINTF(" ..%.*s\n", (int) (linew - 3), entry + entlen - (linew - 3)); @@ -338,7 +352,7 @@ browse_handlekey(int c) selected = 0; break; case 'G': - selected = (ssize_t) delims_cnt - 1; + selected = (ssize_t) entries_cnt - 1; break; case 'q': return true; @@ -351,17 +365,17 @@ browse_handlekey(int c) break; case KEY_PGDN: cnt = fwdctx + bwdctx + 1; - if (selected < delims_cnt - cnt) + if (selected < entries_cnt - cnt) selected += (ssize_t) cnt; else - selected = (ssize_t) delims_cnt - 1; + selected = (ssize_t) entries_cnt - 1; break; case KEY_UP: if (selected != 0) selected--; break; case KEY_DOWN: - if (selected != delims_cnt - 1) + if (selected != entries_cnt - 1) selected++; break; } @@ -443,8 +457,8 @@ search_prompt(void) if (index < 0) { EPRINTF("\n"); } else { - entlen = entry_len((size_t) index); - entry = get_entry((size_t) index); + entlen = vis_entry_len((size_t) index); + entry = vis_entry((size_t) index); off = entlen >= linew ? entlen - linew : 0; off = MIN(entry_off, off); EPRINTF("%.*s\n", (int) linew, entry + off); @@ -521,8 +535,8 @@ search_match_linear(ssize_t start, int dir, index = start + dir * (ssize_t) (new + cnt - 1); if (index < 0) return closest ? 0 : fallback; - if (index >= delims_cnt) - return closest ? (ssize_t) delims_cnt - 1 : fallback; + if (index >= entries_cnt) + return closest ? (ssize_t) entries_cnt - 1 : fallback; return index; } @@ -541,13 +555,13 @@ search_match_substr(ssize_t start, int dir, prev = -1; found = 0; - for (i = new; i < delims_cnt; i++) { + for (i = new; i < entries_cnt; i++) { index = start + dir * (ssize_t) i; - if (index < 0 || index >= delims_cnt) + if (index < 0 || index >= entries_cnt) break; - entry = get_entry((size_t) index); - end = entry + entry_len((size_t) index); + entry = vis_entry((size_t) index); + end = entry + vis_entry_len((size_t) index); for (bp = entry; *bp; bp++) { if (searchlen > end - bp) continue; @@ -577,13 +591,13 @@ search_match_fuzzy(ssize_t start, int dir, prev = -1; found = 0; - for (i = new; i < delims_cnt; i++) { + for (i = new; i < entries_cnt; i++) { index = start + dir * (ssize_t) i; - if (index < 0 || index >= delims_cnt) + if (index < 0 || index >= entries_cnt) break; - entry = get_entry((size_t) index); - end = entry + entry_len((size_t) index); + entry = vis_entry((size_t) index); + end = entry + vis_entry_len((size_t) index); pos = entry; for (c = searchbuf; c - searchbuf < searchlen; c++) { @@ -608,34 +622,47 @@ load(int fd) size_t i; char *c; + if (!entries_cap) + entries = addcap(entries, sizeof(struct entry), 1, &entries_cap); + + if (!entries_len) { + entries[0].full = 0; + entries[0].visible = 0; + entries_len = 1; + } + while (1) { - input = addcap(input, 1, input_len + BUFSIZ, &input_cap); + input = addcap(input, 1, input_len + BUFSIZ + 1, &input_cap); nread = read(fd, input + input_len, BUFSIZ); if (nread <= 0) break; c = input + input_len; - for (i = 0; i < (size_t) nread; i++, c++) { - if (*c != delim) continue; - *c = '\0'; - delims = addcap(delims, sizeof(size_t), - delims_cnt + 1, &delims_cap); - delims[delims_cnt++] = input_len + i; - entry_max = MAX(entry_max, entry_len(delims_cnt-1)); + for (i = input_len; i < input_len + (size_t) nread; i++, c++) { + if (*c == vis_delim) { + entries[entries_len-1].visible = i + 1; + } else if (*c == delim) { + *c = '\0'; + entries = addcap(entries, sizeof(struct entry), + entries_len + 1, &entries_cap); + entries[entries_len].full = i + 1; + entries[entries_len].visible = i + 1; + entries_len++; + } } - input_len += (size_t) nread; } + input[input_len] = '\0'; - if (!delims_cnt && input_len - || delims_cnt && delims[delims_cnt-1] != input_len-1) { - delims = addcap(delims, sizeof(size_t), - delims_cnt + 1, &delims_cap); - delims[delims_cnt++] = input_len; - entry_max = MAX(entry_max, entry_len(delims_cnt-1)); + entries_cnt = 0; + if (entries_len) { + if (input_len <= entries[entries_len-1].full) + entries_cnt = entries_len-1; + else + entries_cnt = entries_len; } if (verbose) - EPRINTF("Loaded %lu entries\n", delims_cnt); + EPRINTF("Loaded %lu entries\n", entries_cnt); } static void @@ -644,7 +671,7 @@ run(void) struct termios prevterm, newterm = { 0 }; int c; - if (!delims_cnt) return; + if (!entries_cnt) return; if (tcgetattr(0, &prevterm)) die("tcgetattr:"); @@ -689,9 +716,9 @@ run(void) case KEY_CTRL('J'): case '\r': if (selected < 0) break; - entry = get_entry((size_t) selected); + entry = full_entry((size_t) selected); modes[mode].cleanup(); - printf("%.*s\n", (int) entry_len((size_t) selected), entry); + puts(entry); if (!multiout) goto exit; break; default: @@ -753,11 +780,16 @@ parseopt(const char *flag, const char **args) if (args[0][0] && args[0][1]) die("bad -d arg"); delim = **args; return 1; + case 'D': + if (!*args) die("missing -d arg"); + if (args[0][0] && args[0][1]) die("bad -d arg"); + vis_delim = **args; + return 1; case 't': top_prompt = true; return 0; case 'h': - printf("Usage: tmenu [-h] [-m] [-a LINES] [-b LINES]"); + printf("Usage: tmenu [-h] [-m] [-d DELIM] [-D DELIM] [-a LINES] [-b LINES]"); exit(0); default: die("unknown opt '%s'", *flag); |
