ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
lib/tui/stats.c
Go to the documentation of this file.
1
2/* Storage capacities in elements; text buffers include the terminating NUL. */
3#define TUI_STATS_TITLE_BUFFER_SIZE 160
4#define TUI_STATS_FOOTER_BUFFER_SIZE 160
5#define TUI_STATS_TEXT_BUFFER_SIZE 4096
6
10#include <ascii-chat/ui/table.h>
11#include <ascii-chat/otel.h>
13#include <libplatform/atomic.h>
14#include <ascii-chat/common.h>
16#include <libplatform/compiler.h>
17#include <libplatform/system.h>
18#include <libplatform/terminal.h>
19#include <libplatform/thread.h>
27#include <stdarg.h>
28#include <stdio.h>
29#include <math.h>
30#include <ctype.h>
31#include <stdlib.h>
33#include <string.h>
34
36static size_t stats_body_width(const stats_view_t *view) {
37 size_t width = 0;
38 for (unsigned i = 0; i < view->count; ++i) {
39 size_t length = strlen(view->lines[i]);
40 if (length > width)
41 width = length;
42 }
43 return width;
44}
45
46static void stats_footer(const stats_view_t *view, char *footer, size_t capacity) {
47 snprintf(footer, capacity, "= / Esc close | Tab page | Up/Down select | %u rows", view->count);
48}
49
50terminal_size_t tui_stats_minimum(const stats_view_t *view) {
52 snprintf(title, sizeof(title), " ASCII-CHAT / %-20s LIVE STATS", view->mode);
53 stats_footer(view, footer, sizeof(footer));
54 size_t width = stats_body_width(view) + 4;
55 if (strlen(title) + 1 > width)
56 width = strlen(title) + 1;
57 if (strlen(footer) + 3 > width)
58 width = strlen(footer) + 3;
59 // Both subtitles are shorter than the title. Keep one spare row and column
60 // to avoid terminal auto-wrap/scroll, in addition to the fixed header/footer.
61 return (terminal_size_t){.cols = (int)width, .rows = 10};
62}
63
73static void stats_cells(size_t row, const char **cells, size_t count, void *data) {
74 (void)count;
75 stats_table_context_t *context = data;
76 if (context->view->headings[row])
77 snprintf(context->text, sizeof(context->text), "%s", colored_string(LOG_COLOR_DEBUG, context->view->lines[row]));
78 else
79 ui_text_values_style(context->text, sizeof(context->text), context->view->lines[row], LOG_COLOR_FATAL);
80 cells[0] = context->text;
81}
82
83void tui_stats_render(terminal_size_t size, const void *data) {
84 const stats_view_t *view = data;
85 frame_buffer_t *buffer = frame_buffer_create(size.rows, size.cols + 64);
86 if (!buffer)
87 return;
88 terminal_capabilities_t caps = detect_terminal_capabilities(options_terminal_settings());
89 terminal_color_mode_t mode = GET_OPTION(color_mode);
90 bool color = mode != TERM_COLOR_NONE && GET_OPTION(color) != COLOR_SETTING_FALSE && !GET_OPTION(strip_ansi) &&
91 (mode != TERM_COLOR_AUTO || caps.color_level != TERM_COLOR_NONE);
92 const char *blue = color ? ui_text_color_prefix(LOG_COLOR_DEBUG) : "";
94 frame_buffer_printf(buffer, "\033[1m%s ASCII-CHAT / %-20s LIVE STATS\033[0m\033[K\n", blue, view->mode);
95 frame_buffer_printf(buffer, " ");
96 frame_buffer_printf(buffer, "%s", blue);
97 ui_text_render_values(buffer, view->page ? "CONNECTIONS & MODE DETAILS" : "OVERVIEW / rates over ~1 second");
98 frame_buffer_printf(buffer, "\033[K\n");
99 frame_buffer_render_border(buffer, size.cols, blue);
100 ui_layout_t layout;
101 if (ui_layout_measure(size, 3, 1, 2, &layout) != ASCIICHAT_OK) {
102 frame_buffer_destroy(buffer);
103 return;
104 }
105 int available = layout.body_rows > 0 ? layout.body_rows : 1;
106 const ui_table_column_t column = {.heading = "Statistics", .width = size.cols - 4};
107 stats_table_context_t context = {.view = view};
108 ui_table_t table = {.columns = &column,
109 .column_count = 1,
110 .row_count = view->count,
111 .viewport = {.selected = view->selected, .first_visible = view->offset},
112 .cells = stats_cells,
113 .data = &context,
114 .selectable = true};
115 ui_table_render(buffer, &table, 4, 2, size.cols - 2, available);
116 frame_buffer_printf(buffer, "\033[%d;1H", size.rows - 2);
117 frame_buffer_render_border(buffer, size.cols, blue);
118 char footer[TUI_STATS_FOOTER_BUFFER_SIZE];
119 stats_footer(view, footer, sizeof(footer));
120 frame_buffer_printf(buffer, " ");
121 ui_text_render_values(buffer, footer);
122 frame_buffer_printf(buffer, "\033[K");
124 frame_buffer_destroy(buffer);
125}
⚙️ Common definitions, error codes, macros, and types shared throughout the application
int color_mode
Definition fft.c:25
char cells[(512 *256 *2)]
Definition fft.c:21
unsigned int width
Definition fft.c:23
void frame_buffer_cursor_home(frame_buffer_t *buf)
Append cursor home escape code (\033[H).
void frame_buffer_destroy(frame_buffer_t *buf)
Destroy a frame buffer.
size_t frame_buffer_get_length(const frame_buffer_t *buf)
Get the current content length of the frame buffer.
const char * frame_buffer_get_content(const frame_buffer_t *buf)
Get a pointer to the buffer content.
frame_buffer_t * frame_buffer_create(int rows, int cols)
Create a new frame buffer.
void frame_buffer_printf(frame_buffer_t *buf, const char *fmt,...)
Printf-style append to the buffer.
void frame_buffer_render_border(frame_buffer_t *buf, int cols, const char *color)
Render a horizontal border line (used by both splash and status screens).
Buffered terminal frame rendering.
struct frame_buffer frame_buffer_t
Opaque frame buffer handle.
@ ASCIICHAT_OK
Definition error_codes.h:46
@ LOG_COLOR_FATAL
Definition log/log.h:153
@ LOG_COLOR_DEBUG
Definition log/log.h:149
#define GET_OPTION(field)
Safely get a specific option field (lock-free read).
Definition options.h:1336
#define options_terminal_settings()
Definition options.h:1296
@ COLOR_SETTING_FALSE
Force colors OFF: disable all colors and logging colors.
Definition options.h:249
const char * colored_string(log_color_t color, const char *text)
Build a colored string for terminal output.
Definition string.c:284
void tui_stats_render(terminal_size_t size, const void *data)
#define TUI_STATS_FOOTER_BUFFER_SIZE
#define TUI_STATS_TEXT_BUFFER_SIZE
terminal_size_t tui_stats_minimum(const stats_view_t *view)
#define TUI_STATS_TITLE_BUFFER_SIZE
🔢 Mathematical Utility Functions
⚙️ Unified options parsing system for ascii-chat with builder pattern and lock-free access
Interactive search filtering for terminal screens.
Shutdown check system for clean library/application separation.
🔤 String Manipulation and Shell Escaping Utilities
const stats_view_t * view
char mode[32]
bool headings[128]
unsigned page
char lines[128][160]
unsigned selected
unsigned offset
unsigned count
int body_rows
Definition ui/layout.h:5
The useful part of ui table column is in heading, width, alignment, ellipsis: together they describe ...
Definition table.h:22
void ui_table_render(frame_buffer_t *out, ui_table_t *t, int row, int col, int width, int height)
Definition table.c:76
Reusable "fixed header + scrolling logs" terminal screen abstraction.
const char * ui_text_color_prefix(log_color_t color)
Definition text.c:18
void ui_text_values_style(char *out, size_t cap, const char *text, log_color_t zero_color)
Definition text.c:95
void ui_text_render_values(frame_buffer_t *out, const char *text)
Definition text.c:146
⏱️ High-precision timing utilities using sokol_time.h and uthash
asciichat_error_t ui_controller_write(int fd, const char *data, size_t len)
int ui_controller_active_fd(void)
asciichat_error_t ui_layout_measure(terminal_size_t size, int header, int detail, int footer, ui_layout_t *out)
Definition ui/layout.c:3