module Internal = struct   let (|>) f x =  x f   module String = struct     include StringLabels     let get_exn = get     let get s ~index = try Some (get_exn s index) with _ -> None     let sub_exn = sub     let find_index s ~char = try Some (rindex s char) with _ -> None    end   module List = ListLabels end open Internal open Printf module Metadoc = struct   include SmartPrint   let (%) = (^-^)   let s str =      let has_leading_space = String.get str ~index:0 = Some ' ' in     let has_ending_space = String.(get str ~index:(length str - 1)) = Some ' ' in     (if has_leading_space then space else empty)      % words str      % (if has_ending_space then space  else empty)   let sp = space   let sf fmt = ksprintf s fmt   let i i = OCaml.int i   let f f = OCaml.float f   let n = newline   let verbatim s = string s   let exn e = s (Printexc.to_string e)   let option ~f = function   | Some o -> f o   | None -> empty   let escape c = ksprintf string "\027[%sm" c    let color c t = escape c % t % escape "0"   let bold_red t =  color "1;31" t   let bold_yellow t =  color "1;33" t   let bold_green t =  color "1;32" t   let greyish t = color "37" t   let to_string ~line_width ~indent t =     SmartPrint.to_string line_width indent t   let to_list ~line_width ~indent t =     let res = ref [] in     let add c = res := c :: !res in     SmartPrint.to_something line_width indent       (fun c -> `Char c |> add)       (fun s -> `String s |> add)       (fun s ofs len -> `Sub_string (s, ofs, len) |> add)       t;     List.rev !res end (* Experimental Markdown printer. *) module Markdown = struct      include Metadoc   let to_markdown_string ?(line_width=72) sm =     to_string ~line_width ~indent:4 sm    let new_par = n % n   let h underliner t =      let title = to_markdown_string t in     let l = String.length title in     let underline = String.make l underliner in     verbatim title % n % verbatim underline % new_par   let h1 t = h '=' t   let h2 t = h '-' t   let par t = t % new_par   let emph t = s "*" % t % s "*"   let ul_filter l =     concat (List.filter l ~f:(fun t -> t <> empty)              |> List.map ~f:(fun t -> s "- " % t % n))     % n   let ul_inner l =     indent (separate n (List.map l ~f:(fun t -> s "- " % t)))   let url u = s "<" % verbatim u % s ">"   let link t ~url = brakets t % parens (s url) end module type LOGGER_CONFIGURATION = sig   
  (** The input type for Make_logger. *)
  type ('a, 'b) result   
  (** The potential result of print_string *)
  val debug_level: unit -> int   val with_color: unit -> bool   val line_width: int   val indent: int   val print_string: string -> (unit, 'b) result   val do_nothing: unit -> (unit, 'b) result   val name: string end module type LOGGER = sig   
  (** The output type of Make_logger, most functions come from SmartPrint. *)
  type t = SmartPrint.t   type ('a, 'b) result   val empty : t   val string : string -> t   val sub_string : string -> int -> int -> t   val ( !^ ) : string -> t   val space : t   val newline : t   val append : t -> t -> t   val ( ^-^ ) : t -> t -> t   val concat_with_space : t -> t -> t   val ( ^^ ) : t -> t -> t   val words : string -> t   val lines : string -> t   val indent : t -> t   val nest : t -> t   val nest_all : t -> t   val group : t -> t   val group_all : t -> t   val parens : t -> t   val braces : t -> t   val brakets : t -> t   val angle_brakets : t -> t   val single_quotes : t -> t   val double_quotes : t -> t   val concat : t list -> t   val separate : t -> t list -> t   module OCaml :   sig     val unit : unit -> t     val bool : bool -> t     val int : int -> t     val float : float -> t     val string : string -> t     val option : ('-> t) -> 'a option -> t     val list : ('-> t) -> 'a list -> t     val tuple : t list -> t   end   val to_something :     int ->     int ->     (char -> unit) ->     (string -> unit) -> (string -> int -> int -> unit) -> t -> unit   val to_buffer : int -> int -> Buffer.t -> t -> unit   val to_out_channel : int -> int -> out_channel -> t -> unit   val to_stdout : int -> int -> t -> unit   val ( % ) : t -> t -> t   
  (** Basic concatenation. *)
  val s : string -> t   
  (** Add a string, that may ve wrapped at each whitespace, s " bla " preserves spacing at the beginning or the end. *)
  val sp : t   
  (** A space. *)
  val sf : ('a, unit, string, t) format4 -> 'a   
  (** The equivalent of sprintf; e.g. sf "%f %d" 4.2 42. *)
  val i : int -> t   val f : float -> t   val n : t   
  (** Forced new line. *)
  val verbatim : string -> t   val exn : exn -> t   val option : f:('-> t) -> 'a option -> t   val escape : string -> t   val color : string -> t -> t   
  (** ANSI colored string. *)
  val bold_red : t -> t   val bold_yellow : t -> t   val bold_green : t -> t   val greyish : t -> t   val to_string : line_width:int -> indent:int -> SmartPrint.t -> string   val to_list :     line_width:int ->     indent:int ->     SmartPrint.t ->     [> `Char of char     | `String of string     | `Sub_string of string * int * int ] list   val print :     [< `Debug of int | `Error | `Normal | `Warning ] -> t ->     (unit, 'a) result   
  (** Print a log message. *)
  val ( @ ) :     t ->     [< `Debug of int | `Error | `Normal | `Warning ] ->     (unit, 'a) result   
  (** Operator alias for print. *)
  val normal : [> `Normal ]   val error : [> `Error ]   val warning : [> `Warning ]   val verbose : [> `Debug of int ]   val very_verbose : [> `Debug of int ] end module Make_logger (P : LOGGER_CONFIGURATION) :    LOGGER with type ('a, 'b) result = ('a, 'b) P.result = struct   include Metadoc   type ('a, 'b) result = ('a, 'b) P.result      let print log_kind t =     let convert_to_string formatted =       SmartPrint.to_string P.line_width P.indent formatted in     let display formatted = convert_to_string formatted |> P.print_string in     let using_colors = P.with_color () in     let no_color t = t in     let normal_color = if using_colors then bold_green else no_color in     let error_color = if using_colors then bold_red else no_color in     let warning_color = if using_colors then bold_yellow else no_color in     let debug_color = if using_colors then greyish else no_color in     let format_log ?(color_h=no_color) ?(color_t=no_color) head t =       let colorless = head % t in       let has_newline =         String.find_index (convert_to_string colorless) ~char:'\n' <> None in       display (         color_h (brakets head)         % string " "          % (if has_newline           then color_t (n % indent t)           else color_t t)         % newline       ) in     match log_kind with     | `Normal ->        format_log ~color_h:normal_color (string P.name) t     | `Error ->        format_log ~color_h:error_color (s P.name % s ": ERROR") t     | `Warning ->        format_log ~color_h:warning_color (s P.name % s ": Warning") t     | `Debug level when P.debug_level () >= level ->       format_log  ~color_h:debug_color (s P.name %s  ": debug")         ~color_t:debug_color t     | `Debug _ -> P.do_nothing ()   let (@) t kind = print kind t   let normal = `Normal    let error = `Error    let warning = `Warning   let verbose = `Debug 1   let very_verbose = `Debug 2 end