@@ -4,7 +4,8 @@ use kstring::KString;
4
4
5
5
use crate :: file_type_specifics;
6
6
7
- pub const SUPPORTED_FILE_NAMES : & [ & str ] = & [ "typos.toml" , "_typos.toml" , ".typos.toml" ] ;
7
+ pub const SUPPORTED_FILE_NAMES : & [ & str ] =
8
+ & [ "typos.toml" , "_typos.toml" , ".typos.toml" , "pyproject.toml" ] ;
8
9
9
10
#[ derive( Debug , Clone , Default , PartialEq , Eq , serde:: Serialize , serde:: Deserialize ) ]
10
11
#[ serde( deny_unknown_fields) ]
@@ -19,26 +20,54 @@ pub struct Config {
19
20
pub overrides : EngineConfig ,
20
21
}
21
22
23
+ #[ derive( Debug , Clone , Default , PartialEq , Eq , serde:: Serialize , serde:: Deserialize ) ]
24
+ #[ serde( default ) ]
25
+ #[ serde( rename_all = "kebab-case" ) ]
26
+ pub struct PyprojectTomlConfig {
27
+ pub tool : PyprojectTomlTool ,
28
+ }
29
+
30
+ #[ derive( Debug , Clone , Default , PartialEq , Eq , serde:: Serialize , serde:: Deserialize ) ]
31
+ #[ serde( default ) ]
32
+ #[ serde( rename_all = "kebab-case" ) ]
33
+ pub struct PyprojectTomlTool {
34
+ pub typos : Option < Config > ,
35
+ }
36
+
22
37
impl Config {
23
38
pub fn from_dir ( cwd : & std:: path:: Path ) -> Result < Option < Self > , anyhow:: Error > {
24
- let config = if let Some ( path) = find_project_file ( cwd, SUPPORTED_FILE_NAMES ) {
25
- log:: debug!( "Loading {}" , path. display( ) ) ;
26
- Some ( Self :: from_file ( & path) ?)
27
- } else {
28
- None
29
- } ;
30
- Ok ( config)
39
+ for file in find_project_files ( cwd, SUPPORTED_FILE_NAMES ) {
40
+ log:: debug!( "Loading {}" , file. display( ) ) ;
41
+ if let Some ( config) = Self :: from_file ( & file) ? {
42
+ return Ok ( Some ( config) ) ;
43
+ }
44
+ }
45
+
46
+ Ok ( None )
31
47
}
32
48
33
- pub fn from_file ( path : & std:: path:: Path ) -> Result < Self , anyhow:: Error > {
49
+ pub fn from_file ( path : & std:: path:: Path ) -> Result < Option < Self > , anyhow:: Error > {
34
50
let s = std:: fs:: read_to_string ( path) . map_err ( |err| {
35
51
let kind = err. kind ( ) ;
36
52
std:: io:: Error :: new (
37
53
kind,
38
54
format ! ( "could not read config at `{}`" , path. display( ) ) ,
39
55
)
40
56
} ) ?;
41
- Self :: from_toml ( & s)
57
+
58
+ if path. file_name ( ) . unwrap ( ) == "pyproject.toml" {
59
+ let config = toml:: from_str :: < PyprojectTomlConfig > ( & s) ?;
60
+
61
+ if config. tool . typos . is_none ( ) {
62
+ log:: debug!( "No `tool.typos` section found in `pyproject.toml`, skipping" ) ;
63
+
64
+ Ok ( None )
65
+ } else {
66
+ Ok ( config. tool . typos )
67
+ }
68
+ } else {
69
+ Self :: from_toml ( & s) . map ( Some )
70
+ }
42
71
}
43
72
44
73
pub fn from_toml ( data : & str ) -> Result < Self , anyhow:: Error > {
@@ -455,15 +484,14 @@ impl DictConfig {
455
484
}
456
485
}
457
486
458
- fn find_project_file ( dir : & std:: path:: Path , names : & [ & str ] ) -> Option < std:: path:: PathBuf > {
459
- let mut file_path = dir. join ( "placeholder" ) ;
460
- for name in names {
461
- file_path. set_file_name ( name) ;
462
- if file_path. exists ( ) {
463
- return Some ( file_path) ;
464
- }
465
- }
466
- None
487
+ fn find_project_files < ' a > (
488
+ dir : & ' a std:: path:: Path ,
489
+ names : & ' a [ & ' a str ] ,
490
+ ) -> impl Iterator < Item = std:: path:: PathBuf > + ' a {
491
+ names
492
+ . iter ( )
493
+ . map ( |name| dir. join ( name) )
494
+ . filter ( |path| path. exists ( ) )
467
495
}
468
496
469
497
impl PartialEq for DictConfig {
0 commit comments