Refine help text, keybindings, GUI themes, and undo system.
Some checks failed
Release / Bump Homebrew formula (push) Has been cancelled
Release / Build Linux amd64 (push) Has been cancelled
Release / Build Linux arm64 (push) Has been cancelled
Release / Build macOS arm64 (.app) (push) Has been cancelled
Release / Create GitHub Release (push) Has been cancelled
Some checks failed
Release / Bump Homebrew formula (push) Has been cancelled
Release / Build Linux amd64 (push) Has been cancelled
Release / Build Linux arm64 (push) Has been cancelled
Release / Build macOS arm64 (.app) (push) Has been cancelled
Release / Create GitHub Release (push) Has been cancelled
- Expanded help text and command documentation with detailed keybinding descriptions. - Added theme customization support to GUIConfig (Nord default, light/dark variants). - Adjusted for consistent indentation and debug instrumentation in undo system. - Enhanced test cases for multi-line, UTF-8, and branching scenarios.
This commit is contained in:
74
docs/kge.1
74
docs/kge.1
@@ -1,7 +1,7 @@
|
||||
.\" kge(1) — Kyle's Graphical Editor (GUI-first)
|
||||
.\"
|
||||
.\" Project homepage: https://github.com/wntrmute/kte
|
||||
.TH KGE 1 "2025-11-30" "kte 0.1.0" "User Commands"
|
||||
.TH KGE 1 "2025-12-01" "kte 0.1.0" "User Commands"
|
||||
.SH NAME
|
||||
kge \- Kyle's Graphical Editor (GUI-first)
|
||||
.SH SYNOPSIS
|
||||
@@ -52,11 +52,8 @@ tree for the canonical reference and notes:
|
||||
.PP
|
||||
Enter K-command mode with Ctrl-K. Exit K-command mode with ESC or Ctrl-G.
|
||||
.TP
|
||||
.B C-k BACKSPACE
|
||||
Delete from the cursor to the beginning of the line.
|
||||
.TP
|
||||
.B C-k SPACE
|
||||
Toggle the mark.
|
||||
.B C-k '
|
||||
Toggle read-only for the current buffer.
|
||||
.TP
|
||||
.B C-k -
|
||||
If the mark is set, unindent the region.
|
||||
@@ -64,6 +61,9 @@ If the mark is set, unindent the region.
|
||||
.B C-k =
|
||||
If the mark is set, indent the region.
|
||||
.TP
|
||||
.B C-k ;
|
||||
Open the generic command prompt (": ").
|
||||
.TP
|
||||
.B C-k a
|
||||
Set the mark at the beginning of the file, then jump to the end of the file.
|
||||
.TP
|
||||
@@ -80,7 +80,7 @@ Delete from the cursor to the end of the line.
|
||||
Delete the entire line.
|
||||
.TP
|
||||
.B C-k e
|
||||
Edit a new file.
|
||||
Edit (open) a new file.
|
||||
.TP
|
||||
.B C-k f
|
||||
Flush the kill ring.
|
||||
@@ -88,14 +88,20 @@ Flush the kill ring.
|
||||
.B C-k g
|
||||
Go to a specific line.
|
||||
.TP
|
||||
.B C-k h
|
||||
Show the built-in help (+HELP+ buffer).
|
||||
.TP
|
||||
.B C-k j
|
||||
Jump to the mark.
|
||||
.TP
|
||||
.B C-k l
|
||||
Reload the current buffer from disk.
|
||||
.TP
|
||||
.B C-k m
|
||||
Run make(1), reporting success or failure.
|
||||
.B C-k n
|
||||
Switch to the previous buffer.
|
||||
.TP
|
||||
.B C-k o
|
||||
Change working directory (prompt).
|
||||
.TP
|
||||
.B C-k p
|
||||
Switch to the next buffer.
|
||||
@@ -106,14 +112,20 @@ Exit the editor. If the file has unsaved changes, a warning will be printed; a s
|
||||
.B C-k C-q
|
||||
Immediately exit the editor.
|
||||
.TP
|
||||
.B C-k r
|
||||
Redo changes.
|
||||
.TP
|
||||
.B C-k s
|
||||
Save the file, prompting for a filename if needed.
|
||||
.TP
|
||||
.B C-k u
|
||||
Undo.
|
||||
.TP
|
||||
.B C-k r
|
||||
Redo changes.
|
||||
.B C-k v
|
||||
Toggle visual file picker (GUI).
|
||||
.TP
|
||||
.B C-k w
|
||||
Show the current working directory.
|
||||
.TP
|
||||
.B C-k x
|
||||
Save the file and exit. Also C-k C-x.
|
||||
@@ -121,23 +133,50 @@ Save the file and exit. Also C-k C-x.
|
||||
.B C-k y
|
||||
Yank the kill ring.
|
||||
.TP
|
||||
.B C-k \e
|
||||
Dump core.
|
||||
.B C-k C-x
|
||||
Save the file and exit.
|
||||
|
||||
.SS Other keybindings
|
||||
.TP
|
||||
.B C-g
|
||||
Cancel the current operation.
|
||||
.TP
|
||||
.B C-a
|
||||
Move to the beginning of the line.
|
||||
.TP
|
||||
.B C-e
|
||||
Move to the end of the line.
|
||||
.TP
|
||||
.B C-b
|
||||
Move left.
|
||||
.TP
|
||||
.B C-f
|
||||
Move right.
|
||||
.TP
|
||||
.B C-n
|
||||
Move down.
|
||||
.TP
|
||||
.B C-p
|
||||
Move up.
|
||||
.TP
|
||||
.B C-l
|
||||
Refresh the display.
|
||||
.TP
|
||||
.B C-d
|
||||
Delete the character at the cursor.
|
||||
.TP
|
||||
.B C-r
|
||||
Regex search.
|
||||
.TP
|
||||
.B C-s
|
||||
Incremental find.
|
||||
.TP
|
||||
.B C-t
|
||||
Regex search and replace.
|
||||
.TP
|
||||
.B C-h
|
||||
Search and replace.
|
||||
.TP
|
||||
.B C-u
|
||||
Universal argument. C-u followed by numbers will repeat an operation n times.
|
||||
.TP
|
||||
@@ -147,6 +186,15 @@ Kill the region if the mark is set.
|
||||
.B C-y
|
||||
Yank the kill ring.
|
||||
.TP
|
||||
.B ESC <
|
||||
Move to the beginning of the file.
|
||||
.TP
|
||||
.B ESC >
|
||||
Move to the end of the file.
|
||||
.TP
|
||||
.B ESC m
|
||||
Toggle the mark.
|
||||
.TP
|
||||
.B ESC BACKSPACE
|
||||
Delete the previous word.
|
||||
.TP
|
||||
|
||||
100
docs/kte.1
100
docs/kte.1
@@ -1,7 +1,7 @@
|
||||
.\" kte(1) — Kyle's Text Editor (terminal-first)
|
||||
.\"
|
||||
.\" Project homepage: https://github.com/wntrmute/kte
|
||||
.TH KTE 1 "2025-11-30" "kte 0.1.0" "User Commands"
|
||||
.TH KTE 1 "2025-12-01" "kte 0.1.0" "User Commands"
|
||||
.SH NAME
|
||||
kte \- Kyle's Text Editor (terminal-first)
|
||||
.SH SYNOPSIS
|
||||
@@ -57,11 +57,8 @@ in the source tree for the canonical reference and notes.
|
||||
.PP
|
||||
Enter K-command mode with Ctrl-K. Exit K-command mode with ESC or Ctrl-G.
|
||||
.TP
|
||||
.B C-k BACKSPACE
|
||||
Delete from the cursor to the beginning of the line.
|
||||
.TP
|
||||
.B C-k SPACE
|
||||
Toggle the mark.
|
||||
.B C-k '
|
||||
Toggle read-only for the current buffer.
|
||||
.TP
|
||||
.B C-k -
|
||||
If the mark is set, unindent the region.
|
||||
@@ -69,6 +66,9 @@ If the mark is set, unindent the region.
|
||||
.B C-k =
|
||||
If the mark is set, indent the region.
|
||||
.TP
|
||||
.B C-k ;
|
||||
Open the generic command prompt (": ").
|
||||
.TP
|
||||
.B C-k a
|
||||
Set the mark at the beginning of the file, then jump to the end of the file.
|
||||
.TP
|
||||
@@ -85,7 +85,7 @@ Delete from the cursor to the end of the line.
|
||||
Delete the entire line.
|
||||
.TP
|
||||
.B C-k e
|
||||
Edit a new file.
|
||||
Edit (open) a new file.
|
||||
.TP
|
||||
.B C-k f
|
||||
Flush the kill ring.
|
||||
@@ -93,14 +93,20 @@ Flush the kill ring.
|
||||
.B C-k g
|
||||
Go to a specific line.
|
||||
.TP
|
||||
.B C-k h
|
||||
Show the built-in help (+HELP+ buffer).
|
||||
.TP
|
||||
.B C-k j
|
||||
Jump to the mark.
|
||||
.TP
|
||||
.B C-k l
|
||||
Reload the current buffer from disk.
|
||||
.TP
|
||||
.B C-k m
|
||||
Run make(1), reporting success or failure.
|
||||
.B C-k n
|
||||
Switch to the previous buffer.
|
||||
.TP
|
||||
.B C-k o
|
||||
Change working directory (prompt).
|
||||
.TP
|
||||
.B C-k p
|
||||
Switch to the next buffer.
|
||||
@@ -111,14 +117,20 @@ Exit the editor. If the file has unsaved changes, a warning will be printed; a s
|
||||
.B C-k C-q
|
||||
Immediately exit the editor.
|
||||
.TP
|
||||
.B C-k r
|
||||
Redo changes.
|
||||
.TP
|
||||
.B C-k s
|
||||
Save the file, prompting for a filename if needed.
|
||||
.TP
|
||||
.B C-k u
|
||||
Undo.
|
||||
.TP
|
||||
.B C-k r
|
||||
Redo changes.
|
||||
.B C-k v
|
||||
Toggle visual file picker (GUI).
|
||||
.TP
|
||||
.B C-k w
|
||||
Show the current working directory.
|
||||
.TP
|
||||
.B C-k x
|
||||
Save the file and exit. Also C-k C-x.
|
||||
@@ -126,23 +138,76 @@ Save the file and exit. Also C-k C-x.
|
||||
.B C-k y
|
||||
Yank the kill ring.
|
||||
.TP
|
||||
.B C-k \e
|
||||
Dump core.
|
||||
.B C-k C-x
|
||||
Save the file and exit.
|
||||
|
||||
.SH GUI APPEARANCE
|
||||
When running the GUI frontend, you can control appearance via the generic
|
||||
command prompt (type "C-k ;" then enter commands):
|
||||
.TP
|
||||
.B : theme NAME
|
||||
Set the GUI theme. Available names: "nord", "gruvbox", "plan9", "solarized", "eink".
|
||||
Compatibility aliases are also accepted: "gruvbox-dark", "gruvbox-light",
|
||||
"solarized-dark", "solarized-light", "eink-dark", "eink-light".
|
||||
.TP
|
||||
.B : background MODE
|
||||
Set background mode for supported themes. MODE is either "light" or "dark".
|
||||
Themes that respond to background: eink, gruvbox, solarized. The
|
||||
"nord" and "plan9" themes do not vary with background.
|
||||
|
||||
.SH CONFIGURATION
|
||||
The GUI reads a simple configuration file at
|
||||
~/.config/kte/kge.ini. Recognized keys include:
|
||||
.IP "fullscreen=on|off"
|
||||
.IP "columns=NUM"
|
||||
.IP "rows=NUM"
|
||||
.IP "font_size=NUM"
|
||||
.IP "theme=NAME"
|
||||
.IP "background=light|dark"
|
||||
The theme name accepts the values listed above. The background key controls
|
||||
light/dark variants when the selected theme supports it.
|
||||
|
||||
.SS Other keybindings
|
||||
.TP
|
||||
.B C-g
|
||||
Cancel the current operation.
|
||||
.TP
|
||||
.B C-a
|
||||
Move to the beginning of the line.
|
||||
.TP
|
||||
.B C-e
|
||||
Move to the end of the line.
|
||||
.TP
|
||||
.B C-b
|
||||
Move left.
|
||||
.TP
|
||||
.B C-f
|
||||
Move right.
|
||||
.TP
|
||||
.B C-n
|
||||
Move down.
|
||||
.TP
|
||||
.B C-p
|
||||
Move up.
|
||||
.TP
|
||||
.B C-l
|
||||
Refresh the display.
|
||||
.TP
|
||||
.B C-d
|
||||
Delete the character at the cursor.
|
||||
.TP
|
||||
.B C-r
|
||||
Regex search.
|
||||
.TP
|
||||
.B C-s
|
||||
Incremental find.
|
||||
.TP
|
||||
.B C-t
|
||||
Regex search and replace.
|
||||
.TP
|
||||
.B C-h
|
||||
Search and replace.
|
||||
.TP
|
||||
.B C-u
|
||||
Universal argument. C-u followed by numbers will repeat an operation n times.
|
||||
.TP
|
||||
@@ -152,6 +217,15 @@ Kill the region if the mark is set.
|
||||
.B C-y
|
||||
Yank the kill ring.
|
||||
.TP
|
||||
.B ESC <
|
||||
Move to the beginning of the file.
|
||||
.TP
|
||||
.B ESC >
|
||||
Move to the end of the file.
|
||||
.TP
|
||||
.B ESC m
|
||||
Toggle the mark.
|
||||
.TP
|
||||
.B ESC BACKSPACE
|
||||
Delete the previous word.
|
||||
.TP
|
||||
|
||||
102
docs/syntax on.md
Normal file
102
docs/syntax on.md
Normal file
@@ -0,0 +1,102 @@
|
||||
### Objective
|
||||
Introduce fast, minimal‑dependency syntax highlighting to kte, consistent with current architecture (Editor/Buffer + GUI/Terminal renderers), preserving ke UX and performance.
|
||||
|
||||
### Guiding principles
|
||||
- Keep core small and fast; no heavy deps (C++17 only).
|
||||
- Start simple (stateless line regex), evolve incrementally (stateful, caching).
|
||||
- Work in both Terminal (ncurses) and GUI (ImGui) with consistent token classes and theme mapping.
|
||||
- Integrate without disrupting existing search highlight, selection, or cursor rendering.
|
||||
|
||||
### Scope of v1
|
||||
- Languages: plain text (off), C/C++ minimal set (keywords, types, strings, chars, comments, numbers, preprocessor).
|
||||
- Stateless per‑line highlighting; handle single‑line comments and strings; defer multi‑line state to v2.
|
||||
- Toggle: `:syntax on|off` and per‑buffer filetype selection.
|
||||
|
||||
### Architecture
|
||||
1. Core types (new):
|
||||
- `enum class TokenKind { Default, Keyword, Type, String, Char, Comment, Number, Preproc, Constant, Function, Operator, Punctuation, Identifier, Whitespace, Error };`
|
||||
- `struct HighlightSpan { int col_start; int col_end; TokenKind kind; };` // 0‑based columns in buffer indices per rendered line
|
||||
- `struct LineHighlight { std::vector<HighlightSpan> spans; uint64_t version; };`
|
||||
|
||||
2. Interfaces (new):
|
||||
- `class LanguageHighlighter { public: virtual ~LanguageHighlighter() = default; virtual void HighlightLine(const Buffer& buf, int row, std::vector<HighlightSpan>& out) const = 0; virtual bool Stateful() const { return false; } };`
|
||||
- `class HighlighterEngine { public: void SetHighlighter(std::unique_ptr<LanguageHighlighter>); const LineHighlight& GetLine(const Buffer&, int row, uint64_t buf_version); void InvalidateFrom(int row); };`
|
||||
- `class HighlighterRegistry { public: static const LanguageHighlighter& ForFiletype(std::string_view ft); static std::string DetectForPath(std::string_view path, std::string_view first_line); };`
|
||||
|
||||
3. Editor/Buffer integration:
|
||||
- Per‑Buffer settings: `bool syntax_enabled; std::string filetype; std::unique_ptr<HighlighterEngine> highlighter;`
|
||||
- Buffer emits a monotonically increasing `version` on edit; renderers request line highlights by `(row, version)`.
|
||||
- Invalidate cache minimally on edits (v1: current line only; v2: from current line down when stateful constructs present).
|
||||
|
||||
### Rendering integration
|
||||
- TerminalRenderer/GUIRenderer changes:
|
||||
- During line rendering, query `Editor.CurrentBuffer()->highlighter->GetLine(buf, row, buf_version)` to obtain spans.
|
||||
- Apply token styles while drawing glyph runs.
|
||||
- Z‑order and blending:
|
||||
1) Backgrounds (e.g., selection, search highlight rectangles)
|
||||
2) Text with syntax colors
|
||||
3) Cursor/IME decorations
|
||||
- Search highlights must remain visible over syntax colors:
|
||||
- Terminal: combine color/attr with reverse/bold for search; if color conflicts, prefer search.
|
||||
- GUI: draw semi‑transparent rects behind text (already present); keep syntax color for text.
|
||||
|
||||
### Theme and color mapping
|
||||
- Extend `GUITheme.h` with a `SyntaxPalette` mapping `TokenKind -> ImVec4 ink` (and optional background tint for comments/strings disabled by default). Provide default Light/Dark palettes.
|
||||
- Terminal: map `TokenKind` to ncurses color pairs where available; degrade gracefully on 8/16‑color terminals (e.g., comments=dim, keywords=bold, strings=yellow/green if available).
|
||||
|
||||
### Language detection
|
||||
- v1: by file extension; allow manual `:set filetype=<lang>`.
|
||||
- v2: add shebang detection for scripts, simple modelines (optional).
|
||||
|
||||
### Commands/UX
|
||||
- `:syntax on|off` — global default; buffer inherits on open.
|
||||
- `:set filetype=<lang>` — per‑buffer override.
|
||||
- `:syntax reload` — rebuild patterns/themes.
|
||||
- Status line shows filetype and syntax state when changed.
|
||||
|
||||
### Implementation plan (phased)
|
||||
1. Phase 1 — Minimal regex highlighter for C/C++
|
||||
- Implement `CppRegexHighlighter : LanguageHighlighter` with precompiled `std::regex` (or hand‑rolled simple scanners to avoid regex backtracking). Classes: line comment `//…`, block comment start `/*` (no state), string `"…"`, char `'…'` (no multiline), numbers, keywords/types, preprocessor `^\s*#\w+`.
|
||||
- Add `HighlighterEngine` with a simple per‑row cache keyed by `(row, buf_version)`; no background worker.
|
||||
- Integrate into both renderers; add palette to `GUITheme.h`; add terminal color selection.
|
||||
- Add commands.
|
||||
|
||||
2. Phase 2 — Stateful constructs and more languages
|
||||
- Add state machine for multiline comments `/*…*/` and multiline strings (C++11 raw strings), with invalidation from edit line downward until state stabilizes.
|
||||
- Add simple highlighters: JSON (strings, numbers, booleans, null, punctuation), Markdown (headers/emphasis/code fences), Shell (comments, strings, keywords), Go (types, constants, keywords), Python (strings, comments, keywords), Rust (strings, comments, keywords), Lisp (comments, strings, keywords),.
|
||||
- Filetype detection by extension + shebang.
|
||||
|
||||
3. Phase 3 — Performance and caching
|
||||
- Viewport‑first highlighting: compute only visible rows each frame; background task warms cache around viewport.
|
||||
- Reuse span buffers, avoid allocations; small‑vector optimization if needed.
|
||||
- Bench with large files; ensure O(n_visible) cost per frame.
|
||||
|
||||
4. Phase 4 — Extensibility
|
||||
- Public registration API for external highlighters.
|
||||
- Optional Tree‑sitter adapter behind a compile flag (off by default) to keep dependencies minimal.
|
||||
|
||||
### Data flow (per frame)
|
||||
- Renderer asks Editor for Buffer and viewport rows.
|
||||
- For each row: `engine.GetLine(buf, row, buf.version)` → spans.
|
||||
- Renderer emits runs with style from `SyntaxPalette[kind]`.
|
||||
- Search highlights are applied as separate background rectangles (GUI) or attribute toggles (Terminal), not overriding text color.
|
||||
|
||||
### Testing
|
||||
- Unit tests for tokenization per language: golden inputs → spans.
|
||||
- Fuzz/edge cases: escaped quotes, numeric literals, preprocessor lines.
|
||||
- Renderer tests with `TestRenderer` asserting the sequence of style changes for a line.
|
||||
- Performance tests: highlight 1k visible lines repeatedly; assert time under threshold.
|
||||
|
||||
### Risks and mitigations
|
||||
- Regex backtracking/perf: prefer linear scans; precompute keyword tables; avoid nested regex.
|
||||
- Terminal color limitations: feature‑detect colors; provide bold/dim fallbacks.
|
||||
- Stateful correctness: invalidate conservatively (from edit line downward) and cap work per frame.
|
||||
|
||||
### Deliverables
|
||||
- New files: `Highlight.h/.cc`, `HighlighterEngine.h/.cc`, `LanguageHighlighter.h`, `CppHighlighter.h/.cc`, optional `HighlighterRegistry.h/.cc`.
|
||||
- Renderer updates: `GUIRenderer.cc`, `TerminalRenderer.cc` to consume spans.
|
||||
- Theming: `GUITheme.h` additions for syntax colors.
|
||||
- Editor/Buffer: per‑buffer syntax settings and highlighter handle.
|
||||
- Commands in `Command.cc` and help text updates.
|
||||
- Docs: README/ROADMAP update and a brief `docs/syntax.md`.
|
||||
- Tests: unit and renderer golden tests.
|
||||
Reference in New Issue
Block a user