oxwm

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