aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nnoll523@gmail.com>2021-10-29 16:21:35 -0700
committerNicholas Noll <nnoll523@gmail.com>2021-10-29 16:21:35 -0700
commit5d1e21d28a93415b66401d27a30ee8eb6b2b66a8 (patch)
tree05915cb47dc9a5208f4b969587b496f831562f94
parent6db99f51209ebde97311df3aac081f82589319cb (diff)
checkin
-rw-r--r--include/libunicode.h1
-rw-r--r--sys/cmd/rc/input.c68
-rw-r--r--sys/cmd/rc/prompt.c9
-rw-r--r--sys/cmd/rules.mk4
-rw-r--r--sys/libunicode/rules.mk2
-rw-r--r--sys/libunicode/vendor/mkrunewidth.c113
6 files changed, 166 insertions, 31 deletions
diff --git a/include/libunicode.h b/include/libunicode.h
index 773f9ab..d6618eb 100644
--- a/include/libunicode.h
+++ b/include/libunicode.h
@@ -16,6 +16,7 @@ typedef uint32 rune;
*/
int utf8·len(char *s); // returns number of runes for s
int utf8·runelen(rune r); // returns number of bytes for rune
+int utf8·runewidth(rune r); // returns number of printed columns for rune
int utf8·decode(char *, rune *); // decode 1 rune from char stream, store into rune, return number of bytes
int utf8·encode(rune *, char *); // encode 1 rune from rune stream, store into char, return number of bytes
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<NumRunes; c++){
if(table.width[0][c] + table.width[1][c] + table.width[2][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"
+ "}"
+ );
}