oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
5,020 bytes raw
1
use std::path::PathBuf;
2
3
fn main() -> Result<(), Box<dyn std::error::Error>> {
4
    let arguments: Vec<String> = std::env::args().collect();
5
6
    let mut custom_config_path: Option<PathBuf> = None;
7
8
    match arguments.get(1).map(|string| string.as_str()) {
9
        Some("--version") => {
10
            println!("oxwm {}", env!("CARGO_PKG_VERSION"));
11
            return Ok(());
12
        }
13
        Some("--help") => {
14
            print_help();
15
            return Ok(());
16
        }
17
        Some("--init") => {
18
            init_config()?;
19
            return Ok(());
20
        }
21
        Some("--config") => {
22
            if let Some(path) = arguments.get(2) {
23
                custom_config_path = Some(PathBuf::from(path));
24
            } else {
25
                eprintln!("Error: --config requires a path argument");
26
                std::process::exit(1);
27
            }
28
        }
29
        _ => {}
30
    }
31
32
    let (config, config_error) = load_config(custom_config_path)?;
33
34
    let mut window_manager = oxwm::window_manager::WindowManager::new(config)?;
35
36
    if let Some(error) = config_error {
37
        window_manager.show_startup_config_error(&error);
38
    }
39
40
    let should_restart = window_manager.run()?;
41
42
    drop(window_manager);
43
44
    if should_restart {
45
        use std::os::unix::process::CommandExt;
46
        let error = std::process::Command::new(&arguments[0])
47
            .args(&arguments[1..])
48
            .exec();
49
        eprintln!("Failed to restart: {}", error);
50
    }
51
52
    Ok(())
53
}
54
55
fn load_config(
56
    custom_path: Option<PathBuf>,
57
) -> Result<(oxwm::Config, Option<String>), Box<dyn std::error::Error>> {
58
    let config_path = if let Some(path) = custom_path {
59
        path
60
    } else {
61
        let config_directory = get_config_path();
62
        let lua_path = config_directory.join("config.lua");
63
64
        if !lua_path.exists() {
65
            let ron_path = config_directory.join("config.ron");
66
            let had_ron_config = ron_path.exists();
67
68
            println!("No config found at {:?}", config_directory);
69
            println!("Creating default Lua config...");
70
            init_config()?;
71
72
            if had_ron_config {
73
                println!("\n NOTICE: OXWM has migrated to Lua configuration.");
74
                println!("   Your old config.ron has been preserved, but is no longer used.");
75
                println!("   Your settings have been reset to defaults.");
76
                println!("   Please manually port your configuration to the new Lua format.");
77
                println!("   See the new config.lua template for examples.\n");
78
            }
79
        }
80
81
        lua_path
82
    };
83
84
    let config_string = std::fs::read_to_string(&config_path)
85
        .map_err(|error| format!("Failed to read config file: {}", error))?;
86
87
    let config_directory = config_path.parent();
88
89
    let (mut config, config_error) =
90
        match oxwm::config::parse_lua_config(&config_string, config_directory) {
91
            Ok(config) => (config, None),
92
            Err(error) => {
93
                let template = include_str!("../../templates/config.lua");
94
                let config = oxwm::config::parse_lua_config(template, None).map_err(|error| {
95
                    format!("Failed to parse default template config: {}", error)
96
                })?;
97
                (config, Some(format!("{}", error)))
98
            }
99
        };
100
101
    config.path = Some(config_path);
102
103
    Ok((config, config_error))
104
}
105
106
fn init_config() -> Result<(), Box<dyn std::error::Error>> {
107
    let config_directory = get_config_path();
108
    std::fs::create_dir_all(&config_directory)?;
109
110
    let config_template = include_str!("../../templates/config.lua");
111
    let config_path = config_directory.join("config.lua");
112
    std::fs::write(&config_path, config_template)?;
113
114
    println!("✓ Config created at {:?}", config_path);
115
    println!("  Edit the file and reload with Mod+Shift+R");
116
    println!("  No compilation needed - changes take effect immediately!");
117
118
    Ok(())
119
}
120
121
fn get_config_path() -> PathBuf {
122
    dirs::config_dir()
123
        .expect("Could not find config directory")
124
        .join("oxwm")
125
}
126
127
fn print_help() {
128
    println!("OXWM - A dynamic window manager written in Rust\n");
129
    println!("USAGE:");
130
    println!("    oxwm [OPTIONS]\n");
131
    println!("OPTIONS:");
132
    println!("    --init              Create default config in ~/.config/oxwm/config.lua");
133
    println!("    --config <PATH>     Use custom config file");
134
    println!("    --version           Print version information");
135
    println!("    --help              Print this help message\n");
136
    println!("CONFIG:");
137
    println!("    Location: ~/.config/oxwm/config.lua");
138
    println!("    Edit the config file and use Mod+Shift+R to reload");
139
    println!("    No compilation needed - instant hot-reload!");
140
    println!("    LSP support included with oxwm.lua type definitions\n");
141
    println!("FIRST RUN:");
142
    println!("    Run 'oxwm --init' to create a config file");
143
    println!("    Or just start oxwm and it will create one automatically\n");
144
}