Supporting using ask
in the middle of a line without erasing the line.
This commit is contained in:
parent
982d4100ab
commit
03dd8d56f3
55
ask.c
55
ask.c
@ -68,15 +68,15 @@ static int matches(const char *str, const char *patt)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_line(FILE *out, const char *line, const char *patt, int cursor)
|
static void draw_line(FILE *out, const char *line, const char *patt, int cursor, int stop_at_cursor)
|
||||||
{
|
{
|
||||||
size_t linelen = strlen(line), patlen = strlen(patt);
|
size_t linelen = strlen(line), patlen = strlen(patt);
|
||||||
int dim = 0;
|
int dim = 0;
|
||||||
int p = 0;
|
int p = 0;
|
||||||
int run = 0;
|
int run = 0;
|
||||||
int *cache = calloc((linelen+1)*(patlen+1), sizeof(int));
|
int *cache = calloc((linelen+1)*(patlen+1), sizeof(int));
|
||||||
if (cursor >= (int)patlen)
|
if (patlen == 0 && stop_at_cursor)
|
||||||
fputs("\0337", out);
|
return;
|
||||||
for (int i = 0; i < (int)linelen; i++) {
|
for (int i = 0; i < (int)linelen; i++) {
|
||||||
if (EQ(patt[p], line[i]) &&
|
if (EQ(patt[p], line[i]) &&
|
||||||
run + lcs(line,patt,(int)linelen,(int)patlen,i,p,cache)
|
run + lcs(line,patt,(int)linelen,(int)patlen,i,p,cache)
|
||||||
@ -85,11 +85,13 @@ static void draw_line(FILE *out, const char *line, const char *patt, int cursor)
|
|||||||
fputs("\033[22m", out);
|
fputs("\033[22m", out);
|
||||||
dim = 0;
|
dim = 0;
|
||||||
}
|
}
|
||||||
|
if (cursor == p && stop_at_cursor)
|
||||||
|
return;
|
||||||
fputc(patt[p], out);
|
fputc(patt[p], out);
|
||||||
++run;
|
++run;
|
||||||
++p;
|
++p;
|
||||||
if (cursor == p)
|
if (cursor == p && stop_at_cursor)
|
||||||
fputs("\0337", out);
|
return;
|
||||||
} else {
|
} else {
|
||||||
run = 0;
|
run = 0;
|
||||||
if (!dim) {
|
if (!dim) {
|
||||||
@ -99,7 +101,6 @@ static void draw_line(FILE *out, const char *line, const char *patt, int cursor)
|
|||||||
fputc(line[i], out);
|
fputc(line[i], out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fputs("\0338", out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -107,39 +108,35 @@ 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)
|
static char *get_input(FILE *in, FILE *out, const char *prompt, const char *initial, int nopts, char **opts)
|
||||||
{
|
{
|
||||||
|
fputs("\0337", out);
|
||||||
|
if (!prompt) prompt = "> ";
|
||||||
size_t cap = initial ? strlen(initial) + 100 : 100;
|
size_t cap = initial ? strlen(initial) + 100 : 100;
|
||||||
char *buf = memcheck(calloc(cap, 1));
|
char *buf = memcheck(calloc(cap, 1));
|
||||||
char *picked = NULL;
|
char *picked = NULL;
|
||||||
int b = 0, len = 0;
|
int b = 0, len = 0;
|
||||||
if (initial) {
|
if (initial) {
|
||||||
if (!strcpy(buf, initial)) return NULL;
|
strcpy(buf, initial);
|
||||||
len = (int)strlen(initial);
|
len = (int)strlen(initial);
|
||||||
b = len;
|
b = len;
|
||||||
fputs(initial, out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int start = 0;
|
int start = 0;
|
||||||
// Show cursor and set to blinking line:
|
|
||||||
while (1) {
|
while (1) {
|
||||||
fputs("\033[G\033[K\033[0m", out);
|
|
||||||
if (prompt) {
|
|
||||||
fputs("\033[1G\033[K\033[37;1m", out);
|
|
||||||
fputs(prompt, out);
|
|
||||||
fputs("\033[0m", out);
|
|
||||||
}
|
|
||||||
case_sensitive = 0;
|
case_sensitive = 0;
|
||||||
for (const char *p = buf; *p; ++p)
|
for (const char *p = buf; *p; ++p)
|
||||||
case_sensitive |= ('A' <= *p && *p <= 'Z');
|
case_sensitive |= ('A' <= *p && *p <= 'Z');
|
||||||
|
|
||||||
int ncandidates = 0;
|
int ncandidates = 0;
|
||||||
picked = NULL;
|
picked = NULL;
|
||||||
for (int i = 0; i < nopts; i++) {
|
if (buf[0]) {
|
||||||
int j = (start + i) % nopts;
|
for (int i = 0; i < nopts; i++) {
|
||||||
if (matches(opts[j], buf)) {
|
int j = (start + i) % nopts;
|
||||||
++ncandidates;
|
if (matches(opts[j], buf)) {
|
||||||
if (!picked) {
|
++ncandidates;
|
||||||
picked = opts[j];
|
if (!picked) {
|
||||||
start = j;
|
picked = opts[j];
|
||||||
|
start = j;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,6 +144,7 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init
|
|||||||
if (quickpick && ncandidates == 1 && picked)
|
if (quickpick && ncandidates == 1 && picked)
|
||||||
goto finished;
|
goto finished;
|
||||||
|
|
||||||
|
fprintf(out, "\0338\033[K\033[0;1m%s\033[0m", prompt);
|
||||||
if (password) {
|
if (password) {
|
||||||
if (picked) fputs("\033[0;32m", out);
|
if (picked) fputs("\033[0;32m", out);
|
||||||
else if (nopts > 0) fputs("\033[0;31m", out);
|
else if (nopts > 0) fputs("\033[0;31m", out);
|
||||||
@ -155,7 +153,13 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init
|
|||||||
fputs("\033[0m", out);
|
fputs("\033[0m", out);
|
||||||
} else {
|
} else {
|
||||||
if (picked) {
|
if (picked) {
|
||||||
draw_line(out, picked, buf, b);
|
// 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);
|
||||||
} else {
|
} else {
|
||||||
if (nopts > 0)
|
if (nopts > 0)
|
||||||
fprintf(out, "\033[0;31m%s\033[0m", buf);
|
fprintf(out, "\033[0;31m%s\033[0m", buf);
|
||||||
@ -254,6 +258,7 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init
|
|||||||
finished:
|
finished:
|
||||||
if (picked) picked = memcheck(strdup(picked));
|
if (picked) picked = memcheck(strdup(picked));
|
||||||
else picked = buf;
|
else picked = buf;
|
||||||
|
fputs("\0338\033[0m\033[K", out);
|
||||||
return picked;
|
return picked;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +318,6 @@ int main(int argc, char *argv[])
|
|||||||
++a;
|
++a;
|
||||||
}
|
}
|
||||||
if (!prompt && a < argc) prompt = argv[a++];
|
if (!prompt && a < argc) prompt = argv[a++];
|
||||||
if (!prompt) prompt = "> ";
|
|
||||||
|
|
||||||
while (a < argc) {
|
while (a < argc) {
|
||||||
if ((size_t)nlines >= linescap)
|
if ((size_t)nlines >= linescap)
|
||||||
@ -323,7 +327,6 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
char *output = get_input(tty_in, tty_out, prompt, initial, nlines, lines);
|
char *output = get_input(tty_in, tty_out, prompt, initial, nlines, lines);
|
||||||
|
|
||||||
fputs("\033[G\033[K\033[0m", tty_out);
|
|
||||||
fflush(tty_out);
|
fflush(tty_out);
|
||||||
tcsetattr(fileno(tty_out), TCSAFLUSH, &orig_termios);
|
tcsetattr(fileno(tty_out), TCSAFLUSH, &orig_termios);
|
||||||
fclose(tty_out);
|
fclose(tty_out);
|
||||||
@ -333,7 +336,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (!output) return 1;
|
if (!output) return 1;
|
||||||
|
|
||||||
puts(output);
|
fputs(output, stdout);
|
||||||
free(output);
|
free(output);
|
||||||
|
|
||||||
// This doesn't free the memory in lines, but it doesn't need to because
|
// This doesn't free the memory in lines, but it doesn't need to because
|
||||||
|
Loading…
Reference in New Issue
Block a user