hirc

IRC client
Log | Files | Refs

commit 1b58278084b28df1198cbb9b15788d1dd5be9760
parent 62e61abbba4e8b51e10446b7e6da5002f6b0c5b4
Author: hhvn <dev@hhvn.uk>
Date:   Fri, 25 Feb 2022 16:03:58 +0000

Implement string tokenization using %{split:n,c,...} formatting

Diffstat:
Mhirc.1.header | 2++
Msrc/hirc.h | 1+
Msrc/main.c | 16++++++++++++++++
Msrc/ui.c | 35+++++++++++++++++++++++++++++++++--
4 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/hirc.1.header b/hirc.1.header @@ -53,6 +53,8 @@ Set/reset underline. Place divider here. If disabled, acts like space. .It %{pad:n,...} Pad string to n length. Positive pads to the left, negative to the right. +.It %{split:n,c,...} +Split string using character c, and print nth element. .El Certain variables may also be used in formats: diff --git a/src/hirc.h b/src/hirc.h @@ -52,6 +52,7 @@ char * homepath(char *path); char chrcmp(char c, char *s); char * struntil(char *str, char until); int strisnum(char *str); +char * strntok(char *str, char *sep, int n); /* chan.c */ void chan_free(struct Channel *channel); diff --git a/src/main.c b/src/main.c @@ -349,6 +349,22 @@ strisnum(char *str) { return 1; } +char * +strntok(char *str, char *sep, int n) { + static char buf[8192]; + char *ret, *save; + + strlcpy(buf, str, sizeof(buf)); + + ret = strtok_r(buf, sep, &save); + if (--n == 0) + return ret; + while ((ret = strtok_r(NULL, sep, &save)) != NULL) + if (--n == 0) + return ret; + return NULL; +} + void sighandler(int signal) { return; diff --git a/src/ui.c b/src/ui.c @@ -1235,9 +1235,10 @@ ui_format(struct Window *window, char *format, struct History *hist) { int rhs = 0; int divider = 0; char **params; - char *content, *p; + char *content, *p, *p2; char *ts, *save; char colourbuf[2][3]; + char chs[2]; enum { sub_raw, sub_cmd, @@ -1456,7 +1457,7 @@ ui_format(struct Window *window, char *format, struct History *hist) { break; } - /* pad: and nick: must come last as it modifies content */ + /* pad, nick and split must then continue as they modify content */ if (strncmp(content, "pad:", strlen("pad:")) == 0 && strchr(content, ',')) { pn = strtol(content + strlen("pad:"), NULL, 10); content = estrdup(ui_format_get_content(strchr(format+2+strlen("pad:"), ',') + 1, 1)); @@ -1474,6 +1475,36 @@ ui_format(struct Window *window, char *format, struct History *hist) { continue; } + /* second comma ptr - second comma ptr = distance. + * If the distance is 2, then there is one non-comma char between. */ + p = strchr(content, ','); + if (p) + p2 = strchr(p + 1, ','); + if (strncmp(content, "split:", strlen("split:")) == 0 && p2 - p == 2) { + pn = strtol(content + strlen("split:"), NULL, 10); + chs[0] = *(strchr(content, ',') + 1); + chs[1] = '\0'; + content = estrdup(ui_format_get_content( + strchr( + strchr(format+2+strlen("split:"), ',') + 1, + ',') + 1, + 1)); + save = estrdup(ret); + recursive = 1; + p = estrdup(ui_format(NULL, content, hist)); + recursive = 0; + memcpy(ret, save, rc); + rc += snprintf(&ret[rc], sizeof(ret) - rc, "%s", strntok(p, chs, pn)); + format = strchr( + strchr(format+2+strlen("split:"), ',') + 1, + ',') + strlen(content) + 2; + + free(content); + free(save); + free(p); + continue; + } + if (hist && !recursive && strncmp(content, "nick:", strlen("nick:")) == 0) { content = estrdup(ui_format_get_content(format+2+strlen("nick:"), 1)); save = estrdup(ret); /* save ret, as this will be modified by recursing */