@@ -8,6 +8,7 @@ use crate::{
8
8
} ;
9
9
10
10
use arc_swap:: { ArcSwap , Guard } ;
11
+ use globset:: { Glob , GlobSet , GlobSetBuilder } ;
11
12
use slotmap:: { DefaultKey as LayerId , HopSlotMap } ;
12
13
13
14
use std:: {
@@ -25,6 +26,16 @@ use serde::{Deserialize, Serialize};
25
26
26
27
use helix_loader:: grammar:: { get_language, load_runtime_file} ;
27
28
29
+ fn deserialize_glob_set < ' de , D : serde:: Deserializer < ' de > > (
30
+ deserializer : D ,
31
+ ) -> Result < GlobSet , D :: Error > {
32
+ let globs = Vec :: < String > :: deserialize ( deserializer) ?;
33
+ let mut builder = GlobSetBuilder :: new ( ) ;
34
+ for glob in globs {
35
+ builder. add ( Glob :: new ( & glob) . map_err ( serde:: de:: Error :: custom) ?) ;
36
+ }
37
+ builder. build ( ) . map_err ( serde:: de:: Error :: custom)
38
+ }
28
39
fn deserialize_regex < ' de , D > ( deserializer : D ) -> Result < Option < Regex > , D :: Error >
29
40
where
30
41
D : serde:: Deserializer < ' de > ,
@@ -61,11 +72,14 @@ pub struct Configuration {
61
72
pub struct LanguageConfiguration {
62
73
#[ serde( rename = "name" ) ]
63
74
pub language_id : String , // c-sharp, rust
64
- pub scope : String , // source.rust
75
+ pub scope : String , // source.rust
76
+ #[ serde( default ) ]
65
77
pub file_types : Vec < String > , // filename ends_with? <Gemfile, rb, etc>
78
+ #[ serde( default , skip_serializing, deserialize_with = "deserialize_glob_set" ) ]
79
+ pub file_globs : GlobSet ,
66
80
#[ serde( default ) ]
67
81
pub shebangs : Vec < String > , // interpreter(s) associated with language
68
- pub roots : Vec < String > , // these indicate project roots <.git, Cargo.toml>
82
+ pub roots : Vec < String > , // these indicate project roots <.git, Cargo.toml>
69
83
pub comment_token : Option < String > ,
70
84
pub max_line_length : Option < usize > ,
71
85
@@ -436,6 +450,7 @@ pub struct Loader {
436
450
// highlight_names ?
437
451
language_configs : Vec < Arc < LanguageConfiguration > > ,
438
452
language_config_ids_by_file_type : HashMap < String , usize > , // Vec<usize>
453
+ language_config_ids_by_globset : Vec < ( GlobSet , usize ) > ,
439
454
language_config_ids_by_shebang : HashMap < String , usize > ,
440
455
441
456
scopes : ArcSwap < Vec < String > > ,
@@ -447,6 +462,7 @@ impl Loader {
447
462
language_configs : Vec :: new ( ) ,
448
463
language_config_ids_by_file_type : HashMap :: new ( ) ,
449
464
language_config_ids_by_shebang : HashMap :: new ( ) ,
465
+ language_config_ids_by_globset : Vec :: new ( ) ,
450
466
scopes : ArcSwap :: from_pointee ( Vec :: new ( ) ) ,
451
467
} ;
452
468
@@ -465,6 +481,9 @@ impl Loader {
465
481
. language_config_ids_by_shebang
466
482
. insert ( shebang. clone ( ) , language_id) ;
467
483
}
484
+ loader
485
+ . language_config_ids_by_globset
486
+ . push ( ( config. file_globs . clone ( ) , language_id) ) ;
468
487
469
488
loader. language_configs . push ( Arc :: new ( config) ) ;
470
489
}
@@ -478,16 +497,27 @@ impl Loader {
478
497
let configuration_id = path
479
498
. file_name ( )
480
499
. and_then ( |n| n. to_str ( ) )
481
- . and_then ( |file_name| self . language_config_ids_by_file_type . get ( file_name) )
500
+ . and_then ( |file_name| {
501
+ self . language_config_ids_by_file_type
502
+ . get ( file_name)
503
+ . copied ( )
504
+ } )
482
505
. or_else ( || {
483
506
path. extension ( )
484
507
. and_then ( |extension| extension. to_str ( ) )
485
- . and_then ( |extension| self . language_config_ids_by_file_type . get ( extension) )
486
- } ) ;
487
-
488
- configuration_id. and_then ( |& id| self . language_configs . get ( id) . cloned ( ) )
508
+ . and_then ( |extension| {
509
+ self . language_config_ids_by_file_type
510
+ . get ( extension)
511
+ . copied ( )
512
+ } )
513
+ } )
514
+ . or_else ( || {
515
+ self . language_config_ids_by_globset
516
+ . iter ( )
517
+ . find_map ( |( gs, id) | if gs. is_match ( path) { Some ( * id) } else { None } )
518
+ } ) ?;
489
519
490
- // TODO: content_regex handling conflict resolution
520
+ self . language_configs . get ( configuration_id ) . cloned ( )
491
521
}
492
522
493
523
pub fn language_config_for_shebang ( & self , source : & Rope ) -> Option < Arc < LanguageConfiguration > > {
0 commit comments