@@ -12,6 +12,7 @@ use std::{
12
12
use abi_stable:: std_types:: { ROption , RVec } ;
13
13
use anyrun_interface:: { HandleResult , Match , PluginInfo , PluginRef , PollResult } ;
14
14
use clap:: { Parser , ValueEnum } ;
15
+ use dirs;
15
16
use gtk:: { gdk, gdk_pixbuf, gio, glib, prelude:: * } ;
16
17
use nix:: unistd;
17
18
use serde:: { Deserialize , Serialize } ;
@@ -182,11 +183,76 @@ struct RuntimeData {
182
183
/// Used for displaying errors later on
183
184
error_label : String ,
184
185
config_dir : String ,
186
+ state_dir : Option < String > ,
185
187
}
186
188
187
189
impl RuntimeData {
190
+ fn new ( config_dir_path : Option < String > , cli_config : ConfigArgs ) -> Self {
191
+ // Setup config directory
192
+ let config_dir = config_dir_path. unwrap_or_else ( || {
193
+ dirs:: config_dir ( )
194
+ . map ( |dir| dir. join ( "anyrun" ) )
195
+ . and_then ( |path| path. to_str ( ) . map ( String :: from) )
196
+ . filter ( |path| PathBuf :: from ( path) . exists ( ) )
197
+ . unwrap_or_else ( || DEFAULT_CONFIG_DIR . to_string ( ) )
198
+ } ) ;
199
+
200
+ // Load config, if unable to then read default config
201
+ let ( mut config, error_label) = match fs:: read_to_string ( format ! ( "{}/config.ron" , config_dir) ) {
202
+ Ok ( content) => ron:: from_str ( & content)
203
+ . map ( |config| ( config, String :: new ( ) ) )
204
+ . unwrap_or_else ( |why| {
205
+ (
206
+ Config :: default ( ) ,
207
+ format ! (
208
+ "Failed to parse Anyrun config file, using default config: {}" ,
209
+ why
210
+ ) ,
211
+ )
212
+ } ) ,
213
+ Err ( why) => (
214
+ Config :: default ( ) ,
215
+ format ! (
216
+ "Failed to read Anyrun config file, using default config: {}" ,
217
+ why
218
+ ) ,
219
+ ) ,
220
+ } ;
221
+
222
+ // Merge CLI config if provided
223
+ config. merge_opt ( cli_config) ;
224
+
225
+ // Setup state directory only if persistence is enabled
226
+ let state_dir = if config. persist_state {
227
+ let state_dir = dirs:: state_dir ( )
228
+ . unwrap_or_else ( || dirs:: cache_dir ( ) . expect ( "Failed to get state or cache directory" ) )
229
+ . join ( "anyrun" ) ;
230
+
231
+ // Ensure atomically that the directory exists
232
+ if let Err ( e) = fs:: create_dir_all ( & state_dir) {
233
+ eprintln ! ( "Failed to create state directory at {}: {}" , state_dir. display( ) , e) ;
234
+ std:: process:: exit ( 1 ) ;
235
+ }
236
+
237
+ Some ( state_dir. to_str ( ) . unwrap ( ) . to_string ( ) )
238
+ } else {
239
+ None
240
+ } ;
241
+
242
+ Self {
243
+ exclusive : None ,
244
+ plugins : Vec :: new ( ) ,
245
+ post_run_action : PostRunAction :: None ,
246
+ config,
247
+ error_label,
248
+ config_dir,
249
+ state_dir,
250
+ }
251
+ }
252
+
188
253
fn state_file ( & self ) -> String {
189
- format ! ( "{}/state.txt" , self . config_dir)
254
+ let state_dir = self . state_dir . as_ref ( ) . expect ( "state operations called when persistence is disabled" ) ;
255
+ PathBuf :: from ( state_dir) . join ( "state.txt" ) . to_str ( ) . unwrap ( ) . to_string ( )
190
256
}
191
257
192
258
fn save_state ( & self , text : & str ) -> io:: Result < ( ) > {
@@ -281,51 +347,10 @@ fn main() {
281
347
282
348
let args = Args :: parse ( ) ;
283
349
284
- // Figure out the config dir
285
- let user_dir = format ! (
286
- "{}/.config/anyrun" ,
287
- env:: var( "HOME" ) . expect( "Could not determine home directory! Is $HOME set?" )
288
- ) ;
289
- let config_dir = args. config_dir . unwrap_or_else ( || {
290
- if PathBuf :: from ( & user_dir) . exists ( ) {
291
- user_dir
292
- } else {
293
- DEFAULT_CONFIG_DIR . to_string ( )
294
- }
295
- } ) ;
296
-
297
- // Load config, if unable to then read default config. If an error occurs the message will be displayed.
298
- let ( mut config, error_label) = match fs:: read_to_string ( format ! ( "{}/config.ron" , config_dir) ) {
299
- Ok ( content) => ron:: from_str ( & content)
300
- . map ( |config| ( config, String :: new ( ) ) )
301
- . unwrap_or_else ( |why| {
302
- (
303
- Config :: default ( ) ,
304
- format ! (
305
- "Failed to parse Anyrun config file, using default config: {}" ,
306
- why
307
- ) ,
308
- )
309
- } ) ,
310
- Err ( why) => (
311
- Config :: default ( ) ,
312
- format ! (
313
- "Failed to read Anyrun config file, using default config: {}" ,
314
- why
315
- ) ,
316
- ) ,
317
- } ;
318
-
319
- config. merge_opt ( args. config ) ;
320
-
321
- let runtime_data = Rc :: new ( RefCell :: new ( RuntimeData {
322
- exclusive : None ,
323
- plugins : Vec :: new ( ) ,
324
- post_run_action : PostRunAction :: None ,
325
- config,
326
- error_label,
327
- config_dir,
328
- } ) ) ;
350
+ let runtime_data = Rc :: new ( RefCell :: new ( RuntimeData :: new (
351
+ args. config_dir ,
352
+ args. config ,
353
+ ) ) ) ;
329
354
330
355
let runtime_data_clone = runtime_data. clone ( ) ;
331
356
app. connect_activate ( move |app| activate ( app, runtime_data_clone. clone ( ) ) ) ;
0 commit comments