open ExtLib
open Format

let escape_char c =
  match c with
      '>' -> ">"
    | '<' -> "&lt;"
    | '&' -> "&amp;"
    | _ -> string_of_char c

let houtput print buf pos len =
  let ss = String.sub buf pos len in
  let es = String.replace_chars escape_char ss in
    print es

let hppf_of ppf =
  let output = houtput (pp_print_string ppf) in
  let flush = pp_print_flush ppf in
    make_formatter output flush

let hprintf ppf fmt = fprintf (hppf_of ppf) (fmt ^^ "@?")
let hprintf_of printer ppf = hprintf ppf "%a" printer

こういうコードを書いて,

let () = 
  hprintf Format.std_formatter "<pre>%a</pre>" Format.pp_print_string "hogehoge"

とかして,タグがエスケープされて出力されてウマーとか思っていたんだが,やっぱりダメだこれ.

let print_pair ppf (a,b) = Format.fprintf ppf "(%s,@\n%s)" a b
let () = 
  Format.fprintf Format.std_formatter "<pre>@[%a@]</pre>" (hprintf_of print_pair) ("hello","world")

とかすれば,HTMLタグのことを考えてないprint_pairも安全に出力できて最強なつもりだったのだが,hppf_ofのflushが変な感じになって,fprintfのボックスが閉じちゃうので,改行がそのまま出てしまう.

しばらく考えてみたんだけど,うまい方法を思いつかん.ExtLibのOOな入出力とかうまく使えばできるかも.