open! Core
open Expect_test_helpers_base
open Patdiff_kernel

let patdiff ?location_style ?context ?keep_ws ?float_tolerance string1 string2 =
  Patdiff_core.Without_unix.patdiff (* turns off ANSI codes for color *)
    ?location_style
    ?float_tolerance
    ~output:Ascii
      (* without color, cannot produce the "!|" lines that mix add/keep/remove *)
    ~produce_unified_lines:false
      (* line splitting produces confusing output in ASCII format *)
    ~split_long_lines:false
    ?context
    ?keep_ws
    ~prev:{ name = "a"; text = string1 }
    ~next:{ name = "b"; text = string2 }
    ()
;;

let patdiff_s ?location_style ?context ?keep_ws ?float_tolerance sexp1 sexp2 =
  patdiff
    ?location_style
    ?context
    ?keep_ws
    ?float_tolerance
    (sexp_to_string sexp1)
    (sexp_to_string sexp2)
;;

let print_endline_if_non_empty = function
  | "" -> ()
  | string -> print_endline string
;;

let print_patdiff ?location_style ?context ?keep_ws ?float_tolerance string1 string2 =
  print_endline_if_non_empty
    (patdiff ?location_style ?context ?keep_ws ?float_tolerance string1 string2)
;;

let print_patdiff_s ?location_style ?context ?keep_ws ?float_tolerance sexp1 sexp2 =
  print_endline_if_non_empty
    (patdiff_s ?location_style ?context ?keep_ws ?float_tolerance sexp1 sexp2)
;;

let diff_printer ?location_style ?context ?keep_ws ?float_tolerance initial =
  let print =
    let previous = ref None in
    fun current ->
      (match !previous with
       | None -> print_endline current
       | Some previous ->
         print_patdiff ?location_style ?context ?keep_ws ?float_tolerance previous current);
      previous := Some current
  in
  let () = Option.iter initial ~f:print in
  stage print
;;

let diff_printer_s ?location_style ?context ?keep_ws ?float_tolerance initial =
  let diff_printer =
    unstage
      (diff_printer
         ?location_style
         ?context
         ?keep_ws
         ?float_tolerance
         (Option.map ~f:sexp_to_string initial))
  in
  stage (fun sexp -> diff_printer (sexp_to_string sexp))
;;
