Skip to content

Commit

Permalink
docs: update main.rs docs
Browse files Browse the repository at this point in the history
Add a more extensive summary atop, as this is a bin package
  • Loading branch information
roosta committed Dec 15, 2024
1 parent 92a7a31 commit 7b4d2b1
Showing 1 changed file with 218 additions and 19 deletions.
237 changes: 218 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,95 @@
//! # i3wsr - i3/Sway Workspace Renamer
//!
//! A workspace renamer for i3 and Sway window managers that dynamically updates workspace names
//! based on their content. It monitors window events and renames workspaces to show the applications
//! running in them.
//!
//! ## Usage
//!
//! 1. Install using cargo:
//! ```bash
//! cargo install i3wsr
//! ```
//!
//! 2. Add to your i3/Sway config:
//! ```
//! exec_always --no-startup-id i3wsr
//! ```
//!
//! 3. Ensure numbered workspaces in i3/Sway config:
//! ```
//! bindsym $mod+1 workspace number 1
//! assign [class="(?i)firefox"] number 1
//! ```
//!
//! ## Configuration
//!
//! Configuration can be done via:
//! - Command line arguments
//! - TOML configuration file (default: `$XDG_CONFIG_HOME/i3wsr/config.toml`)
//!
//! ### Config File Sections:
//!
//! ```toml
//! [icons]
//! # Map window classes to icons
//! Firefox = "🌍"
//! default_icon = "💻"
//!
//! [aliases.class]
//! # Map window classes to friendly names
//! "Google-chrome" = "Chrome"
//!
//! [aliases.instance]
//! # Map window instances to friendly names
//! "web.whatsapp.com" = "WhatsApp"
//!
//! [aliases.name]
//! # Map window names using regex
//! ".*mutt$" = "Mail"
//!
//! [general]
//! separator = " | " # Separator between window names
//! split_at = ":" # Character to split workspace number
//! empty_label = "🌕" # Label for empty workspaces
//! display_property = "class" # Default property to display (class/instance/name)
//!
//! [options]
//! remove_duplicates = false # Remove duplicate window names
//! no_names = false # Show only icons
//! no_icon_names = false # Show names only if no icon available
//! ```
//!
//! ### Command Line Options:
//!
//! - `--verbose`: Enable detailed logging
//! - `--config <FILE>`: Use alternative config file
//! - `--no-icon-names`: Show only icons when available
//! - `--no-names`: Never show window names
//! - `--remove-duplicates`: Remove duplicate entries
//! - `--display-property <PROPERTY>`: Window property to use (class/instance/name)
//! - `--split-at <CHAR>`: Character to split workspace names
//!
//! ### Window Properties:
//!
//! Three window properties can be used for naming:
//! - `class`: Default, most stable (WM_CLASS)
//! - `instance`: More specific than class (WM_INSTANCE)
//! - `name`: Most detailed but volatile (WM_NAME)
//!
//! Properties are checked in order: name -> instance -> class
//!
//! ### Special Features:
//!
//! - Regex support in aliases
//! - Custom icons per window
//! - Default icons
//! - Empty workspace labels
//! - Duplicate removal
//! - Custom separators
//!
//! For more details, see the [README](https://github.com/roosta/i3wsr)
use clap::{Parser, ValueEnum};
use dirs::config_dir;
use swayipc::{Connection, Event, EventType, Fallible};
Expand All @@ -7,7 +99,13 @@ use std::path::Path;

use i3wsr::AppError;

/// Window property types for display
/// Window property types that can be used for workspace naming.
///
/// These properties determine which window attribute is used when displaying
/// window names in workspaces:
/// - `Class`: Uses WM_CLASS (default, most stable)
/// - `Instance`: Uses WM_INSTANCE (more specific than class)
/// - `Name`: Uses WM_NAME (most detailed but volatile)
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
enum Properties {
Class,
Expand All @@ -25,39 +123,116 @@ impl Properties {
}
}

/// Command line arguments
/// Command line arguments for i3wsr
///
/// Configuration can be provided either through command line arguments
/// or through a TOML configuration file. Command line arguments take
/// precedence over configuration file settings.
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
#[command(author, version, about = "Dynamic workspace renamer for i3 and Sway window managers")]
#[command(long_about = "Automatically renames workspaces based on their window contents. \
Supports custom icons, aliases, and various display options. \
Can be configured via command line flags or a TOML configuration file.")]
struct Args {
/// Enable verbose logging
#[arg(short, long)]
/// Enable verbose logging of events and operations
#[arg(short, long, help = "Print detailed information about events and operations")]
verbose: bool,
/// Path to toml config file
#[arg(short, long)]
/// Path to TOML configuration file
#[arg(
short,
long,
help = "Path to TOML config file (default: $XDG_CONFIG_HOME/i3wsr/config.toml)",
value_name = "FILE"
)]
config: Option<String>,

