Skip to content

Input Engine

The input engine is Klix's thin wrapper around prompt_toolkit. It provides the prompt session, input modes, key bindings, and CI-safe fallback behavior.

See also:

Why It Exists

Klix needs one place to own terminal input behavior so that:

  • prompt history is consistent
  • key bindings are centralized
  • modes can influence prompt behavior
  • CI and pipe mode can bypass interactive UI cleanly

Without that layer, every input component would need to reinvent prompt setup.

What The Engine Handles

Current responsibilities:

  • PromptSession setup
  • session-backed command history
  • current InputMode
  • Ctrl+L binding
  • multiline bindings
  • password mode flagging
  • optional clear-after-submit behavior
  • optional themed prompt styling
  • CI/non-TTY fallback via stdin.readline()

CI And Non-Interactive Behavior

When Klix selects CIRenderer, the input engine avoids interactive prompt_toolkit use and reads lines from stdin instead.

That is why tests can do things like:

bash
printf '/hello hi\n/exit\n' | python main.py

This is great for automation, but it also means some richer widgets are effectively interactive-only. See Input Components.

Modes

The engine currently understands:

  • COMMAND
  • MULTILINE
  • SELECT
  • SEARCH
  • CONFIRM
  • PASSWORD
  • INTERRUPT

In the current implementation, not every mode changes low-level prompt behavior equally. Some modes are primarily semantic signals used by higher-level components.

Examples:

  • PASSWORD changes prompt masking
  • MULTILINE changes Enter behavior
  • COMMAND mode participates in session history navigation
  • selector-style inputs are implemented through prompt_toolkit dialogs in session.ui.input, not directly through prompt_async()

Realistic Example

python
@app.command("/notes", help="Capture a multiline note")
async def notes(session: klix.Session):
    session.input_engine.set_mode(klix.InputMode.MULTILINE)
    text = await session.input_engine.prompt_async("Note > ")
    session.input_engine.set_mode(klix.InputMode.COMMAND)
    session.ui.output.panel(text, title="Captured Note", border_color="accent")

Key Bindings

Current built-ins:

  • Ctrl+L clears the screen
  • Up/Down navigate session history through prompt_toolkit
  • in multiline mode:
    • Escape + Enter inserts a newline
    • Ctrl+J inserts a newline in terminals that emit LF
    • Enter submits

When AppConfig(clear_input_on_submit=True) is enabled, the active prompt line is also erased after submit.

If ThemeConfig(input_background=...) is set, prompt_toolkit applies a themed input bar background in interactive terminals.

Pitfalls

Assuming every input component goes through prompt_async()

Simple prompts do. Richer selectors often build their own prompt_toolkit sessions or dialogs on top of the same engine-level context.

Forgetting to reset mode

If you manually change modes in custom flows, return to COMMAND when you are done.

Expecting rich dialogs in CI

CI fallback is intentionally plain.

Released under the MIT License.