Files
kte/AGENTS.md
T
kyleandClaude Opus 5.5 2125583407 Remove the Qt frontend
The Qt GUI was unused: out of make-app-release since March, not built by
the gate, and its app bundle could not start (no platform plugin). Every
renderer and input change had to be made in it separately. kge is the
ImGui frontend only.

Removes QtFrontend/QtInputHandler/QtRenderer, the KTE_USE_QT option and
its #if branches (Command.cc, GUITheme.h, main.cc), the Nix qt package
and dev shell, the commented-out Qt release steps, the Qt frontend plan,
and Qt mentions in AGENTS.md, DEVELOPER_GUIDE.md, REWRITE.md and code
comments. Git history keeps the code.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:32:58 -07:00

6.7 KiB

kte

kte (Kyle's Text Editor) is a C++20 text editor with a terminal-first design (ncurses) and an optional ImGui GUI frontend (SDL2/OpenGL/Freetype); it uses a WordStar/VDE-style command model. Standards: none. The Metacircular service standards do not apply here.

Bootstrap (run once per checkout, idempotent)

nix develop (default shell; also provides a terminal devshell) or system SDL2/Freetype/ncurses if not using nix.

Gate (run before saying "done"; must exit 0)

make gate # what it runs: configure (cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_GUI=ON -DBUILD_TESTS=ON) -> build (cmake --build build) -> test (./build/kte_tests) Fast check while editing: cmake --build build --target kte_tests && ./build/kte_tests Also run clang-tidy on changed files via build/compile_commands.json (not part of make gate; clang-tidy is not on this Mac's PATH).

Run

Terminal editor: ./build/kte <file> (always built). GUI editor: ./build/kge <file> (built when -DBUILD_GUI=ON; requires SDL2/OpenGL/Freetype). Docker (cross-platform Linux testing): docker build -t kte-linux . && docker run --rm -v "$(pwd):/kte" kte-linux.

Sensors the harness watches

  • make gate exit status and last 40 lines; kte_tests runs via ctest too (ctest --test-dir build)
  • clang-tidy warning count on the diff (when clang-tidy is available)
  • for GUI bugs: launch ./build/kge and report what was seen; a green test suite is not proof

Rules (do not re-litigate)

  • Release: bump CMakeLists version, checkpoint, ./make-release.sh, report the SHA256 it prints; a GitHub push failure at the same commit is fine; then update /opt/homebrew/Library/Taps/kisom/homebrew-tap.
  • All text mutations must go through the PieceTable API (insert_text, delete_text) so undo and swap recording work.
  • Read lines with Nrows() and GetLineString() (a copy, cheap on any buffer) or GetLineView() (zero-copy when the line lies within one piece; a line straddling an edit materializes the whole buffer); GetLineView() and ContentView() are valid only until the next buffer modification.
  • C++20, compiled with -Wall -Wextra -Werror -pedantic; Clang uses -stdlib=libc++.
  • Naming: PascalCase for classes/methods, snake_case for variables, trailing underscore for private members (e.g. pieces_); indentation is tabs.
  • Fallible ops use bool func(args..., std::string &err): clear err at start, capture errno immediately after syscall failure, use EINTR-safe wrappers from SyscallWrappers.h instead of raw syscalls.
  • After editing ops, call ensure_cursor_visible() to update the viewport.

Docs that govern

  • docs/ke.md — canonical keybinding/spec reference, inherited from the predecessor editor ke
  • REWRITE.md, ROADMAP.md, CONFIG.md — design rationale, roadmap, and config reference
  • README.md — project overview

Remote target

None: kte builds and runs locally (or in the Docker/CI Linux image); it has no remote deployment target.

Architecture

Three-layer design with strict frontend independence:

Frontend Layer (Terminal / ImGui / Test)
  InputHandler.h, Renderer.h, Frontend.h interfaces
        ↓
Command Layer
  CommandId enum → CommandRegistry → handler functions in Command.cc
        ↓
Core Model Layer
  Editor → Buffer → PieceTable
  UndoSystem (tree-based, records at PieceTable level)
  SwapManager (crash recovery journal per buffer)

Core Components

  • PieceTable (PieceTable.h/.cc) - Text storage. Lazy materialization; most ops work on the piece list directly. Line index and materialization caches must be invalidated on content changes.
  • Buffer (Buffer.h/.cc) - Wraps PieceTable.
  • Editor (Editor.h/.cc) - Top-level state container. Primarily getters/setters; editing logic lives in commands.
  • Command (Command.h/.cc) - 120+ editing commands. This is the main place to add new editing operations. Register via CommandRegistry::Register() in InstallDefaultCommands().
  • UndoSystem/UndoTree/UndoNode - Tree-based undo with branching. Group related ops with buf.Undo()->BeginGroup() / EndGroup().
  • Swap (Swap.h/.cc) - Append-only crash recovery journal. Uses circuit breaker pattern for resilience. Files in ~/.local/state/kte/.
  • Syntax highlighting (syntax/) - Pluggable per-language highlighters registered in HighlighterRegistry. Per-line caching with buffer version tracking.

Frontend Implementations

Each frontend implements three interfaces (Frontend.h, InputHandler.h, Renderer.h):

  • Terminal: ncurses-based (always built)
  • ImGui: SDL2+OpenGL+Freetype (built with -DBUILD_GUI=ON)
  • Test: Programmatic frontend for testing (always built, no UI deps)

Key CMake Options

Flag Default Purpose
BUILD_GUI ON Build kge (ImGui GUI)
BUILD_TESTS ON Build test suite
ENABLE_ASAN OFF AddressSanitizer
KTE_STATIC_LINK OFF Static linking (Linux only)
KTE_ENABLE_TREESITTER OFF Tree-sitter syntax highlighting
KTE_USE_PCRE2 ON Regex search/replace via PCRE2 when libpcre2-8 is found (std::regex otherwise; see RegexEngine.h)

Testing

Tests live in tests/test_*.cc, run by the single kte_tests binary (also registered with ctest as add_test(NAME kte_tests COMMAND kte_tests)); ./build/kte_tests Swap_ Undo_ runs only the tests whose names contain one of the arguments. Tests use a minimal custom framework in tests/Test.h with TEST(), ASSERT_EQ(), ASSERT_TRUE(), EXPECT_TRUE() macros. Use TestFrontend/TestInputHandler/TestRenderer for integration tests that exercise the full Editor+Buffer+Command stack without UI dependencies.

Key test files by area:

  • PieceTable: test_piece_table.cc
  • Buffer I/O: test_buffer_io.cc
  • Commands: test_command_semantics.cc
  • Search/replace: test_search_replace_flow.cc
  • Undo: test_undo.cc
  • Swap (crash recovery): test_swap_*.cc (7 files)
  • Reflow: test_reflow_paragraph.cc, test_reflow_indented_bullets.cc
  • Integration: test_daily_workflows.cc

Important Caveats

  • GetLineView() and ContentView() return a string_view valid only until the next buffer modification; views of different lines need not be contiguous.
  • Buffers, PieceTable and HighlighterEngine are used from the main thread only (the swap writer thread receives copies of the bytes).
  • All source files are in the project root (no src/ directory); tests are in tests/; syntax highlighters in syntax/; themes in themes/; embedded fonts in fonts/.
  • External deps: ext/imgui/ (Dear ImGui), ext/tomlplusplus/ (TOML parser).
  • GUI config: ~/.config/kte/kge.toml (TOML preferred over legacy INI).
  • ErrorHandler: centralized logging to ~/.local/state/kte/error.log with severity levels (Info/Warning/Error/Critical).