Etcetera

repository·master·Indexed 41 days ago

https://github.com/lunacookies/etcetera

An unopinionated Rust library for determining cross-platform filesystem locations for configuration, data, and cache files. It supports XDG base directory, Apple's Standard Directories, Windows' Known Folder Locations, and the Unix Single-folder Convention, providing both BaseStrategy and AppStrategy modes to resolve paths based on application metadata and target operating systems.

Tokens
6.9K
Snippets
16
Records
28
Agent score
96%

What's inside Etcetera

  1. Overview of Etcetera

    master
    Etcetera is a Rust library designed to help developers determine the correct filesystem locations for application-specific files, such as configuration, data, and cache. Unlike other libraries that enforce a single standard, Etcetera allows you to choose between different directory conventions based on your application's needs (e.g., CLI vs. GUI) and the target operating system.
  2. How BaseStrategy and AppStrategy work

    master

    Etcetera operates using two distinct modes of operation:

    BaseStrategy

    Returns the root location of a specific directory type without application-specific subdirectories.

    • Example (config_dir()):
      • XDG: ~/.config
      • Apple: ~/Library/Preferences
      • Windows: ~\AppData\Roaming

    AppStrategy

    Returns a path specific to your application by combining the base directory with application metadata. You must provide details like top_level_domain, author, and app_name.

    • Example (with { top_level_domain: "org", author: "Acme Corp", app_name: "Frobnicator Plus" }):
      • XDG: ~/.config/frobnicator-plus
      • Unix: ~/.frobnicator-plus
      • Apple: ~/Library/Preferences/org.acme-corp.Frobnicator-Plus
      • Windows: ~\AppData\Roaming\Acme Corp\Frobnicator Plus

    Note: The home directory (~) is determined using std::env::home_dir.

  3. Supported directory conventions in Etcetera

    master

    Etcetera supports four primary directory conventions to ensure cross-platform compatibility:

    • XDG base directory: The standard for Linux/Unix systems.
    • Apple's Standard Directories: Used on macOS and iOS.
    • Windows' Known Folder Locations: The standard for Windows applications.
    • Unix Single-folder Convention: A pattern where all application files are stored in a single hidden directory in the home folder (e.g., ~/.myapp).
  4. Use convenience functions to select strategies

    master

    Etcetera provides helper functions to automatically select the most appropriate strategy for your application type based on the host platform:

    For CLI Tools

    Use these functions if you want to follow the standard for CLI tools (Windows uses Windows conventions, while all other platforms use XDG):

    • base_strategy::choose_base_strategy
    • app_strategy::choose_app_strategy

    For GUI Applications

    Use these functions if you want to follow native platform standards (Windows uses Windows, macOS/iOS uses Apple, and all other platforms use XDG):

    • base_strategy::choose_native_strategy
    • app_strategy::choose_native_strategy
  5. How AppStrategy and BaseStrategy work together

    master

    Etcetera provides two main ways to resolve paths depending on your application type:

    1. BaseStrategy: Best for general-purpose tools or when you want to follow the OS's default directory structure without specific application subfolders. It uses XDG on Linux/macOS and Windows on Windows.
    2. AppStrategy: Best for specific applications. It uses the application's metadata (name, author, TLD) to create a unique directory structure following platform conventions.

    Choosing a strategy for macOS GUI apps: While choose_app_strategy() uses the XDG convention on macOS (which is often preferred if users need to manually edit config files), you can use choose_native_strategy() if you want to follow Apple's 'Standard Directories' specifically for a GUI application.

  6. Choose a strategy based on application type

    master

    The library provides two helper functions to select a strategy based on whether you are building a GUI or a CLI application. This ensures your application follows the correct OS conventions.

    For GUI Applications

    Use choose_native_strategy() to get the OS-specific strategy:

    • Windows: Uses Windows strategy.
    • macOS & iOS: Uses Apple strategy.
    • Other (Linux/Unix): Uses Xdg strategy.

    For CLI Applications

    Use choose_base_strategy() to get the default strategy for CLI tools:

    • Windows: Uses Windows strategy.
    • Other (macOS, iOS, Linux/Unix): Uses Xdg strategy.
    use etcetera::{choose_native_strategy, choose_base_strategy};
    
    // For a GUI app
    let strategy = choose_native_strategy().expect("Failed to resolve strategy");
    let config = strategy.config_dir();
    
    // For a CLI app
    let strategy = choose_base_strategy().expect("Failed to resolve strategy");
    let data = strategy.data_dir();
  7. Choose a strategy for GUI or CLI applications

    master

    Depending on whether you are building a GUI application or a CLI application, you should choose a different strategy to ensure your application follows OS-specific conventions.

    For GUI Applications

    Use choose_native_strategy(args) to select the strategy most appropriate for the current operating system:

    • Windows: Uses the Windows strategy.
    • macOS/iOS: Uses the Apple strategy.
    • Linux/Other: Uses the Xdg strategy.

    For CLI Applications

    Use choose_app_strategy(args) to select a more standard strategy for command-line tools:

    • Windows: Uses the Windows strategy.
    • macOS/iOS/Linux/Other: Uses the Xdg strategy.

    Both functions return a Result<T, HomeDirError>.

    use etcetera::app_strategy::{AppStrategyArgs, choose_native_strategy};
    
    let args = AppStrategyArgs {
        top_level_domain: "com".to_string(),
        author: "Example".to_string(),
        app_name: "MyApp".to_string(),
    };
    
    // For a GUI app
    let strategy = choose_native_strategy(args).expect("Failed to resolve strategy");
    let config = strategy.config_dir();
  8. Configure application identity with AppStrategyArgs

    master

    To use an AppStrategy, you must first define your application's identity using AppStrategyArgs. This struct provides the metadata used to resolve platform-specific paths for configuration, data, and cache.

    Key fields:

    • top_level_domain: The TLD of your application (e.g., com, org, or io.github).
    • author: The name of the application's author.
    • app_name: The name of the application.

    AppStrategyArgs provides two helper methods for generating identifiers:

    1. bundle_id(): Returns a reverse-DNS style string (e.g., org.acme-corp.Frobnicator-Plus). It converts the author to lowercase and replaces spaces with hyphens, and replaces spaces in the app name with hyphens.
    2. unixy_name(): Returns a lowercase, hyphenated version of the app name, suitable for binary names (e.g., frobnicator-plus).
    use etcetera::app_strategy::AppStrategyArgs;
    
    let strategy_args = AppStrategyArgs {
        top_level_domain: "org".to_string(),
        author: "Acme Corp".to_string(),
        app_name: "Frobnicator Plus".to_string(),
    };
    
    // bundle_id() -> "org.acme-corp.Frobnicator-Plus"
    // unixy_name() -> "frobnicator-plus"
  9. MSRV requirements for Etcetera

    master

    The Minimum Supported Rust Version (MSRV) depends on the version of Etcetera you are using:

    • v0.11.0 (Current): MSRV 1.87.0
    • v0.10: MSRV 1.81.0
    • v0.9: MSRV 1.70.0

    Note: v0.12 raised the MSRV to 1.95.0 to utilize the cfg_select! macro and remove the cfg-if dependency.

  10. Use the AppStrategy trait to resolve application paths

    master

    The AppStrategy trait allows your application to retrieve standard platform-specific directories. This ensures your app follows the correct conventions for where to store configuration, data, and cache files.

    Core Directory Methods

    • home_dir(): Returns the current user's home directory.
    • config_dir(): Returns the directory for application configuration.
    • data_dir(): Returns the directory for application data.
    • cache_dir(): Returns the directory for application cache.
    • state_dir(): Returns an Option<PathBuf> for the state directory. Supported by Xdg and Unix strategies.
    • runtime_dir(): Returns an Option<PathBuf> for the runtime directory. Supported by Xdg and Unix strategies.

    Path Helper Methods

    Instead of manually joining paths, use these helpers to construct paths inside specific directories:

    • in_config_dir(path)
    • in_data_dir(path)
    • in_cache_dir(path)
    • in_state_dir(path) (Returns Option)
    • in_runtime_dir(path) (Returns Option)

    Note: For runtime_dir, this library does not enforce the ownership or persistence requirements specified by the XDG Base Directory Specification.

  11. Use the Windows AppStrategy for path resolution

    master

    The Windows strategy implements path resolution following Windows conventions (based on the SHGetKnownFolderPath API). It organizes application files under an author/app_name hierarchy within standard Windows directories.

    Directory Mapping

    When initialized with AppStrategyArgs, the following paths are resolved:

    • Config Directory: {APPDATA}/{author}/{app_name}/config
    • Data Directory: {APPDATA}/{author}/{app_name}/data
    • Cache Directory: {LOCALAPPDATA}/{author}/{app_name}/cache
    • Home Directory: Resolved via Windows system APIs (e.g., USERPROFILE).

    Note that state_dir() and runtime_dir() currently return None for this strategy.

    Implementation Details

    On Windows, this strategy uses the SHGetKnownFolderPath API. On non-Windows platforms, it falls back to Windows default directory patterns. The strategy reads from the following environment variables:

    • USERPROFILE
    • APPDATA
    • LOCALAPPDATA
    use etcetera::app_strategy::{AppStrategy, AppStrategyArgs, Windows};
    
    let app_strategy = Windows::new(AppStrategyArgs {
        top_level_domain: "org".to_string(),
        author: "Acme Corp".to_string(),
        app_name: "Frobnicator Plus".to_string(),
    }).unwrap();
    
    let config = app_strategy.config_dir(); // e.g., AppData/Roaming/Acme Corp/Frobnicator Plus/config
    let cache = app_strategy.cache_dir();    // e.g., AppData/Local/Acme Corp/Frobnicator Plus/cache
  12. Use the Windows base directory strategy

    master

    The Windows strategy implements directory resolution following Windows conventions. It prioritizes environment variables (USERPROFILE, APPDATA, LOCALAPPDATA) and falls back to the Windows SHGetKnownFolderPath API. If environment variables are missing, it uses default Windows directory paths.

    Key directory mappings:

    • home_dir(): Returns the user profile directory.
    • config_dir(): Maps to data_dir() (typically APPDATA).
    • data_dir(): Uses APPDATA environment variable or falls back to AppData/Roaming within the home directory.
    • cache_dir(): Uses LOCALAPPDATA environment variable or falls back to AppData/Local within the home directory.
    • state_dir(): Always returns None.
    • runtime_dir(): Always returns None.
    use etcetera::base_strategy::BaseStrategy;
    use etcetera::base_strategy::Windows;
    
    let base_strategy = Windows::new().unwrap();
    
    let home = base_strategy.home_dir();
    let config = base_strategy.config_dir();
    let cache = base_strategy.cache_dir();