M .ocamlformat => .ocamlformat +1 -1
@@ 1,2 1,2 @@
profile = default
-version = 0.20.1>
\ No newline at end of file
+version = 0.20.1
M src/common/err.ml => src/common/err.ml +21 -2
@@ 4,7 4,16 @@ type expsn_err = [ `ExpsnAmbiguity of string | `UnknownExpsn of string ]
type parser_err = [ `IllegalCharacter of loc | `SyntaxError of loc ]
type t = [ checker_err | expsn_err | parser_err | `NoSuchFile of string ]
-(* TODO: overview of concerned line. *)
+let get_line ic n =
+ try
+ let i = ref 1 in
+ while !i < n do
+ let _ = input_line ic in
+ incr i
+ done;
+ input_line ic
+ with End_of_file -> assert false
+
let rec pp_loc ?hint ~msg (spos, epos) =
let schar = Lexing.(spos.pos_cnum - spos.pos_bol) in
let echar = Lexing.(epos.pos_cnum - epos.pos_bol) in
@@ 16,10 25,20 @@ let rec pp_loc ?hint ~msg (spos, epos) =
Printf.sprintf {|File "%s", line %i, characters %s:|} epos.Lexing.pos_fname
spos.Lexing.pos_lnum char_pos
in
+ let overview =
+ let line = get_line (open_in epos.Lexing.pos_fname) spos.Lexing.pos_lnum in
+ let margin =
+ String.make
+ (schar + (spos.Lexing.pos_lnum |> string_of_int |> String.length))
+ ' '
+ in
+ let cursor = if echar <= 0 then "^" else String.make (echar - schar) '^' in
+ Printf.sprintf "%d | %s\n %s%s" spos.Lexing.pos_lnum line margin cursor
+ in
let descr =
match hint with None -> pp_string msg | Some hint -> pp_string msg ~hint
in
- Printf.sprintf "%s\n%s" carret descr
+ Printf.sprintf "%s\n%s\n%s" carret overview descr
and pp_string ?hint msg =
let err = Printf.sprintf "Error: %s" msg in