DevelopmentAll versions
On this page

KetraTerm Swing Host

Optional host-side helpers for applications embedding SwingTerminal: search chrome, terminal action bindings, context menus, completion adapters, and clipboard consent. Hosts explicitly construct and install the helpers they need. The terminal view and session retain their own rendering and input responsibilities.

Dependency

Add io.github.ketraterm:ketraterm-ui-swing-host alongside your terminal entry point, using the BOM and repository setup. This module exposes the Swing UI, completion API, and coroutine dependencies. Filesystem completion and persistence are separate optional modules.

Search chrome

SwingTerminalSearchBar delegates scanning, highlights, and result navigation to the terminal's search API. The bar includes independent match-case, whole-word, and regex toggles with explanatory tooltips, and shows invalid-pattern errors. SwingTerminalOverlayPane places the bar over the terminal content, so opening it does not reduce the grid's available space.

Construct Swing components on the event dispatch thread (EDT). This example wraps an existing terminal; its owner still binds and disposes the terminal.

import io.github.ketraterm.ui.swing.api.SwingTerminal
import io.github.ketraterm.ui.swing.host.SwingTerminalOverlayPane
import io.github.ketraterm.ui.swing.host.SwingTerminalSearchBar
import javax.swing.JComponent
import javax.swing.SwingUtilities

class TerminalSearchPane(terminal: SwingTerminal) : AutoCloseable {
    init {
        check(SwingUtilities.isEventDispatchThread())
    }

    private val searchBar = SwingTerminalSearchBar(terminal)
    val component: JComponent =
        SwingTerminalOverlayPane(terminal, searchBar.component)

    fun openSearch() = searchBar.open()

    override fun close() = searchBar.close()
}

Mount component in the host window and invoke openSearch from a host action. Call close when removing the pane; it cancels search observation and clears active highlights. Removing the bar from a displayable hierarchy also cancels its observation. open, close, and refreshColors enqueue work when called off the EDT; read isOpen and manipulate component on the EDT.

The bar installs no command shortcuts, including Enter, Shift+Enter, or Escape. Hosts invoke performAction(SwingTerminalSearchAction) on the EDT and bind those commands through their own action system. It returns false when search is closed. setShortcutTextProvider supplies plain-text labels from those same bindings; tooltips read the provider when requested, so a changed keymap is reflected immediately. Return null for an unbound action. Tab focus traversal and Space activation use normal Swing button behavior and remain available without command bindings.

For a plain Swing host, map keystrokes on searchBar.component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) and install corresponding AbstractActions in its actionMap, calling searchBar.performAction(action). The standalone app owns its defaults; the IntelliJ plugin registers IDE actions so keymap remapping and multi-stroke shortcuts remain platform responsibilities. Keep search bindings scoped to the bar so they do not intercept terminal or unrelated editor input.

Use SwingTerminalSearchColors.create, copy, or a builder to supply an immutable palette through refreshColors(colors). Updating colors preserves the query and visibility. The palette is retained across close/open cycles.

Host actions and context menus

SwingTerminalHostShortcutMap.platformDefault() supplies optional platform bindings. It does not register Swing actions. Install the entries with forEachShortcut, or resolve a key event with actionFor(keyCode, modifiersEx) inside your SwingHostServices key handler. Return whether the host consumed the event so unhandled keys continue to terminal input.

Use withShortcut and withoutShortcut to customize bindings. Shortcuts must remain unique and use extended keyboard modifier masks.

SwingTerminalContextMenuItems.addTerminalActions appends selection, paste, search, screen-clear, and applicable hyperlink actions to a host-owned JPopupMenu. Pass the terminal's context-menu request and your search-opening callback, append product-specific items, and show the menu from the host callback on the EDT. See Swing host services for callback configuration.

Completion bridge

SwingCompletionSuggestionProvider adapts a TerminalCompletionEngine to the terminal's suggestion contract. It preserves replacement ranges, source identity, presentation fields, matched ranges, and opaque feedback tokens. The host selects the engine and sources and supplies current profile, directory, and shell metadata.

import io.github.ketraterm.completion.api.TerminalCompletionEngine
import io.github.ketraterm.ui.swing.api.SwingTerminal
import io.github.ketraterm.ui.swing.host.SwingCompletionContext
import io.github.ketraterm.ui.swing.host.SwingCompletionSuggestionProvider
import io.github.ketraterm.ui.swing.suggestion.SwingShellSuggestionFeedbackHandler
import javax.swing.SwingUtilities

fun installCompletion(
    terminal: SwingTerminal,
    engine: TerminalCompletionEngine,
    contextProvider: () -> SwingCompletionContext,
    feedbackHandler: SwingShellSuggestionFeedbackHandler =
        SwingShellSuggestionFeedbackHandler.NONE,
) {
    check(SwingUtilities.isEventDispatchThread())
    terminal.setShellSuggestionProvider(
        SwingCompletionSuggestionProvider(
            engine = engine,
            contextProvider = contextProvider,
            sourceLabels = mapOf("spec" to "Commands", "path" to "Files"),
            feedbackHandler = feedbackHandler,
        ),
    )
}

The terminal opens the provider on the EDT, capturing one immutable context and feedback handler before background collection. Keep contextProvider cheap. Direct calls to suggestions(request) capture context in the caller's thread; the returned flow is cold and runs engine work only when collected. This adapter does not choose a dispatcher, launch jobs, or close the engine. Collection cancellation and engine failures propagate to the caller. An invalid converted completion request produces one empty suggestion snapshot.

Optional sourceLabels customize display labels, including localization.

SwingCompletionFeedbackRecorder.createHandler() maps accepted and explicitly dismissed suggestions to a host-owned learning sink. Admission rejection is ignored. The host owns learning-store synchronization.

Configure completion on the EDT and keep engine resources alive for their owning host's lifetime. See suggestion request ownership for editing authority, request invalidation, custom presentation, and diagnostics. Use completion-host for filesystem sources and completion-persistence for optional saved learning.

SwingClipboardReadPrompt owns cancellable consent for one terminal pane. Construct it with a product dialog callback, or bridge SwingMessageDialogs.showModeless. Operations and decisions belong to the EDT; close the prompt there when disposing the pane. Denial, Escape, cancellation, and closure cannot approve a read. A block decision lasts for the pane's lifetime.

Use one SwingClipboardReader per window. Call its suspending read on the EDT with the requesting pane's prompt, message, and clipboard handler, after earlier posted clipboard writes. It enforces admitted permission and reads native clipboard data on its I/O dispatcher. Busy prompts are denied; a busy native read is unavailable. Only one native read runs across reader instances, and a cancelled blocking call keeps that slot until it returns. The session owns the request deadline, permission revocation, and response serialization.

SwingClipboardPrompts builds consent text from terminal names and character counts without placing clipboard contents in the dialog. SwingDialogRequest holds plain text and copied choices; SwingMessageDialogs escapes message text for Swing display. Modal and modeless presenters return an option index or null for dismissal. Hosts still wire these helpers into their session's clipboard services and choose write-consent policy.

Localization and host settings

Supply SwingHostMessages to search, context-menu, dialog, and clipboard helpers to integrate a host message framework. forLocale(locale, bundle) uses JDK resource bundles and MessageFormat, with missing keys falling back to the bundled English catalog. The selected locale is captured; static component labels are resolved at construction. The catalog defines keys and arguments. Message arguments are plain text, not markup.

SwingTerminalSettingsBounds provides shared preference-control ranges for hosts. These limits do not define the core grid or renderer's valid configuration.

For packages and dependencies, see Module.md.