Optimize startup, HTTP/SSE streaming, and fix macOS libedit bindings
This commit is contained in:
+34
-14
@@ -55,13 +55,41 @@ std::string read_plain(std::string_view prompt, bool &ok) {
|
||||
}
|
||||
|
||||
/* ----------------------------- readline editor ------------------------ */
|
||||
static void ensure_readline_init() {
|
||||
static bool initialized = false;
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
rl_initialize();
|
||||
#if !defined(__APPLE__) && defined(RL_READLINE_VERSION) && (RL_READLINE_VERSION >= 0x0500)
|
||||
/* On GNU Readline (Linux, FreeBSD), terminal raw mode clears ICRNL so
|
||||
* Enter sends '\r' (rl_newline = submit) while Ctrl+J sends '\n'
|
||||
* (rl_insert = literal newline). On macOS / BSD libedit (EditLine),
|
||||
* ICRNL remains enabled in termios (translating Enter '\r' into '\n') and
|
||||
* '\n' is the sole accept-line key (ed-newline), so rebinding '\n' to
|
||||
* rl_insert prevents submitting any prompt. */
|
||||
if (!rl_library_version || std::strncmp(rl_library_version, "EditLine", 8) != 0) {
|
||||
rl_bind_key('\n', rl_insert);
|
||||
rl_bind_key('\r', rl_newline);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string read_line(std::string_view prompt, bool &ok) {
|
||||
if (!is_terminal(STDIN_FILENO)) return read_plain(prompt, ok);
|
||||
/* Enter (\r) submits the line; Ctrl+J inserts a literal newline so a
|
||||
* multi-line prompt can be composed before submitting. */
|
||||
rl_bind_key('\n', rl_insert);
|
||||
ensure_readline_init();
|
||||
char *line = readline(prompt.empty() ? "" : std::string(prompt).c_str());
|
||||
if (!line) { ok = false; return ""; }
|
||||
setup_signal_handler();
|
||||
if (!line) {
|
||||
if (g_interrupted) {
|
||||
g_interrupted = 0;
|
||||
std::fputc('\n', stdout);
|
||||
std::fflush(stdout);
|
||||
ok = true;
|
||||
return "";
|
||||
}
|
||||
ok = false;
|
||||
return "";
|
||||
}
|
||||
std::string r(line);
|
||||
free(line);
|
||||
ok = true;
|
||||
@@ -74,19 +102,11 @@ int is_terminal(int fd) { return isatty(fd) != 0; }
|
||||
int term_width() {
|
||||
#ifdef TIOCGWINSZ
|
||||
struct winsize ws{};
|
||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0) return (int)ws.ws_col;
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0) return (int)ws.ws_col;
|
||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0) return (int)ws.ws_col;
|
||||
if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0) return (int)ws.ws_col;
|
||||
#endif
|
||||
const char *c = std::getenv("COLUMNS");
|
||||
if (c && *c) { int n = std::atoi(c); if (n > 0) return n; }
|
||||
FILE *p = popen("tput cols 2>/dev/null", "r");
|
||||
if (p) {
|
||||
char buf[32];
|
||||
if (fgets(buf, sizeof buf, p)) {
|
||||
int n = std::atoi(buf);
|
||||
pclose(p);
|
||||
if (n > 0) return n;
|
||||
} else pclose(p);
|
||||
}
|
||||
return 80;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user