A cross-platform Rust library for resolving XDG and platform-specific directories with proper fallbacks.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Rust 88.2%
Shell 11.8%
9 1 0

Clone this repository

https://tangled.org/aaronmallen.dev/dir_spec https://tangled.org/did:plc:536uepxkdil42jqx74lt4xqe/dir_spec
git@tangled.org:aaronmallen.dev/dir_spec git@tangled.org:did:plc:536uepxkdil42jqx74lt4xqe/dir_spec

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

dir_spec#

A cross-platform Rust library for resolving XDG and platform-specific directories with proper fallbacks.

Why Another Directory Library?#

Most existing directory libraries (like dirs) ignore XDG environment variables on macOS and Windows, defaulting to platform-specific locations even when users have explicitly set XDG variables. This crate prioritizes XDG compliance across all platforms while providing sensible platform-specific fallbacks.

Features#

  • XDG-first approach: Respects XDG environment variables on all platforms
  • Platform-aware fallbacks: Uses native conventions when XDG variables aren't set
  • Cross-platform: Works on Linux, macOS, and Windows
  • Minimal dependencies: Only uses libc for Unix systems
  • Type-safe: Returns Option<PathBuf> for simple error handling

Usage#

Add this to your Cargo.toml:

[dependencies]
dir_spec = "0.2.0"

Basic usage:

use dir_spec::Dir;

fn main() {
    // Get config directory (respects XDG_CONFIG_HOME if set)
    if let Some(config_dir) = Dir::config_home() {
        println!("Config: {}", config_dir.display());
    }
    
    // Get cache directory (respects XDG_CACHE_HOME if set)
    if let Some(cache_dir) = Dir::cache_home() {
        println!("Cache: {}", cache_dir.display());
    }
    
    // Get user's home directory
    if let Some(home_dir) = Dir::home() {
        println!("Home: {}", home_dir.display());
    }
}

Supported Directories#

Method XDG Variable Linux Default macOS Default Windows Default
bin_home() XDG_BIN_HOME ~/.local/bin ~/.local/bin %LOCALAPPDATA%\Programs
cache_home() XDG_CACHE_HOME ~/.cache ~/Library/Caches %LOCALAPPDATA%
config_home() XDG_CONFIG_HOME ~/.config ~/Library/Application Support %APPDATA%
data_home() XDG_DATA_HOME ~/.local/share ~/Library/Application Support %APPDATA%
desktop() XDG_DESKTOP_DIR ~/Desktop ~/Desktop %USERPROFILE%\Desktop
documents() XDG_DOCUMENTS_DIR ~/Documents ~/Documents %USERPROFILE%\Documents
downloads() XDG_DOWNLOAD_DIR ~/Downloads ~/Downloads %USERPROFILE%\Downloads
music() XDG_MUSIC_DIR ~/Music ~/Music %USERPROFILE%\Music
pictures() XDG_PICTURES_DIR ~/Pictures ~/Pictures %USERPROFILE%\Pictures
publicshare() XDG_PUBLICSHARE_DIR ~/Public ~/Public C:\Users\Public
runtime() XDG_RUNTIME_DIR /run/user/$UID $TMPDIR or /tmp %TEMP%
state_home() XDG_STATE_HOME ~/.local/state ~/Library/Application Support %LOCALAPPDATA%
templates() XDG_TEMPLATES_DIR ~/Templates ~/Templates %USERPROFILE%\Templates
videos() XDG_VIDEOS_DIR ~/Videos ~/Movies %USERPROFILE%\Videos
home() HOME / USERPROFILE $HOME $HOME %USERPROFILE%

XDG Environment Variable Priority#

This crate always checks XDG environment variables first, regardless of platform:

// This will use XDG_CONFIG_HOME if set, even on macOS/Windows
export XDG_CONFIG_HOME="/custom/config/path"

let config = Dir::config_home(); // Returns Some("/custom/config/path")

If XDG variables aren't set, the crate falls back to platform-appropriate defaults.

Cross-Platform Behavior#

Linux#

Follows XDG Base Directory Specification defaults when XDG variables aren't set.

macOS#

  • Respects XDG variables if set (common among CLI tool users)
  • Falls back to native macOS locations (~/Library/Application Support, etc.)
  • Uses ~/Movies for videos (not ~/Videos)

Windows#

  • Respects XDG variables if set
  • Falls back to Windows conventions (%APPDATA%, %LOCALAPPDATA%, etc.)
  • Public directory points to system-wide C:\Users\Public

Error Handling#

All methods return Option<PathBuf>. Methods return None when:

  • Home directory cannot be determined
  • Required environment variables are missing (Windows-specific cases)
  • Platform-specific directory resolution fails
match Dir::config_home() {
    Some(path) => println!("Config dir: {}", path.display()),
    None => eprintln!("Failed to get config dir"),
}

// Or using if-let
if let Some(config_path) = Dir::config_home() {
    println!("Config dir: {}", config_path.display());
}

// For fallback handling
let config_dir = Dir::config_home().unwrap_or_else(|| {
    // Fallback to current directory or panic, depending on your needs
    std::env::current_dir().expect("Cannot determine current directory")
});

Dependencies#

  • libc: For Unix systems (accessing user database when $HOME isn't set)

License#

Licensed under the MIT LICENSE

Contributing#

Contributions are welcome! Please ensure:

  1. All platforms are tested
  2. XDG compliance is maintained
  3. Platform-specific fallbacks follow native conventions
  4. New methods include appropriate documentation

References#