ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
colorize.h File Reference

Log message colorization for terminal output. More...

Go to the source code of this file.

Functions

const char * colorize_log_message (const char *message)
 Colorize a log message for terminal output.
 

Detailed Description

Log message colorization for terminal output.

Colorizes log messages for terminal output by applying colors to:

  • Numbers and numeric units (cyan/light blue)
  • File paths like /path/to/file or C:\path (magenta)
  • Environment variables like $VAR_NAME (grey)

Only applies colors when output goes to TTY (not when piped). File logging output remains uncolorized.

Definition in file colorize.h.

Function Documentation

◆ colorize_log_message()

const char * colorize_log_message ( const char *  message)

Colorize a log message for terminal output.

Applies semantic colors to:

  • Numeric values: 0, 25, 0.24, 1920x1080, 25 MB, 1024 GiB, etc. (cyan)
  • File paths: /path/to/file, C:\path, src/main.c, etc. (magenta)
  • Environment variables: $VAR_NAME, $HOME, etc. (grey)
Parameters
messageThe log message to colorize
Returns
Colorized string in static buffer (reused across calls)
Note
Caller must use returned string immediately before next call
Only colorizes if output is going to TTY, otherwise returns message unchanged

Uses 4 rotating static buffers like colored_string() to handle multiple colorizations in a single expression.

Only applies colors if output is going to a TTY (not piped/redirected). Only colorizes text that is not already colored (in reset state).

Definition at line 509 of file colorize.c.

