Generated reference › API — ICoreEssentials/Terminal
kind: generated#api#icoreessentials-terminal

API — ICoreEssentials/Terminal

The public contract of 4 header(s) under src/ICoreEssentials/Terminal — 9 class/struct definition(s), 49 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.

ICoreTerminalKeyEncoder.h#

src/ICoreEssentials/Terminal/ICoreTerminalKeyEncoder.h

ICoreTerminalKeyStroke#

ICoreTerminalKeyEncoder.h:39 · struct · 0 declaration(s)

struct ICoreTerminalKeyStroke {
public:
    ICoreTerminalKey key       = ICoreTerminalKey::None;
    std::uint8_t     modifiers = ICoreTerminalModNone;

    // The printable text the keystroke produced, UTF-8, when it produced any.
    // Empty for the named keys above. When both are set, `key` wins.
    std::string text;
};
};

ICoreTerminalKeyEncoder#

ICoreTerminalKeyEncoder.h:48 · class · 2 declaration(s)

class ICoreTerminalKeyEncoder {
public:
    ICoreTerminalKeyEncoder() = delete;

    // The bytes to write to the pty, or empty when the stroke sends nothing.
    //
    // `applicationCursorKeys` is the screen's ?1 mode: with it on, the arrows
    // send SS3 (ESC O A) instead of CSI (ESC [ A). This is not cosmetic -- a
    // readline prompt and a full-screen program expect different bytes for the
    // same key, and sending the wrong one makes the arrows do nothing.
    [[nodiscard]] static std::string encode(const ICoreTerminalKeyStroke& stroke,
                                            bool applicationCursorKeys);

    // Clipboard text, ready to write.
    //
    // ⚠ ESC IS ALWAYS STRIPPED, bracketed or not, and that is a safety
    // property rather than tidiness: pasted text is untrusted, and an escape
    // sequence hidden in it would otherwise be executed by the terminal as if
    // the user had typed it. Newlines are normalised to CR, which is what a
    // terminal sends for Return.
    //
    // With `bracketed` (the screen's ?2004 mode) the text is wrapped in the
    // paste markers, which is how a program knows the input was pasted rather
    // than typed -- an editor uses it to suspend auto-indent, and a shell to
    // avoid running a multi-line paste line by line.
    [[nodiscard]] static std::string encodePaste(const std::string& utf8Text, bool bracketed);

    // --- mouse (T4.5) -------------------------------------------------------

    enum class MouseButton : std::uint8_t { Left, Middle, Right, None };
    enum class MouseAction : std::uint8_t { Press, Release, Move, WheelUp, WheelDown };

    // A mouse report, or empty when this event should not be reported at all
    // under `trackingMode` (0 off, 1000 press/release, 1002 drag, 1003 any
    // motion). Column and row are 0-BASED here and 1-based on the wire.
    //
    // `sgrEncoding` is the screen's ?1006 mode. Prefer it: the legacy encoding
    // packs a coordinate into one byte with a +32 bias, so it simply cannot
    // address a column past 223 -- on a wide window the reports silently stop
    // making sense rather than failing.
    [[nodiscard]] static std::string encodeMouse(MouseButton button, MouseAction action,
                                                 int column, int row,
                                                 std::uint8_t modifiers,
                                                 int trackingMode, bool sgrEncoding);
};
};

File-scope declarations#

// Turns a keystroke into the bytes a terminal sends. Rows T4.1, T4.3, T4.5.
// 
// ⚠ IT HAS ITS OWN KEY ENUM RATHER THAN TAKING ICoreKeyEvent, and that is the
// whole reason it can live here. ICoreKeyEvent is a UI type carrying an
// ICoreString, which forwards to QString; depending on it would drag the
// toolkit into this folder and cost it the property decision D1 bought --
enum class ICoreTerminalKey : std::uint8_t {
    None,
    Enter, Tab, Backspace, Escape,
    ArrowUp, ArrowDown, ArrowRight, ArrowLeft,
    Home, End, PageUp, PageDown, Insert, Delete,
    F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12
};

enum ICoreTerminalModifier : std::uint8_t {
    ICoreTerminalModNone    = 0,
    ICoreTerminalModShift   = 1 << 0,
    ICoreTerminalModAlt     = 1 << 1,
    ICoreTerminalModControl = 1 << 2
};

ICoreTerminalScreen.h#

src/ICoreEssentials/Terminal/ICoreTerminalScreen.h

ICoreTerminalScreen#

ICoreTerminalScreen.h:39 · class · bases public ICoreVtSink · pImpl · 33 declaration(s)

ICoreTerminalScreen -- what the terminal currently looks like.

class ICoreTerminalScreen : public ICoreVtSink {
public:
    ICoreTerminalScreen(int columns, int rows);
    ~ICoreTerminalScreen() override;

    ICoreTerminalScreen(const ICoreTerminalScreen&) = delete;
    ICoreTerminalScreen& operator=(const ICoreTerminalScreen&) = delete;

