Ship default config/panels/themes with the app: --init, XDG discovery, build/CI bundling
- tui-wm --init [DIR] writes an embedded default config.toml,
panels/topbar.toml and themes/{dark,light}.toml (default target
~/.config/tui-wm, existing files untouched)
- Config discovery: ./config.toml wins, otherwise ~/.config/tui-wm/
is used (process switches working dir there so panels/themes/saves/
hot-reload all resolve consistently); spawned PTYs still start in
the user's original working directory
- VS Code build tasks copy themes/ into builds/, dist/ sample configs
refreshed with all new keys and the settings gear
- CI release now also uploads tui-wm-config.tar.gz (config + panels +
themes) alongside the binaries
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
77
src/main.rs
77
src/main.rs
@@ -28,6 +28,7 @@ enum Mode {
|
||||
Standalone,
|
||||
Daemon,
|
||||
Client(String),
|
||||
Init(Option<String>),
|
||||
Help,
|
||||
}
|
||||
|
||||
@@ -37,6 +38,10 @@ fn parse_args() -> Mode {
|
||||
while i < args.len() {
|
||||
match args[i].as_str() {
|
||||
"-h" | "--help" => return Mode::Help,
|
||||
"--init" => {
|
||||
let dir = args.get(i + 1).filter(|s| !s.starts_with('-')).cloned();
|
||||
return Mode::Init(dir);
|
||||
}
|
||||
"-d" | "--daemon" => return Mode::Daemon,
|
||||
"-c" | "--connect" => {
|
||||
let path = args
|
||||
@@ -58,6 +63,7 @@ fn main() -> io::Result<()> {
|
||||
Mode::Standalone => run_standalone(),
|
||||
Mode::Daemon => run_daemon_mode(),
|
||||
Mode::Client(path) => client::run(&path),
|
||||
Mode::Init(dir) => run_init(dir.as_deref()),
|
||||
Mode::Help => {
|
||||
print_help();
|
||||
Ok(())
|
||||
@@ -65,6 +71,70 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Standardkatalog för konfiguration: $XDG_CONFIG_HOME/tui-wm
|
||||
/// (~/.config/tui-wm), på Windows %APPDATA%\tui-wm.
|
||||
fn default_config_dir() -> std::path::PathBuf {
|
||||
if let Ok(x) = std::env::var("XDG_CONFIG_HOME") {
|
||||
return std::path::PathBuf::from(x).join("tui-wm");
|
||||
}
|
||||
#[cfg(windows)]
|
||||
if let Ok(a) = std::env::var("APPDATA") {
|
||||
return std::path::PathBuf::from(a).join("tui-wm");
|
||||
}
|
||||
if let Ok(h) = std::env::var("HOME") {
|
||||
return std::path::PathBuf::from(h).join(".config").join("tui-wm");
|
||||
}
|
||||
std::path::PathBuf::from(".")
|
||||
}
|
||||
|
||||
/// `tui-wm --init [KATALOG]` — skriv ut standardkonfiguration
|
||||
/// (config.toml, panels/, themes/). Befintliga filer rörs inte.
|
||||
fn run_init(dir: Option<&str>) -> io::Result<()> {
|
||||
let base = dir
|
||||
.map(std::path::PathBuf::from)
|
||||
.unwrap_or_else(default_config_dir);
|
||||
let files: &[(&str, &str)] = &[
|
||||
("config.toml", include_str!("../assets/default-config.toml")),
|
||||
("panels/topbar.toml", include_str!("../assets/default-topbar.toml")),
|
||||
("themes/dark.toml", include_str!("../themes/dark.toml")),
|
||||
("themes/light.toml", include_str!("../themes/light.toml")),
|
||||
];
|
||||
for (rel, content) in files {
|
||||
let path = base.join(rel);
|
||||
if path.exists() {
|
||||
println!(" finns redan: {}", path.display());
|
||||
continue;
|
||||
}
|
||||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
std::fs::write(&path, content)?;
|
||||
println!(" skapade: {}", path.display());
|
||||
}
|
||||
println!("\nKlart. Starta med `tui-wm` — konfigurationen hittas automatiskt");
|
||||
println!("i {} när ./config.toml saknas.", base.display());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Hitta konfigurationskatalogen: ./config.toml vinner, annars
|
||||
/// XDG-katalogen. Byter arbetskatalog dit så att alla relativa
|
||||
/// sökvägar (panels/, themes/, config-sparningar, hot-reload) fungerar
|
||||
/// enhetligt. Ursprungliga arbetskatalogen sparas för PTY-spawns.
|
||||
fn enter_config_dir() {
|
||||
if let Ok(cwd) = std::env::current_dir() {
|
||||
crate::pty::set_spawn_cwd(cwd.clone());
|
||||
if cwd.join("config.toml").exists() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let xdg = default_config_dir();
|
||||
if xdg.join("config.toml").exists() {
|
||||
if let Err(e) = std::env::set_current_dir(&xdg) {
|
||||
eprintln!("Kunde inte byta till {}: {}", xdg.display(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_help() {
|
||||
println!(
|
||||
"\
|
||||
@@ -84,9 +154,12 @@ FLAGGOR:
|
||||
SSH). Tangentbord, mus (klick/scroll/drag) och
|
||||
resize vidarebefordras. Koppla ner med Ctrl+Shift+Q
|
||||
— servern och dess program fortsätter köra.
|
||||
--init [KATALOG] Skriv standardkonfiguration (config.toml, panels/,
|
||||
themes/) till KATALOG — default ~/.config/tui-wm.
|
||||
Befintliga filer rörs inte.
|
||||
-h, --help Visa den här hjälpen.
|
||||
|
||||
KONFIGURATION (./config.toml + panels/*.toml):
|
||||
KONFIGURATION (./config.toml, annars ~/.config/tui-wm/config.toml):
|
||||
default_shell = \"/bin/bash\" # skal för nya terminaler
|
||||
default_window_size = [82, 26] # [bredd, höjd] för nya fönster
|
||||
scrollback_lines = 1000 # historikrader per terminal
|
||||
@@ -121,6 +194,7 @@ SOCKET-API:
|
||||
}
|
||||
|
||||
fn run_standalone() -> io::Result<()> {
|
||||
enter_config_dir();
|
||||
log::init();
|
||||
let socket_path = ipc::default_socket_path();
|
||||
let (ipc_tx, ipc_rx) = mpsc::channel::<IpcEvent>();
|
||||
@@ -346,6 +420,7 @@ fn update_background(
|
||||
}
|
||||
|
||||
fn run_daemon_mode() -> io::Result<()> {
|
||||
enter_config_dir();
|
||||
log::init();
|
||||
let socket_path = ipc::default_socket_path();
|
||||
let (ipc_tx, ipc_rx) = mpsc::channel::<IpcEvent>();
|
||||
|
||||
13
src/pty.rs
13
src/pty.rs
@@ -28,6 +28,16 @@ fn build_command(shell: &str) -> CommandBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Arbetskatalogen som nya PTY-processer ska starta i. Sätts av main
|
||||
/// innan processen ev. byter till konfig-katalogen — annars skulle
|
||||
/// spawnade skal öppnas i ~/.config/tui-wm i stället för där
|
||||
/// användaren startade TUI-WM.
|
||||
static SPAWN_CWD: std::sync::OnceLock<std::path::PathBuf> = std::sync::OnceLock::new();
|
||||
|
||||
pub fn set_spawn_cwd(dir: std::path::PathBuf) {
|
||||
let _ = SPAWN_CWD.set(dir);
|
||||
}
|
||||
|
||||
pub struct PtyTerminal {
|
||||
pub master: Box<dyn portable_pty::MasterPty + Send>,
|
||||
pub writer: Box<dyn std::io::Write + Send>,
|
||||
@@ -45,6 +55,9 @@ impl PtyTerminal {
|
||||
})?;
|
||||
|
||||
let mut cmd = build_command(shell);
|
||||
if let Some(cwd) = SPAWN_CWD.get() {
|
||||
cmd.cwd(cwd);
|
||||
}
|
||||
cmd.env("TERM", "xterm-256color");
|
||||
cmd.env("COLORTERM", "truecolor");
|
||||
for (key, val) in extra_env {
|
||||
|
||||
Reference in New Issue
Block a user