bestline: Implement bestlineFile to override stdin/stdout

This commit is contained in:
Ivan Baravy 2023-01-29 20:00:39 +00:00
parent b5a345ad5f
commit d8ce095598
2 changed files with 22 additions and 16 deletions

View File

@ -132,7 +132,9 @@
#include "bestline.h" #include "bestline.h"
#ifndef __COSMOPOLITAN__ #ifndef __COSMOPOLITAN__
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 1 /* so GCC builds in ANSI mode */ #define _POSIX_C_SOURCE 1 /* so GCC builds in ANSI mode */
#endif
#define _XOPEN_SOURCE 700 /* so GCC builds in ANSI mode */ #define _XOPEN_SOURCE 700 /* so GCC builds in ANSI mode */
#define _DARWIN_C_SOURCE 1 /* so SIGWINCH / IUTF8 on XNU */ #define _DARWIN_C_SOURCE 1 /* so SIGWINCH / IUTF8 on XNU */
#include <termios.h> #include <termios.h>
@ -2187,12 +2189,10 @@ static void bestlineRingRotate(void) {
static char *bestlineRefreshHints(struct bestlineState *l) { static char *bestlineRefreshHints(struct bestlineState *l) {
char *hint; char *hint;
struct abuf ab; struct abuf ab;
const char *ansi1, *ansi2; const char *ansi1 = "\033[90m", *ansi2 = "\033[39m";
if (!hintsCallback) return 0; if (!hintsCallback) return 0;
if (!(hint = hintsCallback(l->buf, &ansi1, &ansi2))) return 0; if (!(hint = hintsCallback(l->buf, &ansi1, &ansi2))) return 0;
abInit(&ab); abInit(&ab);
ansi1 = "\033[90m";
ansi2 = "\033[39m";
if (ansi1) abAppends(&ab, ansi1); if (ansi1) abAppends(&ab, ansi1);
abAppends(&ab, hint); abAppends(&ab, hint);
if (ansi2) abAppends(&ab, ansi2); if (ansi2) abAppends(&ab, ansi2);
@ -3403,33 +3403,36 @@ char *bestlineRaw(const char *prompt, int infd, int outfd) {
* contain ansi escape sequences, color, utf8, etc. * contain ansi escape sequences, color, utf8, etc.
* @return chomped allocated string of read line or null on eof/error * @return chomped allocated string of read line or null on eof/error
*/ */
char *bestline(const char *prompt) { char *bestlineFile(const char *prompt, FILE *fin, FILE *fout) {
if (prompt && *prompt && if (prompt && *prompt &&
(strchr(prompt, '\n') || strchr(prompt, '\t') || (strchr(prompt, '\n') || strchr(prompt, '\t') ||
strchr(prompt + 1, '\r'))) { strchr(prompt + 1, '\r'))) {
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
if ((!isatty(fileno(stdin)) || if ((!isatty(fileno(fin)) ||
!isatty(fileno(stdout)))) { !isatty(fileno(fout)))) {
if (prompt && *prompt && (IsCharDev(fileno(stdin)) && if (prompt && *prompt && (IsCharDev(fileno(fin)) &&
IsCharDev(fileno(stdout)))) { IsCharDev(fileno(fout)))) {
fputs(prompt,stdout); fputs(prompt,fout);
fflush(stdout); fflush(fout);
} }
return GetLine(stdin, stdout); return GetLine(fin, fout);
} else if (bestlineIsUnsupportedTerm()) { } else if (bestlineIsUnsupportedTerm()) {
if (prompt && *prompt) { if (prompt && *prompt) {
fputs(prompt,stdout); fputs(prompt,fout);
fflush(stdout); fflush(fout);
} }
return GetLine(stdin, stdout); return GetLine(fin, fout);
} else { } else {
fflush(stdout); fflush(fout);
return bestlineRaw(prompt,fileno(stdin),fileno(stdout)); return bestlineRaw(prompt,fileno(fin),fileno(fout));
} }
} }
char *bestline(const char *prompt) {
return bestlineFile(prompt, stdin, stdout);
}
/** /**
* Reads line intelligently w/ history, e.g. * Reads line intelligently w/ history, e.g.
* *

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <stdio.h>
typedef struct bestlineCompletions { typedef struct bestlineCompletions {
unsigned long len; unsigned long len;
char **cvec; char **cvec;
@ -17,6 +19,7 @@ void bestlineSetFreeHintsCallback(bestlineFreeHintsCallback *);
void bestlineAddCompletion(bestlineCompletions *, const char *); void bestlineAddCompletion(bestlineCompletions *, const char *);
void bestlineSetXlatCallback(bestlineXlatCallback *); void bestlineSetXlatCallback(bestlineXlatCallback *);
char *bestlineFile(const char *, FILE *, FILE *);
char *bestline(const char *); char *bestline(const char *);
char *bestlineRaw(const char *, int, int); char *bestlineRaw(const char *, int, int);
char *bestlineWithHistory(const char *, const char *); char *bestlineWithHistory(const char *, const char *);