build_tools.tui_common.services.config

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:

[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:

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

TOMLI_AVAILABLE

Classes

KeybindingConfig

Keybinding configuration for TUI applications.

Functions

detect_conflicts(config)

Detect conflicting keybindings within each context.

load_config_file([config_path])

Load keybinding configuration from TOML file.

merge_config(defaults, user_config)

Merge user configuration with defaults.

load_keybindings([config_path])

Load keybindings from config file with fallback to defaults.

Module Contents

build_tools.tui_common.services.config.TOMLI_AVAILABLE = True
class build_tools.tui_common.services.config.KeybindingConfig[source]

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)

global_bindings

Global actions like quit, help

tab_bindings

Tab/screen switching bindings

navigation_bindings

Movement bindings (up, down, left, right)

control_bindings

Widget control bindings (activate, increment)

action_bindings

Domain-specific action bindings

Example

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"
global_bindings: dict[str, list[str]]
tab_bindings: dict[str, list[str]]
navigation_bindings: dict[str, list[str]]
control_bindings: dict[str, list[str]]
action_bindings: dict[str, list[str]]
classmethod default()[source]

Create default keybinding configuration.

Provides sensible defaults for common TUI actions including vim-style navigation and standard keyboard shortcuts.

Returns:

KeybindingConfig with default bindings

Return type:

KeybindingConfig

get_primary_key(context, action)[source]

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.

Parameters:
  • context (str) – Keybinding context (“global”, “tabs”, “navigation”, etc.)

  • action (str) – Action name (e.g., “quit”, “up”, “activate”)

Returns:

Primary key string, or None if not found

Return type:

str | None

get_display_key(context, action)[source]

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 “?”.

Parameters:
  • context (str) – Keybinding context

  • action (str) – Action name

Returns:

Display-friendly key name, or “?” if not found

Return type:

str

build_tools.tui_common.services.config.detect_conflicts(config)[source]

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).

Parameters:

config (KeybindingConfig) – Keybinding configuration to validate

Returns:

List of conflict warning messages (empty if no conflicts)

Return type:

list[str]

Example

config = load_keybindings()
conflicts = detect_conflicts(config)
for conflict in conflicts:
    print(f"Warning: {conflict}")
build_tools.tui_common.services.config.load_config_file(config_path=None)[source]

Load keybinding configuration from TOML file.

Parameters:

config_path (pathlib.Path | None) – 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

Return type:

dict[str, Any] | None

Note

Requires tomli (Python <3.11) or tomllib (Python 3.11+). If neither is available, returns None and uses defaults.

build_tools.tui_common.services.config.merge_config(defaults, user_config)[source]

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.

Parameters:
  • defaults (KeybindingConfig) – Default keybinding configuration

  • user_config (dict[str, Any]) – User-provided configuration from TOML file

Returns:

Merged configuration (user overrides defaults)

Return type:

KeybindingConfig

Example

defaults = KeybindingConfig.default()
user_config = {"keybindings": {"global": {"quit": ["x"]}}}
merged = merge_config(defaults, user_config)
# merged.global_bindings["quit"] == ["x"]
# Other bindings retain defaults
build_tools.tui_common.services.config.load_keybindings(config_path=None)[source]

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.

Parameters:

config_path (pathlib.Path | None) – Optional path to config file. If None, uses default location (~/.config/pipeworks_tui/keybindings.toml)

Returns:

Keybinding configuration (user config merged with defaults)

Return type:

KeybindingConfig

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