Skip to content

Repository files navigation

TerminalFX

A terminal for JavaFX applications: the screen, and a contract for whatever is on the other end of it.

1. What changed in 2.0.0

2.0.0 is a rewrite, not a migration. The 1.x API — TerminalBuilder, Terminal, TerminalTab, TerminalConfig — is gone rather than deprecated, because it could not express the thing this library was being asked for: a terminal that is not a local shell. In 1.x the view started a PtyProcess itself, so every consumer inherited pty4j and its native payload whether it wanted a local shell or not, and there was nowhere to put an SSH channel.

What the rewrite is built around:

  • Two artifacts. terminalfx-core is the terminal and the session contract, with no native library and no idea what it is connected to. terminalfx-local is a shell on this machine and is the only place pty4j and JNA appear.

  • xterm.js instead of hterm. Measured side by side in the same WebView: the same Unicode, box drawing and emoji, about 2.8 times the output rate, and a scrollback that stops growing instead of keeping every line ever printed.

  • The ordering rules are in one place. TerminalSession owns the single ordered writer, the bounded queues in both directions, the coalescing of resizes, the two readinesses, and a close that is idempotent, works before the start and cannot be undone by a late callback.

  • Output is not trusted. A title from the far end is handed over as text and never executed; a clipboard write (OSC 52) is refused unless the embedder allowed it; output crosses into the page as an argument, never as script.

2. Using it

    terminalfx-repo
    https://github.com/javaterminal/TerminalFX/raw/master/releases



    com.kodedu.terminalfx
    terminalfx-local   
    2.0.0

A window with a shell in it, which is the whole of example/:

ExecutorService workers = Executors.newThreadPerTaskExecutor(Thread.ofVirtual().factory());

TerminalView view = new TerminalView(TerminalLook.dark());
view.onCopy(text -> { /* put it on the clipboard */ });
view.onPasteRequested(() -> view.paste(clipboardText()));

TerminalSession session = new TerminalSession(
        view, new LocalShell(LocalShellSpec.defaultShell(), workers), workers);
session.onExit(how -> System.out.println("the shell " + how));
session.start();

stage.setScene(new Scene(view, 900, 520));

3. Connecting it to something else

Implement TerminalConnection: four methods, none of them about JavaFX.

public interface TerminalConnection {
    void open(Wiring wiring) throws Exception;   // off the UI thread; may block
    void send(byte[] bytes) throws IOException;  // called in order, from one thread
    void resize(TerminalSize size) throws IOException;
    void close();                                // idempotent, and callable before open
}

Wiring is what the connection says back: ready(), output(bytes, offset, length) and ended(TerminalExit). The first ended wins, so a callback arriving after a close is harmless. Everything else — ordering, bounds, coalescing, the UI thread — is the session’s.

4. Threads

The library starts no threads. TerminalSession and LocalShell are handed the Executor the embedding application already has, and take two tasks each for the life of a session. The way onto the UI thread can be handed over as well; it defaults to Platform.runLater.

5. Licence

MIT. xterm.js and its addons are MIT and are vendored in core/src/main/resources/com/kodedu/terminalfx/; pty4j (EPL-1.0) and JNA arrive only with terminalfx-local.

About

Java FX Terminal Emulator

Topics

Resources

Stars

300 stars

Watchers

17 watching

Forks

Releases

Packages

Used by

Contributors

Languages