From 9d3e9bc332c87f7e56e328097be96f25a13858b5 Mon Sep 17 00:00:00 2001 From: Torben Ewert Date: Sun, 24 Mar 2024 19:19:58 +0100 Subject: [PATCH] add "no color" mode to diagnostics (fixes #34) --- lib/pinc_diagnostics/Pinc_Diagnostics.ml | 10 +- lib/pinc_diagnostics/Pinc_Printer.ml | 147 +++++++++--------- test/array/run.t | 2 +- test/char/run.t | 2 +- test/component/run.t | 4 +- test/context/run.t | 2 +- test/function/run.t | 3 +- test/interpreter_error/run.t | 5 +- test/loop/run.t | 2 +- test/mutation/run.t | 2 +- test/operators/run.t | 2 +- .../mutation_without_expression.pi | 4 +- test/parse_error/run.t | 23 +-- test/portal/run.t | 2 +- test/record/run.t | 2 +- test/slot/run.t | 5 +- test/store/run.t | 2 +- test/template/run.t | 2 +- test/test/run.t | 2 +- 19 files changed, 117 insertions(+), 106 deletions(-) diff --git a/lib/pinc_diagnostics/Pinc_Diagnostics.ml b/lib/pinc_diagnostics/Pinc_Diagnostics.ml index 2ecfb50..3c55fed 100644 --- a/lib/pinc_diagnostics/Pinc_Diagnostics.ml +++ b/lib/pinc_diagnostics/Pinc_Diagnostics.ml @@ -1,14 +1,20 @@ module Location = Pinc_Location +let set_renderer ppf = + match Sys.getenv_opt "NO_COLOR" with + | None | Some "" -> Fmt.set_style_renderer ppf `Ansi_tty + | Some _ -> Fmt.set_style_renderer ppf `None +;; + let error location message = let ppf = Format.err_formatter in - Fmt.set_style_renderer ppf `Ansi_tty; + set_renderer ppf; Fmt.pf ppf "@[@,%a@,%s@,@]" (Pinc_Printer.print ~kind:`error) location message; exit 1 ;; let warn location message = let ppf = Format.err_formatter in - Fmt.set_style_renderer ppf `Ansi_tty; + set_renderer ppf; Fmt.pf ppf "@[@,%a@,%s@,@]" (Pinc_Printer.print ~kind:`warning) location message ;; diff --git a/lib/pinc_diagnostics/Pinc_Printer.ml b/lib/pinc_diagnostics/Pinc_Printer.ml index a32bdb3..23c169e 100644 --- a/lib/pinc_diagnostics/Pinc_Printer.ml +++ b/lib/pinc_diagnostics/Pinc_Printer.ml @@ -2,34 +2,6 @@ module Source = Pinc_Core.Source module Location = Pinc_Location module Position = Pinc_Position -let _seek_lines_before ~count source_code pos = - let original_line = pos.Position.line in - source_code - |> String.fold_left - (fun (current_line, current_char) curr -> - if current_line + count >= original_line then - (current_line, current_char) - else ( - match curr with - | '\n' -> (current_line + 1, current_char + 1) - | _ -> (current_line, current_char + 1))) - (1, 0) -;; - -let _seek_lines_after ~count source_code pos = - let original_line = pos.Position.line in - source_code - |> String.fold_left - (fun (line_number, char_number) curr -> - if line_number - count - 1 >= original_line then - (line_number, char_number) - else ( - match curr with - | '\n' -> (line_number + 1, char_number + 1) - | _ -> (line_number, char_number + 1))) - (1, 0) -;; - let print_code ~color ~loc source_code = let context_lines = 1 in let start_pos = loc.Location.loc_start in @@ -51,52 +23,76 @@ let print_code ~color ~loc source_code = |> List.mapi (fun i line -> let line_number = i + first_shown_line in (line_number, line)) - (* try - String.sub source_code start_char_offset (end_char_offset - start_char_offset) - |> String.split_on_char '\n' - |> List.mapi (fun i line -> - let line_number = i + first_shown_line in - (line_number, line)) - with Invalid_argument _ -> [] *) in let buf = Buffer.create 400 in let ppf = Format.formatter_of_buffer buf in - Fmt.set_style_renderer ppf `Ansi_tty; - lines - |> List.iter (fun (line_number, line) -> - if line_number >= highlight_line_start && line_number <= highlight_line_end then - Fmt.pf - ppf - "%a" - Fmt.(styled `Bold (styled (`Fg color) (fun ppf -> Fmt.pf ppf "%4d"))) - line_number - else - Fmt.pf ppf "%4d" line_number; - Fmt.pf ppf " %a " Fmt.(styled `Faint string) "│"; + Fmt.set_style_renderer + ppf + (if color <> `None then + `Ansi_tty + else + `None); + + let () = + lines + |> List.iter @@ fun (line_number, line) -> + if line_number >= highlight_line_start && line_number <= highlight_line_end then + Fmt.pf + ppf + "%a" + Fmt.(styled `Bold (styled color (fun ppf -> Fmt.pf ppf "%4d"))) + line_number + else + Fmt.pf ppf "%4d" line_number; + + Fmt.pf ppf " %a " Fmt.(styled `Faint string) "│"; + + let did_highlight = ref false in + + let should_highlight column_number = + let on_line_start = Int.equal line_number highlight_line_start in + let after_column_start = column_number >= highlight_column_start in + let between_lines = + line_number >= highlight_line_start && line_number <= highlight_line_end + in + let between_columns = + column_number >= highlight_column_start + && column_number <= highlight_column_end + in + let on_line_end = Int.equal line_number highlight_line_end in + let before_column_start = column_number <= highlight_column_end in + + (on_line_start && (not on_line_end) && after_column_start) + || (between_lines && between_columns) + || (on_line_end && (not on_line_start) && before_column_start) + in + + let () = line - |> String.iteri (fun column_index ch -> - let column_number = column_index + 1 in - let on_line_start = Int.equal line_number highlight_line_start in - let after_column_start = column_number >= highlight_column_start in - let between_lines = - line_number >= highlight_line_start && line_number <= highlight_line_end - in - let between_columns = - column_number >= highlight_column_start - && column_number <= highlight_column_end - in - let on_line_end = Int.equal line_number highlight_line_end in - let before_column_start = column_number <= highlight_column_end in - if - (on_line_start && (not on_line_end) && after_column_start) - || (between_lines && between_columns) - || (on_line_end && (not on_line_start) && before_column_start) - then - Fmt.pf ppf "%a" Fmt.(styled `Bold (styled (`Fg color) char)) ch - else - Fmt.pf ppf "%a" Fmt.(styled `None char) ch); - Format.pp_print_newline ppf ()); + |> String.iteri @@ fun column_index ch -> + let column_number = column_index + 1 in + if should_highlight column_number then ( + Fmt.pf ppf "%a" Fmt.(styled `Bold (styled color char)) ch; + did_highlight := true) + else + Fmt.pf ppf "%a" Fmt.(styled `None char) ch + in + + let () = + if !did_highlight && color = `None then ( + Format.pp_print_newline ppf (); + Fmt.pf ppf " %a " Fmt.(styled `Faint string) "│"; + line + |> String.iteri @@ fun column_index _ch -> + if should_highlight (succ column_index) then + Fmt.pf ppf "^" + else + Fmt.pf ppf " ") + in + + Format.pp_print_newline ppf () + in Buffer.contents buf ;; @@ -135,10 +131,17 @@ let print_header ppf ~color text = ;; let print ~kind ppf (loc : Location.t) = - let color, header = + let color = + match (Sys.getenv_opt "NO_COLOR", kind) with + | (None | Some ""), `warning -> `Yellow + | (None | Some ""), `error -> `Red + | _ -> `None + in + + let header = match kind with - | `warning -> (`Yellow, "WARNING") - | `error -> (`Red, "ERROR") + | `warning -> "WARNING" + | `error -> "ERROR" in Fmt.pf ppf "@[%a@] " (print_header ~color) header; Fmt.pf ppf "@[%a@]@," print_loc loc; diff --git a/test/array/run.t b/test/array/run.t index 83bf3ee..06ca48a 100644 --- a/test/array/run.t +++ b/test/array/run.t @@ -1,4 +1,4 @@ - $ print . C + $ NO_COLOR="1" print . C
0 1 diff --git a/test/char/run.t b/test/char/run.t index 6864627..dd8c897 100644 --- a/test/char/run.t +++ b/test/char/run.t @@ -1,4 +1,4 @@ - $ print . C + $ NO_COLOR="1" print . C
String.uppercase_ascii("abcàäöüß"): ABCàäöüß String.lowercase_ascii("ABCÁÄÖÜß"): abcÁÄÖÜß diff --git a/test/component/run.t b/test/component/run.t index c9102f2..9ed895b 100644 --- a/test/component/run.t +++ b/test/component/run.t @@ -1,11 +1,11 @@ - $ print . Component + $ NO_COLOR="1" print . Component

Hello, Headline Secondary!

- $ print . Foo + $ NO_COLOR="1" print . Foo ERROR diff --git a/test/context/run.t b/test/context/run.t index a93ee45..98e3168 100644 --- a/test/context/run.t +++ b/test/context/run.t @@ -1,4 +1,4 @@ - $ print . Component + $ NO_COLOR="1" print . Component

Hello, Headline Secondary!

diff --git a/test/function/run.t b/test/function/run.t index 9f8c767..65d54cb 100644 --- a/test/function/run.t +++ b/test/function/run.t @@ -1,4 +1,4 @@ - $ print . Component + $ NO_COLOR="1" print . Component
max(1, 5) = 5 min(1, 5) = 1 @@ -27,4 +27,3 @@ 9 16
- diff --git a/test/interpreter_error/run.t b/test/interpreter_error/run.t index ea186fd..5fa3d14 100644 --- a/test/interpreter_error/run.t +++ b/test/interpreter_error/run.t @@ -1,16 +1,17 @@ - $ print . NotExistingDefinition + $ NO_COLOR="1" print . NotExistingDefinition ERROR Declaration with name `NotExistingDefinition` was not found. [1] - $ print . UseNonLibrary + $ NO_COLOR="1" print . UseNonLibrary ERROR in file ./data.pi:2:7-19 1 │ component UseNonLibrary { 2 │ use NotALibrary; + │ ^^^^^^^^^^^^ 3 │ } Attempted to use a non library definition. diff --git a/test/loop/run.t b/test/loop/run.t index a94308e..2e0533a 100644 --- a/test/loop/run.t +++ b/test/loop/run.t @@ -1,4 +1,4 @@ - $ print . Component + $ NO_COLOR="1" print . Component

EXCLUSIVE RANGES

diff --git a/test/mutation/run.t b/test/mutation/run.t index 8f15adf..22aa3cb 100644 --- a/test/mutation/run.t +++ b/test/mutation/run.t @@ -1,4 +1,4 @@ - $ print . Component + $ NO_COLOR="1" print . Component
a: mutated b: mutated diff --git a/test/operators/run.t b/test/operators/run.t index a710f53..ebb2213 100644 --- a/test/operators/run.t +++ b/test/operators/run.t @@ -1,4 +1,4 @@ - $ print . Component + $ NO_COLOR="1" print . Component
![1] = false ![] = true diff --git a/test/parse_error/mutation_without_expression.pi b/test/parse_error/mutation_without_expression.pi index 39b1a72..b1e7519 100644 --- a/test/parse_error/mutation_without_expression.pi +++ b/test/parse_error/mutation_without_expression.pi @@ -1,8 +1,6 @@ component Component { let mutable fail = ""; - fail := - - ; + fail := ;
{fail} diff --git a/test/parse_error/run.t b/test/parse_error/run.t index 53535a6..3a9680f 100644 --- a/test/parse_error/run.t +++ b/test/parse_error/run.t @@ -1,4 +1,4 @@ - $ print ./empty_template_expression.pi Component + $ NO_COLOR="1" print ./empty_template_expression.pi Component
@@ -7,53 +7,56 @@ 3 │
4 │ {} + │ ^^ 5 │
Expected to see an expression between these braces. This is currently not doing anything, so you can safely remove it. If you wanted to have an empty record here, you need to write `{{}}` - $ print ./tag_transformer_function.pi Component + $ NO_COLOR="1" print ./tag_transformer_function.pi Component ERROR in file ./tag_transformer_function.pi:2:22-34 1 │ component Component { 2 │ let fail = #String :: fn _ -> ; + │ ^^^^^^^^^^^^ 3 │ This tag transformer does not have a valid body. [1] - $ print ./let_without_expression.pi Component + $ NO_COLOR="1" print ./let_without_expression.pi Component ERROR in file ./let_without_expression.pi:2:3-15 1 │ component Component { 2 │ let fail = ; + │ ^^^^^^^^^^^^ 3 │ Expected expression as right hand side of let declaration [1] - $ print ./mutation_without_expression.pi Component + $ NO_COLOR="1" print ./mutation_without_expression.pi Component - ERROR in file ./mutation_without_expression.pi:3:3-5:4 + ERROR in file ./mutation_without_expression.pi:3:3-12 2 │ let mutable fail = ""; - 3 │ fail := - 4 │ - 5 │ ; - 6 │ + 3 │ fail := ; + │ ^^^^^^^^^ + 4 │ Expected expression as right hand side of mutation statement [1] - $ print ./string_interpolation.pi Component + $ NO_COLOR="1" print ./string_interpolation.pi Component ERROR in file ./string_interpolation.pi:4:25-27 3 │ 4 │
+ │ ^^^ 5 │ {fail} Only lowercase identifiers are allowed as string interpolation placeholders. diff --git a/test/portal/run.t b/test/portal/run.t index 0d6183f..0bcd06f 100644 --- a/test/portal/run.t +++ b/test/portal/run.t @@ -1,4 +1,4 @@ - $ print . Main + $ NO_COLOR="1" print . Main diff --git a/test/record/run.t b/test/record/run.t index 39a7833..816a87a 100644 --- a/test/record/run.t +++ b/test/record/run.t @@ -1,4 +1,4 @@ - $ print . Component + $ NO_COLOR="1" print . Component
1 diff --git a/test/slot/run.t b/test/slot/run.t index 8824986..1a4665a 100644 --- a/test/slot/run.t +++ b/test/slot/run.t @@ -1,4 +1,4 @@ - $ print . Component + $ NO_COLOR="1" print . Component
Hello Default
@@ -35,12 +35,13 @@
- $ print . ErrorComponent + $ NO_COLOR="1" print . ErrorComponent ERROR in file ./data.pi:38:5-44 37 │ 38 │
Hello Default
+ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 39 │
Child with tag `div` may not be used inside this #Slot. diff --git a/test/store/run.t b/test/store/run.t index d4ef129..1f791e0 100644 --- a/test/store/run.t +++ b/test/store/run.t @@ -1,4 +1,4 @@ - $ print . StoreValueProvider + $ NO_COLOR="1" print . StoreValueProvider
Somewhere in the World ... or am I?? some@email.invalid diff --git a/test/template/run.t b/test/template/run.t index 5316003..1fa0cf7 100644 --- a/test/template/run.t +++ b/test/template/run.t @@ -1,4 +1,4 @@ - $ print . Template + $ NO_COLOR="1" print . Template diff --git a/test/test/run.t b/test/test/run.t index 4bf0fa8..3231d7d 100644 --- a/test/test/run.t +++ b/test/test/run.t @@ -1,4 +1,4 @@ - $ print . Docs + $ NO_COLOR="1" print . Docs ⌘ apples oranges