oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
6,060 bytes raw
1
use oxwm::errors::ConfigError;
2
use oxwm::errors::MainError;
3
use std::path::Path;
4
use std::path::PathBuf;
5
6
const CONFIG_FILE: &str = "config.lua";
7
const TEMPLATE: &str = include_str!("../../templates/config.lua");
8
9
enum Args {
10
    Exit,
11
    Arguments(Vec<String>),
12
    Error(MainError),
13
}
14
15
fn main() -> Result<(), MainError> {
16
    let arguments = match process_args() {
17
        Args::Exit => return Ok(()),
18
        Args::Arguments(v) => v,
19
        Args::Error(e) => return Err(e),
20
    };
21
22
    let (config, config_warning) = load_config(arguments.get(2))?;
23
24
    let mut window_manager = match oxwm::window_manager::WindowManager::new(config) {
25
        Ok(wm) => wm,
26
        Err(e) => return Err(MainError::CouldNotStartWm(e)),
27
    };
28
29
    if let Some(warning) = config_warning {
30
        window_manager.show_startup_config_error(warning);
31
    }
32
33
    if let Err(e) = window_manager.run() {
34
        return Err(MainError::WmError(e));
35
    }
36
37
    Ok(())
38
}
39
40
fn load_config(
41
    config_path: Option<&String>,
42
) -> Result<(oxwm::Config, Option<ConfigError>), MainError> {
43
    let path = match config_path {
44
        None => {
45
            let config_dir = get_config_path()?;
46
            let config_path = config_dir.join(CONFIG_FILE);
47
            check_convert(&config_path)?;
48
            config_path
49
        }
50
        Some(p) => PathBuf::from(p),
51
    };
52
53
    let config_string = match std::fs::read_to_string(&path) {
54
        Ok(c) => c,
55
        Err(e) => return Err(MainError::FailedReadConfig(e)),
56
    };
57
58
    let config_directory = path.parent();
59
60
    let (mut config, config_warning) =
61
        match oxwm::config::parse_lua_config(&config_string, config_directory) {
62
            Ok(config) => (config, None),
63
            Err(warning) => {
64
                let config = match oxwm::config::parse_lua_config(TEMPLATE, None) {
65
                    Ok(c) => c,
66
                    Err(e) => return Err(MainError::FailedReadConfigTemplate(e)),
67
                };
68
                (config, Some(warning))
69
            }
70
        };
71
    config.path = Some(path);
72
    Ok((config, config_warning))
73
}
74
75
fn init_config() -> Result<(), MainError> {
76
    let config_directory = get_config_path()?;
77
    if let Err(e) = std::fs::create_dir_all(&config_directory) {
78
        return Err(MainError::CouldNotCreateConfigDir(e));
79
    }
80
81
    let config_template = TEMPLATE;
82
    let config_path = config_directory.join(CONFIG_FILE);
83
    if let Err(e) = std::fs::write(&config_path, config_template) {
84
        return Err(MainError::CouldNotWriteConfig(e));
85
    }
86
87
    println!("✓ Config created at {:?}", config_path);
88
    println!("  Edit the file and reload with Mod+Shift+R");
89
    println!("  No compilation needed - changes take effect immediately!");
90
91
    Ok(())
92
}
93
94
fn get_config_path() -> Result<PathBuf, MainError> {
95
    match dirs::config_dir() {
96
        Some(p) => Ok(p.join("oxwm")),
97
        None => Err(MainError::NoConfigDir),
98
    }
99
}
100
101
fn print_help() {
102
    println!("OXWM - A dynamic window manager written in Rust\n");
103
    println!("USAGE:");
104
    println!("    oxwm [OPTIONS]\n");
105
    println!("OPTIONS:");
106
    println!("    --init              Create default config in ~/.config/oxwm/config.lua");
107
    println!("    --config <PATH>     Use custom config file");
108
    println!("    --version           Print version information");
109
    println!("    --help              Print this help message\n");
110
    println!("CONFIG:");
111
    println!("    Location: ~/.config/oxwm/config.lua");
112
    println!("    Edit the config file and use Mod+Shift+R to reload");
113
    println!("    No compilation needed - instant hot-reload!");
114
    println!("    LSP support included with oxwm.lua type definitions\n");
115
    println!("FIRST RUN:");
116
    println!("    Run 'oxwm --init' to create a config file");
117
    println!("    Or just start oxwm and it will create one automatically\n");
118
}
119
120
fn process_args() -> Args {
121
    let mut args = std::env::args();
122
    let name = match args.next() {
123
        Some(n) => n,
124
        None => return Args::Error(MainError::NoProgramName),
125
    };
126
    let switch = args.next();
127
    let path = args.next();
128
129
    let switch = match switch {
130
        Some(s) => s,
131
        None => return Args::Arguments(vec![name]),
132
    };
133
134
    match switch.as_str() {
135
        "--version" => {
136
            println!("{name} {}", env!("CARGO_PKG_VERSION"));
137
            Args::Exit
138
        }
139
        "--help" => {
140
            print_help();
141
            Args::Exit
142
        }
143
        "--init" => match init_config() {
144
            Ok(_) => Args::Exit,
145
            Err(e) => Args::Error(e),
146
        },
147
        "--config" => match check_custom_config(path) {
148
            Ok(p) => Args::Arguments(vec![name, switch, p]),
149
            Err(e) => Args::Error(e),
150
        },
151
        _ => Args::Error(MainError::InvalidArguments),
152
    }
153
}
154
155
fn check_custom_config(path: Option<String>) -> Result<String, MainError> {
156
    let path = match path {
157
        Some(p) => p,
158
        None => {
159
            return Err(MainError::NoConfigPath);
160
        }
161
    };
162
163
    match std::fs::exists(&path) {
164
        Ok(b) => match b {
165
            true => Ok(path),
166
            false => Err(MainError::BadConfigPath),
167
        },
168
        Err(e) => Err(MainError::FailedCheckExist(e)),
169
    }
170
}
171
172
fn check_convert(path: &Path) -> Result<(), MainError> {
173
    let config_directory = get_config_path()?;
174
175
    if !path.exists() {
176
        let ron_path = config_directory.join("config.ron");
177
        let had_ron_config = ron_path.exists();
178
179
        println!("No config found at {:?}", config_directory);
180
        println!("Creating default Lua config...");
181
        init_config()?;
182
183
        if had_ron_config {
184
            println!("\n NOTICE: OXWM has migrated to Lua configuration.");
185
            println!("   Your old config.ron has been preserved, but is no longer used.");
186
            println!("   Your settings have been reset to defaults.");
187
            println!("   Please manually port your configuration to the new Lua format.");
188
            println!("   See the new config.lua template for examples.\n");
189
        }
190
    }
191
    Ok(())
192
}