Optimize startup, HTTP/SSE streaming, and fix macOS libedit bindings

This commit is contained in:
Luxferre
2026-10-14 15:30:12 +03:00
parent 105d283e01
commit a1d5f4bf48
10 changed files with 497 additions and 222 deletions
+34 -14
View File
@@ -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;
}