1+ use std:: path:: Path ;
2+
3+ use serde:: Deserialize ;
4+
15/// Configuration for the formatter.
2- #[ derive( Debug , Clone ) ]
6+ #[ derive( Debug , Clone , Deserialize ) ]
7+ #[ serde( default ) ]
38pub struct FormatterConfig {
49 /// Number of spaces for indentation (default: 2)
510 pub indent_size : usize ,
611 /// Whether to add blank lines between steps (default: true)
712 pub separate_steps : bool ,
813 /// Whether to add blank lines between jobs (default: true)
914 pub separate_jobs : bool ,
15+ /// Files to ignore (can be full paths like `.github/workflows/ci.yml` or just filenames like `ci.yml`)
16+ pub ignore : Vec < String > ,
1017}
1118
1219impl Default for FormatterConfig {
@@ -15,6 +22,56 @@ impl Default for FormatterConfig {
1522 indent_size : 2 ,
1623 separate_steps : true ,
1724 separate_jobs : true ,
25+ ignore : Vec :: new ( ) ,
1826 }
1927 }
2028}
29+
30+ impl FormatterConfig {
31+ /// Load configuration from a TOML file, falling back to defaults if file doesn't exist.
32+ pub fn from_file ( path : & Path ) -> Result < Self , ConfigError > {
33+ if !path. exists ( ) {
34+ return Ok ( Self :: default ( ) ) ;
35+ }
36+
37+ let content = std:: fs:: read_to_string ( path) . map_err ( |e| ConfigError :: Read {
38+ path : path. to_path_buf ( ) ,
39+ source : e,
40+ } ) ?;
41+
42+ toml:: from_str ( & content) . map_err ( |e| ConfigError :: Parse {
43+ path : path. to_path_buf ( ) ,
44+ source : e,
45+ } )
46+ }
47+
48+ /// Check if a file should be ignored based on the ignore patterns.
49+ pub fn should_ignore ( & self , path : & Path ) -> bool {
50+ let path_str = path. to_string_lossy ( ) ;
51+ let file_name = path. file_name ( ) . and_then ( |n| n. to_str ( ) ) ;
52+
53+ self . ignore . iter ( ) . any ( |pattern| {
54+ // Match full path
55+ path_str == * pattern
56+ || path_str. ends_with ( pattern)
57+ // Match just the filename
58+ || file_name. is_some_and ( |name| name == pattern)
59+ } )
60+ }
61+ }
62+
63+ #[ derive( Debug , thiserror:: Error ) ]
64+ pub enum ConfigError {
65+ #[ error( "failed to read config file '{path}'" ) ]
66+ Read {
67+ path : std:: path:: PathBuf ,
68+ #[ source]
69+ source : std:: io:: Error ,
70+ } ,
71+ #[ error( "failed to parse config file '{path}'" ) ]
72+ Parse {
73+ path : std:: path:: PathBuf ,
74+ #[ source]
75+ source : toml:: de:: Error ,
76+ } ,
77+ }
0 commit comments