How Text Mode Handles Multiline Input Submission with Ctrl+D in ngpt

The ngpt CLI captures multiline input in text mode by detecting Ctrl+D either as a key binding in the prompt-toolkit editor or as an EOFError in the plain stdin fallback, returning the complete buffer content as the prompt.

The nazdridoy/ngpt repository provides a flexible command-line interface for interacting with LLMs. When operating in text mode, the tool must accommodate detailed prompts that span multiple lines, requiring a reliable mechanism to signal when the user has finished typing. The implementation handles multiline input submission through two distinct paths depending on whether the optional prompt-toolkit library is available.

How Multiline Input Works in ngpt Text Mode

The architecture delegates input collection to a centralized UI module while keeping the mode-specific logic separate. This separation ensures consistent behavior across different interface implementations.

The Entry Point in text.py

The text_mode() function in ngpt/cli/modes/text.py serves as the primary orchestrator. When invoked without a pre-supplied prompt via command-line arguments, it calls get_multiline_input() to gather user input interactively.


# From ngpt/cli/modes/text.py, lines 17-23

if args.prompt is not None:
    prompt = args.prompt
else:
    prompt = get_multiline_input()

This delegation allows the text mode to remain agnostic of how the input is physically collected, whether through a rich TUI or basic terminal stdin.

The UI Layer in tui.py

The ngpt/ui/tui.py file contains the get_multiline_input() function and the create_multiline_editor() helper. The module checks for the presence of prompt-toolkit via a HAS_PROMPT_TOOLKIT flag and branches accordingly to provide the appropriate input mechanism.

Ctrl+D Handling in Prompt-Toolkit Mode

When prompt-toolkit is available, ngpt constructs a dedicated multiline editor instance. The create_multiline_editor() function registers a custom key binding that intercepts Ctrl+D to submit the buffer.


# From ngpt/ui/tui.py, lines 42-46

@kb.add('c-d')
def _(event):
    event.app.exit(result=event.app.current_buffer.text)

Pressing Ctrl+D triggers this binding, which exits the application context and returns the complete text from the current buffer. This method preserves formatting and newlines exactly as typed, providing a seamless multiline editing experience with syntax highlighting and cursor movement capabilities.

Ctrl+D Handling in Fallback Mode (Plain Stdin)

If prompt-toolkit is not installed or the editor initialization fails, ngpt falls back to a basic stdin implementation. The get_multiline_input() function handles Ctrl+D by catching the EOFError that Python raises when reading past the end of a file stream.


# From ngpt/ui/tui.py, lines 49-57

print("Enter your multi-line prompt (press Ctrl+D to submit):")
lines = []
while True:
    try:
        line = input()
        lines.append(line)
    except EOFError:  # Ctrl+D was pressed

        break
return "\n".join(lines)

In this scenario, the user types lines normally, pressing Enter after each one. When ready to submit, pressing Ctrl+D sends an EOF signal, raising EOFError and breaking the input loop. The function then joins all collected lines with newline characters and returns the resulting string as the final prompt.

Practical Code Examples

Using the Built-in Editor (Prompt-Toolkit Installed)

When running ngpt text with the rich UI available, the editor opens as a full-screen interface. Type your multiline prompt naturally, then press Ctrl+D to submit.

$ ngpt text

# ... editor opens ...

# (User writes multiple lines of text)

# Press Ctrl+D

# The editor closes and the complete buffer is sent to the LLM

Fallback to Plain Stdin (No Prompt-Toolkit)

Without the optional dependency, the CLI provides clear instructions for submission via Ctrl+D.

$ ngpt text
Enter your multi-line prompt (press Ctrl+D to submit):
First line of the request
Second line, still part of the same prompt
Third line with details
<Ctrl+D>

# The tool combines the lines and sends:

# "First line of the request\nSecond line, still part of the same prompt\nThird line with details"

Bypassing Multiline Input with CLI Flags

To avoid the interactive multiline interface entirely, provide the prompt directly using the --prompt flag.

$ ngpt text --prompt "Summarize this article."

# No multiline input UI is invoked; the prompt is sent immediately.

Summary

  • Text mode in nazdridoy/ngpt handles multiline input through the get_multiline_input() function in ngpt/ui/tui.py.
  • When prompt-toolkit is available, Ctrl+D triggers a key binding in create_multiline_editor() that exits the editor and returns the buffer text.
  • In the fallback mode, Ctrl+D raises an EOFError in the stdin loop, breaking the collection and joining the lines into a single prompt string.
  • The entry point in ngpt/cli/modes/text.py orchestrates this flow, allowing users to submit complex, formatted prompts regardless of their terminal capabilities.

Frequently Asked Questions

What happens if I press Ctrl+C instead of Ctrl+D in multiline mode?

Pressing Ctrl+C sends a KeyboardInterrupt signal, which typically terminates the entire ngpt process immediately rather than submitting the input. Unlike Ctrl+D, which signals end-of-file and triggers the submission logic in get_multiline_input(), Ctrl+C is not caught by the input loops and will cause the CLI to exit without sending any prompt to the LLM.

Can I use Ctrl+D to submit input if I have prompt-toolkit installed?

Yes. When prompt-toolkit is installed, ngpt uses the create_multiline_editor() function which registers a specific key binding for c-d (Ctrl+D). Pressing this combination exits the full-screen editor and returns the complete buffer content as the prompt. This provides a more interactive editing experience with syntax highlighting and cursor movement while maintaining the same Ctrl+D submission gesture as the fallback mode.

Why does the fallback mode print a specific message about Ctrl+D?

The fallback implementation in get_multiline_input() explicitly prints "Enter your multi-line prompt (press Ctrl+D to submit):" because the basic input() function in Python does not provide any visual indication that it is waiting for multiline input or how to terminate entry. Without this instruction, users might not realize they need to send an EOF signal to complete their prompt, potentially leaving them stuck in the input loop or unsure how to proceed.

Does ngpt preserve newlines when submitting multiline input?

Yes. In both the prompt-toolkit and fallback paths, ngpt preserves newline characters exactly as entered. In the prompt-toolkit path, event.app.current_buffer.text returns the raw buffer content including \n characters. In the fallback path, the code explicitly joins the collected lines with "\n".join(lines), ensuring that line breaks are maintained in the final prompt string sent to the LLM.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →