mod cli;
mod compat;
mod config;
mod desktop;
mod paste;
mod search;
mod workspace;
use gtk::prelude::*;
use gtk::{gio, glib};
use std::env;
use std::path::PathBuf;
const APP_ID: &str = "dev.lios.Bar";
fn main() -> glib::ExitCode {
match run() {
Ok(code) => code,
Err(message) => {
eprintln!("lios-bar: {message}");
glib::ExitCode::FAILURE
}
}
}
fn run() -> Result<glib::ExitCode, String> {
match cli::parse(env::args().skip(1))? {
cli::Action::Help => {
print!("{}", cli::help());
Ok(glib::ExitCode::SUCCESS)
}
cli::Action::Version => {
println!("lios-bar {}", env!("CARGO_PKG_VERSION"));
Ok(glib::ExitCode::SUCCESS)
}
cli::Action::Check => {
let report = compat::compatibility_report();
print!("{}", report.text);
Ok(if report.compatible {
glib::ExitCode::SUCCESS
} else {
glib::ExitCode::FAILURE
})
}
cli::Action::Install => {
println!("{}", desktop::install()?);
Ok(glib::ExitCode::SUCCESS)
}
cli::Action::Uninstall => {
println!("{}", desktop::uninstall()?);
Ok(glib::ExitCode::SUCCESS)
}
cli::Action::Run {
sidebar,
working_directory,
no_gpu,
} => run_application(sidebar, working_directory, no_gpu),
}
}
fn run_application(
sidebar: Option<config::SidebarSide>,
working_directory: Option<PathBuf>,
no_gpu: bool,
) -> Result<glib::ExitCode, String> {
let working_directory = validate_working_directory(working_directory)?;
let config_path = config::default_path()?;
let mut config = config::Config::load(&config_path)?;
config.sidebar = sidebar.unwrap_or(config.sidebar);
if no_gpu {
unsafe { env::set_var("GSK_RENDERER", "cairo") };
}
gtk::init().map_err(|error| {
format!(
"cannot initialize GTK4: {error}. Run `lios-bar --check` from your \
graphical session and check DISPLAY/WAYLAND_DISPLAY and GDK_BACKEND."
)
})?;
let application = gtk::Application::builder()
.application_id(APP_ID)
.flags(gio::ApplicationFlags::NON_UNIQUE)
.build();
application.connect_activate(move |application| {
let window = workspace::build(
application,
config.clone(),
config_path.clone(),
working_directory.clone(),
);
window.present();
});
Ok(application.run_with_args(&[env!("CARGO_PKG_NAME")]))
}
fn validate_working_directory(path: Option<PathBuf>) -> Result<Option<PathBuf>, String> {
let Some(path) = path else {
return Ok(None);
};
if !path.is_dir() {
return Err(format!(
"working directory '{}' is not a directory",
path.display()
));
}
path.canonicalize()
.map(Some)
.map_err(|error| format!("could not resolve '{}': {error}", path.display()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn missing_working_directory_is_rejected() {
assert!(
validate_working_directory(Some(PathBuf::from("/definitely/not/a/liosbar/directory")))
.is_err()
);
}
#[test]
fn absent_working_directory_is_allowed() {
assert_eq!(validate_working_directory(None).unwrap(), None);
}
}