Source file html_output.ml
1
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
open! Core
open! Import
include Html_output_intf
module Make (Mtime : Mtime) = struct
let string_of_color ?(background = false) : Format.Color.t -> string = function
| Standard Black -> "#000000"
| Standard Red -> "#880000"
| Standard Green -> "#008800"
| Standard Yellow -> "#888800"
| Standard Blue -> "#000088"
| Standard Magenta -> "#880088"
| Standard Cyan -> "#008888"
| Standard White -> "#ffffff"
| Default -> if background then "#000000" else "#ffffff"
| Bright Black -> "#c0c0c0"
| Bright Red -> "#FF0000"
| Bright Green -> "#00FF00"
| Bright Yellow -> "#FFFF00"
| Bright Blue -> "#0000FF"
| Bright Magenta -> "#FF00FF"
| Bright Cyan -> "#00FFFF"
| Bright White -> "#FFFFFF"
| Rgb6 rgb ->
let r, g, b = Ansi_text.Color.Rgb6.to_rgb rgb in
let scaled x = x * 255 / 5 in
sprintf "rgb(%d,%d,%d)" (scaled r) (scaled g) (scaled b)
| Gray24 gray ->
let level = Ansi_text.Color.Gray24.to_level gray in
let scaled = level * 255 / 23 in
sprintf "rgb(%d,%d,%d)" scaled scaled scaled
| Rgb256 rgb ->
let r, g, b = Ansi_text.Color.Rgb256.to_rgb rgb in
sprintf "rgb(%d,%d,%d)" r g b
;;
module Style = struct
let apply text ~styles =
let start_tags, end_tags =
List.fold styles ~init:([], []) ~f:(fun (s, e) style ->
match (style : Format.Style.t) with
| Bold -> "<span style=\"font-weight:bold\">" :: s, "</span>" :: e
| Reset -> s, e
| Fg c ->
sprintf "<span style=\"color:%s\">" (string_of_color c) :: s, "</span>" :: e
| Bg c ->
( sprintf "<span style=\"background-color:%s\">" (string_of_color c) :: s
, "</span>" :: e )
| Underline | Italic -> "<u>" :: s, "</u>" :: e
| Blink -> "<span style=\"text-decoration:blink\">" :: s, "</span>" :: e
| Invert -> s, e
| Hide -> "<!-- " :: s, " -->" :: e
| Faint ->
( sprintf "<span style=\"color:%s\">" (string_of_color (Bright Black)) :: s
, "</span>" :: e )
| _ -> s, e)
in
let lst = start_tags @ [ text ] @ end_tags in
String.concat ~sep:"" lst
;;
end
let html_escape_char = function
| '<' -> "<"
| '>' -> ">"
| '&' -> "&"
| c -> String.of_char c
;;
let html_escape s = String.concat_map s ~f:html_escape_char
module Rule = struct
let apply text ~(rule : Format.Rule.t) ~refined =
let apply styles text = Style.apply text ~styles in
sprintf
"%s%s%s"
(apply rule.pre.styles rule.pre.text)
(if refined then apply [ Reset ] text else apply rule.styles (html_escape text))
(apply rule.suf.styles rule.suf.text)
;;
end
let ~(rules : Format.Rules.t) ~file_names:(prev_file, next_file) ~print =
let print_line file rule =
let get_time file =
match Mtime.mtime file with
| Ok time -> Time_float.to_string_utc time
| Error _ -> ""
in
let time = get_time file in
print (Rule.apply (sprintf !"%{File_name#hum} %s" file time) ~rule ~refined:false)
in
print_line prev_file rules.header_prev;
print_line next_file rules.header_next
;;
let print
~
~file_names:((prev_file, _) as file_names)
~(rules : Format.Rules.t)
~print
~location_style
hunks
=
print "<pre style=\"font-family:consolas,monospace\">";
if print_global_header then print_header ~rules ~file_names ~print;
let f hunk =
Format.Location_style.sprint
location_style
hunk
~prev_filename:(File_name.display_name prev_file)
~rule:(Rule.apply ~rule:rules.hunk ~refined:false)
|> print;
let handle_range : string Patience_diff.Range.t -> unit = function
| Same r ->
let mr = Array.map r ~f:snd in
Array.iter mr ~f:print
| Prev (r, _) | Next (r, _) | Unified (r, _) -> Array.iter r ~f:print
| Replace (ar1, ar2, _) ->
Array.iter ar1 ~f:print;
Array.iter ar2 ~f:print
in
List.iter hunk.ranges ~f:handle_range
in
List.iter hunks ~f;
print "</pre>"
;;
end
module Without_mtime = Make (struct
let mtime _ = Or_error.error_string "Mtime implementation not available"
end)
module Private = struct
module Make = Make
end