@@ -120,20 +120,24 @@ impl AppConfig {
120120 None => home_dir ( ) . unwrap ( ) . join ( ".config/hj/config.toml" ) ,
121121 } ;
122122 // println!("global config path: {:?}", global_config_path);
123- let mut local_config_path = PathBuf :: new ( ) ;
124- if let Ok ( mut base) = env:: current_dir ( ) {
125- base. push ( "hj.toml" ) ;
126- local_config_path = base;
127- }
123+
124+ // Recursively search for hj.toml upwards from current directory
125+ let local_config_path = Self :: find_local_config ( ) ;
128126
129127 let default = AppConfig :: default ( ) ;
130128
131129 // load config
132- let builder = Config :: builder ( )
130+ let mut builder = Config :: builder ( )
133131 // load file (if exists)
134132 . add_source ( Config :: try_from ( & default) ?)
135- . add_source ( File :: from ( global_config_path) . required ( false ) )
136- . add_source ( File :: from ( local_config_path) . required ( false ) )
133+ . add_source ( File :: from ( global_config_path) . required ( false ) ) ;
134+
135+ // Add local config if found
136+ if let Some ( path) = local_config_path {
137+ builder = builder. add_source ( File :: from ( path) . required ( false ) ) ;
138+ }
139+
140+ let builder = builder
137141 // load environment variables with prefix HJ_
138142 . add_source (
139143 Environment :: with_prefix ( "HJ" )
@@ -144,4 +148,24 @@ impl AppConfig {
144148 let config = builder. build ( ) ?;
145149 config. try_deserialize ( )
146150 }
151+
152+ /// Recursively search for hj.toml upwards from the current directory
153+ fn find_local_config ( ) -> Option < PathBuf > {
154+ let mut current_dir = env:: current_dir ( ) . ok ( ) ?;
155+
156+ loop {
157+ let config_path = current_dir. join ( "hj.toml" ) ;
158+ if config_path. exists ( ) {
159+ return Some ( config_path) ;
160+ }
161+
162+ // Move to parent directory
163+ if !current_dir. pop ( ) {
164+ // Reached the root directory
165+ break ;
166+ }
167+ }
168+
169+ None
170+ }
147171}
0 commit comments