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:
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 */