Refresh re and cmdliner

This commit is contained in:
Jeremie Dimino 2017-05-02 14:08:41 +01:00
parent 868f75f146
commit bfb01f4bc3
25 changed files with 89 additions and 130 deletions

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
open Result
@ -30,12 +30,6 @@ module Term = struct
| Ok (`Help _ as help) -> Error help
| Error _ as e -> e
let ret_of_result ?(usage = false) = function
| Ok v -> `Ok v
| Error (`Msg e) -> `Error (usage, e)
let ret_result ?usage t = app (const @@ ret_of_result ?usage) t
let term_result ?(usage = false) (al, v) =
al, fun ei cl -> match v ei cl with
| Ok (Ok _ as ok) -> ok
@ -63,13 +57,12 @@ module Term = struct
let exit_info = Cmdliner_info.exit
let exit_status_success = 0
let exit_status_internal_error = 124
let exit_status_cli_error = 125
let exit_status_cli_error = 124
let exit_status_internal_error = 125
let default_error_exits =
[ exit_info exit_status_internal_error
~doc:"on unexpected internal errors (bugs).";
exit_info exit_status_cli_error
~doc:"on command line parsing errors."; ]
[ exit_info exit_status_cli_error ~doc:"on command line parsing errors.";
exit_info exit_status_internal_error
~doc:"on unexpected internal errors (bugs)."; ]
let default_exits =
(exit_info exit_status_success ~doc:"on success.") :: default_error_exits

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
(** Declarative definition of command line interfaces.
@ -22,7 +22,7 @@
use. Open the module to use it, it defines only three modules in
your scope.
{e %%VERSION%% {{:%%PKG_HOMEPAGE%% }homepage}} *)
{e v1.0.0 {{:http://erratique.ch/software/cmdliner }homepage}} *)
(** {1:top Interface} *)
@ -76,15 +76,14 @@ module Manpage : sig
(** The type for a man page. A title and the page text as a list of blocks. *)
type xref =
[ `Main | `Cmd of string | `Tool of string | `Page of int * string ]
[ `Main | `Cmd of string | `Tool of string | `Page of string * int ]
(** The type for man page cross-references.
{ul
{- [`Main] refers to the man page of the program itself.}
{- [`Cmd cmd] refers to the man page of the program's [cmd]
command (which must exist).}
{- [`Tool bin] refers to the command line tool named [bin].}
{- [`Page (sec, name)] refers to the man page [name] of section
[sec].}} *)
{- [`Page (name, sec)] refers to the man page [name(sec)].}} *)
(** {1:standard_sections Standard section names and content}
@ -224,16 +223,6 @@ module Term : sig
term's man page in the given [format] (or the man page for a
specific [name] term in case of multiple term evaluation).}} *)
val ret_of_result : ?usage:bool -> ('a, [`Msg of string]) result -> 'a ret
(** [ret_of_result ~usage r] is
{ul
{- [`Ok v] if [r] is [Ok v].}
{- [`Error (usage, e)] if [r] is [Error (`Msg e)], [usage] defaults
to [false]}} *)
val ret_result : ?usage:bool -> ('a, [`Msg of string]) result t -> 'a ret t
(** [ret_result ~usage r] is [app (const @@ ret_of_result ~usage) r]. *)
val term_result : ?usage:bool -> ('a, [`Msg of string]) result t -> 'a t
(** [term_result ~usage t] evaluates to
{ul
@ -425,17 +414,22 @@ module Term : sig
{b Note.} If you are using the following functions to handle
the evaluation result of a term you should add {!default_exits} to
the term's information {{!info}[~exits]} argument. *)
the term's information {{!info}[~exits]} argument.
{b WARNING.} You should avoid status codes strictly greater than 125
as those may be used by
{{:https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html}
some} shells. *)
val exit_status_success : int
(** [exit_status_success] is 0, the exit status for success. *)
val exit_status_cli_error : int
(** [exit_status_cli_error] is 125, an exit status for command line
(** [exit_status_cli_error] is 124, an exit status for command line
parsing errors. *)
val exit_status_internal_error : int
(** [exit_status_internal_error] is 124, an exit status for unexpected
(** [exit_status_internal_error] is 125, an exit status for unexpected
internal errors. *)
val exit_status_of_result : ?term_err:int -> 'a result -> int
@ -444,17 +438,12 @@ module Term : sig
{ul
{- {!exit_status_success} if [r] is one of [`Ok _], [`Version], [`Help]}
{- [term_err] if [r] is [`Error `Term], [term_err] defaults to [1].}
{- {!exit_status_internal_error} if [r] is [`Error `Exn]}
{- {!exit_status_cli_error} if [r] is [`Error `Parse]}} *)
{- {!exit_status_cli_error} if [r] is [`Error `Parse]}
{- {!exit_status_internal_error} if [r] is [`Error `Exn]}} *)
val exit_status_of_status_result : ?term_err:int -> int result -> int
(** [exit_status_of_status_result] is like {!exit_status_of_result}
except for [`Ok n] where [n] is used as the status exit code.
{b WARNING.} You should avoid status codes strictly greater than 125
as those may be used by
{{:https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html}
some} shells. *)
except for [`Ok n] where [n] is used as the status exit code. *)
val exit : ?term_err:int -> 'a result -> unit
(** [exit ~term_err r] is
@ -484,7 +473,8 @@ module Arg : sig
type 'a parser = string -> [ `Ok of 'a | `Error of string ]
(** The type for argument parsers.
@deprecated Use a parser with [('a, [ `Msg of string]) result] results. *)
@deprecated Use a parser with [('a, [ `Msg of string]) result] results
and {!conv}. *)
type 'a printer = Format.formatter -> 'a -> unit
(** The type for converted argument printers. *)
@ -500,7 +490,6 @@ module Arg : sig
(** @deprecated Use the {!type:conv} type via the {!val:conv} and {!pconv}
functions. *)
(*
val conv :
?docv:string -> (string -> ('a, [`Msg of string]) result) * 'a printer ->
'a conv
@ -509,7 +498,6 @@ module Arg : sig
[print]. [docv] is a documentation meta-variable used in the
documentation to stand for the argument value, defaults to
["VALUE"]. *)
*)
val pconv :
?docv:string -> 'a parser * 'a printer -> 'a conv
@ -533,7 +521,7 @@ module Arg : sig
(string -> ('a, [`Msg of string]) result)
(** [parser_of_kind_of_string ~kind kind_of_string] is an argument
parser using the [kind_of_string] function for parsing and [kind]
to report errors (e.g. could be "an integer" for an [int] parser.). *)
to report errors (e.g. could be ["an integer"] for an [int] parser.). *)
val some : ?none:string -> 'a conv -> 'a option conv
(** [some none c] is like the converter [c] except it returns
@ -586,10 +574,10 @@ module Arg : sig
The {{!doclang}documentation language} can be used and
the following variables are recognized:
{ul
{- ["$(docv)"] the value of [docv] (see below)}
{- ["$(docv)"] the value of [docv] (see below).}
{- ["$(opt)"], one of the options of [names], preference
is given to a long one.}
{- ["$(env)", the environment var specified by [env] (if any)]}}
{- ["$(env)"], the environment var specified by [env] (if any).}}
{{!doc_helpers}These functions} can help with formatting argument
values.}
{- [docv] is for positional and non-flag optional arguments.
@ -853,7 +841,7 @@ let () = Term.exit @@ Term.eval (revolt_t, Term.info "revolt")
]}
This defines a command line program named ["revolt"], without command
line arguments arguments, that just prints ["Revolt!"] on [stdout].
line arguments, that just prints ["Revolt!"] on [stdout].
{[
> ./revolt
@ -971,9 +959,9 @@ EXIT STATUS
0 on success.
124 on unexpected internal errors (bugs).
124 on command line parsing errors.
125 on command line parsing errors.
125 on unexpected internal errors (bugs).
ENVIRONMENT
These environment variables affect the execution of chorus:
@ -1039,8 +1027,8 @@ populated for you:
{- {{!Manpage.s_synopsis}[SYNOPSIS]} section.}}
The various [doc] documentation strings specified by the term's
subterms and additional metadata get integrated at the end of the
documentation section name [docs] they respecively mention, in the
subterms and additional metadata get inserted at the end of the
documentation section name [docs] they respectively mention, in the
following order:
{ol
@ -1052,18 +1040,18 @@ following order:
{- Environment variables, see {!Arg.env_var} and {!Term.env_info}.}}
If a [docs] section name is mentioned and does not exist in the term's
manual, an empty section is created for it, to which the [doc] strings
are intergrated, possibly prefixed by boilerplate text (e.g. for
manual, an empty section is created for it, after which the [doc] strings
are inserted, possibly prefixed by boilerplate text (e.g. for
{!Manpage.s_environment} and {!Manpage.s_exit_status}).
If the created section is:
{ul
{- {{!Manpage.standard_sections}standard}, it
is inserted at the right place in the order specified
{{!Manpage.standard_sections}here}, but after possible non-standard
section explicitely specified by the term as the latter get the order number
of the last previously specified standard section or the order of
{!Manpage.s_synopsis} if there is no such section.}
{{!Manpage.standard_sections}here}, but after a possible non-standard
section explicitely specified by the term since the latter get the
order number of the last previously specified standard section
or the order of {!Manpage.s_synopsis} if there is no such section.}
{- non-standard, it is inserted before the {!Manpage.s_commands}
section or the first subsequent existing standard section if it
doesn't exist. Taking advantage of this behaviour is discouraged,
@ -1265,7 +1253,7 @@ let cmd =
`S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ]
in
Term.(const rm $ prompt $ recursive $ files),
Term.info "rm" ~version:"%%VERSION%%" ~doc ~exits:Term.default_exits ~man
Term.info "rm" ~version:"v1.0.0" ~doc ~exits:Term.default_exits ~man
let () = Term.(exit @@ eval cmd)
]}
@ -1335,7 +1323,7 @@ let cmd =
`P "Email them to <hehey at example.org>."; ]
in
Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest)),
Term.info "cp" ~version:"%%VERSION%%" ~doc ~exits ~man ~man_xrefs
Term.info "cp" ~version:"v1.0.0" ~doc ~exits ~man ~man_xrefs
let () = Term.(exit @@ eval cmd)
]}
@ -1609,7 +1597,7 @@ let default_cmd =
let exits = Term.default_exits in
let man = help_secs in
Term.(ret (const (fun _ -> `Help (`Pager, None)) $ copts_t)),
Term.info "darcs" ~version:"%%VERSION%%" ~doc ~sdocs ~exits ~man
Term.info "darcs" ~version:"v1.0.0" ~doc ~sdocs ~exits ~man
let cmds = [initialize_cmd; record_cmd; help_cmd]

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
open Result

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
open Result

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
(* Invalid argument strings *)

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
(** A few helpful base definitions. *)

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
open Result

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
open Result

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
let rev_compare n0 n1 = compare n1 n0
@ -142,7 +142,7 @@ let arg_to_man_item ~errs ~subst ~buf a =
strf "%s $(b,%s) env" value (esc @@ Cmdliner_info.env_var e)
in
let absent = match Cmdliner_info.arg_absent a with
| Cmdliner_info.Err -> ""
| Cmdliner_info.Err -> "required"
| Cmdliner_info.Val v ->
match Lazy.force v with
| "" -> strf "%s" (or_env ~value:false a)
@ -258,14 +258,14 @@ let env_docs ~errs ~subst ~buf ~has_senv ei =
let xref_docs ~errs ei =
let main = Cmdliner_info.(term_name @@ eval_main ei) in
let to_xref = function
| `Main -> 1, main
| `Tool tool -> 1, tool
| `Page (sec, name) -> sec, name
| `Main -> main, 1
| `Tool tool -> tool, 1
| `Page (name, sec) -> name, sec
| `Cmd c ->
if Cmdliner_info.eval_has_choice ei c then 1, strf "%s-%s" main c else
(Format.fprintf errs "xref %s: no such term name@." c; 0, "doc-err")
if Cmdliner_info.eval_has_choice ei c then strf "%s-%s" main c, 1 else
(Format.fprintf errs "xref %s: no such term name@." c; "doc-err", 0)
in
let xref_str (sec, name) = strf "%s(%d)" (esc name) sec in
let xref_str (name, sec) = strf "%s(%d)" (esc name) sec in
let xrefs = Cmdliner_info.(term_man_xrefs @@ eval_term ei) in
let xrefs = List.fold_left (fun acc x -> to_xref x :: acc) [] xrefs in
let xrefs = List.(rev_map xref_str (sort rev_compare xrefs)) in

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
val plain_invocation : Cmdliner_info.eval -> string

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
(** Terms, argument, env vars information.

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
open Result
@ -17,7 +17,7 @@ type title = string * int * string * string * string
type t = title * block list
type xref =
[ `Main | `Cmd of string | `Tool of string | `Page of int * string ]
[ `Main | `Cmd of string | `Tool of string | `Page of string * int ]
(* Standard sections *)

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
(** Manpages.
@ -20,7 +20,7 @@ type title = string * int * string * string * string
type t = title * block list
type xref =
[ `Main | `Cmd of string | `Tool of string | `Page of int * string ]
[ `Main | `Cmd of string | `Tool of string | `Page of string * int ]
(** {1 Standard section names} *)

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
let strf = Printf.sprintf

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
(** Messages for the end-user. *)

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
let levenshtein_distance s t =

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
val value : string -> string list -> string list

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
open Result

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
open Result

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
module Cmap = Map.Make (Char) (* character maps. *)

View File

@ -1,7 +1,7 @@
(*---------------------------------------------------------------------------
Copyright (c) 2011 Daniel C. Bünzli. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
%%NAME%% %%VERSION%%
cmdliner v1.0.0
---------------------------------------------------------------------------*)
(** Tries.

34
vendor/re/src/re.mli vendored
View File

@ -127,20 +127,20 @@ end
type 'a gen = unit -> 'a option
val all :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
re -> string -> Group.t list
(** Repeatedly calls {!exec} on the given string, starting at given
position and length.*)
val all_gen :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
re -> string -> Group.t gen
(** Same as {!all} but returns a generator *)
val matches :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
re -> string -> string list
(** Same as {!all}, but extracts the matched substring rather than
@ -148,13 +148,13 @@ val matches :
strings *)
val matches_gen :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
re -> string -> string gen
(** Same as {!matches}, but returns a generator. *)
val split :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
re -> string -> string list
(** [split re s] splits [s] into chunks separated by [re]. It yields
@ -162,7 +162,7 @@ val split :
this can be used with a whitespace-matching re such as ["[\t ]+"]. *)
val split_gen :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
re -> string -> string gen
@ -172,34 +172,34 @@ type split_token =
]
val split_full :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
re -> string -> split_token list
val split_full_gen :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
re -> string -> split_token gen
val replace :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
?all:bool -> (* Default: true. Otherwise only replace first occurrence *)
re -> (* matched groups *)
?all:bool -> (** Default: true. Otherwise only replace first occurrence *)
re -> (** matched groups *)
f:(Group.t -> string) -> (* how to replace *)
string -> (* string to replace in *)
string -> (** string to replace in *)
string
(** [replace ~all re ~f s] iterates on [s], and replaces every occurrence
of [re] with [f substring] where [substring] is the current match.
If [all = false], then only the first occurrence of [re] is replaced. *)
val replace_string :
?pos:int -> (* Default: 0 *)
?pos:int -> (** Default: 0 *)
?len:int ->
?all:bool -> (* Default: true. Otherwise only replace first occurrence *)
re -> (* matched groups *)
by:string -> (* replacement string *)
string -> (* string to replace in *)
?all:bool -> (** Default: true. Otherwise only replace first occurrence *)
re -> (** matched groups *)
by:string -> (** replacement string *)
string -> (** string to replace in *)
string
(** [replace_string ~all re ~by s] iterates on [s], and replaces every
occurrence of [re] with [by]. If [all = false], then only the first

View File

@ -2,20 +2,14 @@
include Format
type 'a t = Format.formatter -> 'a -> unit
(* Only in the stdlib since 4.02, so we copy. *)
let rec list ?(pp_sep = pp_print_cut) pp ppf = function
let rec list pp ppf = function
| [] -> ()
| [v] -> pp ppf v
| v :: vs ->
pp ppf v;
pp_sep ppf ();
list ~pp_sep pp ppf vs
(* want this name to make sure we don't use pp_print_list from stdlib
accidentally *)
let pp_print_list = list
pp_print_space ppf ();
list pp ppf vs
let str = pp_print_string
let sexp fmt s pp x = fprintf fmt "@[<3>(%s@ %a)@]" s pp x
@ -29,19 +23,3 @@ let int = pp_print_int
let optint fmt = function
| None -> ()
| Some i -> fprintf fmt "@ %d" i
let quote fmt s = Format.fprintf fmt "\"%s\"" s
let pp_olist pp_elem fmt =
Format.fprintf fmt "@[<3>[@ %a@ ]@]"
(pp_print_list
~pp_sep:(fun fmt () -> fprintf fmt ";@ ")
pp_elem)
let pp_str_list = pp_olist quote
let to_to_string pp x =
let b = Buffer.create 16 in
let fmt = Format.formatter_of_buffer b in
pp fmt x;
Buffer.contents b