tmenu

Terminal menu for selecting items from stdin
git clone git@sinitax.com:sinitax/tmenu
Log | Files | Refs | README | LICENSE | sfeed.txt

commit 20e32bf4ca0737affcf3035aa2300b7c9cb5a377
parent e223f007400cbbb42de2b00afb25d5535fb9ef02
Author: Louis Burda <quent.burda@gmail.com>
Date:   Tue, 20 Jun 2023 01:28:51 +0200

Fix -Wconversion warning and replace freadln with fgets

Diffstat:
M.gitignore | 2++
MMakefile | 6+++---
Mtmenu.c | 213++++++++++++++++++++++++++++++++++++-------------------------------------------
3 files changed, 101 insertions(+), 120 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1 +1,3 @@ tmenu +.cache +compile_commands.json diff --git a/Makefile b/Makefile @@ -1,8 +1,8 @@ -CFLAGS = -g -Wunused-variable - -PREFIX ?= /usr +PREFIX ?= /usr/local BINDIR ?= /bin +CFLAGS = -g -Wunused-variable -Wunused-function -Wconversion + all: tmenu clean: diff --git a/tmenu.c b/tmenu.c @@ -61,29 +61,29 @@ enum { }; struct mode { - void (*prompt)(); - void (*cleanup)(); - bool (*handlekey)(); + void (*prompt)(void); + void (*cleanup)(void); + bool (*handlekey)(int c); }; struct searchmode { const char *sh; - ssize_t (*match)(size_t, int, bool, size_t, ssize_t); + ssize_t (*match)(ssize_t, int, bool, size_t, ssize_t); }; -void browse_prompt(void); -bool browse_handlekey(int c); -void browse_cleanup(void); +static void browse_prompt(void); +static bool browse_handlekey(int c); +static void browse_cleanup(void); -void search_prompt(void); -bool search_handlekey(int c); -void search_cleanup(void); +static void search_prompt(void); +static bool search_handlekey(int c); +static void search_cleanup(void); -ssize_t search_match(size_t start, int dir, +static ssize_t search_match(ssize_t start, int dir, bool new, size_t cnt, ssize_t fallback); -ssize_t search_match_substr(size_t start, int dir, +static ssize_t search_match_substr(ssize_t start, int dir, bool new, size_t cnt, ssize_t fallback); -ssize_t search_match_fuzzy(size_t start, int dir, +static ssize_t search_match_fuzzy(ssize_t start, int dir, bool new, size_t cnt, ssize_t fallback); static const char *usage = \ @@ -113,30 +113,31 @@ static const struct mode modes[] = { } }; -static FILE *infile; +static FILE *infile = NULL; -static size_t *entries; -static size_t entries_cap, entries_cnt; +static size_t *entries = NULL; +static size_t entries_cap = 0; +static size_t entries_cnt = 0; -static ssize_t selected; -static char *entry; +static ssize_t selected = -1; +static char *entry = NULL; static char searchbuf[1024]; -static size_t searchlen; +static size_t searchlen = 0; static int mode = MODE_BROWSE; static int searchcase = CASE_SENSITIVE; static int searchmode = SEARCH_SUBSTR; -static int fwdctx = 1; -static int bwdctx = 1; -static int termw = 80; +static size_t fwdctx = 1; +static size_t bwdctx = 1; +static size_t termw = 80; static bool multiout = false; static bool verbose = false; static bool prompt = true; -char +static char lower(char c) { if (c >= 'A' && c <= 'Z') @@ -144,7 +145,7 @@ lower(char c) return c; } -int +static int search_cmp(const char *a, const char *b, size_t size) { size_t i; @@ -162,7 +163,7 @@ search_cmp(const char *a, const char *b, size_t size) return 0; } -const char* +static const char* search_find(const char *a, char c, size_t size) { size_t i; @@ -179,7 +180,7 @@ search_find(const char *a, char c, size_t size) return NULL; } -int +static int readkey(FILE *f) { int c; @@ -209,36 +210,19 @@ readkey(FILE *f) return KEY_NONE; } -size_t -freadln(char *buf, size_t size, FILE *f) -{ - size_t i; - int c; - - for (i = 0; i < size; i++) { - c = fgetc(f); - if (c < 0) return -1; - buf[i] = c; - if (c == '\n') - return i + 1; - } - - return i; -} - -size_t +static size_t entry_len(size_t index) { return entries[index + 1] - entries[index]; } -char * +static char * read_entry(char *buf, size_t index) { - ssize_t nleft, nread; + size_t nleft, nread; char *pos, *tok; - fseek(infile, entries[index], SEEK_SET); + fseek(infile, (ssize_t) entries[index], SEEK_SET); nleft = entry_len(index); buf = realloc(buf, nleft); @@ -259,19 +243,19 @@ read_entry(char *buf, size_t index) return buf; } -void -add_entry(size_t index, size_t pos) +static void +add_entry(size_t pos) { - if (index >= entries_cap) { + if (entries_cnt >= entries_cap) { entries_cap *= 2; entries = realloc(entries, entries_cap * sizeof(size_t)); if (!entries) err(1, "realloc"); } - entries[index] = pos; + entries[entries_cnt] = pos; } -void +static void browse_prompt(void) { static const char promptstr[] = "(browse): "; @@ -283,7 +267,8 @@ browse_prompt(void) linew = termw; if (prompt) linew -= ARRLEN(promptstr) - 1; - for (i = selected - bwdctx; i <= selected + fwdctx; i++) { + i = (ssize_t) selected - (ssize_t) bwdctx; + for (; i <= (ssize_t) selected + (ssize_t) fwdctx; i++) { eprintf(CSI_CLEAR_LINE); if (i == selected) @@ -298,8 +283,8 @@ browse_prompt(void) } if (selected >= 0 && i >= 0 && i < entries_cnt) { - entry = read_entry(entry, i); - entlen = entry_len(i); + entry = read_entry(entry, (size_t) i); + entlen = entry_len((size_t) i); if (entlen > linew) { eprintf(" ..%.*s\n", (int) (linew - 3), entry + entlen - (linew - 3)); @@ -318,33 +303,33 @@ browse_prompt(void) eprintf(CSI_CUR_UP); } -bool +static bool browse_handlekey(int c) { - int cnt; - + size_t cnt; + switch (c) { case 'g': selected = 0; break; case 'G': - selected = entries_cnt - 1; + selected = (ssize_t) entries_cnt - 1; break; case 'q': return true; case KEY_PGUP: cnt = fwdctx + bwdctx + 1; if (selected > cnt) - selected -= cnt; + selected -= (ssize_t) cnt; else selected = 0; break; case KEY_PGDN: cnt = fwdctx + bwdctx + 1; if (selected < entries_cnt - cnt) - selected += cnt; + selected += (ssize_t) cnt; else - selected = entries_cnt - 1; + selected = (ssize_t) entries_cnt - 1; break; case KEY_UP: if (selected != 0) @@ -359,7 +344,7 @@ browse_handlekey(int c) return false; } -void +static void browse_cleanup(void) { size_t i; @@ -370,7 +355,7 @@ browse_cleanup(void) eprintf(CSI_CUR_UP); } -void +static void search_prompt(void) { char promptbuf[256]; @@ -393,16 +378,18 @@ search_prompt(void) if (len < 0) err(1, "snprintf"); linew = termw; - if (prompt) linew -= len + 3; + if (prompt) linew -= (size_t) len + 3; - for (i = -bwdctx; i <= fwdctx; i++) { + for (i = -(ssize_t) bwdctx; i <= fwdctx; i++) { if (selected >= 0) { if (i < 0) { - index = search_match(selected, BWD, 1, -i, -1); + index = search_match(selected, + BWD, 1, (size_t) -i, -1); } else if (i == 0) { index = selected; } else if (i > 0) { - index = search_match(selected, FWD, 1, i, -1); + index = search_match(selected, + FWD, 1, (size_t) i, -1); } } else { index = -1; @@ -423,11 +410,11 @@ search_prompt(void) if (index < 0) { eprintf("\n"); } else { - entlen = entry_len(index); - entry = read_entry(entry, index); + entlen = (ssize_t) entry_len((size_t) index); + entry = read_entry(entry, (size_t) index); if (entlen > linew) { - eprintf(" ..%.*s\n", (int) (linew - 3), - entry + MAX(0, entlen - (linew - 3))); + eprintf(" ..%.*s\n", (int) (linew - 3), entry + + MAX(0, (size_t) entlen - (linew - 3))); } else { eprintf("%.*s\n", (int) linew, entry); } @@ -440,10 +427,10 @@ search_prompt(void) eprintf(CSI_CUR_UP); } -bool +static bool search_handlekey(int c) { - int cnt; + size_t cnt; switch (c) { case KEY_CTRL('I'): @@ -467,7 +454,7 @@ search_handlekey(int c) break; case 0x20 ... 0x7e: if (searchlen < sizeof(searchbuf) - 1) - searchbuf[searchlen++] = c & 0xff; + searchbuf[searchlen++] = (char) (c & 0xff); break; case KEY_DEL: if (searchlen) searchlen--; @@ -477,7 +464,7 @@ search_handlekey(int c) return false; } -void +static void search_cleanup(void) { size_t i; @@ -488,14 +475,14 @@ search_cleanup(void) eprintf(CSI_CUR_UP); } -ssize_t -search_match(size_t start, int dir, bool new, size_t cnt, ssize_t fallback) +static ssize_t +search_match(ssize_t start, int dir, bool new, size_t cnt, ssize_t fallback) { return searchmodes[searchmode].match(start, dir, new, cnt, fallback); } -ssize_t -search_match_substr(size_t start, int dir, +static ssize_t +search_match_substr(ssize_t start, int dir, bool new, size_t cnt, ssize_t fallback) { const char *end, *bp; @@ -503,7 +490,7 @@ search_match_substr(size_t start, int dir, ssize_t index; if (!searchlen) { - index = start + dir * (new + cnt - 1); + index = start + dir * (ssize_t) (new + cnt - 1); if (index < 0 || index >= entries_cnt) return fallback; return index; @@ -511,15 +498,15 @@ search_match_substr(size_t start, int dir, found = 0; for (i = new; i < entries_cnt; i++) { - index = start + dir * i; + index = start + dir * (ssize_t) i; if (index < 0 || index >= entries_cnt) break; - entry = read_entry(entry, index); - end = entry + entry_len(index); + entry = read_entry(entry, (size_t) index); + end = entry + entry_len((size_t) index); for (bp = entry; *bp; bp++) { - len = MIN(end - bp, searchlen); + len = MIN(searchlen, (size_t) (end - bp)); if (!search_cmp(bp, searchbuf, len)) { if (++found == cnt) return index; @@ -531,8 +518,8 @@ search_match_substr(size_t start, int dir, return fallback; } -ssize_t -search_match_fuzzy(size_t start, int dir, +static ssize_t +search_match_fuzzy(ssize_t start, int dir, bool new, size_t cnt, ssize_t fallback) { const char *end, *pos, *c; @@ -540,7 +527,7 @@ search_match_fuzzy(size_t start, int dir, ssize_t index; if (!searchlen) { - index = start + dir * (new + cnt - 1); + index = start + dir * (ssize_t) (new + cnt - 1); if (index < 0 || index >= entries_cnt) return fallback; return index; @@ -548,16 +535,16 @@ search_match_fuzzy(size_t start, int dir, found = 0; for (i = new; i < entries_cnt; i++) { - index = start + dir * i; + index = start + dir * (ssize_t) i; if (index < 0 || index >= entries_cnt) break; - entry = read_entry(entry, index); - end = entry + entry_len(index); + entry = read_entry(entry, (size_t) index); + end = entry + entry_len((size_t) index); pos = entry; for (c = searchbuf; c - searchbuf < searchlen; c++) { - pos = search_find(pos, *c, end - pos); + pos = search_find(pos, *c, (size_t) (end - pos)); if (!pos) break; pos++; } @@ -570,14 +557,13 @@ search_match_fuzzy(size_t start, int dir, return fallback; } -void +static void load_entries(const char *filepath) { size_t pos, start; - ssize_t nread; + size_t nread; char iobuf[1024]; - entries_cnt = 0; entries_cap = 100; entries = calloc(entries_cap, sizeof(size_t)); if (!entries) err(1, "alloc"); @@ -587,20 +573,18 @@ load_entries(const char *filepath) if (!infile) err(1, "tmpfile"); start = pos = 0; - while (true) { - nread = freadln(iobuf, sizeof(iobuf), stdin); - if (nread <= 0) break; - + while (fgets(iobuf, sizeof(iobuf), stdin)) { + nread = strlen(iobuf); pos += nread; if (fwrite(iobuf, 1, nread, infile) != nread) errx(1, "fwrite to tmpfile truncated"); if (iobuf[nread - 1] == '\n') { - add_entry(entries_cnt, start); + add_entry(start); entries_cnt++; start = pos; } } - add_entry(entries_cnt, pos); + add_entry(pos); fseek(infile, 0, SEEK_SET); @@ -613,24 +597,22 @@ load_entries(const char *filepath) if (!infile) err(1, "fopen %s", filepath); start = pos = 0; - while (true) { - nread = freadln(iobuf, sizeof(iobuf), infile); - if (nread <= 0) break; - + while (fgets(iobuf, sizeof(iobuf), infile)) { + nread = strlen(iobuf); pos += nread; if (iobuf[nread - 1] == '\n') { - add_entry(entries_cnt, start); + add_entry(start); entries_cnt++; start = pos; } } - add_entry(entries_cnt, pos); + add_entry(pos); fseek(infile, 0, SEEK_SET); } } -void +static void run(const char *filepath) { struct termios prevterm, newterm = { 0 }; @@ -644,7 +626,7 @@ run(const char *filepath) if (!entries_cnt) return; - if (tcgetattr(fileno(stdin), &prevterm)) + if (tcgetattr(fileno(stderr), &prevterm)) err(1, "tcgetattr"); cfmakeraw(&newterm); @@ -689,9 +671,9 @@ run(const char *filepath) case KEY_CTRL('J'): case '\r': if (selected < 0) break; - entry = read_entry(entry, selected); + entry = read_entry(entry, (size_t) selected); modes[mode].cleanup(); - printf("%.*s\n", (int) entry_len(selected), entry); + printf("%.*s\n", (int) entry_len((size_t) selected), entry); if (!multiout) goto exit; break; default: @@ -711,7 +693,7 @@ exit: fclose(infile); } -int +static int parseopt(const char *flag, const char **args) { char *end; @@ -734,11 +716,11 @@ parseopt(const char *flag, const char **args) prompt = false; return 0; case 'a': - fwdctx = strtol(*args, &end, 10); + fwdctx = strtoull(*args, &end, 10); if (end && *end) goto badint; return 1; case 'b': - bwdctx = strtol(*args, &end, 10); + bwdctx = strtoull(*args, &end, 10); if (end && *end) goto badint; return 1; case 'h': @@ -762,9 +744,6 @@ main(int argc, const char **argv) setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); - entry = NULL; - entries = NULL; - filepath = NULL; for (i = 1; i < argc; i++) { if (*argv[i] == '-') {