11use lay:: config:: { CorrectionEngine , LayConfig } ;
22use lay:: desktop:: LayoutBackend ;
33use lay:: text_backend:: TextBackendPreference ;
4+ #[ cfg( not( test) ) ]
5+ use std:: path:: PathBuf ;
6+ #[ cfg( not( test) ) ]
7+ use std:: sync:: Mutex ;
48use std:: sync:: OnceLock ;
9+ #[ cfg( not( test) ) ]
10+ use std:: time:: { Duration , Instant , SystemTime } ;
511
612use super :: { detect_auto_layout_backend_hint, ENTER_AUTOCORRECT_EXPERIMENT_ENV } ;
713
814static AUTO_LAYOUT_BACKEND_HINT : OnceLock < Option < LayoutBackend > > = OnceLock :: new ( ) ;
915
16+ #[ cfg( not( test) ) ]
17+ const CONFIG_CACHE_CHECK_INTERVAL : Duration = Duration :: from_millis ( 250 ) ;
18+
19+ #[ cfg( not( test) ) ]
20+ struct CachedLayConfig {
21+ config : LayConfig ,
22+ modified : Option < SystemTime > ,
23+ checked_at : Instant ,
24+ }
25+
26+ #[ cfg( not( test) ) ]
27+ static CONFIG_CACHE : OnceLock < Mutex < CachedLayConfig > > = OnceLock :: new ( ) ;
28+
29+ fn current_config ( ) -> LayConfig {
30+ #[ cfg( test) ]
31+ {
32+ LayConfig :: load ( )
33+ }
34+ #[ cfg( not( test) ) ]
35+ {
36+ let cache = CONFIG_CACHE . get_or_init ( || {
37+ Mutex :: new ( CachedLayConfig {
38+ config : LayConfig :: load ( ) ,
39+ modified : config_modified_at ( ) ,
40+ checked_at : Instant :: now ( ) ,
41+ } )
42+ } ) ;
43+ let mut cache = cache
44+ . lock ( )
45+ . unwrap_or_else ( |poisoned| poisoned. into_inner ( ) ) ;
46+ if cache. checked_at . elapsed ( ) < CONFIG_CACHE_CHECK_INTERVAL {
47+ return cache. config . clone ( ) ;
48+ }
49+
50+ cache. checked_at = Instant :: now ( ) ;
51+ let modified = config_modified_at ( ) ;
52+ if modified != cache. modified {
53+ cache. config = LayConfig :: load ( ) ;
54+ cache. modified = modified;
55+ }
56+ cache. config . clone ( )
57+ }
58+ }
59+
60+ #[ cfg( not( test) ) ]
61+ fn config_modified_at ( ) -> Option < SystemTime > {
62+ std:: fs:: metadata ( config_path ( ) )
63+ . and_then ( |metadata| metadata. modified ( ) )
64+ . ok ( )
65+ }
66+
67+ #[ cfg( not( test) ) ]
68+ fn config_path ( ) -> PathBuf {
69+ let home = std:: env:: var ( "HOME" ) . unwrap_or_default ( ) ;
70+ PathBuf :: from ( home) . join ( lay:: config:: CONFIG_PATH )
71+ }
72+
1073pub ( super ) fn active_replace_words ( ) -> usize {
11- LayConfig :: load ( ) . active_replace_words ( )
74+ current_config ( ) . active_replace_words ( )
1275}
1376
1477pub ( super ) fn active_typing_assist_words ( ) -> usize {
15- LayConfig :: load ( ) . active_typing_assist_words ( )
78+ current_config ( ) . active_typing_assist_words ( )
1679}
1780
1881pub ( super ) fn active_correction_engine ( ) -> CorrectionEngine {
19- LayConfig :: load ( ) . active_correction_engine ( )
82+ current_config ( ) . active_correction_engine ( )
2083}
2184
2285pub ( super ) fn active_layout_backend ( ) -> LayoutBackend {
23- let config = LayConfig :: load ( ) ;
86+ let config = current_config ( ) ;
2487 let backend = config. active_layout_backend ( ) ;
2588 let configured = config. layout_backend . trim ( ) . to_ascii_lowercase ( ) ;
2689 if configured != "auto" {
@@ -34,19 +97,19 @@ pub(super) fn active_layout_backend() -> LayoutBackend {
3497}
3598
3699pub ( super ) fn active_text_backend ( ) -> TextBackendPreference {
37- LayConfig :: load ( ) . active_text_backend ( )
100+ current_config ( ) . active_text_backend ( )
38101}
39102
40103pub ( super ) fn active_auto_replace ( ) -> bool {
41- LayConfig :: load ( ) . auto_replace
104+ current_config ( ) . auto_replace
42105}
43106
44107pub ( super ) fn active_typing_assist ( ) -> bool {
45- LayConfig :: load ( ) . typing_assist
108+ current_config ( ) . typing_assist
46109}
47110
48111pub ( super ) fn active_enter_autocorrect ( ) -> bool {
49- let cfg = LayConfig :: load ( ) ;
112+ let cfg = current_config ( ) ;
50113 active_enter_autocorrect_from_env (
51114 cfg. enter_autocorrect ,
52115 std:: env:: var ( ENTER_AUTOCORRECT_EXPERIMENT_ENV )
@@ -73,22 +136,22 @@ pub(super) fn active_enter_autocorrect_from_env(
73136}
74137
75138pub ( super ) fn active_auto_switch_layout ( ) -> bool {
76- LayConfig :: load ( ) . auto_switch_layout
139+ current_config ( ) . auto_switch_layout
77140}
78141
79142pub ( super ) fn active_learning_log ( ) -> bool {
80- LayConfig :: load ( ) . learning_log
143+ current_config ( ) . learning_log
81144}
82145
83146pub ( super ) fn active_lem_enabled_for_scope ( word_count : usize ) -> bool {
84- LayConfig :: load ( ) . lem_enabled_for_scope ( word_count)
147+ current_config ( ) . lem_enabled_for_scope ( word_count)
85148}
86149
87150#[ cfg( not( test) ) ]
88151pub ( super ) fn active_typing_assist_pipeline_for_auto_replace (
89152 context : & str ,
90153) -> Vec < lay:: config:: TypingAssistRuleConfig > {
91- let cfg = LayConfig :: load ( ) ;
154+ let cfg = current_config ( ) ;
92155 lay:: typing_context:: typing_assist_pipeline_for_context (
93156 cfg. auto_replace ,
94157 cfg. active_correction_safety ( ) ,
0 commit comments