ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
colorize.c 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.

Definition in file colorize.c.

Function Documentation

◆ colorize_log_message()

const char * colorize_log_message ( const char *  message)

Colorize a log message for terminal output.

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 513 of file colorize.c.

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

References ansi_is_already_colorized(), colored_string(), safe_snprintf(), and terminal_should_color_output().

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