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.
| Header | Defines | Declarations | Bases |
|---|---|---|---|
ICoreTerminalKeyEncoder.h | ICoreTerminalKeyStroke, ICoreTerminalKeyEncoder | 2 | — |
ICoreTerminalScreen.h | ICoreTerminalScreen | 33 | public ICoreVtSink |
ICoreVtParser.h | ICoreVtSink, ICoreVtParser | 13 | — |
ICoreVtTypes.h | ICoreVtColor, ICoreVtAttributes, ICoreVtCell, ICoreVtSequence | 1 | — |
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
};