    // --- geometry -----------------------------------------------------------

    // Content is preserved top-left-anchored; the cursor is clamped inside the
    // new bounds. Both buffers resize together, since a program can be in
    // either one when the window changes.
    void resize(int columns, int rows);

    [[nodiscard]] int columns() const;
    [[nodiscard]] int rows() const;

    // Out-of-range coordinates return a blank cell rather than throwing --
    // a paint loop racing a resize must not be a crash.
    [[nodiscard]] ICoreVtCell cellAt(int column, int row) const;

    // The whole line as text, trailing blanks trimmed. For tests and for
    // accessibility; the view reads cells, not this.
    [[nodiscard]] std::string lineText(int row) const;

    // --- scrollback (T2.8) --------------------------------------------------
    //
    // Lines that have scrolled off the top. Indexed by how far ABOVE the
    // current top row they are -- 0 is the line that just left, 1 the one
    // before it -- because that is the question a scrolled viewport asks
    // (§T3.5). Only the primary buffer contributes; the alternate screen
    // deliberately does not, or a session of vim would bury the user's
    // shell output.

    [[nodiscard]] int scrollbackCount() const;

    // Beyond the end returns a blank cell / empty string rather than throwing.
    [[nodiscard]] ICoreVtCell scrollbackCellAt(int column, int linesAboveTop) const;
    [[nodiscard]] std::string scrollbackLineText(int linesAboveTop) const;

    // 0 disables history entirely and drops what is held. Default 5000 lines.
    void setScrollbackLimit(int lines);
    void clearScrollback();

    // --- cursor -------------------------------------------------------------

    [[nodiscard]] int  cursorColumn() const;
    [[nodiscard]] int  cursorRow() const;
    [[nodiscard]] bool cursorVisible() const;

    // --- modes the INPUT layer has to know about ----------------------------
    //
    // These are why the screen tracks modes it does not itself act on: what
    // the keyboard and mouse encoders must send depends on what the program
    // has switched on (§T4.3, §T4.5).

    [[nodiscard]] bool isAlternateScreen() const;
    [[nodiscard]] bool bracketedPasteEnabled() const;

    // 0 when off, else the DEC mode number that is on: 1000 (press/release),
    // 1002 (drag), 1003 (any motion). Claude Code turns on 1003.
    [[nodiscard]] int  mouseTrackingMode() const;

    // ?1006. When true the encoder uses SGR mouse reports, which are the only
    // ones that work past column 223.
    [[nodiscard]] bool mouseSgrEncoding() const;

    // ?1 -- the cursor keys send SS3 (ESC O A) rather than CSI (ESC [ A).
    [[nodiscard]] bool applicationCursorKeys() const;

    // --- what OSC reported (T2.6) -------------------------------------------

    [[nodiscard]] std::string title() const;

    // OSC 7's file:// URL, when the shell has the integration to send one.
    // Empty otherwise -- and an empty value means "unknown", never "root".
    [[nodiscard]] std::string workingDirectoryUrl() const;

    // --- damage (§T3.2) -----------------------------------------------------

    [[nodiscard]] bool isLineDirty(int row) const;
    [[nodiscard]] bool anyLineDirty() const;
    void clearDirty();
    void markAllDirty();

    // --- ICoreVtSink --------------------------------------------------------

    void vtPrint(char32_t codepoint) override;
    void vtExecute(unsigned char control) override;
    void vtCsi(const ICoreVtSequence& sequence) override;
    void vtEsc(const ICoreVtSequence& sequence) override;
    void vtOsc(int command, const std::string& payload) override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreVtParser.h#

src/ICoreEssentials/Terminal/ICoreVtParser.h

ICoreVtSink#

ICoreVtParser.h:12 · class · 6 declaration(s)

What a parser reports.

class ICoreVtSink {
public:
    virtual ~ICoreVtSink();

    // A printable character. Already decoded from UTF-8, so this is a
    // codepoint and not a byte.
    virtual void vtPrint(char32_t codepoint) = 0;

    // A C0 control: BS, HT, LF, VT, FF, CR, BEL...
    virtual void vtExecute(unsigned char control) = 0;

    // ESC [ ... final
    virtual void vtCsi(const ICoreVtSequence& sequence) = 0;

    // ESC final, for the two-byte escapes (ESC 7, ESC M, ESC c...).
    virtual void vtEsc(const ICoreVtSequence& sequence) = 0;

    // ESC ] command ; payload BEL|ST. `command` is -1 when the sequence had
    // no leading number.
    virtual void vtOsc(int command, const std::string& payload) = 0;
};
};

ICoreVtParser#

ICoreVtParser.h:61 · class · pImpl · 7 declaration(s)

ICoreVtParser -- bytes in, terminal actions out.

class ICoreVtParser {
public:
    ICoreVtParser();
    ~ICoreVtParser();

    ICoreVtParser(const ICoreVtParser&) = delete;
    ICoreVtParser& operator=(const ICoreVtParser&) = delete;