509 {
510 if (!message) {
511 return message;
512 }
513
514 // Check if colors should be used based on TTY status (same as ASCII art)
515 // Colors are only applied when output is actually a TTY
516 bool should_colorize = terminal_should_color_output(STDOUT_FILENO);
517
518 if (!should_colorize) {
519 return message;
520 }
521
522 // Use 4 static buffers for rotation (handles nested calls)
523 static char buffers[4][4096];
524 static int buffer_index = 0;
525
526 char *output = buffers[buffer_index];
527 buffer_index = (buffer_index + 1) % 4;
528
529 size_t out_pos = 0;
530 const size_t max_size = sizeof(buffers[0]);
531
532 // Process the input string
533 for (size_t i = 0; message[i] != '\0' && out_pos < max_size - 100; i++) {
534 size_t end_pos = 0;
535
536 // Check if already colorized - only colorize if NOT already colored
537 bool can_colorize = !ansi_is_already_colorized(message, i);
538
539 // Try key=value pair first (highest priority pattern)
540 size_t key_end = 0, value_start = 0, value_end = 0;
541 if (can_colorize && is_key_value_pair(message, i, &key_end, &value_start, &value_end)) {
542 size_t key_len = key_end - i;
543 size_t value_len = value_end - value_start;
544
545 // Extract key
546 char key_buf[256];
547 safe_snprintf(key_buf, sizeof(key_buf), "%.*s", (int)key_len, message + i);
548
549 // Extract value
550 char value_buf[512];
551 safe_snprintf(value_buf, sizeof(value_buf), "%.*s", (int)value_len, message + value_start);
552
553 // Color the key (magenta)
554 const char *colored_key = colored_string(LOG_COLOR_FATAL, key_buf);
555 size_t colored_key_len = strlen(colored_key);
556
557 // Check if we have enough space for key + equals + value
558 // (accounting for ANSI codes which will be added by colored_string)
559 if (out_pos + colored_key_len + 1 + value_len + 100 < max_size) {
560 memcpy(output + out_pos, colored_key, colored_key_len);
561 out_pos += colored_key_len;
562
563 // Add uncolored equals sign
564 output[out_pos++] = '=';
565
566 // Determine value color and add colored value
567 log_color_t value_color = get_value_color(value_buf);
568 const char *colored_value = colored_string(value_color, value_buf);
569 size_t colored_value_len = strlen(colored_value);
570 if (out_pos + colored_value_len < max_size) {
571 memcpy(output + out_pos, colored_value, colored_value_len);
572 out_pos += colored_value_len;
573 }
574 }
575 i = value_end - 1;
576 continue;
577 }
578
579 // Try numeric pattern
580 if (can_colorize && is_numeric_pattern(message, i, &end_pos)) {
581 size_t pattern_len = end_pos - i;
582 char pattern_buf[256];
583 safe_snprintf(pattern_buf, sizeof(pattern_buf), "%.*s", (int)pattern_len, message + i);
584
585 const char *colored = colored_string(LOG_COLOR_GREY, pattern_buf);
586 size_t colored_len = strlen(colored);
587 if (out_pos + colored_len < max_size) {
588 memcpy(output + out_pos, colored, colored_len);
589 out_pos += colored_len;
590 }
591 i = end_pos - 1;
592 continue;
593 }
594
595 // Try file path
596 if (can_colorize && is_file_path(message, i, &end_pos)) {
597 size_t path_len = end_pos - i;
598 char path_buf[512];
599 safe_snprintf(path_buf, sizeof(path_buf), "%.*s", (int)path_len, message + i);
600
601 const char *colored = colored_string(LOG_COLOR_DEBUG, path_buf);
602 size_t colored_len = strlen(colored);
603 if (out_pos + colored_len < max_size) {
604 memcpy(output + out_pos, colored, colored_len);
605 out_pos += colored_len;
606 }
607 i = end_pos - 1;
608 continue;
609 }
610
611 // Try environment variable
612 if (can_colorize && is_env_var(message, i, &end_pos)) {
613 size_t var_len = end_pos - i;
614 char var_buf[256];
615 safe_snprintf(var_buf, sizeof(var_buf), "%.*s", (int)var_len, message + i);
616
617 const char *colored = colored_string(LOG_COLOR_GREY, var_buf);
618 size_t colored_len = strlen(colored);
619 if (out_pos + colored_len < max_size) {
620 memcpy(output + out_pos, colored, colored_len);
621 out_pos += colored_len;
622 }
623 i = end_pos - 1;
624 continue;
625 }
626
627 // Try URL
628 if (can_colorize && is_url(message, i, &end_pos)) {
629 size_t url_len = end_pos - i;
630 char url_buf[2048];
631 safe_snprintf(url_buf, sizeof(url_buf), "%.*s", (int)url_len, message + i);
632
633 const char *colored = colored_string(LOG_COLOR_INFO, url_buf);
634 size_t colored_len = strlen(colored);
635 if (out_pos + colored_len < max_size) {
636 memcpy(output + out_pos, colored, colored_len);
637 out_pos += colored_len;
638 }
639 i = end_pos - 1;
640 continue;
641 }
642
643 // Regular character - just copy
644 if (out_pos < max_size - 1) {
645 output[out_pos++] = message[i];
646 }
647 }
648
649 output[out_pos] = '\0';
650 return output;
651}
bool ansi_is_already_colorized(const char *message, size_t pos)
Check if a position in text is already colored.
Definition ansi.c:98
log_color_t
Color enum for logging - indexes into color arrays.
Definition log/log.h:130
@ LOG_COLOR_GREY
Definition log/log.h:137
@ LOG_COLOR_FATAL
Definition log/log.h:136
@ LOG_COLOR_DEBUG
Definition log/log.h:132
@ LOG_COLOR_INFO
Definition log/log.h:133
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Safe formatted string printing to buffer.
Definition system.c:148
const char * colored_string(log_color_t color, const char *text)
Build a colored string for terminal output.
bool terminal_should_color_output(int fd)
Determine if color output should be used.

References ansi_is_already_colorized(), colored_string(), LOG_COLOR_DEBUG, LOG_COLOR_FATAL, LOG_COLOR_GREY, LOG_COLOR_INFO, safe_snprintf(), and terminal_should_color_output().

Referenced by log_msg(), log_plain_msg(), log_recolor_plain_entry(), and log_template_apply().