From 2496722b433166935e4591fc757074ef647a4833 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Tue, 15 Sep 2026 22:50:30 -0700 Subject: [PATCH] Project guide: AGENTS.md as the single guide, gate target, Junie pointer CLAUDE.md is a one-line @AGENTS.md import; make gate configures, builds, and runs kte_tests. CMakeLists.txt registers the tests with CTest. .junie/guidelines.md points Junie at AGENTS.md. Co-Authored-By: Claude Fable 5.1 --- .junie/guidelines.md | 60 +--------------------- AGENTS.md | 107 +++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 117 +------------------------------------------ CMakeLists.txt | 3 ++ Makefile | 12 +++++ 5 files changed, 125 insertions(+), 174 deletions(-) create mode 100644 AGENTS.md create mode 100644 Makefile diff --git a/.junie/guidelines.md b/.junie/guidelines.md index f92bcaf..de3f1f9 100644 --- a/.junie/guidelines.md +++ b/.junie/guidelines.md @@ -1,58 +1,2 @@ -# Project Guidelines - -kte is Kyle's Text Editor — a simple, fast text editor written in C++20. -It -replaces the earlier C implementation, ke (see the ke manual in -`docs/ke.md`). The -design draws inspiration from Antirez' kilo, with keybindings rooted in -the -WordStar/VDE family and emacs. The spiritual parent is `mg(1)`. - -These guidelines summarize the goals, interfaces, key operations, and -current -development practices for kte. - -## Goals - -- Keep the core small, fast, and understandable. -- Provide an ncurses-based terminal-first editing experience, with an - additional ImGui GUI. -- Preserve familiar keybindings from ke while modernizing the internals. -- Favor simple data structures (e.g., piece table) and incremental - evolution. - -Project entry point: `main.cpp` - -## Core Components (current codebase) - -- Buffer: editing model and file I/O (`Buffer.h/.cpp`). -- PieceTable: editable in-memory text representation ( - `PieceTable.h/.cpp`). -- InputHandler: interface for handling text input (`InputHandler.h/`), - along - with `TerminalInputHandler` (ncurses-based) and `GUIInputHandler`. -- Renderer: interface for rendering text (`Renderer.h`), along with - `TerminalRenderer` (ncurses-based) and `GUIRenderer`. -- Editor: top-level editor state (`Editor.h/.cpp`). -- Command: command model (`Command.h/.cpp`). -- General purpose editor functionality (`Editing.h/.cpp`) - -## Keybindings (inherited from ke) - -The file `docs/ke.md` contains the canonical reference for keybindings. - -## Contributing/Development Notes - -- C++ standard: C++20. -- Keep dependencies minimal. -- Prefer small, focused changes that preserve ke’s UX unless explicitly - changing - behavior. - -## References - -- Previous editor manual: `ke.md` (canonical keybinding/spec reference - for now). -- Inspiration: kilo, WordStar/VDE, emacs, `mg(1)`. - - +Read AGENTS.md at the repository root before anything else. It is the only +project guide; this file exists because Junie cannot import it. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..226cc3c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,107 @@ +# kte + +kte (Kyle's Text Editor) is a C++20 text editor with a terminal-first design (ncurses) and optional GUI frontends (ImGui via SDL2/OpenGL/Freetype, or Qt6); 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 `terminal` and `qt` devshells) 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 ` (always built). +GUI editor: `./build/kge ` (built when `-DBUILD_GUI=ON`; requires SDL2/OpenGL/Freetype, or Qt6 with `-DKTE_USE_QT=ON`). +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. +- Prefer `GetLineView()` (zero-copy) or `GetLineString()` over `Rows()` (legacy, materializes all lines); `GetLineView()` is 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 / Qt / 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`) +- **Qt**: Qt6 (built with `-DBUILD_GUI=ON -DKTE_USE_QT=ON`) +- **Test**: Programmatic frontend for testing (always built, no UI deps) + +### Key CMake Options + +| Flag | Default | Purpose | +|------|---------|---------| +| `BUILD_GUI` | ON | Build `kge` (ImGui GUI) | +| `KTE_USE_QT` | OFF | Use Qt6 instead of ImGui for 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 | + +## 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)`); there is no single-test runner. 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.cc`, `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 + +- `Buffer::Rows()` is legacy; use `GetLineView()` / `GetLineString()` in new code. +- `GetLineView()` returns a `string_view` valid only until the next buffer modification. +- 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). diff --git a/CLAUDE.md b/CLAUDE.md index 7877058..43c994c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,116 +1 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -**kte** (Kyle's Text Editor) is a C++20 text editor with a terminal-first design (ncurses) and optional GUI frontends (ImGui via SDL2/OpenGL/Freetype, or Qt6). It uses a WordStar/VDE-style command model. The terminal editor is `kte`; the GUI editor is `kge`. - -## Build Commands - -```bash -# Configure (from project root, build dir is "build") -cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_GUI=ON -DBUILD_TESTS=ON - -# Build everything -cmake --build build - -# Build specific targets -cmake --build build --target kte # terminal editor -cmake --build build --target kge # GUI editor (requires -DBUILD_GUI=ON) -cmake --build build --target kte_tests # test suite - -# Run all tests -cmake --build build --target kte_tests && ./build/kte_tests -``` - -The test binary runs all tests, or only those whose names contain one of its arguments (`./build/kte_tests Swap_ Undo_`). Tests use a minimal custom framework in `tests/Test.h` with `TEST()`, `ASSERT_EQ()`, `ASSERT_TRUE()`, `EXPECT_TRUE()` macros. - -### Key CMake Options - -| Flag | Default | Purpose | -|------|---------|---------| -| `BUILD_GUI` | ON | Build `kge` (ImGui GUI) | -| `KTE_USE_QT` | OFF | Use Qt6 instead of ImGui for 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`) | - -### Nix - -`flake.nix` provides devshells: `default` (ImGui+debug tools), `terminal`, `qt`. - -### Docker (cross-platform Linux testing) - -```bash -docker build -t kte-linux . && docker run --rm -v "$(pwd):/kte" kte-linux -``` - -## Architecture - -Three-layer design with strict frontend independence: - -``` -Frontend Layer (Terminal / ImGui / Qt / 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. Prefer `GetLineView(row)` (zero-copy) or `GetLineString(row)` over `Rows()` (legacy, materializes all lines). All text mutations must go through PieceTable API (`insert_text`, `delete_text`) to ensure undo and swap recording work. -- **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`) -- **Qt**: Qt6 (built with `-DBUILD_GUI=ON -DKTE_USE_QT=ON`) -- **Test**: Programmatic frontend for testing (always built, no UI deps) - -## Code Style - -- **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**: Tabs -- **Error handling**: Fallible ops use `bool func(args..., std::string &err)` pattern. Always clear `err` at start, capture `errno` immediately after syscall failure. Use EINTR-safe wrappers from `SyscallWrappers.h` instead of raw syscalls. -- **ErrorHandler**: Centralized logging to `~/.local/state/kte/error.log` with severity levels (Info/Warning/Error/Critical). - -## Testing - -Tests live in `tests/test_*.cc`. 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.cc`, `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 - -- `Buffer::Rows()` is legacy; use `GetLineView()` / `GetLineString()` in new code -- `GetLineView()` returns a `string_view` valid only until next buffer modification -- After editing ops, call `ensure_cursor_visible()` to update viewport -- 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) +@AGENTS.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 5762b8e..f1d5f3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -442,6 +442,9 @@ if (BUILD_TESTS) if (NOT APPLE AND KTE_STATIC_LINK) target_link_options(kte_tests PRIVATE -static) endif () + + enable_testing() + add_test(NAME kte_tests COMMAND kte_tests) endif () if (BUILD_GUI) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8cd3d3c --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: configure build test gate + +configure: + cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_GUI=ON -DBUILD_TESTS=ON + +build: + cmake --build build + +test: + ./build/kte_tests + +gate: configure build test