degesch: add logging to file
This commit is contained in:
parent
3503b76015
commit
94d495fbfa
115
degesch.c
115
degesch.c
|
@ -1018,6 +1018,8 @@ struct buffer
|
||||||
unsigned unseen_messages_count; ///< # messages since last visited
|
unsigned unseen_messages_count; ///< # messages since last visited
|
||||||
bool highlighted; ///< We've been highlighted
|
bool highlighted; ///< We've been highlighted
|
||||||
|
|
||||||
|
FILE *log_file; ///< Log file
|
||||||
|
|
||||||
// Origin information:
|
// Origin information:
|
||||||
|
|
||||||
struct server *server; ///< Reference to server
|
struct server *server; ///< Reference to server
|
||||||
|
@ -1041,6 +1043,8 @@ buffer_destroy (struct buffer *self)
|
||||||
input_buffer_destroy (self->input_data);
|
input_buffer_destroy (self->input_data);
|
||||||
LIST_FOR_EACH (struct buffer_line, iter, self->lines)
|
LIST_FOR_EACH (struct buffer_line, iter, self->lines)
|
||||||
buffer_line_destroy (iter);
|
buffer_line_destroy (iter);
|
||||||
|
if (self->log_file)
|
||||||
|
(void) fclose (self->log_file);
|
||||||
if (self->user)
|
if (self->user)
|
||||||
user_unref (self->user);
|
user_unref (self->user);
|
||||||
if (self->channel)
|
if (self->channel)
|
||||||
|
@ -1550,6 +1554,10 @@ static struct config_schema g_config_behaviour[] =
|
||||||
.comment = "Beep when highlighted or on a new invisible PM",
|
.comment = "Beep when highlighted or on a new invisible PM",
|
||||||
.type = CONFIG_ITEM_BOOLEAN,
|
.type = CONFIG_ITEM_BOOLEAN,
|
||||||
.default_ = "on" },
|
.default_ = "on" },
|
||||||
|
{ .name = "logging",
|
||||||
|
.comment = "Log buffer contents to file",
|
||||||
|
.type = CONFIG_ITEM_BOOLEAN,
|
||||||
|
.default_ = "off" },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2482,6 +2490,20 @@ buffer_update_time (struct app_context *ctx, time_t now)
|
||||||
// Else the buffer was too small, which is pretty weird
|
// Else the buffer was too small, which is pretty weird
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_line_flush (struct buffer_line *line, struct formatter *f, FILE *output)
|
||||||
|
{
|
||||||
|
int flags = line->flags;
|
||||||
|
if (flags & BUFFER_LINE_INDENT) formatter_add (f, " ");
|
||||||
|
if (flags & BUFFER_LINE_STATUS) formatter_add (f, " - ");
|
||||||
|
if (flags & BUFFER_LINE_ERROR) formatter_add (f, "#a=!=#r ", ATTR_ERROR);
|
||||||
|
|
||||||
|
formatter_add_from (f, line->formatter);
|
||||||
|
formatter_add (f, "\n");
|
||||||
|
formatter_flush (f, output);
|
||||||
|
formatter_free (f);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
buffer_line_display (struct app_context *ctx,
|
buffer_line_display (struct app_context *ctx,
|
||||||
struct buffer_line *line, bool is_external)
|
struct buffer_line *line, bool is_external)
|
||||||
|
@ -2494,12 +2516,13 @@ buffer_line_display (struct app_context *ctx,
|
||||||
formatter_init (&f, ctx, NULL);
|
formatter_init (&f, ctx, NULL);
|
||||||
|
|
||||||
struct tm current;
|
struct tm current;
|
||||||
|
char buf[9];
|
||||||
if (!localtime_r (&line->when, ¤t))
|
if (!localtime_r (&line->when, ¤t))
|
||||||
print_error ("%s: %s", "localtime_r", strerror (errno));
|
print_error ("%s: %s", "localtime_r", strerror (errno));
|
||||||
|
else if (!strftime (buf, sizeof buf, "%T", ¤t))
|
||||||
|
print_error ("%s: %s", "strftime", "buffer too small");
|
||||||
else
|
else
|
||||||
formatter_add (&f, "#a#&s#r ", ATTR_TIMESTAMP,
|
formatter_add (&f, "#a#s#r ", ATTR_TIMESTAMP, buf);
|
||||||
xstrdup_printf ("%02d:%02d:%02d",
|
|
||||||
current.tm_hour, current.tm_min, current.tm_sec));
|
|
||||||
|
|
||||||
// Ignore all formatting for messages coming from other buffers, that is
|
// Ignore all formatting for messages coming from other buffers, that is
|
||||||
// either from the global or server buffer. Instead print them in grey.
|
// either from the global or server buffer. Instead print them in grey.
|
||||||
|
@ -2509,26 +2532,33 @@ buffer_line_display (struct app_context *ctx,
|
||||||
FORMATTER_ADD_ITEM (&f, IGNORE_ATTR, .attribute = 1);
|
FORMATTER_ADD_ITEM (&f, IGNORE_ATTR, .attribute = 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line->flags & BUFFER_LINE_INDENT)
|
|
||||||
formatter_add (&f, " ");
|
|
||||||
if (line->flags & BUFFER_LINE_STATUS)
|
|
||||||
formatter_add (&f, " - ");
|
|
||||||
if (line->flags & BUFFER_LINE_ERROR)
|
|
||||||
formatter_add (&f, "#a=!=#r ", ATTR_ERROR);
|
|
||||||
formatter_add_from (&f, line->formatter);
|
|
||||||
|
|
||||||
input_hide (&ctx->input);
|
input_hide (&ctx->input);
|
||||||
|
buffer_line_flush (line, &f, stdout);
|
||||||
// TODO: write the line to a log file; note that the global and server
|
|
||||||
// buffers musn't collide with filenames
|
|
||||||
|
|
||||||
formatter_add (&f, "\n");
|
|
||||||
formatter_flush (&f, stdout);
|
|
||||||
formatter_free (&f);
|
|
||||||
|
|
||||||
input_show (&ctx->input);
|
input_show (&ctx->input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_line_write_to_log (struct app_context *ctx,
|
||||||
|
struct buffer_line *line, FILE *log_file)
|
||||||
|
{
|
||||||
|
if (line->flags & BUFFER_LINE_SKIP_FILE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct formatter f;
|
||||||
|
formatter_init (&f, ctx, NULL);
|
||||||
|
|
||||||
|
struct tm current;
|
||||||
|
char buf[20];
|
||||||
|
if (!gmtime_r (&line->when, ¤t))
|
||||||
|
print_error ("%s: %s", "gmtime_r", strerror (errno));
|
||||||
|
else if (!strftime (buf, sizeof buf, "%F %T", ¤t))
|
||||||
|
print_error ("%s: %s", "strftime", "buffer too small");
|
||||||
|
else
|
||||||
|
formatter_add (&f, "#s ", buf);
|
||||||
|
|
||||||
|
buffer_line_flush (line, &f, log_file);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
log_formatter (struct app_context *ctx,
|
log_formatter (struct app_context *ctx,
|
||||||
struct buffer *buffer, int flags, struct formatter *f)
|
struct buffer *buffer, int flags, struct formatter *f)
|
||||||
|
@ -2547,6 +2577,9 @@ log_formatter (struct app_context *ctx,
|
||||||
LIST_APPEND_WITH_TAIL (buffer->lines, buffer->lines_tail, line);
|
LIST_APPEND_WITH_TAIL (buffer->lines, buffer->lines_tail, line);
|
||||||
buffer->lines_count++;
|
buffer->lines_count++;
|
||||||
|
|
||||||
|
if (buffer->log_file)
|
||||||
|
buffer_line_write_to_log (ctx, line, buffer->log_file);
|
||||||
|
|
||||||
if (get_config_boolean (ctx->config.root, "behaviour.beep_on_highlight"))
|
if (get_config_boolean (ctx->config.root, "behaviour.beep_on_highlight"))
|
||||||
if ((flags & BUFFER_LINE_HIGHLIGHT)
|
if ((flags & BUFFER_LINE_HIGHLIGHT)
|
||||||
|| (buffer->type == BUFFER_PM && buffer != ctx->current_buffer))
|
|| (buffer->type == BUFFER_PM && buffer != ctx->current_buffer))
|
||||||
|
@ -2634,6 +2667,41 @@ log_full (struct app_context *ctx, struct server *s, struct buffer *buffer,
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
static void
|
||||||
|
make_log_filename (const char *filename, struct str *output)
|
||||||
|
{
|
||||||
|
for (const char *p = filename; *p; p++)
|
||||||
|
// XXX: anything more to replace?
|
||||||
|
if (strchr ("/\\ ", *p))
|
||||||
|
str_append_c (output, '_');
|
||||||
|
else
|
||||||
|
str_append_c (output, tolower_ascii (*p));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_open_log_file (struct app_context *ctx, struct buffer *buffer)
|
||||||
|
{
|
||||||
|
if (!get_config_boolean (ctx->config.root, "behaviour.logging"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct str path;
|
||||||
|
str_init (&path);
|
||||||
|
get_xdg_home_dir (&path, "XDG_DATA_HOME", ".local/share");
|
||||||
|
str_append_printf (&path, "/%s/%s", PROGRAM_NAME, "logs");
|
||||||
|
|
||||||
|
(void) mkdir_with_parents (path.str, NULL);
|
||||||
|
|
||||||
|
// TODO: make sure global and server buffers don't collide with filenames
|
||||||
|
str_append_c (&path, '/');
|
||||||
|
make_log_filename (buffer->name, &path);
|
||||||
|
str_append (&path, ".log");
|
||||||
|
|
||||||
|
if (!(buffer->log_file = fopen (path.str, "ab")))
|
||||||
|
log_global_error (ctx, "Couldn't open log file `#s': #s",
|
||||||
|
path.str, strerror (errno));
|
||||||
|
str_free (&path);
|
||||||
|
}
|
||||||
|
|
||||||
static struct buffer *
|
static struct buffer *
|
||||||
buffer_by_name (struct app_context *ctx, const char *name)
|
buffer_by_name (struct app_context *ctx, const char *name)
|
||||||
{
|
{
|
||||||
|
@ -2648,6 +2716,8 @@ buffer_add (struct app_context *ctx, struct buffer *buffer)
|
||||||
str_map_set (&ctx->buffers_by_name, buffer->name, buffer);
|
str_map_set (&ctx->buffers_by_name, buffer->name, buffer);
|
||||||
LIST_APPEND_WITH_TAIL (ctx->buffers, ctx->buffers_tail, buffer);
|
LIST_APPEND_WITH_TAIL (ctx->buffers, ctx->buffers_tail, buffer);
|
||||||
|
|
||||||
|
buffer_open_log_file (ctx, buffer);
|
||||||
|
|
||||||
// In theory this can't cause changes in the prompt
|
// In theory this can't cause changes in the prompt
|
||||||
refresh_prompt (ctx);
|
refresh_prompt (ctx);
|
||||||
}
|
}
|
||||||
|
@ -2776,6 +2846,13 @@ buffer_rename (struct app_context *ctx,
|
||||||
str_map_set (&ctx->buffers_by_name, buffer->name, NULL);
|
str_map_set (&ctx->buffers_by_name, buffer->name, NULL);
|
||||||
str_map_set (&ctx->buffers_by_name, new_name, buffer);
|
str_map_set (&ctx->buffers_by_name, new_name, buffer);
|
||||||
|
|
||||||
|
if (buffer->log_file)
|
||||||
|
{
|
||||||
|
(void) fclose (buffer->log_file);
|
||||||
|
buffer->log_file = NULL;
|
||||||
|
}
|
||||||
|
buffer_open_log_file (ctx, buffer);
|
||||||
|
|
||||||
free (buffer->name);
|
free (buffer->name);
|
||||||
buffer->name = xstrdup (new_name);
|
buffer->name = xstrdup (new_name);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue