Files
tai/taicpp/docs/mplex.md
T

6.5 KiB

mplex + uiflow (detz port)

Spec delta for the C++ port of tai's terminal multiplexer and the interactive UI flows. The behavior specification is unchanged and lives in ../../mplex.md and ../../uiflow.md; the code being transcribed is the Mplex* and Plexer* classes of ../../tai.py. This page records what the port adds: the file layout, the Python-to-C++ mapping rules, the parity table, the tests and the known gaps.

Goal

A literal transpilation with identical behavior: the same keys, commands, options, formats, wire frames, control protocol, config file and error texts. Where Python and C++ differ at the language level, the port reproduces Python's semantics (mplex_py.h) instead of adopting C++'s.

Layout

All Mplex code is in taicpp/src/mplex/, namespace detz::mplex; the uiflow code is in taicpp/src/plexer/plexer_flow.{h,cpp}, namespace detz::plexer. One class per header and source pair; every file name is prefixed mplex_ so the flat include path of the Makefile cannot clash with other modules. Class and method names are the Python names (snake_case methods, Mplex* classes).

Mapping rules

Python C++
str std::string (UTF-8) at API edges, UStr (std::wstring, one wchar_t per code point) wherever len, index or slice count code points
bytes Bytes (std::string holding raw bytes)
None std::optional, an empty shared_ptr, or Color 0
iterated dict OrderedMap (insertion order is iteration order)
(fg, bg, attr) / cell tuple Style / Cell (ch == 0 is a never written cell)
SGR colour fragment "38;5;12" Color (32 bit pack, lossless for every fragment tai.py produces)
MplexError, ValueError MplexError, ValueError (both std::runtime_error)
closures std::function
back references (pane.window, window.session, layout parent) weak_ptr with an accessor returning shared_ptr
modes and overlays on a client shared_ptr held by the owner; MplexServer::discard_pane clears pane.modes to break the pane/mode cycle
json, tomllib, re, fnmatch, textwrap, shlex, time.strftime, subprocess.run mplex_json.h, mplex_toml.h, mplex_py.h (py::Regex, py::fnmatchcase, py::textwrap_wrap, py::shlex_quote, py::strftime, py::run_shell)

Parity table

tai.py symbol C++ symbol files
MplexError MplexError mplex_common.h
MplexKeys MplexKeys mplex_keys.{h,cpp}
tui_parse_one and helpers tui_parse_one mplex_input.{h,cpp}
MplexArgs, MplexCommandParser same mplex_args.{h,cpp}
MplexStyle MplexStyle mplex_style.{h,cpp}
MplexOptions MplexOptions mplex_options.{h,cpp}
MplexBinding, MplexConfig, MPLEX_DEFAULT_KEYS same mplex_config.{h,cpp}, mplex_default_keys.cpp (generated)
MplexFormat MplexFormat mplex_format.{h,cpp}
MplexLayoutNode, MplexLayout same mplex_layout.{h,cpp}
TuiVtScreen (as used by panes) MplexVtScreen mplex_vtscreen.{h,cpp}
MplexPane, MplexWindow, MplexSession same mplex_pane.{h,cpp}
MplexCanvas, MplexStatusText, MplexFont same mplex_canvas.{h,cpp}
MplexMode, MplexClockMode same mplex_mode.{h,cpp}, mplex_clockmode.{h,cpp}
MplexCopyMode MplexCopyMode mplex_copymode.{h,cpp}
MplexPrompt MplexPrompt mplex_prompt.{h,cpp}
MplexPaneNumbers, MplexFlowScreen same mplex_panenumbers.{h,cpp}, mplex_flowscreen.{h,cpp}
MplexChoice, MplexChooser same mplex_chooser.{h,cpp}
MplexRenderer MplexRenderer mplex_renderer.{h,cpp}
MplexCtx, MplexTargets same mplex_ctx.{h,cpp}
MplexClientConn, MplexPending same mplex_clientconn.{h,cpp}
MplexServer MplexServer mplex_server.{h,cpp}
MplexCommands, MPLEX_COMMAND_SPECS, MPLEX_DEFAULT_FORMATS same mplex_commands.{h,cpp}, mplex_command_specs.cpp (generated)
MplexClient, MplexCli, NativePlexerBackend, plexer_should_wrap, bashrc blocks same mplex_client.{h,cpp}
PlexerController, NativePlexerController, TmuxPlexerController, PlexerControllerFactory same src/plexer/plexer_flow.{h,cpp}
validate_flow_*, PlexerFlow, PlexerBackend same src/plexer/plexer_flow.{h,cpp}

The two generated files are produced from the Python tables; they carry a header saying so and mplex_spec_test compares them with mplex.md.

Tests

  • tests/mplex_spec_test.cpp: the C++ twin of MplexSpecTests and UiflowDocTests: mplex.md and uiflow.md must list exactly the options, commands, default bindings, copy-mode commands, caps and flow words that the C++ tables hold.
  • tests/mplex_foundation_test.cpp: the Python-shaped helpers, JSON and TOML, against Python 3.14.
  • tests/mplex_vt_test.cpp: the VT screen, input parser and keys against TuiVtScreen and MplexKeys.
  • tests/mplex_core_test.cpp: args, parser, style, options, config, format and layout against tai.py.
  • tests/mplex_model_test.cpp: panes, canvas, prompt, chooser, flow screen, renderer, targets.
  • tests/mplex_copy_test.cpp: copy mode against tai.py's recorded tmux results and a seeded fuzz.
  • tests/mplex_server_test.cpp, tests/mplex_commands_test.cpp: the real C++ server over its socket, scripted command corpus compared with the Python server.
  • tests/mplex_flow_test.cpp: validate_flow_spec and PlexerFlow against tai.py.
  • tests/mplex_e2e.py with tests/mplex_cli_main.cpp: the real client under a pty, as tests/mplex.py does.

Expected values in these tests are produced by running tai.py (and tmux 3.6 where mplex.md names it the oracle), never typed in from memory.

Known gaps of the port

Listed next to what would close them; the final status of each is recorded in the milestone report.

  • Regular expressions (py::Regex, std::wregex ECMAScript): Python-only syntax (lookbehind, named groups, possessive quantifiers, \Z) is translated where an equivalent exists and rejected with a loud error otherwise; copy-mode search then falls back to a literal, like Python does for an invalid expression.
  • Unicode classification (str.isalpha, isprintable, case mapping) uses the glibc C.UTF-8 tables, which may lag or lead CPython's unicodedata by a Unicode version.
  • TOML error texts follow tomllib's wording; positions are reproduced, rare messages may differ.
  • Anything else found while testing is added here, never hidden.