Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
inuit_format.ml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176external reraise : exn -> 'a = "%reraise" module Make (M : sig type flag end) : sig type cursor = M.flag Inuit.cursor val formatter_of_cursor : cursor -> Format.formatter val push_cursor : (cursor -> cursor) -> Format.formatter -> unit val push_flags : (M.flag list -> M.flag list) -> Format.formatter -> unit val pop : Format.formatter -> unit val with_cursor : (cursor -> cursor) -> (Format.formatter -> 'a -> 'b) -> Format.formatter -> 'a -> 'b val with_flags : (M.flag list -> M.flag list) -> (Format.formatter -> 'a -> 'b) -> Format.formatter -> 'a -> 'b end = struct type cursor = M.flag Inuit.cursor let magic_tag = "inuit-cookie" let = ref Empty type state = { mutable mark_head: cursor list; mutable mark_tail: cursor list; mutable print_stack: cursor list; } let formatter_of_cursor c = let state = { mark_head = [Inuit_cursor.sub c]; mark_tail = []; print_stack = [c] } in let pp = Format.make_formatter (fun txt ofs len -> let txt = if ofs = 0 && len = String.length txt then txt else String.sub txt ofs len in match state.mark_head with | [] -> assert false | c' :: cs -> let c = match state.print_stack with | [c] when Inuit.Cursor.is_closed c' -> let c = Inuit.Cursor.sub c in state.mark_head <- c :: cs; c | _ -> c' in Inuit.Cursor.text c txt ) (fun () -> ()) in let pop_tag tag = if tag == magic_tag then ( match state.mark_head with | [] -> assert false | [_] -> state.mark_head <- List.rev state.mark_tail; state.mark_tail <- [] | _ :: xs -> state.mark_head <- xs; ); "" in Format.pp_set_formatter_tag_functions pp { Format. mark_open_tag = pop_tag; mark_close_tag = pop_tag; print_open_tag = (fun tag -> if tag == magic_tag then ( match !magic_cookie with | Empty -> invalid_arg "Inuit_format.print_open_tag: handler not found (internal error?)" | Cursor f -> magic_cookie := Empty; begin match state.print_stack with | [] -> invalid_arg "Inuit_format.print_open_tag: stack is empty (internal error?)" | x :: _ -> let x = f x in state.print_stack <- x :: state.print_stack; state.mark_tail <- Inuit.Cursor.sub x :: state.mark_tail end | Flags f -> magic_cookie := Empty; begin match state.print_stack with | [] -> invalid_arg "Inuit_format.print_open_tag: stack is empty (internal error?)" | x :: _ -> let x = Inuit.Cursor.with_flags (f (Inuit.Cursor.get_flags x)) x in state.print_stack <- x :: state.print_stack; state.mark_tail <- Inuit.Cursor.sub x :: state.mark_tail end )); print_close_tag = (fun tag -> if tag == magic_tag then ( match state.print_stack with | _ :: (x :: _ as xs) -> state.print_stack <- xs; state.mark_tail <- Inuit.Cursor.sub x :: state.mark_tail; | [_] | [] -> invalid_arg "Inuit_format.print_close_tag: unbalanced tag" )); }; Format.pp_set_tags pp true; pp let push_cursor f pp = let = !magic_cookie in magic_cookie := Cursor f; match Format.pp_open_tag pp magic_tag with | () -> begin let = !magic_cookie in magic_cookie := magic_cookie'; match magic_cookie'' with | Empty -> () | _ -> invalid_arg "Inuit_format.push_cursor: not a cursor formatter" end | exception exn -> magic_cookie := magic_cookie'; reraise exn let push_flags f pp = let = !magic_cookie in magic_cookie := Flags f; match Format.pp_open_tag pp magic_tag with | () -> begin let = !magic_cookie in magic_cookie := magic_cookie'; match magic_cookie'' with | Empty -> () | _ -> invalid_arg "Inuit_format.push_flags: not a cursor formatter" end | exception exn -> magic_cookie := magic_cookie'; reraise exn let pop pp = Format.pp_close_tag pp () let with_cursor f k pp x = push_cursor f pp; match k pp x with | result -> pop pp; result | exception exn -> pop pp; reraise exn let with_flags f k pp x = push_flags f pp; match k pp x with | result -> pop pp; result | exception exn -> pop pp; reraise exn let null_formatter = let pp = Format.make_formatter (fun _ _ _ -> ()) (fun () -> ()) in Format.pp_set_mark_tags pp false; Format.pp_set_print_tags pp true; Format.pp_set_formatter_tag_functions pp { Format. mark_open_tag = (fun _ -> ""); mark_close_tag = (fun _ -> ""); print_open_tag = (fun tag -> if tag == magic_tag then (magic_cookie := Empty)); print_close_tag = (fun _ -> ()); }; pp end