mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
feat(Pp): add wrap for extension nodes
This commit is contained in:
parent
cea844fdde
commit
d36c57459e
3 changed files with 105 additions and 9 deletions
|
|
@ -1,3 +1,33 @@
|
||||||
|
module B = Buffer
|
||||||
|
|
||||||
|
module Ext = struct
|
||||||
|
module type OUT = sig
|
||||||
|
val char : char -> unit
|
||||||
|
val sub_string : string -> int -> int -> unit
|
||||||
|
val string : string -> unit
|
||||||
|
val newline : unit -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
type out = (module OUT)
|
||||||
|
|
||||||
|
let out_of_buf (buf : Buffer.t) : out =
|
||||||
|
(module struct
|
||||||
|
let char = B.add_char buf
|
||||||
|
let sub_string = B.add_substring buf
|
||||||
|
let string = B.add_string buf
|
||||||
|
let newline () = B.add_char buf '\n'
|
||||||
|
end)
|
||||||
|
|
||||||
|
module type S = sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
val pre : out -> t -> unit
|
||||||
|
val post : out -> t -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
type 'a t = (module S with type t = 'a)
|
||||||
|
end
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
view: view; (** Document view *)
|
view: view; (** Document view *)
|
||||||
wfl: int; (** Width if flattened *)
|
wfl: int; (** Width if flattened *)
|
||||||
|
|
@ -13,6 +43,7 @@ and view =
|
||||||
| Text_sub of string * int * int
|
| Text_sub of string * int * int
|
||||||
| Group of t
|
| Group of t
|
||||||
| Fill of { sep: t; l: t list }
|
| Fill of { sep: t; l: t list }
|
||||||
|
| Wrap : 'a Ext.t * 'a * t -> view
|
||||||
|
|
||||||
let nil : t = { view = Nil; wfl = 0 }
|
let nil : t = { view = Nil; wfl = 0 }
|
||||||
let newline : t = { view = Newline; wfl = 1 }
|
let newline : t = { view = Newline; wfl = 1 }
|
||||||
|
|
@ -42,6 +73,7 @@ let group d : t =
|
||||||
| Group _ -> d
|
| Group _ -> d
|
||||||
| _ -> { view = Group d; wfl = d.wfl }
|
| _ -> { view = Group d; wfl = d.wfl }
|
||||||
|
|
||||||
|
let wrap ext v d : t = { view = Wrap (ext, v, d); wfl = d.wfl }
|
||||||
let ( ^ ) = append
|
let ( ^ ) = append
|
||||||
let text_sub_ s i len : t = { view = Text_sub (s, i, len); wfl = len }
|
let text_sub_ s i len : t = { view = Text_sub (s, i, len); wfl = len }
|
||||||
|
|
||||||
|
|
@ -76,8 +108,6 @@ let text (str : string) : t =
|
||||||
let textpf fmt = Printf.ksprintf text fmt
|
let textpf fmt = Printf.ksprintf text fmt
|
||||||
let textf fmt = Format.kasprintf text fmt
|
let textf fmt = Format.kasprintf text fmt
|
||||||
|
|
||||||
module B = Buffer
|
|
||||||
|
|
||||||
module Flatten = struct
|
module Flatten = struct
|
||||||
let to_buffer buf (self : t) : unit =
|
let to_buffer buf (self : t) : unit =
|
||||||
let rec loop (d : t) =
|
let rec loop (d : t) =
|
||||||
|
|
@ -98,7 +128,13 @@ module Flatten = struct
|
||||||
if i > 0 then loop sep;
|
if i > 0 then loop sep;
|
||||||
loop x)
|
loop x)
|
||||||
l
|
l
|
||||||
|
| Wrap ((module E), v, d) ->
|
||||||
|
let out = Ext.out_of_buf buf in
|
||||||
|
E.pre out v;
|
||||||
|
loop d;
|
||||||
|
E.post out v
|
||||||
in
|
in
|
||||||
|
|
||||||
loop self
|
loop self
|
||||||
|
|
||||||
let to_string self : string =
|
let to_string self : string =
|
||||||
|
|
@ -145,6 +181,12 @@ module Pretty = struct
|
||||||
n := !n + pp_flatten st x)
|
n := !n + pp_flatten st x)
|
||||||
l;
|
l;
|
||||||
!n
|
!n
|
||||||
|
| Wrap ((module E), v, d) ->
|
||||||
|
let out = Ext.out_of_buf st.buf in
|
||||||
|
E.pre out v;
|
||||||
|
let n = pp_flatten st d in
|
||||||
|
E.post out v;
|
||||||
|
n
|
||||||
|
|
||||||
(** Does [x] fit in the current line when flattened, given that [k] chars
|
(** Does [x] fit in the current line when flattened, given that [k] chars
|
||||||
are already on the line? *)
|
are already on the line? *)
|
||||||
|
|
@ -194,6 +236,12 @@ module Pretty = struct
|
||||||
) else
|
) else
|
||||||
pp_rec_top st ~k ~i x kont
|
pp_rec_top st ~k ~i x kont
|
||||||
| Fill { sep; l } -> pp_fill st ~k ~i sep l kont
|
| Fill { sep; l } -> pp_fill st ~k ~i sep l kont
|
||||||
|
| Wrap ((module E), v, d) ->
|
||||||
|
let out = Ext.out_of_buf st.buf in
|
||||||
|
E.pre out v;
|
||||||
|
pp_rec_top st ~k ~i d (fun k ->
|
||||||
|
E.post out v;
|
||||||
|
kont k)
|
||||||
|
|
||||||
and pp_fill st ~k ~i sep l (kont : int -> unit) : unit =
|
and pp_fill st ~k ~i sep l (kont : int -> unit) : unit =
|
||||||
(* [k] is the current offset in the line *)
|
(* [k] is the current offset in the line *)
|
||||||
|
|
|
||||||
|
|
@ -55,13 +55,42 @@ val newline : t
|
||||||
val nl : t
|
val nl : t
|
||||||
(** Alias for {!newline} *)
|
(** Alias for {!newline} *)
|
||||||
|
|
||||||
(* TODO:
|
(** Extension node.
|
||||||
val ext : pre:(unit -> string) -> post:(unit -> string) -> t -> t
|
|
||||||
(** Extension. This is a custom-rendered document.
|
In here, we can stuff custom printer nodes. *)
|
||||||
TODO: customize how long it is?
|
module Ext : sig
|
||||||
TODO: generic output, not [unit -> string]
|
module type OUT = sig
|
||||||
*)
|
val char : char -> unit
|
||||||
*)
|
val sub_string : string -> int -> int -> unit
|
||||||
|
val string : string -> unit
|
||||||
|
val newline : unit -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
type out = (module OUT)
|
||||||
|
|
||||||
|
module type S = sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
val pre : out -> t -> unit
|
||||||
|
val post : out -> t -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
type 'a t = (module S with type t = 'a)
|
||||||
|
end
|
||||||
|
|
||||||
|
val wrap : 'a Ext.t -> 'a -> t -> t
|
||||||
|
(** [wrap ext v d] wraps [d] with value [v].
|
||||||
|
|
||||||
|
It is a document that has the same
|
||||||
|
shape (and size) as [d], except that additional data will
|
||||||
|
be output when it is rendered.
|
||||||
|
|
||||||
|
Let [(module Ext)] be [ext], and [out]
|
||||||
|
be the output buffer/stream for rendering.
|
||||||
|
|
||||||
|
When this is rendered, first [Ext.pre out v] is called;
|
||||||
|
then [d] is printed; then [Exp.post out v] is called.
|
||||||
|
*)
|
||||||
|
|
||||||
(** {2 Pretty print and rendering} *)
|
(** {2 Pretty print and rendering} *)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,3 +39,22 @@ let () =
|
||||||
[ text "bar"; text "baaz"; sexp_apply "g" [ int 42; int 10 ] ]
|
[ text "bar"; text "baaz"; sexp_apply "g" [ int 42; int 10 ] ]
|
||||||
in
|
in
|
||||||
Pretty.to_string ~width:10 d)
|
Pretty.to_string ~width:10 d)
|
||||||
|
|
||||||
|
module Ext_coucou : Ext.S with type t = unit = struct
|
||||||
|
type t = unit
|
||||||
|
|
||||||
|
let pre (module O : Ext.OUT) () = O.string "<coucou>"
|
||||||
|
let post (module O : Ext.OUT) () = O.string "</coucou>"
|
||||||
|
end
|
||||||
|
|
||||||
|
let () =
|
||||||
|
eq ~name:"wrap1" ~printer:(spf "%S")
|
||||||
|
"(foo\n bar\n <coucou>(g 42 10)</coucou>)"
|
||||||
|
(let d =
|
||||||
|
sexp_apply "foo"
|
||||||
|
[
|
||||||
|
text "bar";
|
||||||
|
wrap (module Ext_coucou) () (sexp_apply "g" [ int 42; int 10 ]);
|
||||||
|
]
|
||||||
|
in
|
||||||
|
Pretty.to_string ~width:10 d)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue