xF: push huge logs directly to external editors
Alpine 3.24 Success
Arch Linux AUR Success
OpenBSD 7.8 Success

At around 10 megabytes, processing starts taking quite long.

It might be a good idea to remove the log view altogether now;
it's only there because we copied other frontends.
This commit is contained in:
2026-08-09 18:13:43 +02:00
parent 9f1ef95f46
commit 800a4e354c
+46 -34
View File
@@ -422,7 +422,8 @@ struct log_view
char *buffer_name; ///< Stamp: the buffer we want logs for
bool visible; ///< We see the log rather than backlog
ARRAY (struct buffer_line *, lines) ///< Log split into display lines
struct buffer_line **lines; ///< Log split into display lines
size_t lines_len; ///< Number of lines
int offset; ///< XUI pixels above the bottom
};
@@ -1123,6 +1124,9 @@ app_process_completion_response
// ~~~ Log request ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static bool app_launch_external_editor (const char *template_name,
const char *contents, size_t contents_len, bool viewing_transcript);
static void
log_view_request_start (struct log_view *self, uint32_t request_seq,
const char *buffer_name)
@@ -1149,7 +1153,7 @@ log_view_hide (struct log_view *self)
buffer_line_destroy (self->lines[i]);
free (self->lines);
self->lines = NULL;
self->lines_len = self->lines_alloc = 0;
self->lines_len = 0;
self->offset = 0;
}
@@ -1161,19 +1165,18 @@ log_view_free (struct log_view *self)
}
static void
log_view_show (struct log_view *self, char *text_owned)
log_view_show (struct log_view *self, const char *text)
{
log_view_hide (self);
struct strv lines = strv_make ();
cstr_split (text_owned, "\r\n", true, &lines);
free (text_owned);
ARRAY_INIT (self->lines);
cstr_split (text, "\r\n", true, &lines);
self->lines = xcalloc (lines.len, sizeof *self->lines);
for (size_t i = 0; i < lines.len; i++)
{
struct buffer_line *line = xcalloc (1, sizeof *line);
buffer_line_add_item (line, lines.vector[i], -1, -1, 0);
buffer_line_finalize (line);
ARRAY_RESERVE (self->lines, 1);
self->lines[self->lines_len++] = line;
}
strv_free (&lines);
@@ -1186,10 +1189,15 @@ app_process_log_response (const struct relay_response_data_buffer_log *response)
if (g.buffer_current && g.log.buffer_name
&& !strcmp (g.buffer_current->buffer_name, g.log.buffer_name))
{
log_view_show (&g.log,
utf8_validate ((const char *) response->log, response->log_len)
? xstrndup ((const char *) response->log, response->log_len)
: xstrdup ("Log is not valid UTF-8."));
// We're not that performant with layouting.
const char *log = (const char *) response->log;
if (response->log_len > 1 << 20)
app_launch_external_editor
("log.XXXXXX.txt", log, response->log_len, true);
else if (!utf8_validate (log, response->log_len))
print_error ("log is not valid UTF-8");
else
log_view_show (&g.log, log);
}
log_view_request_reset (&g.log);
g.log.offset = 0;
@@ -3796,42 +3804,25 @@ transcript_text_visit (enum transcript_visit_kind kind,
}
static bool
app_launch_external_editor (bool view_transcript)
app_launch_external_editor (const char *template_name,
const char *contents, size_t contents_len, bool viewing_transcript)
{
if (g.editor_running_for || !g.buffer_current)
return false;
char *contents = NULL;
size_t contents_len = 0;
const char *template_name = "input.XXXXXX.txt";
if (view_transcript)
{
struct str text = str_make ();
app_walk_transcript (time (NULL), transcript_text_visit, &text);
contents_len = text.len;
contents = str_steal (&text);
template_name = "transcript.XXXXXX.txt";
}
else
{
contents = app_editor_text ();
contents_len = strlen (contents);
}
struct error *err = NULL;
char *filename = app_external_editor_make_file (template_name,
contents, contents_len, &err);
free (contents);
if (!filename)
{
print_error ("failed to prepare input for editing: %s", err->message);
print_error ("failed to prepare editor contents: %s", err->message);
error_free (err);
return false;
}
g.editor_running_for = xstrdup (g.buffer_current->buffer_name);
g.editor_filename = filename;
g.editor_shows_transcript = view_transcript;
g.editor_shows_transcript = viewing_transcript;
xui_invalidate ();
if (!app_external_editor_launch (&err))
@@ -3844,6 +3835,27 @@ app_launch_external_editor (bool view_transcript)
return true;
}
static bool
app_launch_input_editor (void)
{
char *contents = app_editor_text ();
bool result = app_launch_external_editor ("input.XXXXXX.txt",
contents, strlen (contents), false);
free (contents);
return result;
}
static bool
app_launch_transcript_editor (void)
{
struct str text = str_make ();
app_walk_transcript (time (NULL), transcript_text_visit, &text);
bool result = app_launch_external_editor ("transcript.XXXXXX.txt",
text.str, text.len, true);
str_free (&text);
return result;
}
// ~~~ Action and mouse dispatch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static const enum line_editor_action g_editor_actions[] =
@@ -3942,9 +3954,9 @@ app_process_action (enum action action)
case ACTION_LOG:
return app_toggle_log ();
case ACTION_EDIT_INPUT:
return app_launch_external_editor (false);
return app_launch_input_editor ();
case ACTION_VIEW_TRANSCRIPT:
return app_launch_external_editor (true);
return app_launch_transcript_editor ();
case ACTION_OPEN:
return app_open_last_link ();
case ACTION_FORMAT: