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>
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 gateexit status and last 40 lines;kte_testsruns via ctest too (ctest --test-dir build)- clang-tidy warning count on the diff (when clang-tidy is available)
- for GUI bugs: launch
./build/kgeand 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()andGetLineString()(a copy, cheap on any buffer) orGetLineView()(zero-copy when the line lies within one piece; a line straddling an edit materializes the whole buffer);GetLineView()andContentView()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): clearerrat start, captureerrnoimmediately after syscall failure, use EINTR-safe wrappers fromSyscallWrappers.hinstead 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 editorkeREWRITE.md,ROADMAP.md,CONFIG.md— design rationale, roadmap, and config referenceREADME.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 viaCommandRegistry::Register()inInstallDefaultCommands(). - 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 inHighlighterRegistry. 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()andContentView()return astring_viewvalid 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 intests/; syntax highlighters insyntax/; themes inthemes/; embedded fonts infonts/. - 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.logwith severity levels (Info/Warning/Error/Critical).