oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
5,975 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, had_broken_config) = load_config(custom_config_path)?;
33
34
    let mut window_manager = oxwm::window_manager::WindowManager::new(config)?;
35
36
    if had_broken_config {
37
        window_manager.show_migration_overlay();
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]).args(&arguments[1..]).exec();
47
        eprintln!("Failed to restart: {}", error);
48
    }
49
50
    Ok(())
51
}
52
53
fn load_config(custom_path: Option<PathBuf>) -> Result<(oxwm::Config, bool), Box<dyn std::error::Error>> {
54
    let config_path = if let Some(path) = custom_path {
55
        path
56
    } else {
57
        let config_directory = get_config_path();
58
        let lua_path = config_directory.join("config.lua");
59
60
        if !lua_path.exists() {
61
            let ron_path = config_directory.join("config.ron");
62
            let had_ron_config = ron_path.exists();
63
64
            println!("No config found at {:?}", config_directory);
65
            println!("Creating default Lua config...");
66
            init_config()?;
67
68
            if had_ron_config {
69
                println!("\n NOTICE: OXWM has migrated to Lua configuration.");
70
                println!("   Your old config.ron has been preserved, but is no longer used.");
71
                println!("   Your settings have been reset to defaults.");
72
                println!("   Please manually port your configuration to the new Lua format.");
73
                println!("   See the new config.lua template for examples.\n");
74
            }
75
        }
76
77
        lua_path
78
    };
79
80
    let config_string = std::fs::read_to_string(&config_path)
81
        .map_err(|error| format!("Failed to read config file: {}", error))?;
82
83
    let config_directory = config_path.parent();
84
85
    match oxwm::config::parse_lua_config(&config_string, config_directory) {
86
        Ok(config) => Ok((config, false)),
87
        Err(_error) => {
88
            let template = include_str!("../../templates/config.lua");
89
            let config = oxwm::config::parse_lua_config(template, None)
90
                .map_err(|error| format!("Failed to parse default template config: {}", error))?;
91
            Ok((config, true))
92
        }
93
    }
94
}
95
96
fn init_config() -> Result<(), Box<dyn std::error::Error>> {
97
    let config_directory = get_config_path();
98
    std::fs::create_dir_all(&config_directory)?;
99
100
    let config_template = include_str!("../../templates/config.lua");
101
    let config_path = config_directory.join("config.lua");
102
    std::fs::write(&config_path, config_template)?;
103
104
    update_lsp_files()?;
105
106
    println!("✓ Config created at {:?}", config_path);
107
    println!("✓ LSP definitions installed at {:?}/lib/oxwm.lua", config_directory);
108
    println!("  Edit the file and reload with Mod+Shift+R");
109
    println!("  No compilation needed - changes take effect immediately!");
110
111
    Ok(())
112
}
113
114
fn update_lsp_files() -> Result<(), Box<dyn std::error::Error>> {
115
    let config_directory = get_config_path();
116
117
    let system_paths = [
118
        PathBuf::from("/usr/share/oxwm/oxwm.lua"),
119
        PathBuf::from("/usr/local/share/oxwm/oxwm.lua"),
120
    ];
121
122
    let system_oxwm_lua = system_paths.iter().find(|path| path.exists());
123
124
    let luarc_content = if let Some(system_path) = system_oxwm_lua {
125
        format!(
126
            r#"{{
127
  "workspace.library": [
128
    "{}"
129
  ]
130
}}
131
"#,
132
            system_path.parent().unwrap().display()
133
        )
134
    } else {
135
        let library_directory = config_directory.join("lib");
136
        std::fs::create_dir_all(&library_directory)?;
137
138
        let oxwm_lua_template = include_str!("../../templates/oxwm.lua");
139
        let oxwm_lua_path = library_directory.join("oxwm.lua");
140
        std::fs::write(&oxwm_lua_path, oxwm_lua_template)?;
141
142
        r#"{
143
  "workspace.library": [
144
    "lib"
145
  ]
146
}
147
"#
148
        .to_string()
149
    };
150
151
    let luarc_path = config_directory.join(".luarc.json");
152
    std::fs::write(&luarc_path, luarc_content)?;
153
154
    Ok(())
155
}
156
157
fn get_config_path() -> PathBuf {
158
    dirs::config_dir()
159
        .expect("Could not find config directory")
160
        .join("oxwm")
161
}
162
163
fn print_help() {
164
    println!("OXWM - A dynamic window manager written in Rust\n");
165
    println!("USAGE:");
166
    println!("    oxwm [OPTIONS]\n");
167
    println!("OPTIONS:");
168
    println!("    --init              Create default config in ~/.config/oxwm/config.lua");
169
    println!("    --config <PATH>     Use custom config file");
170
    println!("    --version           Print version information");
171
    println!("    --help              Print this help message\n");
172
    println!("CONFIG:");
173
    println!("    Location: ~/.config/oxwm/config.lua");
174
    println!("    Edit the config file and use Mod+Shift+R to reload");
175
    println!("    No compilation needed - instant hot-reload!");
176
    println!("    LSP support included with oxwm.lua type definitions\n");
177
    println!("FIRST RUN:");
178
    println!("    Run 'oxwm --init' to create a config file");
179
    println!("    Or just start oxwm and it will create one automatically\n");
180
}