@@ -53,20 +53,34 @@ impl Loader {
53
53
54
54
/// Loads a theme searching directories in priority order.
55
55
pub fn load ( & self , name : & str ) -> Result < Theme > {
56
+ let ( theme, warnings) = self . load_with_warnings ( name) ?;
57
+
58
+ for warning in warnings {
59
+ warn ! ( "Theme '{}': {}" , name, warning) ;
60
+ }
61
+
62
+ Ok ( theme)
63
+ }
64
+
65
+ /// Loads a theme searching directories in priority order, returning any warnings
66
+ pub fn load_with_warnings ( & self , name : & str ) -> Result < ( Theme , Vec < String > ) > {
56
67
if name == "default" {
57
- return Ok ( self . default ( ) ) ;
68
+ return Ok ( ( self . default ( ) , Vec :: new ( ) ) ) ;
58
69
}
59
70
if name == "base16_default" {
60
- return Ok ( self . base16_default ( ) ) ;
71
+ return Ok ( ( self . base16_default ( ) , Vec :: new ( ) ) ) ;
61
72
}
62
73
63
74
let mut visited_paths = HashSet :: new ( ) ;
64
- let theme = self . load_theme ( name, & mut visited_paths) . map ( Theme :: from) ?;
75
+ let ( theme, warnings) = self
76
+ . load_theme ( name, & mut visited_paths)
77
+ . map ( Theme :: from_toml) ?;
65
78
66
- Ok ( Theme {
79
+ let theme = Theme {
67
80
name : name. into ( ) ,
68
81
..theme
69
- } )
82
+ } ;
83
+ Ok ( ( theme, warnings) )
70
84
}
71
85
72
86
/// Recursively load a theme, merging with any inherited parent themes.
@@ -87,10 +101,7 @@ impl Loader {
87
101
88
102
let theme_toml = if let Some ( parent_theme_name) = inherits {
89
103
let parent_theme_name = parent_theme_name. as_str ( ) . ok_or_else ( || {
90
- anyhow ! (
91
- "Theme: expected 'inherits' to be a string: {}" ,
92
- parent_theme_name
93
- )
104
+ anyhow ! ( "Expected 'inherits' to be a string: {}" , parent_theme_name)
94
105
} ) ?;
95
106
96
107
let parent_theme_toml = match parent_theme_name {
@@ -181,9 +192,9 @@ impl Loader {
181
192
} )
182
193
. ok_or_else ( || {
183
194
if cycle_found {
184
- anyhow ! ( "Theme: cycle found in inheriting: {}" , name)
195
+ anyhow ! ( "Cycle found in inheriting: {}" , name)
185
196
} else {
186
- anyhow ! ( "Theme: file not found for: {}" , name)
197
+ anyhow ! ( "File not found for: {}" , name)
187
198
}
188
199
} )
189
200
}
@@ -220,19 +231,11 @@ pub struct Theme {
220
231
221
232
impl From < Value > for Theme {
222
233
fn from ( value : Value ) -> Self {
223
- if let Value :: Table ( table) = value {
224
- let ( styles, scopes, highlights) = build_theme_values ( table) ;
225
-
226
- Self {
227
- styles,
228
- scopes,
229
- highlights,
230
- ..Default :: default ( )
231
- }
232
- } else {
233
- warn ! ( "Expected theme TOML value to be a table, found {:?}" , value) ;
234
- Default :: default ( )
234
+ let ( theme, warnings) = Theme :: from_toml ( value) ;
235
+ for warning in warnings {
236
+ warn ! ( "{}" , warning) ;
235
237
}
238
+ theme
236
239
}
237
240
}
238
241
@@ -242,31 +245,29 @@ impl<'de> Deserialize<'de> for Theme {
242
245
D : Deserializer < ' de > ,
243
246
{
244
247
let values = Map :: < String , Value > :: deserialize ( deserializer) ?;
245
-
246
- let ( styles, scopes, highlights) = build_theme_values ( values) ;
247
-
248
- Ok ( Self {
249
- styles,
250
- scopes,
251
- highlights,
252
- ..Default :: default ( )
253
- } )
248
+ let ( theme, warnings) = Theme :: from_keys ( values) ;
249
+ for warning in warnings {
250
+ warn ! ( "{}" , warning) ;
251
+ }
252
+ Ok ( theme)
254
253
}
255
254
}
256
255
257
256
fn build_theme_values (
258
257
mut values : Map < String , Value > ,
259
- ) -> ( HashMap < String , Style > , Vec < String > , Vec < Style > ) {
258
+ ) -> ( HashMap < String , Style > , Vec < String > , Vec < Style > , Vec < String > ) {
260
259
let mut styles = HashMap :: new ( ) ;
261
260
let mut scopes = Vec :: new ( ) ;
262
261
let mut highlights = Vec :: new ( ) ;
263
262
263
+ let mut warnings = Vec :: new ( ) ;
264
+
264
265
// TODO: alert user of parsing failures in editor
265
266
let palette = values
266
267
. remove ( "palette" )
267
268
. map ( |value| {
268
269
ThemePalette :: try_from ( value) . unwrap_or_else ( |err| {
269
- warn ! ( "{}" , err) ;
270
+ warnings . push ( err) ;
270
271
ThemePalette :: default ( )
271
272
} )
272
273
} )
@@ -279,7 +280,7 @@ fn build_theme_values(
279
280
for ( name, style_value) in values {
280
281
let mut style = Style :: default ( ) ;
281
282
if let Err ( err) = palette. parse_style ( & mut style, style_value) {
282
- warn ! ( "{}" , err) ;
283
+ warnings . push ( err) ;
283
284
}
284
285
285
286
// these are used both as UI and as highlights
@@ -288,7 +289,7 @@ fn build_theme_values(
288
289
highlights. push ( style) ;
289
290
}
290
291
291
- ( styles, scopes, highlights)
292
+ ( styles, scopes, highlights, warnings )
292
293
}
293
294
294
295
impl Theme {
@@ -354,6 +355,27 @@ impl Theme {
354
355
. all ( |color| !matches ! ( color, Some ( Color :: Rgb ( ..) ) ) )
355
356
} )
356
357
}
358
+
359
+ fn from_toml ( value : Value ) -> ( Self , Vec < String > ) {
360
+ if let Value :: Table ( table) = value {
361
+ Theme :: from_keys ( table)
362
+ } else {
363
+ warn ! ( "Expected theme TOML value to be a table, found {:?}" , value) ;
364
+ Default :: default ( )
365
+ }
366
+ }
367
+
368
+ fn from_keys ( toml_keys : Map < String , Value > ) -> ( Self , Vec < String > ) {
369
+ let ( styles, scopes, highlights, load_errors) = build_theme_values ( toml_keys) ;
370
+
371
+ let theme = Self {
372
+ styles,
373
+ scopes,
374
+ highlights,
375
+ ..Default :: default ( )
376
+ } ;
377
+ ( theme, load_errors)
378
+ }
357
379
}
358
380
359
381
struct ThemePalette {
@@ -408,7 +430,7 @@ impl ThemePalette {
408
430
if let Ok ( index) = s. parse :: < u8 > ( ) {
409
431
return Ok ( Color :: Indexed ( index) ) ;
410
432
}
411
- Err ( format ! ( "Theme: malformed ANSI: {}" , s) )
433
+ Err ( format ! ( "Malformed ANSI: {}" , s) )
412
434
}
413
435
414
436
fn hex_string_to_rgb ( s : & str ) -> Result < Color , String > {
@@ -422,13 +444,13 @@ impl ThemePalette {
422
444
}
423
445
}
424
446
425
- Err ( format ! ( "Theme: malformed hexcode: {}" , s) )
447
+ Err ( format ! ( "Malformed hexcode: {}" , s) )
426
448
}
427
449
428
450
fn parse_value_as_str ( value : & Value ) -> Result < & str , String > {
429
451
value
430
452
. as_str ( )
431
- . ok_or ( format ! ( "Theme: unrecognized value: {}" , value) )
453
+ . ok_or ( format ! ( "Unrecognized value: {}" , value) )
432
454
}
433
455
434
456
pub fn parse_color ( & self , value : Value ) -> Result < Color , String > {
@@ -445,14 +467,14 @@ impl ThemePalette {
445
467
value
446
468
. as_str ( )
447
469
. and_then ( |s| s. parse ( ) . ok ( ) )
448
- . ok_or ( format ! ( "Theme: invalid modifier: {}" , value) )
470
+ . ok_or ( format ! ( "Invalid modifier: {}" , value) )
449
471
}
450
472
451
473
pub fn parse_underline_style ( value : & Value ) -> Result < UnderlineStyle , String > {
452
474
value
453
475
. as_str ( )
454
476
. and_then ( |s| s. parse ( ) . ok ( ) )
455
- . ok_or ( format ! ( "Theme: invalid underline style: {}" , value) )
477
+ . ok_or ( format ! ( "Invalid underline style: {}" , value) )
456
478
}
457
479
458
480
pub fn parse_style ( & self , style : & mut Style , value : Value ) -> Result < ( ) , String > {
@@ -462,9 +484,7 @@ impl ThemePalette {
462
484
"fg" => * style = style. fg ( self . parse_color ( value) ?) ,
463
485
"bg" => * style = style. bg ( self . parse_color ( value) ?) ,
464
486
"underline" => {
465
- let table = value
466
- . as_table_mut ( )
467
- . ok_or ( "Theme: underline must be table" ) ?;
487
+ let table = value. as_table_mut ( ) . ok_or ( "Underline must be table" ) ?;
468
488
if let Some ( value) = table. remove ( "color" ) {
469
489
* style = style. underline_color ( self . parse_color ( value) ?) ;
470
490
}
@@ -473,13 +493,11 @@ impl ThemePalette {
473
493
}
474
494
475
495
if let Some ( attr) = table. keys ( ) . next ( ) {
476
- return Err ( format ! ( "Theme: invalid underline attribute: {attr}" ) ) ;
496
+ return Err ( format ! ( "Invalid underline attribute: {attr}" ) ) ;
477
497
}
478
498
}
479
499
"modifiers" => {
480
- let modifiers = value
481
- . as_array ( )
482
- . ok_or ( "Theme: modifiers should be an array" ) ?;
500
+ let modifiers = value. as_array ( ) . ok_or ( "Modifiers should be an array" ) ?;
483
501
484
502
for modifier in modifiers {
485
503
if modifier
@@ -492,7 +510,7 @@ impl ThemePalette {
492
510
}
493
511
}
494
512
}
495
- _ => return Err ( format ! ( "Theme: invalid style attribute: {}" , name) ) ,
513
+ _ => return Err ( format ! ( "Invalid style attribute: {}" , name) ) ,
496
514
}
497
515
}
498
516
} else {
0 commit comments