/// Display only icon (if available) otherwise display name
#[arg(short = 'm', long)]
#[arg(
short = 'm',
long,
help = "Show only icons when available, fallback to names otherwise"
)]
no_icon_names: bool,

/// Do not display names
#[arg(short, long)]
/// Do not display window names, only show icons
#[arg(
short,
long,
help = "Show only icons, never display window names"
)]
no_names: bool,

/// Remove duplicate entries in workspace
#[arg(short, long)]
/// Remove duplicate entries in workspace names
#[arg(
short,
long,
help = "Remove duplicate window names from workspace labels"
)]
remove_duplicates: bool,

/// Which window property to use when no alias is found
#[arg(short = 'p', long)]
#[arg(
short = 'p',
long,
value_enum,
help = "Window property to use for naming (class/instance/name)",
value_name = "PROPERTY"
)]
display_property: Option<Properties>,

/// What character used to split the workspace title string
#[arg(short = 'a', long)]
/// Character used to split the workspace title string
#[arg(
short = 'a',
long,
help = "Character that separates workspace number from window names",
value_name = "CHAR"
)]
split_at: Option<String>,
}

/// Loads configuration from file or creates default
/// Loads configuration from a TOML file or creates default configuration
///
/// # Configuration File Search Order
///
/// 1. Path specified via command line argument
/// 2. $XDG_CONFIG_HOME/i3wsr/config.toml
/// 3. Default configuration if no file found
///
/// # Configuration File Format
///
/// The configuration file uses TOML format with these main sections:
///
/// ```toml
/// [icons]
/// # Map window classes to icons
/// Firefox = "🌍"
/// default_icon = "💻"
///
/// [aliases.class]
/// # Map window classes to friendly names
/// "Google-chrome" = "Chrome"
///
/// [aliases.instance]
/// # Map window instances to friendly names
/// "web.whatsapp.com" = "WhatsApp"
///
/// [aliases.name]
/// # Map window names using regex
/// ".*mutt$" = "Mail"
///
/// [general]
/// # General settings
/// separator = " | " # Separator between window names
/// split_at = ":" # Character to split workspace number
/// empty_label = "🌕" # Label for empty workspaces
/// display_property = "class" # Default property to display
///
/// [options]
/// # Boolean options
/// remove_duplicates = false
/// no_names = false
/// no_icon_names = false
/// ```
fn load_config(config_path: Option<&str>) -> Result<Config, ConfigError> {
let xdg_config = config_dir()
.ok_or_else(|| ConfigError::IoError(io::Error::new(
Expand Down Expand Up @@ -110,7 +285,15 @@ fn apply_args_to_config(config: &mut Config, args: &Args) {
config.general.insert("display_property".to_string(), display_property.to_string());
}

/// Setup program by handling args and populating config
/// Sets up the program by processing arguments and initializing configuration
///
/// This function:
/// 1. Parses command line arguments
/// 2. Sets up verbose logging if requested
/// 3. Loads configuration from file
/// 4. Applies command line overrides to configuration
///
/// Command line arguments take precedence over configuration file settings.
fn setup() -> Result<Config, AppError> {
let args = Args::parse();

Expand All @@ -123,7 +306,14 @@ fn setup() -> Result<Config, AppError> {
Ok(config)
}

/// Handles sway events and updates workspace names
/// Processes window manager events and updates workspace names accordingly
///
/// Handles two types of events:
/// - Window events (new, close, move, title changes)
/// - Workspace events (focus changes, empty workspace events)
///
/// For each event, it updates the relevant workspace names based on
/// the current configuration and window properties.
fn handle_event(
event: Fallible<Event>,
conn: &mut Connection,
Expand All @@ -145,7 +335,16 @@ fn handle_event(
Ok(())
}

/// Entry main loop: continuously listen to sway window events and workspace events
/// Main event loop that monitors window manager events
///
/// This function:
/// 1. Initializes configuration and connections
/// 2. Subscribes to window and workspace events
/// 3. Performs initial workspace name updates
/// 4. Continuously processes events and updates workspace names
///
/// The program will continue running and handling events until
/// interrupted or an unrecoverable error occurs.
fn run() -> Result<(), AppError> {
let config = setup()?;
let res = i3wsr::regex::parse_config(&config)?;
Expand Down

0 comments on commit 7b4d2b1

Please sign in to comment.