@@ -5,187 +5,164 @@ use crate::{
5
5
} ;
6
6
use std:: io;
7
7
8
+ #[ derive( Debug , Copy , Clone , Default ) ]
8
9
pub struct Ascii {
9
- use_ansi : bool ,
10
+ pub ansi : bool ,
11
+ #[ allow( unused) ] // TODO
12
+ pub fold : bool ,
13
+ pub box_drawing : bool ,
14
+ #[ doc( hidden) ] // to allow structural creation with `Ascii { ..Default::default() }`
15
+ pub __non_exhaustive : ( ) ,
10
16
}
11
17
12
18
impl Ascii {
13
- pub fn plain ( ) -> Self {
14
- Ascii { use_ansi : false }
19
+ pub fn new ( ) -> Self {
20
+ Default :: default ( )
15
21
}
16
22
17
- pub fn ansi ( ) -> Self {
18
- Ascii { use_ansi : true }
23
+ pub fn ansi ( & mut self , b : bool ) -> & mut Self {
24
+ self . ansi = b;
25
+ self
26
+ }
27
+
28
+ pub fn box_drawing ( & mut self , b : bool ) -> & mut Self {
29
+ self . box_drawing = b;
30
+ self
19
31
}
20
32
}
21
33
22
34
impl Ascii {
23
35
#[ inline( always) ]
24
- fn reset ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
25
- if self . use_ansi {
36
+ fn reset ( self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
37
+ if self . ansi {
26
38
write ! ( w, "\x1B [0m" )
27
39
} else {
28
40
Ok ( ( ) )
29
41
}
30
42
}
31
43
32
- fn bold ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
33
- if self . use_ansi {
34
- write ! ( w, "\x1B [0;1m" )
35
- } else {
36
- Ok ( ( ) )
37
- }
38
- }
39
-
40
- // fg(Fixed(9))
41
44
#[ inline( always) ]
42
- fn bright_red ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
43
- if self . use_ansi {
44
- write ! ( w, "\x1B [0;31;1m" )
45
- } else {
46
- Ok ( ( ) )
47
- }
48
- }
49
-
50
- // bold + fg(Fixed(9))
51
- #[ inline( always) ]
52
- fn bold_bright_red ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
53
- if self . use_ansi {
54
- write ! ( w, "\x1B [1;31;1m" )
55
- } else {
56
- Ok ( ( ) )
57
- }
58
- }
59
-
60
- // fg(Fixed(11))
61
- #[ inline( always) ]
62
- fn bright_yellow ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
63
- if self . use_ansi {
64
- write ! ( w, "\x1B [0;33;1m" )
65
- } else {
66
- Ok ( ( ) )
67
- }
68
- }
69
-
70
- // bold + fg(Fixed(11))
71
- #[ inline( always) ]
72
- fn bold_bright_yellow ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
73
- if self . use_ansi {
74
- write ! ( w, "\x1B [1;33;1m" )
75
- } else {
76
- Ok ( ( ) )
77
- }
78
- }
79
-
80
- // fg(Fixed(12))
81
- #[ inline( always) ]
82
- fn bright_blue ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
83
- if self . use_ansi {
84
- write ! ( w, "\x1B [0;34;1m" )
45
+ fn bold ( self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
46
+ if self . ansi {
47
+ write ! ( w, "\x1B [0;1m" )
85
48
} else {
86
49
Ok ( ( ) )
87
50
}
88
51
}
89
52
90
53
// bold + fg(Fixed(12))
91
54
#[ inline( always) ]
92
- fn bold_bright_blue ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
93
- if self . use_ansi {
55
+ fn bold_bright_blue ( self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
56
+ if self . ansi {
94
57
write ! ( w, "\x1B [1;34;1m" )
95
58
} else {
96
59
Ok ( ( ) )
97
60
}
98
61
}
99
62
100
- // fg(Fixed(14))
63
+ // FIXME: emitted ANSI codes are highly redundant when repeated
101
64
#[ inline( always) ]
102
- fn bright_cyan ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
103
- if self . use_ansi {
104
- write ! ( w, "\x1B [0;36;1m" )
65
+ fn style_for ( self , level : Level , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
66
+ if self . ansi {
67
+ match level {
68
+ Level :: Error => write ! ( w, "\x1B [0;31;1m" ) ,
69
+ Level :: Warning => write ! ( w, "\x1B [0;33;1m" ) ,
70
+ Level :: Info => write ! ( w, "\x1B [0;34;1m" ) ,
71
+ Level :: Note => self . reset ( w) ,
72
+ Level :: Help => write ! ( w, "\x1B [0;36;1m" ) ,
73
+ }
105
74
} else {
106
75
Ok ( ( ) )
107
76
}
108
77
}
109
78
110
- // bold + fg(Fixed(14))
79
+ // FIXME: emitted ANSI codes are highly redundant when repeated
111
80
#[ inline( always) ]
112
- fn bold_bright_cyan ( & self , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
113
- if self . use_ansi {
114
- write ! ( w, "\x1B [1;36;1m" )
81
+ fn style_bold_for ( self , level : Level , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
82
+ if self . ansi {
83
+ match level {
84
+ Level :: Error => write ! ( w, "\x1B [1;31;1m" ) ,
85
+ Level :: Warning => write ! ( w, "\x1B [1;33;1m" ) ,
86
+ Level :: Info => write ! ( w, "\x1B [1;34;1m" ) ,
87
+ Level :: Note => self . reset ( w) ,
88
+ Level :: Help => write ! ( w, "\x1B [1;36;1m" ) ,
89
+ }
115
90
} else {
116
91
Ok ( ( ) )
117
92
}
118
93
}
119
-
120
- // FIXME: emitted ANSI codes are highly redundant when repeated
121
- #[ inline( always) ]
122
- fn style_for ( & self , level : Level , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
123
- match level {
124
- Level :: Error => self . bright_red ( w) ,
125
- Level :: Warning => self . bright_yellow ( w) ,
126
- Level :: Info => self . bright_blue ( w) ,
127
- Level :: Note => self . reset ( w) ,
128
- Level :: Help => self . bright_cyan ( w) ,
129
- }
130
- }
131
-
132
- // FIXME: emitted ANSI codes are highly redundant when repeated
133
- #[ inline( always) ]
134
- fn style_bold_for ( & self , level : Level , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
135
- match level {
136
- Level :: Error => self . bold_bright_red ( w) ,
137
- Level :: Warning => self . bold_bright_yellow ( w) ,
138
- Level :: Info => self . bold_bright_blue ( w) ,
139
- Level :: Note => self . reset ( w) ,
140
- Level :: Help => self . bold_bright_cyan ( w) ,
141
- }
142
- }
143
94
}
144
95
145
96
impl Ascii {
146
- fn render_marks ( & self , marks : & [ Mark ] , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
97
+ fn render_marks ( self , marks : & [ Mark ] , w : & mut dyn io:: Write ) -> io:: Result < ( ) > {
147
98
for mark in marks {
148
99
self . style_for ( mark. level , w) ?;
149
- let c = match mark. kind {
150
- MarkKind :: Start => '/' ,
151
- MarkKind :: Continue => '|' ,
152
- MarkKind :: Here => '\\' ,
100
+ let c = if self . box_drawing {
101
+ match mark. kind {
102
+ MarkKind :: Start => '┌' ,
103
+ MarkKind :: Continue => '│' ,
104
+ MarkKind :: Here => '└' ,
105
+ }
106
+ } else {
107
+ match mark. kind {
108
+ MarkKind :: Start => '/' ,
109
+ MarkKind :: Continue => '|' ,
110
+ MarkKind :: Here => '\\' ,
111
+ }
153
112
} ;
154
113
write ! ( w, "{}" , c) ?;
155
114
}
156
115
self . reset ( w)
157
116
}
158
117
159
118
fn render_source_line < Span : crate :: Span > (
160
- & self ,
119
+ self ,
161
120
line : & SourceLine < ' _ , Span > ,
121
+ is_long : bool ,
162
122
f : & dyn SpanWriter < Span > ,
163
123
w : & mut dyn io:: Write ,
164
124
) -> io:: Result < ( ) > {
165
125
match line {
166
- SourceLine :: Content { span, subspan } => f. write ( w, span, subspan) ,
126
+ SourceLine :: Content { span, subspan } => {
127
+ write ! ( w, " " ) ?;
128
+ f. write ( w, span, subspan)
129
+ }
167
130
SourceLine :: Annotation { message, underline } => {
168
- write ! ( w, "{:>width$}" , "" , width = underline. 0 ) ?;
169
- self . style_bold_for ( message. map_or ( Level :: Info , |message| message. level ) , w) ?;
170
- // FIXME: respect level for pointer character
171
- if underline. 0 == 0 {
172
- write ! ( w, "{:_>width$} " , "^" , width = underline. 1 ) ?;
131
+ let ( indent, len) = if is_long {
132
+ ( 0 , underline. 0 + underline. 1 + 1 )
133
+ } else {
134
+ ( underline. 0 + 1 , underline. 1 )
135
+ } ;
136
+ write ! ( w, "{:>width$}" , "" , width = indent) ?;
137
+ let level = message. map_or ( Level :: Info , |message| message. level ) ;
138
+ self . style_bold_for ( level, w) ?;
139
+ if is_long {
140
+ if self . box_drawing {
141
+ write ! ( w, "{:─>width$} " , "┘" , width = len) ?;
142
+ } else {
143
+ write ! ( w, "{:_>width$} " , "^" , width = len) ?;
144
+ }
173
145
} else {
174
- write ! ( w, "{:->width$} " , "" , width = underline. 1 ) ?;
146
+ match level {
147
+ Level :: Error => write ! ( w, "{:^>width$} " , "" , width = len) ?,
148
+ Level :: Warning => write ! ( w, "{:~>width$} " , "" , width = len) ?,
149
+ Level :: Info | Level :: Help | Level :: Note => {
150
+ write ! ( w, "{:->width$} " , "" , width = len) ?
151
+ }
152
+ }
175
153
}
176
154
write ! (
177
155
w,
178
156
"{}" ,
179
157
message. map_or( & "" as & dyn DebugAndDisplay , |message| message. text)
180
- ) ?;
181
- self . reset ( w)
158
+ )
182
159
}
183
160
SourceLine :: Empty => Ok ( ( ) ) ,
184
161
}
185
162
}
186
163
187
164
fn render_raw_line (
188
- & self ,
165
+ self ,
189
166
line : & RawLine < ' _ > ,
190
167
line_num_width : usize ,
191
168
w : & mut dyn io:: Write ,
@@ -194,7 +171,11 @@ impl Ascii {
194
171
& RawLine :: Origin { path, pos } => {
195
172
write ! ( w, "{:>width$}" , "" , width = line_num_width) ?;
196
173
self . bold_bright_blue ( w) ?;
197
- write ! ( w, "-->" ) ?;
174
+ if self . box_drawing {
175
+ write ! ( w, "═╦═" ) ?;
176
+ } else {
177
+ write ! ( w, "-->" ) ?;
178
+ }
198
179
self . reset ( w) ?;
199
180
write ! ( w, " {}" , path) ?;
200
181
if let Some ( ( line, column) ) = pos {
@@ -228,7 +209,7 @@ impl Ascii {
228
209
write ! ( w, "[{}]" , code) ?;
229
210
}
230
211
self . bold ( w) ?;
231
- writeln ! ( w, ": {}" , title. message. text)
212
+ writeln ! ( w, ": {}" , title. message. text)
232
213
}
233
214
}
234
215
}
@@ -266,10 +247,11 @@ impl Renderer for Ascii {
266
247
line,
267
248
} => {
268
249
self . bold_bright_blue ( w) ?;
250
+ let sep = if self . box_drawing { '║' } else { '|' } ;
269
251
if let Some ( lineno) = lineno {
270
- write ! ( w, "{:>width$} | " , lineno, width = line_num_width) ?;
252
+ write ! ( w, "{:>width$} {} " , lineno, sep , width = line_num_width) ?;
271
253
} else {
272
- write ! ( w, "{:>width$} | " , "" , width = line_num_width) ?;
254
+ write ! ( w, "{:>width$} {} " , "" , sep , width = line_num_width) ?;
273
255
}
274
256
self . reset ( w) ?;
275
257
write ! (
@@ -279,7 +261,10 @@ impl Renderer for Ascii {
279
261
width = marks_width - inline_marks. len( )
280
262
) ?;
281
263
self . render_marks ( inline_marks, w) ?;
282
- self . render_source_line ( line, f, w) ?;
264
+ let is_long = inline_marks
265
+ . last ( )
266
+ . map_or ( false , |mark| mark. kind == MarkKind :: Here ) ;
267
+ self . render_source_line ( line, is_long, f, w) ?;
283
268
writeln ! ( w)
284
269
}
285
270
DisplayLine :: Raw ( line) => self . render_raw_line ( line, line_num_width, w) ,
0 commit comments