build_tools.tui_common.services.config ====================================== .. py:module:: build_tools.tui_common.services.config .. autoapi-nested-parse:: Configuration management for Textual-based TUIs. This module handles loading and validating user-configurable keybindings from TOML files, with fallback to sensible defaults. **Configuration File Location:** By default, configuration is loaded from: ``~/.config/pipeworks_tui/keybindings.toml`` **TOML Format:** .. code-block:: toml [keybindings.global] quit = ["q", "ctrl+q"] help = ["?", "f1"] [keybindings.tabs] tab1 = ["1"] tab2 = ["2"] [keybindings.navigation] up = ["k", "up"] down = ["j", "down"] left = ["h", "left"] right = ["l", "right"] **Example Usage:** .. code-block:: python from build_tools.tui_common.services import load_keybindings # Load with defaults config = load_keybindings() # Get primary key for an action quit_key = config.get_primary_key("global", "quit") # "q" # Get display-friendly name quit_display = config.get_display_key("global", "quit") # "q" # Check for conflicts from build_tools.tui_common.services import detect_conflicts conflicts = detect_conflicts(config) if conflicts: for conflict in conflicts: print(f"Warning: {conflict}") Attributes ---------- .. autoapisummary:: build_tools.tui_common.services.config.TOMLI_AVAILABLE Classes ------- .. autoapisummary:: build_tools.tui_common.services.config.KeybindingConfig Functions --------- .. autoapisummary:: build_tools.tui_common.services.config.detect_conflicts build_tools.tui_common.services.config.load_config_file build_tools.tui_common.services.config.merge_config build_tools.tui_common.services.config.load_keybindings Module Contents --------------- .. py:data:: TOMLI_AVAILABLE :value: True .. py:class:: KeybindingConfig Keybinding configuration for TUI applications. Organizes keybindings by context (global, tabs, navigation, etc.) where each action maps to a list of keys that can trigger it. **Contexts:** - ``global``: Application-wide actions (quit, help) - ``tabs``: Tab/screen switching - ``navigation``: Movement within panels/controls - ``controls``: Widget manipulation (increment, decrement, activate) - ``actions``: Domain-specific operations (generate, copy, paste) .. attribute:: global_bindings Global actions like quit, help .. attribute:: tab_bindings Tab/screen switching bindings .. attribute:: navigation_bindings Movement bindings (up, down, left, right) .. attribute:: control_bindings Widget control bindings (activate, increment) .. attribute:: action_bindings Domain-specific action bindings .. admonition:: Example .. code-block:: python config = KeybindingConfig.default() # Multiple keys can trigger the same action quit_keys = config.global_bindings["quit"] # ["q", "ctrl+q"] # Get the primary (first) key for UI display primary = config.get_primary_key("global", "quit") # "q" .. py:attribute:: global_bindings :type: dict[str, list[str]] .. py:attribute:: tab_bindings :type: dict[str, list[str]] .. py:attribute:: navigation_bindings :type: dict[str, list[str]] .. py:attribute:: control_bindings :type: dict[str, list[str]] .. py:attribute:: action_bindings :type: dict[str, list[str]] .. py:method:: default() :classmethod: Create default keybinding configuration. Provides sensible defaults for common TUI actions including vim-style navigation and standard keyboard shortcuts. :returns: KeybindingConfig with default bindings .. py:method:: get_primary_key(context, action) Get the primary (first) keybinding for an action. The primary key is typically used for display in the UI and is the first key in the binding list. :param context: Keybinding context ("global", "tabs", "navigation", etc.) :param action: Action name (e.g., "quit", "up", "activate") :returns: Primary key string, or None if not found .. py:method:: get_display_key(context, action) Get human-readable key name for display in UI. Converts internal Textual key names to user-friendly display names. For example, "ctrl+q" becomes "Ctrl+Q" and "question_mark" becomes "?". :param context: Keybinding context :param action: Action name :returns: Display-friendly key name, or "?" if not found .. py:function:: detect_conflicts(config) Detect conflicting keybindings within each context. A conflict occurs when the same key is bound to multiple actions within the same context. Cross-context conflicts are allowed (e.g., "j" for both navigation and control increment). :param config: Keybinding configuration to validate :returns: List of conflict warning messages (empty if no conflicts) .. admonition:: Example .. code-block:: python config = load_keybindings() conflicts = detect_conflicts(config) for conflict in conflicts: print(f"Warning: {conflict}") .. py:function:: load_config_file(config_path = None) Load keybinding configuration from TOML file. :param config_path: Path to config file, or None to use default location (~/.config/pipeworks_tui/keybindings.toml) :returns: Parsed TOML configuration as dict, or None if file doesn't exist or tomli is not available .. note:: Requires tomli (Python <3.11) or tomllib (Python 3.11+). If neither is available, returns None and uses defaults. .. py:function:: merge_config(defaults, user_config) Merge user configuration with defaults. User configuration completely replaces default values for any context that is specified. Contexts not specified in user config retain their default values. :param defaults: Default keybinding configuration :param user_config: User-provided configuration from TOML file :returns: Merged configuration (user overrides defaults) .. admonition:: Example .. code-block:: python defaults = KeybindingConfig.default() user_config = {"keybindings": {"global": {"quit": ["x"]}}} merged = merge_config(defaults, user_config) # merged.global_bindings["quit"] == ["x"] # Other bindings retain defaults .. py:function:: load_keybindings(config_path = None) Load keybindings from config file with fallback to defaults. This is the main entry point for loading keybinding configuration. It handles all the complexity of finding config files, parsing TOML, merging with defaults, and detecting conflicts. :param config_path: Optional path to config file. If None, uses default location (~/.config/pipeworks_tui/keybindings.toml) :returns: Keybinding configuration (user config merged with defaults) .. note:: - If config file doesn't exist, returns defaults - If config file has errors, prints warning and returns defaults - Prints conflict warnings to stderr if detected