diff --git a/prism_compile.c b/prism_compile.c index 62182c73bfd7b2..e29bde19d02408 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -10137,7 +10137,8 @@ typedef struct { size_t divider_length; } pm_parse_error_format_t; -#define PM_COLOR_GRAY "\033[38;5;102m" +#define PM_COLOR_BOLD "\033[1m" +#define PM_COLOR_GRAY "\033[2m" #define PM_COLOR_RED "\033[1;31m" #define PM_COLOR_RESET "\033[m" #define PM_ERROR_TRUNCATE 30 @@ -10194,6 +10195,9 @@ pm_parse_errors_format_sort(const pm_parser_t *parser, const pm_list_t *error_li return errors; } +/* Append a literal string to the buffer. */ +#define pm_buffer_append_literal(buffer, str) pm_buffer_append_string(buffer, str, rb_strlen_lit(str)) + static inline void pm_parse_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *newline_list, const char *number_prefix, int32_t line, uint32_t column_start, uint32_t column_end, pm_buffer_t *buffer) { int32_t line_delta = line - parser->start_line; @@ -10239,7 +10243,7 @@ pm_parse_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t * * Format the errors on the parser into the given buffer. */ static void -pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_t *buffer, bool colorize, bool inline_messages) { +pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_t *buffer, int highlight, bool inline_messages) { assert(error_list->size != 0); // First, we're going to sort all of the errors by line number using an @@ -10265,7 +10269,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p int32_t max_line_number = first_line_number > last_line_number ? first_line_number : last_line_number; if (max_line_number < 10) { - if (colorize) { + if (highlight > 0) { error_format = (pm_parse_error_format_t) { .number_prefix = PM_COLOR_GRAY "%1" PRIi32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, @@ -10279,7 +10283,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p }; } } else if (max_line_number < 100) { - if (colorize) { + if (highlight > 0) { error_format = (pm_parse_error_format_t) { .number_prefix = PM_COLOR_GRAY "%2" PRIi32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, @@ -10293,7 +10297,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p }; } } else if (max_line_number < 1000) { - if (colorize) { + if (highlight > 0) { error_format = (pm_parse_error_format_t) { .number_prefix = PM_COLOR_GRAY "%3" PRIi32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, @@ -10307,7 +10311,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p }; } } else if (max_line_number < 10000) { - if (colorize) { + if (highlight > 0) { error_format = (pm_parse_error_format_t) { .number_prefix = PM_COLOR_GRAY "%4" PRIi32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, @@ -10321,7 +10325,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p }; } } else { - if (colorize) { + if (highlight > 0) { error_format = (pm_parse_error_format_t) { .number_prefix = PM_COLOR_GRAY "%5" PRIi32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, @@ -10370,10 +10374,12 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p // If this is the first error or we're on a new line, then we'll display // the line that has the error in it. if ((index == 0) || (error->line != last_line)) { - if (colorize) { - pm_buffer_append_string(buffer, PM_COLOR_RED "> " PM_COLOR_RESET, 12); + if (highlight > 1) { + pm_buffer_append_literal(buffer, PM_COLOR_RED "> " PM_COLOR_RESET); + } else if (highlight > 0) { + pm_buffer_append_literal(buffer, PM_COLOR_BOLD "> " PM_COLOR_RESET); } else { - pm_buffer_append_string(buffer, "> ", 2); + pm_buffer_append_literal(buffer, "> "); } last_column_start = error->column_start; @@ -10416,7 +10422,8 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p column += (char_width == 0 ? 1 : char_width); } - if (colorize) pm_buffer_append_string(buffer, PM_COLOR_RED, 7); + if (highlight > 1) pm_buffer_append_literal(buffer, PM_COLOR_RED); + else if (highlight > 0) pm_buffer_append_literal(buffer, PM_COLOR_BOLD); pm_buffer_append_byte(buffer, '^'); size_t char_width = encoding->char_width(start + column, parser->end - (start + column)); @@ -10429,7 +10436,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p column += (char_width == 0 ? 1 : char_width); } - if (colorize) pm_buffer_append_string(buffer, PM_COLOR_RESET, 3); + if (highlight > 0) pm_buffer_append_literal(buffer, PM_COLOR_RESET); if (inline_messages) { pm_buffer_append_byte(buffer, ' '); @@ -10517,6 +10524,12 @@ pm_parse_process_error(const pm_parse_result_t *result) pm_buffer_t buffer = { 0 }; const pm_string_t *filepath = &parser->filepath; + int highlight = rb_stderr_tty_p(); + if (highlight) { + const char *no_color = getenv("NO_COLOR"); + highlight = (no_color == NULL || no_color[0] == '\0') ? 2 : 1; + } + for (const pm_diagnostic_t *error = head; error != NULL; error = (const pm_diagnostic_t *) error->node.next) { switch (error->level) { case PM_ERROR_LEVEL_SYNTAX: @@ -10550,7 +10563,7 @@ pm_parse_process_error(const pm_parse_result_t *result) pm_list_node_t *list_node = (pm_list_node_t *) error; pm_list_t error_list = { .size = 1, .head = list_node, .tail = list_node }; - pm_parse_errors_format(parser, &error_list, &buffer, rb_stderr_tty_p(), false); + pm_parse_errors_format(parser, &error_list, &buffer, highlight, false); } VALUE value = rb_exc_new(rb_eArgError, pm_buffer_value(&buffer), pm_buffer_length(&buffer)); @@ -10580,7 +10593,7 @@ pm_parse_process_error(const pm_parse_result_t *result) ); if (valid_utf8) { - pm_parse_errors_format(parser, &parser->error_list, &buffer, rb_stderr_tty_p(), true); + pm_parse_errors_format(parser, &parser->error_list, &buffer, highlight, true); } else { for (const pm_diagnostic_t *error = head; error != NULL; error = (const pm_diagnostic_t *) error->node.next) {