    // Borrowed, not owned, and must outlive the parser. Null is legal and
    // makes feed() a well-defined no-op rather than a crash.
    void setSink(ICoreVtSink* sink);

    // Consume `count` bytes. Any suffix that is an incomplete sequence is
    // retained for the next call.
    void feed(const char* bytes, std::size_t count);

    // Back to the ground state, dropping any partial sequence. This is what a
    // caller does after an error or before reusing the parser -- it is NOT a
    // terminal reset, which is the screen's business (ESC c).
    void reset();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreVtTypes.h#

src/ICoreEssentials/Terminal/ICoreVtTypes.h

The vocabulary of the terminal emulator: what a cell is, what it looks like, and what one parsed control sequence carries.

⚠ QT-FREE BY CONSTRUCTION, and that is the point of this whole folder -- owner decision D1, TERMINAL_EMULATOR.md. Not just "no QColor": deliberately no ICoreString and no ICoreList either, exactly as Theme/ avoids them, since those forward to QString and QList and would drag the toolkit in through the back door. Colours here are raw components, strings are std::string. The grid view (§T3) converts at its own boundary, where UI types belong.

The upside is not purity for its own sake: it is that the parser and the screen model can be compiled and tested with no toolkit, no event loop and no display, which is what makes §T6.1 a fast headless suite instead of a GUI test.

ICoreVtColor#

ICoreVtTypes.h:36 · struct · 0 declaration(s)

struct ICoreVtColor {
public:
    ICoreVtColorKind kind  = ICoreVtColorKind::Default;
    std::uint8_t     index = 0;
    std::uint8_t     red   = 0;
    std::uint8_t     green = 0;
    std::uint8_t     blue  = 0;
};
};

ICoreVtAttributes#

ICoreVtTypes.h:59 · struct · 0 declaration(s)

struct ICoreVtAttributes {
public:
    ICoreVtColor  foreground;
    ICoreVtColor  background;
    std::uint16_t flags = ICoreVtFlagNone;
};
};

ICoreVtCell#

ICoreVtTypes.h:65 · struct · 0 declaration(s)

struct ICoreVtCell {
public:
    char32_t          codepoint = U' ';
    ICoreVtAttributes attributes;

    // How many columns this cell's character occupies (T2.7).
    //   1 -- an ordinary character
    //   2 -- the LEFT half of a double-width character (CJK, emoji)
    //   0 -- the RIGHT half of one: a continuation cell, which the view must
    //        skip rather than draw, because the left half already painted over
    //        this column.
    std::uint8_t width = 1;

    // One combining mark applied to `codepoint` -- an accent, a variation
    // selector, a ZWJ. Zero when there is none.
    //
    // ⚠ ONE, not a list, and that is a deliberate trade rather than an
    // oversight. A cell is copied on every scroll and every line shuffle, so
    // giving it a heap-allocating container would put an allocation in the
    // hot path for a case that is already rare. One slot covers accented
    // Latin, which is what actually turns up; a second mark on the same base
    // is dropped. If a real workload ever needs more, the fix is a side table
    // keyed by position, NOT a container in here.
    char32_t combining = 0;
};
};

ICoreVtSequence#

ICoreVtTypes.h:113 · struct · 1 declaration(s)

One parsed control sequence, handed to the sink.

struct ICoreVtSequence {
public:
    std::vector<int> parameters;
    std::string      intermediates;   // 0x20-0x2F bytes, in order
    char             privateMarker = '\0';   // '?', '<', '=', '>' or 0
    char             finalByte     = '\0';

    [[nodiscard]] int parameterAt(std::size_t index, int fallback) const;
};
};

File-scope declarations#

// How a cell's colour was specified. The distinction is preserved rather than
// resolved to RGB immediately, because the first two MUST follow the theme:
// "default foreground" and "colour 4" have to change when the user switches
// light/dark, and a value already flattened to RGB cannot (§T3.6).
enum class ICoreVtColorKind : std::uint8_t {
    Default,    // the theme's default fg/bg
    Indexed,    // 0-255: the 16 ANSI slots, the 6x6x6 cube, the greyscale ramp
    Rgb         // 24-bit truecolor, as Claude Code emits
};

// Bit flags rather than bools: a cell is copied constantly by the paint loop
// and by the scroll operations, so its attribute block is kept to two colours
// and one word.
enum ICoreVtAttributeFlag : std::uint16_t {
    ICoreVtFlagNone      = 0,
    ICoreVtFlagBold      = 1u << 0,
    ICoreVtFlagDim       = 1u << 1,
    ICoreVtFlagItalic    = 1u << 2,
    ICoreVtFlagUnderline = 1u << 3,
    ICoreVtFlagBlink     = 1u << 4,
    ICoreVtFlagInverse   = 1u << 5,
    ICoreVtFlagHidden    = 1u << 6,
    ICoreVtFlagStrike    = 1u << 7
};