xdgkit/
user_dirs.rs

1/*! # User directories
2This reads the `~/config/user-dirs.dirs` file
3
4You can get the location of the file with `filename()`
5
6Or you can build a struct
7```
8use xdgkit::user_dirs::UserDirs;
9let user_dirs = UserDirs::new();
10// music directory
11let music = user_dirs.music; // usually ~/Music
12// documents directory
13let documents = user_dirs.documents; // usually ~/Documents
14// etc....
15```
16
17*/
18use crate::basedir;
19use std::env::VarError;
20use std::fs::File;
21use std::io::{BufRead, BufReader};
22
23/// get the `user-dirs.dirs` full path + filename
24pub fn filename() -> Result<String, VarError> {
25    let conf_dir = match basedir::config_home() {
26        Ok(c) => c,
27        Err(e) => return Err(e),
28    };
29    Ok(format!("{}/user-dirs.dirs", conf_dir.as_str()))
30}
31
32/// The file is written by xdg-user-dirs-update
33/// it contains the locations of each directory
34#[derive(Debug, Default)]
35pub struct UserDirs {
36    /// xdg default is: $HOME/Desktop
37    pub desktop: String,
38    /// xdg default is: $HOME/Downloads
39    pub download: String,
40    /// xdg default is: $HOME/Templates
41    pub template: String,
42    /// xdg default is: $HOME/Public
43    pub public_share: String,
44    /// xdg default is: $HOME/Documents
45    pub documents: String,
46    /// xdg default is: $HOME/Music
47    pub music: String,
48    /// xdg default is: $HOME/Pictures
49    pub pictures: String,
50    /// xdg default is: $HOME/Videos
51    pub videos: String,
52}
53impl UserDirs {
54    /// make and empty one
55    pub fn empty() -> Self {
56        Self {
57            desktop: String::new(),
58            download: String::new(),
59            template: String::new(),
60            public_share: String::new(),
61            documents: String::new(),
62            music: String::new(),
63            pictures: String::new(),
64            videos: String::new(),
65        }
66    }
67    /// Attempt to create and populate, or send an empty one
68    pub fn new() -> Self {
69        let mut desktop = String::new();
70        let mut download = String::new();
71        let mut template = String::new();
72        let mut public_share = String::new();
73        let mut documents = String::new();
74        let mut music = String::new();
75        let mut pictures = String::new();
76        let mut videos = String::new();
77        let file_name = match filename() {
78            Ok(f) => f,
79            Err(_) => return Self::empty(),
80        };
81        // try to get home directory
82        let home = match basedir::home() {
83            Ok(h) => h,
84            Err(_) => "$HOME".to_string(),
85        };
86        // try to open the file
87        let file = match File::open(file_name.as_str()) {
88            Ok(f) => f,
89            Err(_) => return Self::empty(),
90        };
91        let file_reader = BufReader::new(file);
92        for (_line_number, line) in file_reader.lines().enumerate() {
93            if line.is_err() {
94                continue;
95            }
96            let mut line = line.unwrap();
97            // check to see if the line is a comment
98            if let Some(position) = line.find('#') {
99                if position == 0 {
100                    continue;
101                }
102            }
103            line.retain(|c| c != '"'); //remove_matches('"');
104            if let Some((var, dir)) = line.rsplit_once('=') {
105                let _ = dir.replace("$HOME", home.as_str());
106                if var == "XDG_DESKTOP_DIR" {
107                    desktop = dir.to_string();
108                } else if var == "XDG_DOWNLOAD_DIR" {
109                    download = dir.to_string();
110                } else if var == "XDG_TEMPLATES_DIR" {
111                    template = dir.to_string();
112                } else if var == "XDG_PUBLICSHARE_DIR" {
113                    public_share = dir.to_string();
114                } else if var == "XDG_DOCUMENTS_DIR" {
115                    documents = dir.to_string();
116                } else if var == "XDG_MUSIC_DIR" {
117                    music = dir.to_string();
118                } else if var == "XDG_PICTURES_DIR" {
119                    pictures = dir.to_string();
120                } else if var == "XDG_VIDEOS_DIR" {
121                    videos = dir.to_string();
122                }
123            }
124        }
125        Self {
126            desktop,
127            download,
128            template,
129            public_share,
130            documents,
131            music,
132            pictures,
133            videos,
134        }
135    }
136}