From 5d1e21d28a93415b66401d27a30ee8eb6b2b66a8 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Fri, 29 Oct 2021 16:21:35 -0700 Subject: checkin --- sys/cmd/rc/input.c | 68 +++++++++++++++------- sys/cmd/rc/prompt.c | 9 +-- sys/cmd/rules.mk | 4 +- sys/libunicode/rules.mk | 2 +- sys/libunicode/vendor/mkrunewidth.c | 113 +++++++++++++++++++++++++++++++++++- 5 files changed, 165 insertions(+), 31 deletions(-) (limited to 'sys') diff --git a/sys/cmd/rc/input.c b/sys/cmd/rc/input.c index 8ca3145..08363f0 100644 --- a/sys/cmd/rc/input.c +++ b/sys/cmd/rc/input.c @@ -133,7 +133,7 @@ insertcursor(int fd) write(fd,"\e[6 q",5); } -/* Raw mode: 1960 magic shit. */ +/* raw mode: 1960 magic shit. */ static int enterraw(int fd) @@ -143,7 +143,7 @@ enterraw(int fd) if(!shell.interactive) goto fatal; - if(!mode.defer) { + if(!mode.defer){ atexit(doatexit); mode.defer = 1; } @@ -167,7 +167,9 @@ enterraw(int fd) raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ /* put terminal in raw mode after flushing */ - if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal; + if(tcsetattr(fd,TCSAFLUSH,&raw) < 0) + goto fatal; + mode.raw = 1; return 1; @@ -180,13 +182,13 @@ static void exitraw(int fd) { - /* Don't even check the return value as it's too late. */ + /* don't even check the return value as it's too late. */ if(mode.raw && tcsetattr(fd,TCSAFLUSH,&originalterm) != -1) mode.raw = 0; } -/* Use the ESC [6n escape sequence to query the horizontal cursor position - * and return it. On error -1 is returned, on success the position of the +/* use the esc [6n escape sequence to query the horizontal cursor position + * and return it. on error -1 is returned, on success the position of the * cursor. */ static int @@ -325,7 +327,7 @@ refreshsingleline(struct TerminalState *term) char esc[64]; struct Buffer ab; - int n; + int n, w; rune r; int fd = term->ofd; intptr off = term->prompt.size; @@ -334,13 +336,12 @@ refreshsingleline(struct TerminalState *term) intptr pos = term->cursor.pos; intptr col = term->cursor.len; - assert(col); - assert(off); - while((off+pos) >= term->cursor.cap){ n = utf8·decode(buf, &r); + w = utf8·runewidth(r); + buf+=n, len-=n; - pos--, col--; + pos-=w, col-=w; } assert(buf <= term->edit.buf + len); @@ -481,19 +482,18 @@ refreshline(struct TerminalState *term) int insertrune(struct TerminalState *term, int n, char *c) { + int w; rune r; + utf8·decode(c, &r); + w = utf8·runewidth(r); + if(term->edit.len + n <= term->edit.cap){ if(term->edit.pos == term->edit.len){ memcpy(term->edit.buf+term->edit.pos, c, n); - term->edit.pos+=n, term->edit.len+=n; - term->cursor.pos++, term->cursor.len++; - - utf8·decode(c, &r); - if(wcwidth(r) < 1){ - exit(1); - } + term->edit.pos += n, term->edit.len += n; + term->cursor.pos += w, term->cursor.len += w; term->edit.buf[term->edit.len] = '\0'; @@ -968,6 +968,33 @@ action: #define END(term) (Position){(term).edit.len, (term).cursor.len} +static +int +size(char *s) +{ + rune c; + int n, len = 0;; + while((c=*s)){ + if(c == '\033'){ + n = 1; + esccode: + c = s[n]; + if(!c) // we hit end of string in the middle of parsing an escape code! + return len; + if(c == 'm'){ + s += n + 1; + continue; // outer loop + } + n++; + goto esccode; + } + n = utf8·decode(s, &c); + s += n; + len += utf8·runewidth(c); + } + return len; +} + /* this function is the core of the line editing capability of linenoise. * it expects 'fd' to be already in "raw mode" so that every key pressed * will be returned asap to read(). @@ -1000,7 +1027,7 @@ interact(int ifd, int ofd, char *buf, intptr len, char *prompt) term.prompt.s = prompt; term.prompt.len = strlen(prompt); - term.prompt.size = utf8·len(prompt); + term.prompt.size = size(prompt); term.cursor.pos = 0; term.cursor.len = 0; @@ -1271,8 +1298,7 @@ printkeycode(void) } /* - * This function calls the line editing function edit() using - * the stdin set in raw mode + * this function calls the line editing function edit() using the stdin set in raw mode */ static int diff --git a/sys/cmd/rc/prompt.c b/sys/cmd/rc/prompt.c index 6a32d59..ebda9fb 100644 --- a/sys/cmd/rc/prompt.c +++ b/sys/cmd/rc/prompt.c @@ -1,11 +1,12 @@ #include "rc.h" -static char promptbuf[7] = {'>', ' ', 0, ' ' , ' ', ' ', 0}; +/* static char promptbuf[7] = {'>', ' ', 0, ' ' , ' ', ' ', 0}; */ +static char *base= "\x1b[1;31m" ">" "\x1b[0;0m" " ", *promptstr; void resetprompt(void) { - promptbuf[2] = 0; + promptstr = base; } int @@ -14,13 +15,13 @@ prompt(ushort *flag) int f = *flag; if(f){ - if(!readline(promptbuf)){ + if(!readline(promptstr)){ runner->flag.eof = 1; return 0; } write(mapfd(0), "\n\r", 2); - promptbuf[2] = ' '; + promptstr = " "; runner->line++; *flag = 0; diff --git a/sys/cmd/rules.mk b/sys/cmd/rules.mk index 026e212..07adaf1 100644 --- a/sys/cmd/rules.mk +++ b/sys/cmd/rules.mk @@ -14,8 +14,8 @@ include $(DIR)/rules.mk DIR := $(d)/filter include $(DIR)/rules.mk -DIR := $(d)/test -include $(DIR)/rules.mk +# DIR := $(d)/test +# include $(DIR)/rules.mk DIR := $(d)/dwm include $(DIR)/rules.mk diff --git a/sys/libunicode/rules.mk b/sys/libunicode/rules.mk index 5ba9b89..acfce32 100644 --- a/sys/libunicode/rules.mk +++ b/sys/libunicode/rules.mk @@ -48,7 +48,7 @@ $(d)/vendor/mkrunewidth: $(d)/vendor/mkrunewidth.c $(d)/vendor/common.o $(OBJ_DI GENS += $(d)/vendor/mkrunewidth $(d)/runewidth-$(UNICODE).c: $(d)/vendor/mkrunewidth $(d)/vendor/UnicodeData-$(UNICODE).txt $(d)/vendor/EastAsianWidth-$(UNICODE).txt - @$(dir $@)vendor/mkrunewidth $(filter-out $<, $^) #> $@ + @$(dir $@)vendor/mkrunewidth $(filter-out $<, $^) > $@ # grapheme boundaries $(d)/vendor/GraphemeBreakProperty-$(UNICODE).txt: diff --git a/sys/libunicode/vendor/mkrunewidth.c b/sys/libunicode/vendor/mkrunewidth.c index d821863..43feb5e 100644 --- a/sys/libunicode/vendor/mkrunewidth.c +++ b/sys/libunicode/vendor/mkrunewidth.c @@ -136,6 +136,76 @@ parse_eawidths(char *path) io·close(utf8); } +static +void +maketable(char *label, char *table, int pairs, int onlyranges) +{ + int r, p=0, s=0; + char ident[3][128]; + + enum + { + Irange, + Ipair, + Isingle, + }; + + /* ranges */ + if(snprintf(ident[Irange], arrlen(ident[Irange]), "%s_range", label) == arrlen(ident[Irange])) + panicf("out of identifier space\n"); + r = putrange(ident[Irange], table, onlyranges); + + if(!onlyranges && pairs){ + if(snprintf(ident[Ipair], arrlen(ident[Ipair]), "%s_pair", label) == arrlen(ident[Ipair])) + panicf("out of identifier space\n"); + p = putpair(ident[Ipair], table); + } + if(!onlyranges){ + if(snprintf(ident[Isingle], arrlen(ident[Isingle]), "%s_single", label) == arrlen(ident[Isingle])) + panicf("out of identifier space\n"); + + s = putsingle(ident[Isingle], table); + } + + printf( + "static int\n" + "is%s(rune c)\n" + "{\n" + " rune *p;\n" + "\n", + label); + + if(r){ + printf( + " p = rangesearch(c, %s, arrlen(%s)/2, 2);\n" + " if(p && c >= p[0] && c <= p[1])\n" + " return 1;\n", + ident[Irange], ident[Irange]); + } + + if(p){ + printf( + " p = rangesearch(c, %s, arrlen(%s)/2, 2);\n" + " if(p && c >= p[0] && c <= p[1] && !((c - p[0]) & 1))\n" + " return 1;\n", + ident[Ipair], ident[Ipair]); + } + + if(s) + printf( + " p = rangesearch(c, %s, arrlen(%s), 1);\n" + " if(p && c == p[0])\n" + " return 1;\n", + ident[Isingle], ident[Isingle]); + + printf( + " return 0;\n" + "}\n" + "\n"); +} + + + // ----------------------------------------------------------------------- // main point of entry @@ -147,6 +217,22 @@ usage(void) exit(1); } +#define SETW0(c) \ + table.width[0][(c)] = 1, \ + table.width[1][(c)] = 0, \ + table.width[2][(c)] = 0; + +#define SETW1(c) \ + table.width[0][(c)] = 0, \ + table.width[1][(c)] = 1, \ + table.width[2][(c)] = 0; + +#define SETW2(c) \ + table.width[0][(c)] = 0, \ + table.width[1][(c)] = 0, \ + table.width[2][(c)] = 1; + + int main(int argc, char *argv[]) { @@ -161,13 +247,34 @@ main(int argc, char *argv[]) parse_category(*argv++); parse_eawidths(*argv); + /* overrides */ + SETW0(0x2028); + SETW0(0x2029); + + SETW1(0x00AD); + /* simple checking */ for(c=0; c 1) panicf("improper table state"); } - putrange("zero", table.width[0], 1); - putrange("single", table.width[1], 1); - putrange("double", table.width[2], 1); + putsearch(); + + maketable("width0", table.width[0], 1, 0); + maketable("width1", table.width[1], 1, 0); + maketable("width2", table.width[2], 1, 0); + + puts( + "\n" + "int\n" + "utf8·runewidth(rune c)\n" + "{\n" + " if(iswidth1(c))\n" + " return 1;\n" + " if(iswidth2(c))\n" + " return 2;\n" + " return 0;\n" + "}" + ); } -- cgit v1.2.1