artify.ml 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. open CamomileLibrary
  2. let input_all ic =
  3. let bufsize = 512 in
  4. let buf = Bytes.create bufsize in
  5. let rec loop cur =
  6. match input ic buf 0 bufsize with
  7. | 0 -> close_in ic; cur
  8. | nread -> loop (cur ^ Bytes.sub_string buf 0 nread)
  9. in
  10. loop ""
  11. let pad_right s =
  12. let rec repeat s n = if n < 1 then "" else s ^ (repeat s (n - 1)) in
  13. let lines = Str.split (Str.regexp " *\n") s in
  14. let cmp_length max line =
  15. let l = String.length line in
  16. if l > max then l else max
  17. in
  18. let w = List.fold_left cmp_length 0 lines in
  19. let pad buf line = buf ^ line ^ repeat " " (w - String.length line + 1) ^ "\n" in
  20. List.fold_left pad "" lines
  21. let artify replace_pat s =
  22. let w = try String.index s '\n' + 1 with Not_found -> String.length s in
  23. let h = String.length s / w in
  24. let char_at x y =
  25. if x < 0 || y < 0 || x >= w || y >= h
  26. then ' '
  27. else String.get s (y * w + x)
  28. in
  29. let make_pat i =
  30. let x = i mod w in
  31. let y = i / w in
  32. let o ox oy = char_at (x + ox) (y + oy) in
  33. let m1 = -1 in
  34. [|o m1 m1; o 0 m1; o 1 m1;
  35. o m1 0; o 0 0; o 1 0;
  36. o m1 1; o 0 1; o 1 1|]
  37. in
  38. UTF8.init (String.length s) (fun i -> replace_pat (make_pat i))
  39. let u s = UTF8.get s 0
  40. let replace_pat_safe = function
  41. | [| _ ; '|'|'+'; _ ;
  42. '-'|'+'; '+' ; '-'|'+';
  43. _ ; '|'|'+'; _ |] -> u "┼"
  44. | [| _ ; _ ; _ ;
  45. '-'|'+'; '+' ; '-'|'+';
  46. _ ; '|'|'+'; _ |] -> u "┬"
  47. | [| _ ; '|'|'+'; _ ;
  48. '-'|'+'; '+' ; '-'|'+';
  49. _ ; _ ; _ |] -> u "┴"
  50. | [| _ ; '|'|'+'; _ ;
  51. _ ; '+' ; '-'|'+';
  52. _ ; '|'|'+'; _ |] -> u "├"
  53. | [| _ ; '|'|'+'; _ ;
  54. '-'|'+'; '+' ; _ ;
  55. _ ; '|'|'+'; _ |] -> u "┤"
  56. | [| _ ; _ ; _ ;
  57. _ ; '+' ; '-'|'+';
  58. _ ; '|'|'+'; _ |] -> u "┌"
  59. | [| _ ; '|'|'+'; _ ;
  60. _ ; '+' ; '-'|'+';
  61. _ ; _ ; _ |] -> u "└"
  62. | [| _ ; _ ; _ ;
  63. '-'|'+'; '+' ; _ ;
  64. _ ; '|'|'+'; _ |] -> u "┐"
  65. | [| _ ; '|'|'+'; _ ;
  66. '-'|'+'; '+' ; _ ;
  67. _ ; _ ; _ |] -> u "┘"
  68. | [| _ ; _ ; _ ;
  69. _ ; '-' ; '-'|'+';
  70. _ ; _ ; _ |]
  71. | [| _ ; _ ; _ ;
  72. '-'|'+'; '-' ; _ ;
  73. _ ; _ ; _ |] -> u "─"
  74. | [| _ ; _ ; _ ;
  75. _ ; '|' ; _ ;
  76. _ ; '|'|'+'; _ |]
  77. | [| _ ; '|'|'+'; _ ;
  78. _ ; '|' ; _ ;
  79. _ ; _ ; _ |] -> u "│"
  80. | [| _ ; '|'|'+'; _ ;
  81. '=' ; '+' ; '=' ;
  82. _ ; '|'|'+'; _ |] -> u "╪"
  83. | [| _ ; _ ; _ ;
  84. '=' ; '+' ; '=' ;
  85. _ ; '|'|'+'; _ |] -> u "╤"
  86. | [| _ ; '|'|'+'; _ ;
  87. '=' ; '+' ; '=' ;
  88. _ ; _ ; _ |] -> u "╧"
  89. | [| _ ; '|'|'+'; _ ;
  90. _ ; '+' ; '=' ;
  91. _ ; '|'|'+'; _ |] -> u "╞"
  92. | [| _ ; '|'|'+'; _ ;
  93. '=' ; '+' ; _ ;
  94. _ ; '|'|'+'; _ |] -> u "╡"
  95. | [| _ ; _ ; _ ;
  96. _ ; '+' ; '=' ;
  97. _ ; '|'|'+'; _ |] -> u "╒"
  98. | [| _ ; '|'|'+'; _ ;
  99. _ ; '+' ; '=' ;
  100. _ ; _ ; _ |] -> u "╘"
  101. | [| _ ; _ ; _ ;
  102. '=' ; '+' ; _ ;
  103. _ ; '|'|'+'; _ |] -> u "╕"
  104. | [| _ ; '|'|'+'; _ ;
  105. '=' ; '+' ; _ ;
  106. _ ; _ ; _ |] -> u "╛"
  107. | [| _ ; _ ; _ ;
  108. _ ; '=' ; '='|'+';
  109. _ ; _ ; _ |]
  110. | [| _ ; _ ; _ ;
  111. '='|'+'; '=' ; _ ;
  112. _ ; _ ; _ |] -> u "═"
  113. | [| _ ; _ ; _ ;
  114. _ ; c ; _ ;
  115. _ ; _ ; _ |] -> UChar.of_char c
  116. | _ -> failwith "invalid pattern"
  117. let replace_pat_unsafe =
  118. let both_double x y = if x = y then x else '-' in
  119. let pick_double x s = UTF8.get s (if x = '=' then 1 else 0) in
  120. function
  121. | [| _ ; ' '; _ ;
  122. ' '; '+'; ' ';
  123. _ ; ' '; _ |] -> u "·" (* XXX: maybe just leave the '+' *)
  124. | [| _ ; ' '; _ ;
  125. _ ; '+'; ' ';
  126. _ ; ' '; _ |] -> u "╴"
  127. | [| _ ; ' '; _ ;
  128. ' '; '+'; _ ;
  129. _ ; ' '; _ |] -> u "╶"
  130. | [| _ ; ' '; _ ;
  131. ' '; '+'; ' ';
  132. _ ; _ ; _ |] -> u "╷"
  133. | [| _ ; _ ; _ ;
  134. ' '; '+'; ' ';
  135. _ ; ' '; _ |] -> u "╵"
  136. | [| _ ; ' '; _ ;
  137. ' '; '+'; x ;
  138. _ ; _ ; _ |] -> pick_double x "┌╒"
  139. | [| _ ; _ ; _ ;
  140. ' '; '+'; x ;
  141. _ ; ' '; _ |] -> pick_double x "└╘"
  142. | [| _ ; ' '; _ ;
  143. x ; '+'; ' ';
  144. _ ; _ ; _ |] -> pick_double x "┐╕"
  145. | [| _ ; _ ; _ ;
  146. x ; '+'; ' ';
  147. _ ; ' '; _ |] -> pick_double x "┘╛"
  148. | [| _ ; ' '; _ ;
  149. x ; '+'; y ;
  150. _ ; _ ; _ |] -> pick_double (both_double x y) "┬╤"
  151. | [| _ ; _ ; _ ;
  152. x ; '+'; y ;
  153. _ ; ' '; _ |] -> pick_double (both_double x y) "┴╧"
  154. | [| _ ; _ ; _ ;
  155. ' '; '+'; x ;
  156. _ ; _ ; _ |] -> pick_double x "├╞"
  157. | [| _ ; _ ; _ ;
  158. x ; '+'; ' ';
  159. _ ; _ ; _ |] -> pick_double x "┤╡"
  160. | [| _ ; _ ; _ ;
  161. x ; '+'; y ;
  162. _ ; _ ; _ |] -> pick_double (both_double x y) "┼╪"
  163. | [| _ ; _ ; _ ;
  164. _ ; '-' ; '-'|'+';
  165. _ ; _ ; _ |]
  166. | [| _ ; _ ; _ ;
  167. '-'|'+'; '-' ; _ ;
  168. _ ; _ ; _ |] -> u "─"
  169. | [| _ ; _ ; _ ;
  170. _ ; '|' ; _ ;
  171. _ ; '|'|'+'; _ |]
  172. | [| _ ; '|'|'+'; _ ;
  173. _ ; '|' ; _ ;
  174. _ ; _ ; _ |] -> u "│"
  175. | [| _ ; _ ; _ ;
  176. '-'|'='|'+'; '='; _ ;
  177. _ ; _ ; _ |]
  178. | [|_ ; _ ; _ ;
  179. _ ; '='; '-'|'='|'+';
  180. _ ; _ ; _ |] -> u "═"
  181. | [|_; _; _;
  182. _; c; _;
  183. _; _; _|] -> UChar.of_char c
  184. | _ -> failwith "invalid pattern"
  185. let () =
  186. let args = List.tl (Array.to_list Sys.argv) in
  187. let replace_pat =
  188. if List.mem "-s" args
  189. then replace_pat_safe
  190. else replace_pat_unsafe
  191. in
  192. stdin |> input_all |> pad_right |> artify replace_pat |> print_endline