From 51f35b781dd3c6c53a17ca7ca2aa5738a28679ea Mon Sep 17 00:00:00 2001 From: Soup <50962850+soupy-boy@users.noreply.github.com> Date: Sun, 26 Jul 2026 16:50:29 -0600 Subject: [PATCH] config: added clap and figment --- ' | 972 ++++++++++ .github/workflows/pr.yml | 3 - .github/workflows/rust.yml | 4 - Cargo.lock | 836 +++++---- Cargo.toml | 6 + contrib/man/tuigreet-1 | 312 ++++ contrib/man/tuigreet-1.scd | 155 -- crates/tuigreet-config/Cargo.toml | 18 +- crates/tuigreet-config/src/config.rs | 619 +++++++ crates/tuigreet-config/src/env.rs | 585 ------ crates/tuigreet-config/src/error.rs | 77 + crates/tuigreet-config/src/lib.rs | 96 +- crates/tuigreet-config/src/loader.rs | 142 ++ crates/tuigreet-config/src/parser.rs | 1621 ----------------- crates/tuigreet-config/src/schema.rs | 700 ------- crates/tuigreet-config/src/tests.rs | 582 ++++++ crates/tuigreet-config/src/validation.rs | 409 +++++ crates/tuigreet-system/src/lib.rs | 2 +- crates/tuigreet-theme/src/config.rs | 83 - crates/tuigreet-theme/src/lib.rs | 169 +- crates/tuigreet-theme/src/style.rs | 148 -- crates/tuigreet-types/src/lib.rs | 18 + crates/tuigreet/Cargo.toml | 8 + crates/tuigreet/src/greeter.rs | 1317 +++---------- crates/tuigreet/src/info.rs | 48 +- crates/tuigreet/src/integration/common/mod.rs | 5 - crates/tuigreet/src/integration/display.rs | 8 +- crates/tuigreet/src/integration/menus.rs | 8 +- crates/tuigreet/src/integration/remember.rs | 2 +- crates/tuigreet/src/ipc.rs | 23 +- crates/tuigreet/src/keyboard.rs | 26 +- crates/tuigreet/src/main.rs | 29 +- crates/tuigreet/src/power.rs | 4 +- crates/tuigreet/src/ui/command.rs | 4 +- crates/tuigreet/src/ui/common/menu.rs | 2 +- crates/tuigreet/src/ui/mod.rs | 88 +- crates/tuigreet/src/ui/processing.rs | 2 +- crates/tuigreet/src/ui/prompt.rs | 30 +- crates/tuigreet/src/ui/tests.rs | 126 +- crates/tuigreet/src/ui/util.rs | 79 +- crates/tuigreet/src/watcher.rs | 146 +- crates/tuigreet/tools/gen-manpage.rs | 27 + nix/package.nix | 4 +- 43 files changed, 4361 insertions(+), 5182 deletions(-) create mode 100644 ' create mode 100644 contrib/man/tuigreet-1 delete mode 100644 contrib/man/tuigreet-1.scd create mode 100644 crates/tuigreet-config/src/config.rs delete mode 100644 crates/tuigreet-config/src/env.rs create mode 100644 crates/tuigreet-config/src/error.rs create mode 100644 crates/tuigreet-config/src/loader.rs delete mode 100644 crates/tuigreet-config/src/parser.rs delete mode 100644 crates/tuigreet-config/src/schema.rs create mode 100644 crates/tuigreet-config/src/tests.rs create mode 100644 crates/tuigreet-config/src/validation.rs delete mode 100644 crates/tuigreet-theme/src/config.rs delete mode 100644 crates/tuigreet-theme/src/style.rs create mode 100644 crates/tuigreet/tools/gen-manpage.rs diff --git a/' b/' new file mode 100644 index 0000000..be989d4 --- /dev/null +++ b/' @@ -0,0 +1,972 @@ +use std::{convert::TryInto, env, path::PathBuf, process, sync::Arc}; + +use chrono::Locale; +use i18n_embed::DesktopLanguageRequester; +use tokio::{ + net::UnixStream, + sync::{RwLock, RwLockWriteGuard, mpsc::Sender}, +}; +use tracing_appender::non_blocking::WorkerGuard; +use tuigreet_config::config::{ + AlignGreeting, + BackgroundConfig, + Config, + SecretMode, +}; +use tuigreet_theme::Theme; +use tuigreet_types::{AuthStatus, GreetAlign, Mode, SecretDisplay}; +use zeroize::Zeroize; + +use crate::{ + event::Event, + info::{ + get_issue, + get_last_command, + get_last_session_path, + get_last_user_command, + get_last_user_name, + get_last_user_session, + get_last_user_username, + get_sessions, + }, + power::PowerOption, + ui::{ + background::Background, + bg_animation::{self, Animation, AnimationSpec}, + common::{masked::MaskedString, menu::Menu}, + power::Power, + sessions::{Session, SessionSource, SessionType}, + users::User, + }, +}; + +/// Default render rate when animation is enabled +pub const ANIMATION_DEFAULT_FPS: u32 = 30; +/// Base/floor render rate +pub const DEFAULT_FPS: u32 = 2; + +const DEFAULT_LOCALE: Locale = Locale::en_US; + +/// Core greeter state managing authentication, UI, and session selection. +pub struct Greeter { + pub logger: Option, + + pub locale: Locale, + pub config: Config, // store config + pub socket: String, + pub stream: Option>>, + pub events: Option>, + + // Current mode of the application, will define what actions are permitted. + pub mode: Mode, + // Mode the application will return to when exiting the current mode. + pub previous_mode: Mode, + // Offset the cursor should be at from its base position for the current + // mode. + pub cursor_offset: i16, + + // Buffer to be used as a temporary editing zone for the various modes. + // Previous buffer is saved when a transient screen has to use the buffer, to + // be able to restore it when leaving the transient screen. + pub previous_buffer: Option, + pub buffer: String, + + // Define the selected session and how to resolve it. + pub session_source: SessionSource, + // List of session files found on disk. + pub session_paths: Vec<(PathBuf, SessionType)>, + // Menu for session selection. + pub sessions: Menu, + + // Menu for user selection. + pub users: Menu, + // Current username. Masked to display the full name if available. + pub username: MaskedString, + // Prompt that should be displayed to ask for entry. + pub prompt: Option, + + // Whether the current edition prompt should be hidden. + pub asking_for_secret: bool, + // How should secrets be displayed? + pub secret_display: SecretDisplay, + + // Style object for the terminal UI + pub themeui: Theme, + // Greeting message (MOTD) to use to welcome the user. + pub greeting: Option, + // Transaction message to show to the user. + pub message: Option, + + // Menu for power options. + pub powers: Menu, + + // Background animation, drawn before the login UI. + pub animation: Option>, + // Menu for the on-the-fly background switcher (F4 by default). + pub backgrounds: Menu, + + // The software is waiting for a response from `greetd`. + pub working: bool, + // We are done working. + pub done: bool, + // Should we exit? + pub exit: Option, +} + +impl std::ops::Deref for Greeter { + type Target = Config; + fn deref(&self) -> &Self::Target { + &self.config + } +} + +impl std::ops::DerefMut for Greeter { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.config + } +} + +impl Default for Greeter { + fn default() -> Self { + Self { + logger: None, + locale: DEFAULT_LOCALE, + config: Config::defaults(), + socket: String::new(), + stream: None, + events: None, + mode: Mode::default(), + previous_mode: Mode::default(), + cursor_offset: 0, + previous_buffer: None, + buffer: String::new(), + session_source: SessionSource::default(), + session_paths: Vec::new(), + sessions: Menu::default(), + users: Menu::default(), + username: MaskedString::default(), + prompt: None, + asking_for_secret: false, + secret_display: SecretDisplay::default(), + themeui: Theme::default(), + greeting: None, + message: None, + powers: Menu::default(), + animation: None, + backgrounds: Menu::default(), + working: false, + done: false, + exit: None, + } + } +} + +impl Drop for Greeter { + fn drop(&mut self) { + self.scrub(true, false); + } +} + +impl Greeter { + pub async fn new(events: Sender) -> Self { + let mut greeter = Self::default(); + + greeter.events = Some(events); + greeter.set_locale(); + + greeter.powers = Menu { + title: fl!("title_power"), + options: Default::default(), + selected: 0, + }; + + #[cfg(not(test))] + { + let mut config_error_str: Option = None; +//Result<(Config, Vec), (Config, (Vec, Vec))> + + let (config, (errors, warnings)) = match tuigreet_config::loader::load_config() { + Ok(config) => { + tracing::debug!("Config loaded successfully"); + // Apply config to greeter only if validation passed + config + }, + Err(e) => { + config_error_str = Some(e.to_string()); + (Config::defaults(), Vec::new()) + }, + }; + greeter.apply_config(config); + + // Apply terminal sizing based on [[outputs]] / [terminal] + // config. This must happen before the TUI is started so + // that ratatui sees the correct terminal dimensions. + if !greeter.outputs.is_empty() || greeter.terminal.cols.is_some() { + tuigreet_system::apply_output_config( + &greeter.outputs, + &greeter.terminal, + ); + } + + greeter.logger = crate::init_logger(&greeter); + + // show config warnings and errors now that the logger is initialized + if let Some(err) = config_error_str { + tracing::error!(err); + } + for warning in warnings { + tracing::error!(warning); + } + + greeter.connect().await; + } + + let mut sessions = get_sessions(&greeter).unwrap_or_default(); + + if greeter.general.mock && sessions.is_empty() { + sessions = mock_sessions(); + } + + if matches!(greeter.session_source, SessionSource::None) + && !sessions.is_empty() + { + greeter.session_source = SessionSource::Session(0); + } + + greeter.sessions = Menu { + title: fl!("title_session"), + options: sessions, + selected: 0, + }; + + // If a default user is specified, use it. + if let Some(ref default_user) = greeter.remember.default_user { + greeter.username = MaskedString::from(default_user.clone(), None); + } + + // If we should remember the last logged-in user. + if greeter.remember.username + && let Some(username) = get_last_user_username() + { + greeter.username = MaskedString::from(username, get_last_user_name()); + + // If, on top of that, we should remember their last session. + if greeter.remember.user_session { + // See if we have the last free-form command from the user. + if let Ok(command) = get_last_user_command(greeter.username.get()) { + greeter.session_source = SessionSource::Command(command); + } + + // If a session was saved, use it and its name. + if let Ok(ref session_path) = + get_last_user_session(greeter.username.get()) + { + // Set the selected menu option and the session source. + if let Some(index) = greeter.sessions.options.iter().position( + |Session { path, .. }| path.as_deref() == Some(session_path), + ) { + greeter.sessions.selected = index; + greeter.session_source = + SessionSource::Session(greeter.sessions.selected); + } + } + } + } + + // Same thing, but not user specific. + if greeter.remember.session { + if let Ok(command) = get_last_command() { + greeter.session_source = + SessionSource::Command(command.trim().to_string()); + } + + if let Ok(ref session_path) = get_last_session_path() + && let Some(index) = greeter.sessions.options.iter().position( + |Session { path, .. }| path.as_deref() == Some(session_path), + ) + { + greeter.sessions.selected = index; + greeter.session_source = + SessionSource::Session(greeter.sessions.selected); + } + } + + greeter + } + + // Scrub memory of all data, unless `soft` is true, in which case, we will + // keep the username (can happen if a wrong password was entered, we want to + // give the user another chance, as PAM would). + fn scrub(&mut self, scrub_message: bool, soft: bool) { + self.buffer.zeroize(); + self.prompt.zeroize(); + + if !soft { + self.username.zeroize(); + } + + if scrub_message { + self.message.zeroize(); + } + } + + // Reset the software to its initial state. + pub async fn reset(&mut self, soft: bool) { + if soft { + self.mode = Mode::Password; + self.previous_mode = Mode::Password; + } else { + self.mode = Mode::Username; + self.previous_mode = Mode::Username; + } + + self.working = false; + self.done = false; + + self.scrub(false, soft); + self.connect().await; + } + + // Connect to `greetd` and return a stream we can safely write to. + pub async fn connect(&mut self) { + if self.general.mock { + tracing::info!("mock mode: skipping greetd socket connect"); + return; + } + + // If socket is not already set (by tests), read from environment + if self.socket.is_empty() { + self.socket = if let Ok(socket) = env::var("GREETD_SOCK") { + socket + } else { + eprintln!("GREETD_SOCK must be defined"); + process::exit(1); + }; + } + + match UnixStream::connect(&self.socket).await { + Ok(stream) => { + self.stream = Some(Arc::new(RwLock::new(stream))); + }, + + Err(err) => { + eprintln!("{err}"); + process::exit(1); + }, + } + } + + pub async fn stream(&self) -> RwLockWriteGuard<'_, UnixStream> { + self + .stream + .as_ref() + .expect("stream accessed before connect") + .write() + .await + } + + #[must_use] + pub fn greet_align(&self) -> GreetAlign { + match self.display.align_greeting { + AlignGreeting::Left => GreetAlign::Left, + AlignGreeting::Right => GreetAlign::Right, + AlignGreeting::Center => GreetAlign::Center, + } + } + + // Sets the locale that will be used for this invocation from environment. + fn set_locale(&mut self) { + let locale = DesktopLanguageRequester::requested_languages() + .into_iter() + .next() + .and_then(|locale| { + locale + .region + .map(|region| format!("{}_{region}", locale.language)) + }) + .and_then(|id| id.as_str().try_into().ok()); + + if let Some(locale) = locale { + self.locale = locale; + } + } + + fn populate_backgrounds_menu(&mut self) { + let title = fl!("title_background"); + let none_label = fl!("background_none"); + let options = crate::ui::background::options(&none_label); + // Highlight the first concrete kind when an animation is active, + // otherwise the synthetic "None" at index 0. + let selected = if self.animation.is_none() { + 0 + } else { + 1.min(options.len() - 1) + }; + + self.backgrounds = Menu { + title, + options, + selected, + }; + } + + pub fn apply_background_selection(&mut self) { + let Some(item) = self.backgrounds.options.get(self.backgrounds.selected) + else { + return; + }; + match item.kind { + None => { + self.animation = None; + }, + Some(kind) => { + self.animation = Some(bg_animation::build_default(kind)); + }, + } + self.push_frame_rate(); + if let Some(ref sender) = self.events { + let sender = sender.clone(); + tokio::spawn(async move { + let _ = sender.send(crate::event::Event::Refresh).await; + }); + } + } + + fn set_background_from_config(&mut self, cfg: &BackgroundConfig) { + use crate::ui::bg_animation::{Kind, doom, matrix}; + + let Some(kind) = cfg.kind.as_deref().and_then(Kind::from_name) else { + if let Some(name) = cfg.kind.as_deref() + && !name.trim().is_empty() + && !name.eq_ignore_ascii_case("none") + { + tracing::warn!( + "unknown background animation kind '{}', ignoring", + name + ); + } + self.animation = None; + self.push_frame_rate(); + return; + }; + + let parse = |s: &str, fallback: tui::style::Color| { + bg_animation::parse_color(s).unwrap_or(fallback) + }; + + let spec = match kind { + Kind::Doom => { + let d = doom::Options::default(); + AnimationSpec::Doom(doom::Options { + height: cfg.doom.height, + spread: cfg.doom.spread, + top: parse(&cfg.doom.top_color, d.top), + middle: parse(&cfg.doom.middle_color, d.middle), + bottom: parse(&cfg.doom.bottom_color, d.bottom), + }) + }, + Kind::Matrix => { + let d = matrix::Options::default(); + AnimationSpec::Matrix(matrix::Options { + head: parse(&cfg.matrix.head_color, d.head), + bright: parse(&cfg.matrix.bright_color, d.bright), + dim: parse(&cfg.matrix.dim_color, d.dim), + min_length: cfg.matrix.min_length, + max_length: cfg.matrix.max_length, + min_speed: cfg.matrix.min_speed, + max_speed: cfg.matrix.max_speed, + mutate_chance: cfg.matrix.mutate_chance, + }) + }, + }; + self.animation = Some(bg_animation::build(&spec)); + self.push_frame_rate(); + } + + /// Render rate for the event loop. + #[must_use] + pub fn frame_rate(&self) -> f64 { + if self.animation.is_some() { + self.background.fps.max(DEFAULT_FPS) as f64 + } else { + DEFAULT_FPS as f64 + } + } + + /// Push the current frame rate to the event loop. + fn push_frame_rate(&self) { + if let Some(tx) = &self.events { + let fps = self.frame_rate(); + let tx = tx.clone(); + tokio::spawn(async move { + let _ = tx.send(Event::SetFrameRate(fps)).await; + }); + } + } + + fn add_session_path(&mut self, path: PathBuf, session_type: SessionType) { + if self.session_paths.iter().any(|(known_path, known_type)| { + known_path == &path && known_type == &session_type + }) { + return; + } + + self.session_paths.push((path, session_type)); + } + + fn set_power_command( + &mut self, + action: PowerOption, + command: Option, + ) { + if let Some(power) = self + .powers + .options + .iter_mut() + .find(|power| power.action == action) + { + power.command = command; + return; + } + + let label = match action { + PowerOption::Shutdown => fl!("shutdown"), + PowerOption::Reboot => fl!("reboot"), + PowerOption::Suspend => fl!("suspend"), + PowerOption::Hibernate => fl!("hibernate"), + }; + + self.powers.options.push(Power { + action, + label, + command, + }); + } + + pub fn set_prompt(&mut self, prompt: &str) { + self.prompt = if prompt.ends_with(' ') { + Some(prompt.into()) + } else { + Some(format!("{prompt} ")) + }; + } + + pub fn remove_prompt(&mut self) { + self.prompt = None; + } + + // Computes the size of the prompt to help determine where input should start. + #[must_use] + pub fn prompt_width(&self) -> usize { + match &self.prompt { + None => 0, + Some(prompt) => prompt.chars().count(), + } + } + + // Apply configuration settings to the greeter, respecting CLI overrides + pub fn apply_config(&mut self, config: Config) { + use SecretMode; + // Session + self.session_source = config.session.command.as_ref().map_or_else( + SessionSource::default, + |command| { + SessionSource::DefaultCommand( + command.clone(), + (!config.session.environments.is_empty()) + .then(|| config.session.environments.clone()), + ) + }, + ); + self.session_paths.clear(); + for dir in &config.session.sessions_dirs { + self.add_session_path(PathBuf::from(dir), SessionType::Wayland); + } + for dir in &config.session.xsessions_dirs { + self.add_session_path(PathBuf::from(dir), SessionType::X11); + } + // Display + self.greeting = if config.display.issue { + get_issue() + } else { + config.display.greeting.clone() + }; + // User menu + if config.user_menu.enabled { + use crate::info::get_users; + self.users = Menu { + title: fl!("title_users"), + options: get_users(config.user_menu.min_uid, config.user_menu.max_uid), + selected: 0, + }; + } else { + self.users = Menu::default(); + } + // Power + self + .set_power_command(PowerOption::Shutdown, config.power.shutdown.clone()); + self.set_power_command(PowerOption::Reboot, config.power.reboot.clone()); + self.set_power_command(PowerOption::Suspend, config.power.suspend.clone()); + self.set_power_command( + PowerOption::Hibernate, + config.power.hibernate.clone(), + ); + // Secret + self.secret_display = match config.secret.mode { + SecretMode::Hidden => SecretDisplay::Hidden, + SecretMode::Characters => { + SecretDisplay::Character(config.secret.characters.clone()) + }, + }; + // Animation + self.set_background_from_config(&config.background); + self.populate_backgrounds_menu(); + + // Apply theme config + self.themeui = Theme::from_config(&config.theme); + + // set config of greeter + self.config = config; + } + + pub fn reload_sessions(&mut self) { + let selected_path = self + .sessions + .options + .get(self.sessions.selected) + .and_then(|session| session.path.clone()); + let sessions = get_sessions(self).unwrap_or_default(); + self.sessions.options = sessions; + self.sessions.selected = selected_path + .as_ref() + .and_then(|path| { + self + .sessions + .options + .iter() + .position(|session| session.path.as_ref() == Some(path)) + }) + .unwrap_or(0); + if matches!(self.session_source, SessionSource::Session(_)) { + self.session_source = if self.sessions.options.is_empty() { + SessionSource::default() + } else { + SessionSource::Session(self.sessions.selected) + }; + } + } +} + +// Mock session list used to pad otherwise empty session menu +fn mock_sessions() -> Vec { + [ + ("mock-wayland", "Mock Wayland", SessionType::Wayland), + ("mock-x11", "Mock X11", SessionType::X11), + ("mock-shell", "Mock shell", SessionType::None), + ] + .into_iter() + .map(|(slug, name, session_type)| { + Session { + slug: Some(slug.to_string()), + name: name.to_string(), + command: "true".to_string(), + session_type, + path: None, + xdg_desktop_names: None, + } + }) + .collect() +} + +#[cfg(test)] +mod test { + use tuigreet_types::SecretDisplay; + + use crate::{ + Greeter, + power::PowerOption, + ui::sessions::{SessionSource, SessionType}, + }; + + #[test] + fn test_prompt_width() { + let mut greeter = Greeter::default(); + greeter.prompt = None; + + assert_eq!(greeter.prompt_width(), 0); + + greeter.prompt = Some("Hello:".into()); + + assert_eq!(greeter.prompt_width(), 6); + } + + #[test] + fn test_set_prompt() { + let mut greeter = Greeter::default(); + + greeter.set_prompt("Hello:"); + + assert_eq!(greeter.prompt, Some("Hello: ".into())); + + greeter.set_prompt("Hello World: "); + + assert_eq!(greeter.prompt, Some("Hello World: ".into())); + + greeter.remove_prompt(); + + assert_eq!(greeter.prompt, None); + } + + // #[test] + // fn applying_config_replaces_session_state() { + // let mut greeter = Greeter::default(); + // greeter.config = Some( + // Greeter::options() + // .parse(Vec::::new()) + // .expect("empty CLI parses"), + // ); + // + // let mut configured = Config::default(); + // configured.session.command = Some("first".into()); + // configured.session.sessions_dirs = vec!["/first".into()]; + // configured.session.session_wrapper = Some("wrapper".into()); + // configured.user_menu.enabled = true; + // greeter.apply_config(&configured); + // + // let mut replacement = Config::default(); + // replacement.session.sessions_dirs = vec!["/second".into()]; + // greeter.apply_config(&replacement); + // + // assert!(matches!(greeter.session_source, SessionSource::None)); + // assert_eq!(greeter.session_paths.len(), 2); + // assert!( + // greeter + // .session_paths + // .iter() + // .any(|(path, _)| path == "/second") + // ); + // assert!(greeter.session_wrapper.is_none()); + // assert!(!greeter.user_menu); + // assert!(greeter.users.options.is_empty()); + // }dump-config + // + // #[test] + // fn applying_config_updates_log_file() { + // let mut greeter = Greeter::default(); + // let mut config = Config::default(); + // config.general.log_file = "/tmp/configured-tuigreet.log".into(); + // greeter.config = Some( + // Greeter::options() + // .parse(Vec::::new()) + // .expect("empty CLI parses"), + // ); + // + // greeter.apply_config(&config); + // + // assert_eq!(greeter.logfile, "/tmp/configured-tuigreet.log"); + // } + // + // #[tokio::test] + // async fn test_command_line_arguments() { + // let table: &[CommandLineTest] = &[ + // No arguments + // (&[], true, None), + // Valid combinations + // (&["--cmd", "hello"], true, None), + // ( + // &[ + // "--cmd", + // "uname", + // "--env", + // "A=B", + // "--env", + // "C=D=E", + // "--asterisks", + // "--asterisks-char", + // ".", + // "--issue", + // "--time", + // "--prompt-padding", + // "0", + // "--window-padding", + // "1", + // "--container-padding", + // "12", + // "--user-menu", + // ], + // true, + // Some(|greeter| { + // assert!( + // matches!(&greeter.session_source, SessionSource::DefaultCommand(cmd, + // Some(env)) if cmd == "uname" && env.len() == 2) ); + // + // if let SessionSource::DefaultCommand(_, Some(env)) = + // &greeter.session_source + // { + // assert_eq!(env[0], "A=B"); + // assert_eq!(env[1], "C=D=E"); + // } + // + // assert!( + // matches!(&greeter.secret_display, SecretDisplay::Character(c) if c == ".") + // ); + // assert_eq!(greeter.prompt_padding(), 0); + // assert_eq!(greeter.window_padding(), 1); + // assert_eq!(greeter.container_padding(), 13); + // assert!(greeter.user_menu); + // assert!(matches!( + // greeter.xsession_wrapper.as_deref(), + // Some("startx") + // )); + // }), + // ), + // ( + // &["--xsession-wrapper", "mywrapper.sh"], + // true, + // Some(|greeter| { + // assert!(matches!( + // greeter.xsession_wrapper.as_deref(), + // Some("mywrapper.sh") + // )); + // }), + // ), + // ( + // &["--no-xsession-wrapper"], + // true, + // Some(|greeter| { + // assert!(greeter.xsession_wrapper.is_none()); + // }), + // ), + // Invalid combinations + // ( + // &["--remember-session", "--remember-user-session"], + // false, + // None, + // ), + // (&["--asterisk-char", ""], false, None), + // (&["--remember-user-session"], false, None), + // (&["--min-uid", "10000", "--max-uid", "5000"], false, None), + // (&["--issue", "--greeting", "Hello, world!"], false, None), + // (&["--kb-command", "F2", "--kb-sessions", "F2"], false, None), + // (&["--time-format", "%i %"], false, None), + // (&["--cmd", "cmd", "--env"], false, None), + // (&["--cmd", "cmd", "--env", "A"], false, None), + // ]; + // + // for (opts, valid, check) in table { + // let mut greeter = Greeter::default(); + // + // match valid { + // true => { + // assert!( + // matches!(greeter.parse_options(opts).await, Ok(())), + // "{opts:?} cannot be parsed" + // ); + // + // if let Some(check) = check { + // check(&greeter); + // } + // }, + // false => assert!((greeter.parse_options(opts).await).is_err()), + // } + // } + // } + // + // #[tokio::test] + // async fn test_session_paths_are_deduplicated_after_config_overlay() { + // let mut greeter = Greeter::default(); + // + // assert!( + // greeter + // .parse_options(&["--sessions", "/usr/share/wayland-sessions"]) + // .await + // .is_ok() + // ); + // + // let config = Config::default(); + // greeter.apply_config(&config); + // + // assert_eq!( + // greeter + // .session_paths + // .iter() + // .filter(|(path, session_type)| { + // path == &std::path::PathBuf::from("/usr/share/wayland-sessions") + // && session_type == &SessionType::Wayland + // }) + // .count(), + // 1 + // ); + // } + // + // #[tokio::test] + // async fn test_config_session_environments_survive_cli_overlay() { + // let mut greeter = Greeter::default(); + // + // assert!( + // greeter + // .parse_options(&[ + // "--cmd", + // "sway", + // "--env", + // "XDG_CURRENT_DESKTOP=sway", + // "--env", + // "XDG_SESSION_TYPE=wayland", + // ]) + // .await + // .is_ok() + // ); + // + // let mut config = Config::default(); + // config.session.command = Some("sway".to_string()); + // config.session.environments = vec![ + // "XDG_CURRENT_DESKTOP=sway".to_string(), + // "XDG_SESSION_TYPE=wayland".to_string(), + // ]; + // greeter.apply_config(&config); + // + // assert!(matches!( + // &greeter.session_source, + // SessionSource::DefaultCommand(command, Some(environments)) + // if command == "sway" + // && environments + // == &vec![ + // "XDG_CURRENT_DESKTOP=sway".to_string(), + // "XDG_SESSION_TYPE=wayland".to_string() + // ] + // )); + // } + // + // #[tokio::test] + // async fn test_config_power_options_are_applied() { + // let mut greeter = Greeter::default(); + // + // assert!(greeter.parse_options(&[] as &[&str]).await.is_ok()); + // + // let mut config = Config::default(); + // config.power.shutdown = Some("loginctl poweroff".to_string()); + // config.power.reboot = Some("loginctl reboot".to_string()); + // config.power.suspend = Some("loginctl suspend".to_string()); + // config.power.hibernate = Some("loginctl hibernate".to_string()); + // config.power.use_setsid = false; + // greeter.apply_config(&config); + // + // assert!(!greeter.power_setsid); + // assert!(greeter.powers.options.iter().any(|power| { + // power.action == PowerOption::Shutdown + // && power.command.as_deref() == Some("loginctl poweroff") + // })); + // assert!(greeter.powers.options.iter().any(|power| { + // power.action == PowerOption::Reboot + // && power.command.as_deref() == Some("loginctl reboot") + // })); + // assert!(greeter.powers.options.iter().any(|power| { + // power.action == PowerOption::Suspend + // && power.command.as_deref() == Some("loginctl suspend") + // })); + // assert!(greeter.powers.options.iter().any(|power| { + // power.action == PowerOption::Hibernate + // && power.command.as_deref() == Some("loginctl hibernate") + // })); + // } +} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0d3bfb0..1bb9eb8 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -32,9 +32,6 @@ jobs: run: | cargo test LD_PRELOAD=libnss_wrapper.so cargo test --features nsswrapper nsswrapper_ - - name: Generate manpage - run: | - scdoc < contrib/man/tuigreet-1.scd > /dev/null build: strategy: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8fe1dc2..3b0c352 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -61,7 +61,3 @@ jobs: run: | cargo test LD_PRELOAD=libnss_wrapper.so cargo test --features nsswrapper nsswrapper_ - - - name: Generate manpage - run: | - scdoc < contrib/man/tuigreet-1.scd > /dev/null diff --git a/Cargo.lock b/Cargo.lock index da8db85..2825811 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android_system_properties" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" dependencies = [ "libc", ] @@ -27,14 +27,58 @@ dependencies = [ "ratatui-core", "simdutf8", "smallvec", - "thiserror 2.0.18", + "thiserror 2.0.19", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", ] [[package]] -name = "anyhow" -version = "1.0.102" +name = "anstyle-wincon" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] [[package]] name = "approx" @@ -47,29 +91,38 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" dependencies = [ "rustversion", ] [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", +] + +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", ] [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "basic-toml" @@ -80,12 +133,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.13.1" @@ -103,9 +150,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "by_address" @@ -113,6 +160,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" + [[package]] name = "byteorder" version = "1.5.0" @@ -121,9 +174,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "castaway" @@ -136,9 +189,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.60" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" dependencies = [ "find-msvc-tools", "shlex", @@ -152,15 +205,15 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", "cpufeatures", @@ -181,6 +234,56 @@ dependencies = [ "windows-link", ] +[[package]] +name = "clap" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "clap_mangen" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c630ddc90572b3d9abd3f887f0007b4e048faf5c5a59ae607f8ac1c5e3790873" +dependencies = [ + "clap", + "roff", +] + [[package]] name = "codespan-reporting" version = "0.13.1" @@ -192,6 +295,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "compact_str" version = "0.9.1" @@ -258,18 +367,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crossterm" @@ -277,7 +386,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.13.1", + "bitflags", "crossterm_winapi", "derive_more", "document-features", @@ -316,9 +425,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +checksum = "88490bf1b990d87eaaa7ac8aa887f629a08e7359765b4911faf63c3763347d23" dependencies = [ "darling_core", "darling_macro", @@ -326,26 +435,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +checksum = "084e274f91c482280130e1e34e0b8d6e66776a060d7b6de7b84289ca778868c4" dependencies = [ "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] name = "darling_macro" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +checksum = "68f5792fa0d41cd2325ce0ffa64f0a340eaebd4971a3a0c5e1ffd2cc488a355e" dependencies = [ "darling_core", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -353,9 +462,6 @@ name = "deranged" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] [[package]] name = "derive_more" @@ -376,7 +482,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -413,13 +519,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -442,9 +548,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" [[package]] name = "equivalent" @@ -463,16 +569,26 @@ dependencies = [ ] [[package]] -name = "fast-srgb8" -version = "1.0.0" +name = "fastrand" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] -name = "fastrand" -version = "2.4.1" +name = "figment" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" +dependencies = [ + "atomic", + "parking_lot", + "pear", + "serde", + "tempfile", + "toml 0.8.23", + "uncased", + "version_check", +] [[package]] name = "find-crate" @@ -531,15 +647,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54f0d287c53ffd184d04d8677f590f4ac5379785529e5e08b1c8083acdd5c198" dependencies = [ "memchr", - "thiserror 2.0.18", + "thiserror 2.0.19", ] -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foldhash" version = "0.2.0" @@ -611,7 +721,7 @@ checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -665,16 +775,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi", "rand_core", - "wasip2", - "wasip3", ] [[package]] @@ -710,15 +818,6 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - [[package]] name = "hashbrown" version = "0.16.1" @@ -727,18 +826,18 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash 0.2.0", + "foldhash", ] [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "allocator-api2", "equivalent", - "foldhash 0.2.0", + "foldhash", ] [[package]] @@ -749,9 +848,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hybrid-array" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" dependencies = [ "typenum", ] @@ -806,7 +905,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.119", "unic-langid", ] @@ -820,7 +919,7 @@ dependencies = [ "i18n-config", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -847,12 +946,6 @@ dependencies = [ "cc", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -866,9 +959,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", - "serde", - "serde_core", + "hashbrown 0.17.1", ] [[package]] @@ -880,37 +971,43 @@ dependencies = [ "rustversion", ] +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + [[package]] name = "inotify" -version = "0.11.1" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" +checksum = "153be1941a183ec9ccd095ddbe17a8b8d435ef6c76e9e02451b933c3999af2c8" dependencies = [ - "bitflags 2.13.1", + "bitflags", "inotify-sys", "libc", ] [[package]] name = "inotify-sys" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +checksum = "c033f80b2c113cdf91ab7a33faa9cbc014726dcad99880c8609af2a370edf37d" dependencies = [ "libc", ] [[package]] name = "instability" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" +checksum = "2bf84e73fa6f27f299dec58e13223cf70db80da872eb921d4f6138342a0eabc8" dependencies = [ "darling", "indoc", "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -932,6 +1029,12 @@ dependencies = [ "unic-langid", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itertools" version = "0.14.0" @@ -949,11 +1052,12 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.95" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] @@ -965,14 +1069,14 @@ checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" dependencies = [ "hashbrown 0.16.1", "portable-atomic", - "thiserror 2.0.18", + "thiserror 2.0.19", ] [[package]] name = "kqueue" -version = "1.1.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" +checksum = "8d763e5b24120b4ddf50de6c92308156765aabfbbccebf401da7cff2d70a41ea" dependencies = [ "kqueue-sys", "libc", @@ -980,11 +1084,11 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.4" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" dependencies = [ - "bitflags 1.3.2", + "bitflags", "libc", ] @@ -994,17 +1098,11 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libm" @@ -1014,20 +1112,20 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +checksum = "2026a5056764a10b2bf5d56488cba40da507f5493a6a429340e2004d9ed085fa" dependencies = [ "libc", ] [[package]] name = "line-clipping" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" +checksum = "e752191d037c44ad111a8caa762921926658402f01cc1253f7bef2020ece4f5e" dependencies = [ - "bitflags 2.13.1", + "bitflags", ] [[package]] @@ -1053,24 +1151,24 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6180140927ee907000b0aa540091f6ea512ead4447c92b8fc35bc72788a5a6" +checksum = "5d2f2f9b4ba7e6b24d95e7e899329d35be83bcded72c8540cdd5368932d1d90a" dependencies = [ - "hashbrown 0.17.0", + "hashbrown 0.17.1", ] [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "mime" @@ -1090,9 +1188,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", "log", @@ -1106,7 +1204,7 @@ version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags 2.13.1", + "bitflags", "cfg-if", "cfg_aliases", "libc", @@ -1127,7 +1225,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.13.1", + "bitflags", "fsevent-sys", "inotify", "kqueue", @@ -1145,7 +1243,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "bitflags 2.13.1", + "bitflags", ] [[package]] @@ -1159,9 +1257,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-traits" @@ -1193,6 +1291,12 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "option-ext" version = "0.2.0" @@ -1211,26 +1315,35 @@ dependencies = [ [[package]] name = "palette" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +checksum = "ddeed8580d347d2abf3dcf06a5f0b3dc020258338526b277847cd4248a70fc64" dependencies = [ "approx", - "fast-srgb8", "libm", "palette_derive", + "palette_math", ] [[package]] name = "palette_derive" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +checksum = "88537020289b719d81be994ccf1bbf4990f477e2f69ee52fe3e45f43a02e56be" dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", +] + +[[package]] +name = "palette_math" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e6eb142958d64335fb0e345c5b9ead2ecd6fc438c307e9d7d3c4fd428dbaf12" +dependencies = [ + "libm", ] [[package]] @@ -1256,6 +1369,29 @@ dependencies = [ "windows-link", ] +[[package]] +name = "pear" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" +dependencies = [ + "inlinable_string", + "pear_codegen", + "yansi", +] + +[[package]] +name = "pear_codegen" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.119", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -1274,16 +1410,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - [[package]] name = "proc-macro-error-attr3" version = "3.1.0" @@ -1308,13 +1434,26 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "version_check", + "yansi", +] + [[package]] name = "pure-rust-locales" version = "0.8.2" @@ -1323,9 +1462,9 @@ checksum = "869675ad2d7541aea90c6d88c81f46a7f4ea9af8cd0395d38f11a95126998a0d" [[package]] name = "quote" -version = "1.0.45" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -1343,7 +1482,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ "chacha20", - "getrandom 0.4.2", + "getrandom 0.4.3", "rand_core", ] @@ -1374,16 +1513,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ - "bitflags 2.13.1", + "bitflags", "compact_str", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "itertools", "kasuari", "lru", "palette", "serde", "strum", - "thiserror 2.0.18", + "thiserror 2.0.19", "unicode-segmentation", "unicode-truncate", "unicode-width", @@ -1429,8 +1568,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ - "bitflags 2.13.1", - "hashbrown 0.17.0", + "bitflags", + "hashbrown 0.17.1", "indoc", "instability", "itertools", @@ -1449,7 +1588,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.1", + "bitflags", ] [[package]] @@ -1460,9 +1599,15 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 2.0.18", + "thiserror 2.0.19", ] +[[package]] +name = "roff" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323c417e1d9665a65b263ec744ba09030cfb277e9daa0b018a4ab62e57bc8189" + [[package]] name = "rust-embed" version = "8.12.0" @@ -1484,7 +1629,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.117", + "syn 2.0.119", "walkdir", ] @@ -1510,9 +1655,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -1529,7 +1674,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.1", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -1538,9 +1683,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ryu" @@ -1565,9 +1710,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "self_cell" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" +checksum = "2ab42ca02749e120097e328d91d415325bdf43b1c72c4c8badf37375fe40a813" [[package]] name = "semver" @@ -1607,9 +1752,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -1618,6 +1763,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "serde_spanned" version = "1.1.1" @@ -1649,9 +1803,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook" @@ -1698,15 +1852,15 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket2" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", "windows-sys 0.61.2", @@ -1742,7 +1896,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -1753,9 +1907,9 @@ checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" [[package]] name = "syn" -version = "2.0.117" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -1789,7 +1943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix", "windows-sys 0.61.2", @@ -1810,7 +1964,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" dependencies = [ - "bitflags 2.13.1", + "bitflags", "parking_lot", "rustix", "signal-hook", @@ -1838,11 +1992,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl 2.0.19", ] [[package]] @@ -1853,37 +2007,36 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ "cfg-if", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" dependencies = [ "deranged", - "itoa", "libc", "num-conv", "num_threads", @@ -1895,15 +2048,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" dependencies = [ "num-conv", "time-core", @@ -1947,13 +2100,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 3.0.3", ] [[package]] @@ -1965,6 +2118,18 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit", +] + [[package]] name = "toml" version = "1.1.4+spec-1.1.0" @@ -1973,11 +2138,20 @@ checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" dependencies = [ "indexmap", "serde_core", - "serde_spanned", - "toml_datetime", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 1.0.4", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", ] [[package]] @@ -1989,15 +2163,35 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", +] + [[package]] name = "toml_parser" version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ - "winnow", + "winnow 1.0.4", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "toml_writer" version = "1.1.2+spec-1.1.0" @@ -2023,7 +2217,7 @@ checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", "symlink", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "tracing-subscriber", ] @@ -2036,7 +2230,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -2080,8 +2274,11 @@ version = "0.11.0" dependencies = [ "ansi-to-tui", "chrono", + "clap", + "clap_mangen", "crossterm", "dirs", + "figment", "futures", "getopts", "greetd-stub", @@ -2114,12 +2311,15 @@ name = "tuigreet-config" version = "0.11.0" dependencies = [ "chrono", + "clap", "codespan-reporting", "dirs", + "figment", "getopts", "serde", "toml 1.1.4+spec-1.1.0", "tracing", + "tuigreet-types", ] [[package]] @@ -2163,9 +2363,18 @@ dependencies = [ [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "uncased" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +dependencies = [ + "version_check", +] [[package]] name = "unic-langid" @@ -2200,9 +2409,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-truncate" @@ -2222,10 +2431,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] -name = "unicode-xid" -version = "0.2.6" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "utmp-raw" @@ -2267,6 +2476,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "walkdir" version = "2.5.0" @@ -2283,29 +2498,11 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", -] - [[package]] name = "wasm-bindgen" -version = "0.2.118" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -2316,9 +2513,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.118" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2326,60 +2523,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.118" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.118" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.13.1", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2432,7 +2595,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -2443,7 +2606,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] @@ -2555,103 +2718,24 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" - -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", + "memchr", ] [[package]] -name = "wit-component" -version = "0.244.0" +name = "winnow" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.13.1", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" [[package]] -name = "wit-parser" -version = "0.244.0" +name = "yansi" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" @@ -2671,14 +2755,14 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.119", ] [[package]] name = "zerofrom" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" [[package]] name = "zeroize" @@ -2698,6 +2782,6 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 0b1e895..2c77dbd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,9 +20,11 @@ tuigreet-types = { path = "crates/tuigreet-types", version = "0.11.0" } # External ansi-to-tui = "8.0.1" chrono = { version = "0.4.45", features = [ "unstable-locales" ] } +clap = { version = "4.6.4", features = ["derive"] } codespan-reporting = "0.13.1" crossterm = { version = "0.29.0", features = [ "event-stream" ] } dirs = "6.0.0" +figment = { version = "0.10.19", features = [ "env", "toml", "test" ] } futures = "0.3.33" getopts = "0.2.24" greetd_ipc = { version = "0.10.3", features = [ "tokio-codec" ] } @@ -34,6 +36,7 @@ rand = "0.10.2" rust-embed = "8.12.0" rust-ini = "0.21.3" serde = { version = "1.0.229", features = [ "derive" ] } +serde_default_utils = { version = "0.3.1", features = ["inline"] } tokio = { version = "1.53.1", default-features = false, features = [ "macros", "rt-multi-thread", @@ -55,6 +58,9 @@ utmp-rs = "0.4.0" uzers = "0.12.2" zeroize = "1.9.0" +# build time tools +clap_mangen = { version = "0.3.1" } + # Dev greetd-stub = "0.3.0" tempfile = "3.27.0" diff --git a/contrib/man/tuigreet-1 b/contrib/man/tuigreet-1 new file mode 100644 index 0000000..bdfad4d --- /dev/null +++ b/contrib/man/tuigreet-1 @@ -0,0 +1,312 @@ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.TH tuigreet 1 "tuigreet 0.11.0" +.SH NAME +tuigreet \- Stylish graphical console greeter for greetd +.SH SYNOPSIS +\fBtuigreet\fR [\fB\-\-system\-config\fR] [\fB\-\-config\fR] [\fB\-\-no\-config\fR] [\fB\-d\fR|\fB\-\-debug\fR] [\fB\-l\fR|\fB\-\-log\-file\fR] [\fB\-m\fR|\fB\-\-mock\fR] [\fB\-n\fR|\fB\-\-numlock\fR] [\fB\-c\fR|\fB\-\-cmd\fR] [\fB\-s\fR|\fB\-\-sessions\fR] [\fB\-x\fR|\fB\-\-xsessions\fR] [\fB\-\-session\-wrapper\fR] [\fB\-\-xsession\-wrapper\fR] [\fB\-\-env\fR] [\fB\-t\fR|\fB\-\-time\fR] [\fB\-\-time\-format\fR] [\fB\-g\fR|\fB\-\-greeting\fR] [\fB\-\-title\fR] [\fB\-\-custom\-title\fR] [\fB\-i\fR|\fB\-\-issue\fR] [\fB\-b\fR|\fB\-\-battery\fR] [\fB\-\-greet\-align\fR] [\fB\-u\fR|\fB\-\-user\fR] [\fB\-r\fR|\fB\-\-remember\fR] [\fB\-\-remember\-session\fR] [\fB\-\-remember\-user\-session\fR] [\fB\-\-user\-menu\fR] [\fB\-\-user\-menu\-min\-uid\fR] [\fB\-\-user\-menu\-max\-uid\fR] [\fB\-\-secret\-mode\fR] [\fB\-\-secret\-characters\fR] [\fB\-w\fR|\fB\-\-width\fR] [\fB\-\-window\-padding\fR] [\fB\-\-container\-padding\fR] [\fB\-\-prompt\-padding\fR] [\fB\-\-time\-position\fR] [\fB\-\-status\-position\fR] [\fB\-\-battery\-position\fR] [\fB\-\-show\-reset\fR] [\fB\-\-show\-command\fR] [\fB\-\-show\-session\fR] [\fB\-\-show\-power\fR] [\fB\-\-show\-background\fR] [\fB\-\-show\-session\-status\fR] [\fB\-\-show\-caps\-lock\fR] [\fB\-\-power\-shutdown\fR] [\fB\-\-power\-reboot\fR] [\fB\-\-power\-suspend\fR] [\fB\-\-power\-hibernate\fR] [\fB\-\-power\-use\-setsid\fR] [\fB\-\-kb\-command\fR] [\fB\-\-kb\-sessions\fR] [\fB\-\-kb\-power\fR] [\fB\-\-kb\-background\fR] [\fB\-\-theme\-border\fR] [\fB\-\-theme\-text\fR] [\fB\-\-theme\-time\fR] [\fB\-\-theme\-container\fR] [\fB\-\-theme\-title\fR] [\fB\-\-theme\-greet\fR] [\fB\-\-theme\-prompt\fR] [\fB\-\-theme\-input\fR] [\fB\-\-theme\-action\fR] [\fB\-\-theme\-button\fR] [\fB\-\-background\fR] [\fB\-\-background\-fps\fR] [\fB\-\-doom\-height\fR] [\fB\-\-doom\-spread\fR] [\fB\-\-doom\-top\-color\fR] [\fB\-\-doom\-middle\-color\fR] [\fB\-\-doom\-bottom\-color\fR] [\fB\-\-matrix\-head\-color\fR] [\fB\-\-matrix\-bright\-color\fR] [\fB\-\-matrix\-dim\-color\fR] [\fB\-\-matrix\-min\-length\fR] [\fB\-\-matrix\-max\-length\fR] [\fB\-\-matrix\-min\-speed\fR] [\fB\-\-matrix\-max\-speed\fR] [\fB\-\-matrix\-mutate\-chance\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] +.SH DESCRIPTION +Stylish graphical console greeter for greetd +.SH OPTIONS +.TP +\fB\-\-system\-config\fR \fI\fR [default: /etc/tuigreet/config.toml] +path to system configuration toml file +.TP +\fB\-\-config\fR \fI\fR [default: ~/.config/tuigreet/config.toml] +path to user configuration toml file +.TP +\fB\-\-no\-config\fR +disable loading toml configuration files +.TP +\fB\-d\fR, \fB\-\-debug\fR +Enable debug logging +.TP +\fB\-l\fR, \fB\-\-log\-file\fR \fI\fR [default: /tmp/tuigreet.log] +Log file path +.TP +\fB\-m\fR, \fB\-\-mock\fR +visual mock\-up mode: skip the greetd socket and fake the auth flow locally +.TP +\fB\-n\fR, \fB\-\-numlock\fR +Enable numlock on startup +.TP +\fB\-c\fR, \fB\-\-cmd\fR \fI\fR +Override session with a specific command +.TP +\fB\-s\fR, \fB\-\-sessions\fR \fI\fR +Directories containing Wayland session files +.TP +\fB\-x\fR, \fB\-\-xsessions\fR \fI\fR [default: /usr/share/xsessions] +Directories containing X11 session files +.TP +\fB\-\-session\-wrapper\fR \fI\fR +Wrapper command for non\-X11 sessions +.TP +\fB\-\-xsession\-wrapper\fR \fI\fR [default: startx] +Wrapper command for X11 sessions (set to empty string "" for no wrapper) +.TP +\fB\-\-env\fR \fI\fR +Environment variables for default session +.TP +\fB\-t\fR, \fB\-\-time\fR +Show current time +.TP +\fB\-\-time\-format\fR \fI\fR +Custom time format (strftime) +.TP +\fB\-g\fR, \fB\-\-greeting\fR \fI\fR +Custom greeting message +.TP +\fB\-\-title\fR +Show login form title +.TP +\fB\-\-custom\-title\fR \fI\fR +Custom login form title +.TP +\fB\-i\fR, \fB\-\-issue\fR +Show /etc/issue file +.TP +\fB\-b\fR, \fB\-\-battery\fR +Show battery percentage +.TP +\fB\-\-greet\-align\fR \fI\fR [default: center] +Greeting text alignment +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +left +.IP \(bu 2 +center +.IP \(bu 2 +right +.RE +.TP +\fB\-u\fR, \fB\-\-user\fR \fI\fR +Default user to pre\-fill +.TP +\fB\-r\fR, \fB\-\-remember\fR +Remember last logged\-in username +.TP +\fB\-\-remember\-session\fR +Remember last selected session (global) +.TP +\fB\-\-remember\-user\-session\fR +Remember last selected session per user +.TP +\fB\-\-user\-menu\fR +Enable user selection menu +.TP +\fB\-\-user\-menu\-min\-uid\fR \fI\fR [default: 1000] +Minimum UID to display in user menu +.TP +\fB\-\-user\-menu\-max\-uid\fR \fI\fR [default: 60000] +Maximum UID to display in user menu +.TP +\fB\-\-secret\-mode\fR \fI\fR [default: hidden] +How to display secrets +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +hidden +.IP \(bu 2 +characters +.RE +.TP +\fB\-\-secret\-characters\fR \fI\fR [default: *] +Characters to use when mode is Characters +.TP +\fB\-w\fR, \fB\-\-width\fR \fI\fR [default: 80] +Width of the main prompt container +.TP +\fB\-\-window\-padding\fR \fI\fR [default: 0] +Padding around the terminal window +.TP +\fB\-\-container\-padding\fR \fI\fR [default: 2] +Padding inside the main container +.TP +\fB\-\-prompt\-padding\fR \fI\fR [default: 1] +Padding between prompt rows +.TP +\fB\-\-time\-position\fR \fI\fR [default: default] +Position of time widget +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +default +.IP \(bu 2 +top +.IP \(bu 2 +bottom +.IP \(bu 2 +hidden +.RE +.TP +\fB\-\-status\-position\fR \fI\fR [default: default] +Position of status bar widget +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +default +.IP \(bu 2 +top +.IP \(bu 2 +bottom +.IP \(bu 2 +hidden +.RE +.TP +\fB\-\-battery\-position\fR \fI\fR [default: left] +Position of battery widget +.br + +.br +\fIPossible values:\fR +.RS 14 +.IP \(bu 2 +left +.IP \(bu 2 +right +.RE +.TP +\fB\-\-show\-reset\fR +Show the ESC/Reset button +.TP +\fB\-\-show\-command\fR +Show the command button +.TP +\fB\-\-show\-session\fR +Show the session button +.TP +\fB\-\-show\-power\fR +Show the power button +.TP +\fB\-\-show\-background\fR +Show the background button +.TP +\fB\-\-show\-session\-status\fR +Show the current session/command indicator +.TP +\fB\-\-show\-caps\-lock\fR +Show the caps lock indicator +.TP +\fB\-\-power\-shutdown\fR \fI\fR +Custom shutdown command +.TP +\fB\-\-power\-reboot\fR \fI\fR +Custom reboot command +.TP +\fB\-\-power\-suspend\fR \fI\fR +Custom suspend command +.TP +\fB\-\-power\-hibernate\fR \fI\fR +Custom hibernate command +.TP +\fB\-\-power\-use\-setsid\fR +Use setsid to detach power commands +.TP +\fB\-\-kb\-command\fR \fI\fR [default: 2] +F\-key for command menu (1\-12) +.TP +\fB\-\-kb\-sessions\fR \fI\fR [default: 3] +F\-key for sessions menu (1\-12) +.TP +\fB\-\-kb\-power\fR \fI\fR [default: 12] +F\-key for power menu (1\-12) +.TP +\fB\-\-kb\-background\fR \fI\fR [default: 4] +F\-key for the on\-the\-fly background switcher menu (1\-12) +.TP +\fB\-\-theme\-border\fR \fI\fR +Border color +.TP +\fB\-\-theme\-text\fR \fI\fR +Base text color +.TP +\fB\-\-theme\-time\fR \fI