@@ -8,6 +8,9 @@ use std::path::PathBuf;
88
99#[ derive( Debug , Clone , Default , Serialize , Deserialize ) ]
1010pub struct Config {
11+ #[ serde( skip) ]
12+ pub path : Option < PathBuf > ,
13+
1114 #[ serde( default ) ]
1215 pub ui : UiConfig ,
1316
@@ -38,6 +41,9 @@ pub struct UiConfig {
3841 #[ serde( default = "default_theme" ) ]
3942 pub theme : String ,
4043
44+ #[ serde( default = "default_code_theme" ) ]
45+ pub code_theme : String ,
46+
4147 #[ serde( default = "default_outline_width" ) ]
4248 pub outline_width : u16 ,
4349
@@ -241,6 +247,7 @@ impl Default for UiConfig {
241247 fn default ( ) -> Self {
242248 Self {
243249 theme : default_theme ( ) ,
250+ code_theme : default_code_theme ( ) ,
244251 outline_width : default_outline_width ( ) ,
245252 tree_style : default_tree_style ( ) ,
246253 }
@@ -264,6 +271,10 @@ fn default_theme() -> String {
264271 "OceanDark" . to_string ( )
265272}
266273
274+ fn default_code_theme ( ) -> String {
275+ "base16-ocean.dark" . to_string ( )
276+ }
277+
267278fn default_outline_width ( ) -> u16 {
268279 30
269280}
@@ -284,55 +295,56 @@ impl Config {
284295 /// - macOS: ~/Library/Application Support/treemd/config.toml
285296 /// - Linux: ~/.config/treemd/config.toml
286297 /// - Windows: %APPDATA%/treemd/config.toml
287- pub fn config_path ( ) -> Option < PathBuf > {
298+ fn config_path ( ) -> Option < PathBuf > {
288299 dirs:: config_dir ( ) . map ( |p| p. join ( "treemd" ) . join ( "config.toml" ) )
289300 }
290301
291- /// Load config from file, or return default if file doesn't exist
302+ /// Resolve the config file path
292303 /// On macOS, checks ~/.config/treemd first, then falls back to ~/Library/Application Support
293- pub fn load ( ) -> Self {
304+ fn resolve_config_path ( ) -> Option < PathBuf > {
294305 #[ cfg( target_os = "macos" ) ]
295- {
296- // Prefer XDG-style path on macOS for CLI tools
297- if let Some ( xdg_path) = Self :: xdg_config_path ( )
298- && let Ok ( contents) = fs:: read_to_string ( & xdg_path)
299- {
300- match toml:: from_str ( & contents) {
301- Ok ( config) => return config,
302- Err ( e) => {
303- eprintln ! (
304- "warning: failed to parse config {}: {} (using defaults)" ,
305- xdg_path. display( ) ,
306- e
307- ) ;
308- return Self :: default ( ) ;
309- }
310- }
311- }
312- }
306+ return Self :: xdg_config_path ( ) . or_else ( Self :: config_path) ;
313307
314- // Fall back to platform-specific path
308+ # [ cfg ( not ( target_os = "macos" ) ) ]
315309 Self :: config_path ( )
316- . and_then ( |path| {
317- let contents = fs:: read_to_string ( & path) . ok ( ) ?;
318- match toml:: from_str ( & contents) {
319- Ok ( config) => Some ( config) ,
320- Err ( e) => {
321- eprintln ! (
322- "warning: failed to parse config {}: {} (using defaults)" ,
323- path. display( ) ,
324- e
325- ) ;
326- None
327- }
328- }
310+ }
311+
312+ /// Load the configuration file, falling back to `Default` on error.
313+ fn load_from_path ( path : & PathBuf ) -> Self {
314+ let Ok ( content) = fs:: read_to_string ( & path) else {
315+ return Self :: default ( ) ;
316+ } ;
317+
318+ match toml:: from_str :: < Self > ( & content) {
319+ Ok ( config) => return config,
320+ Err ( e) => {
321+ eprintln ! (
322+ "warning: failed to parse config {}: {} (using defaults)" ,
323+ path. display( ) ,
324+ e
325+ ) ;
326+ return Self :: default ( ) ;
327+ }
328+ } ;
329+ }
330+
331+ /// Resolve and load the configuration file, falling back to `Default` if any step fails.
332+ pub fn load ( ) -> Self {
333+ Self :: resolve_config_path ( )
334+ . map ( |path| {
335+ let mut config = Self :: load_from_path ( & path) ;
336+ config. path = Some ( path. to_owned ( ) ) ;
337+ config
329338 } )
330339 . unwrap_or_default ( )
331340 }
332341
333342 /// Save config to file
334343 pub fn save ( & self ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
335- let path = Self :: config_path ( ) . ok_or ( "Could not determine config directory" ) ?;
344+ let path = self
345+ . path
346+ . as_ref ( )
347+ . ok_or ( "Could not determine config directory" ) ?;
336348
337349 // Create parent directory if it doesn't exist
338350 if let Some ( parent) = path. parent ( ) {
@@ -398,4 +410,13 @@ impl Config {
398410 pub fn is_compact_tree ( & self ) -> bool {
399411 self . ui . tree_style == "compact"
400412 }
413+
414+ /// Get the path of the directory that contains the user's sublime color schemes
415+ /// (used for syntax highlighting in code blocks)
416+ pub fn code_theme_dir_path ( & self ) -> Option < PathBuf > {
417+ self . path
418+ . as_ref ( )
419+ . and_then ( |path| path. parent ( ) )
420+ . map ( |parent| parent. join ( "code-themes" ) )
421+ }
401422}
0 commit comments