type sexpr = Atom of string | Node of string * sexpr list type rope = Leaf of string | Concat of rope list let (^+) s r = Concat [Leaf s; r] let (+^) r s = Concat [r; Leaf s] let rec iter f = function | Leaf s -> f s | Concat rs -> List.iter (iter f) rs let rec concat = function | Leaf s -> s | Concat rs -> String.concat "" (List.map concat rs) let rec pp off width = function | Atom s -> String.length s, Leaf s | Node (s, xs) -> let lens, rs = List.split (List.map (pp (off + 2) width) xs) in let len = String.length s + List.length rs + List.fold_left (+) 2 lens in let sep, fin = if off + len <= width then " ", "" else let indent = String.make off ' ' in "\n " ^ indent, "\n" ^ indent in len, "(" ^+ s ^+ Concat (List.map (fun r -> sep ^+ r) rs) +^ fin +^ ")" let output oc width x = iter (output_string oc) (snd (pp 0 width x)); output_string oc "\n"; flush oc let print = output stdout let to_string width x = concat (snd (pp 0 width x)) ^ "\n"