aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ask.c89
1 files changed, 59 insertions, 30 deletions
diff --git a/ask.c b/ask.c
index 04b9196..0593070 100644
--- a/ask.c
+++ b/ask.c
@@ -68,39 +68,56 @@ static int matches(const char *str, const char *patt)
return 1;
}
-static void draw_line(FILE *out, const char *line, const char *patt, int cursor, int stop_at_cursor)
+static int fputc_escaped(char c, FILE *out)
+{
+ static const char *escapes = " abtnvfr e";
+ if (c > 0 && c <= '\x1b' && escapes[(int)c] != ' ') { // "\n", etc.
+ fprintf(out, "\033[35m\\%c\033[37m", escapes[(int)c]);
+ return 2;
+ } else if (c >= 0 && !(' ' <= c && c <= '~')) { // "\x02", etc.
+ fprintf(out, "\033[35m\\x%02X\033[37m", c);
+ return 4;
+ } else {
+ fputc(c, out);
+ return 1;
+ }
+}
+
+static int draw_line(FILE *out, const char *line, const char *patt, int cursor)
{
size_t linelen = strlen(line), patlen = strlen(patt);
int dim = 0;
int p = 0;
int run = 0;
int *cache = calloc((linelen+1)*(patlen+1), sizeof(int));
- if (patlen == 0 && stop_at_cursor)
- return;
+ int backtrack = 0;
+ int to_start = 0;
for (int i = 0; i < (int)linelen; i++) {
if (EQ(patt[p], line[i]) &&
run + lcs(line,patt,(int)linelen,(int)patlen,i,p,cache)
>= lcs(line,patt,(int)linelen,(int)patlen,i+1,p,cache)) {
if (dim) {
- fputs("\033[22m", out);
+ fputs("\033[22;1m", out);
dim = 0;
}
- if (cursor == p && stop_at_cursor)
- return;
- fputc(patt[p], out);
+ int len = fputc_escaped(line[i], out);
+ if (p >= cursor) backtrack += len;
+ else to_start += len;
++run;
++p;
- if (cursor == p && stop_at_cursor)
- return;
} else {
run = 0;
if (!dim) {
- fputs("\033[2m", out);
+ fputs("\033[22;2m", out);
dim = 1;
}
- fputc(line[i], out);
+ int len = fputc_escaped(line[i], out);
+ if (p >= cursor) backtrack += len;
+ else to_start += len;
}
}
+ if (backtrack) fprintf(out, "\033[0m\033[%dD", backtrack);
+ return to_start;
}
/*
@@ -108,8 +125,8 @@ static void draw_line(FILE *out, const char *line, const char *patt, int cursor,
*/
static char *get_input(FILE *in, FILE *out, const char *prompt, const char *initial, int nopts, char **opts)
{
- fputs("\0337", out);
if (!prompt) prompt = "> ";
+ fprintf(out, "\033[K\033[0;1m%s\033[0m", prompt);
size_t cap = initial ? strlen(initial) + 100 : 100;
char *buf = memcheck(calloc(cap, 1));
char *picked = NULL;
@@ -120,7 +137,7 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init
b = len;
}
- int start = 0;
+ int start = 0, backtrack = 0;
while (1) {
case_sensitive = 0;
for (const char *p = buf; *p; ++p)
@@ -144,29 +161,20 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init
if (quickpick && ncandidates == 1 && picked)
goto finished;
- fprintf(out, "\0338\033[K\033[0;1m%s\033[0m", prompt);
+ if (backtrack) fprintf(out, "\033[%dD", backtrack);
+ fputs("\033[K", out);
if (password) {
if (picked) fputs("\033[0;32m", out);
else if (nopts > 0) fputs("\033[0;31m", out);
else fputs("\033[0;2m", out);
fputc((PASSWORD)[strlen(buf) % strlen(PASSWORD)], out);
fputs("\033[0m", out);
+ backtrack = 1;
} else {
if (picked) {
- // Because stuff can have tabs and whatnot and the saved cusor
- // position is already in use, the most reliable way to make
- // sure the cursor ends up in the right place is to draw the
- // whole line, then redraw everything up to the cursor.
- draw_line(out, picked, buf, b, 0);
- fprintf(out, "\0338\033[0m\033[37;1m%s\033[0m", prompt);
- draw_line(out, picked, buf, b, 1);
+ backtrack = draw_line(out, picked, buf, b);
} else {
- if (nopts > 0)
- fprintf(out, "\033[0;31m%s\033[0m", buf);
- else
- fprintf(out, "\033[0m%s\033[0m", buf);
- if (b < (int)strlen(buf))
- fprintf(out, "\033[%dD", (int)strlen(buf) - b);
+ backtrack = draw_line(out, buf, buf, b);
}
}
fflush(out);
@@ -184,10 +192,10 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init
picked = NULL;
goto finished;
case KEY_CTRL_A:
- if (b > 0) b = 0;
+ b = 0;
break;
case KEY_CTRL_E:
- if (b < len) b = len;
+ b = len;
break;
case KEY_CTRL_U: {
int to_clear = b;
@@ -243,8 +251,29 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init
case KEY_ARROW_RIGHT: case KEY_CTRL_F:
if (b < len) ++b;
break;
+ case KEY_CTRL_Q: case KEY_CTRL_V: {
+ int nextkey;
+ while ((nextkey = bgetkey(in, NULL, NULL, -1)) < 0)
+ ;
+ if (len + 1 >= (int)cap)
+ buf = memcheck(realloc(buf, (cap += 100)));
+ if (b < len)
+ memmove(buf+b+1, buf+b, (size_t)(len-b+1));
+ buf[b++] = (char)nextkey;
+ buf[++len] = 0;
+ break;
+ }
+ case KEY_CTRL_T: {
+ if (len < 2 || b == 0) break;
+ if (b < len)
+ b++;
+ char tmp = buf[b-1];
+ buf[b-1] = buf[b-2];
+ buf[b-2] = tmp;
+ break;
+ }
default:
- if (' ' <= key && key <= '~') {
+ if ((' ' <= key && key <= '~') || key == '\t') {
if (len + 1 >= (int)cap)
buf = memcheck(realloc(buf, (cap += 100)));
if (b < len)