ChangeLog:
- prebuild.
This commit is contained in:
+66
-23
@@ -5,10 +5,36 @@
|
||||
Тестовая крупная задача — проверить нашу libc на нетривиальном interactive-приложении (полноэкранный UI, файловый I/O, парсер). Параллельно даст хороший showcase платформы и поможет вытащить недоделки в conio/io. Конечная цель: viewer для `.md` файлов с подсветкой синтаксиса, навигацией по тексту и постраничным скроллингом.
|
||||
|
||||
**Ограничения v1 (зафиксированы пользователем):**
|
||||
- POSIX file API (`open/read/lseek/close`); FILE*/fread/fgets — не использовать
|
||||
- Максимум 16 KB на один файл (одна EMM-страница); многостраничный режим — в v2
|
||||
- POSIX file API (open/read/lseek/close); FILE pointer / fread / fgets — не использовать
|
||||
- Подсветка через цвет: **размер заголовка** → цвет шрифта; **bold/italic** → цвет фона (моноширинный фонт без жирного/курсивного начертания)
|
||||
|
||||
**Расширения, реализованные после плана:**
|
||||
- Файлы до 128 KB (1–8 EMM-страниц, lazy map в W3 через `fb()/map_page()`) — изначально было в v2
|
||||
- Анимированный spinner и предварительная отрисовка UI при старте — UX
|
||||
- Inline emphasis: `_`/`*`/`**` подчиняются XOR flanking-правилу (whitespace ровно с одной стороны), `COLOR_YELLOW` и `2 * 3` остаются литералами
|
||||
|
||||
---
|
||||
|
||||
## Текущий статус (2026-06-05)
|
||||
|
||||
| Phase | Статус | Комментарий |
|
||||
|---|---|---|
|
||||
| 1 Plain text + nav | ✓ | загрузка, индексация, status/menu, ↑↓/PgUp/PgDn/Home/End/F1/F10/Esc |
|
||||
| 2 Headers + HR | ✓ | H1..H4, `---`/`***`/`___` (с ≥3 marker'ов) |
|
||||
| 3 Inline emphasis | ✓ | `**` / `*` / `_` / `` ` ``; XOR flanking (см. выше) |
|
||||
| 4 Lists / quote / fenced code | ✓ | `- / * / +`, `N. / N)`, `> `, ``` ``` ```; light nested lists |
|
||||
| 4-tables | ✗ | таблицы отложены вместе с Phase 6 |
|
||||
| 5 Wrap / Unwrap (F2) | ✓ | wrap-by-default; soft wrap; F2 переключает; hpan ←/→ в truncate-режиме |
|
||||
| 6 Полный layout таблиц | ✗ | deferred |
|
||||
| 7 Links + search | ✗ | deferred |
|
||||
| 8 F8 Raw toggle | ✗ | deferred |
|
||||
| Cache рендеренных строк | ✗ | не нужно по скорости |
|
||||
|
||||
**UX-поправки (отдельно от phase-плана, 2026-06-05):**
|
||||
- UI (menu + title bar) отрисовывается ДО `load_file`/`index_lines` — пользователь сразу видит интерфейс, а не чёрный экран
|
||||
- Title bar: `MDVIEW <spinner> <filename>` (3 пробела между MDVIEW и filename, slot спиннера — col 8)
|
||||
- Spinner крутится во время `load_file` (по странице) и `index_lines` (раз в 32 логических строки), включая `toggle_wrap`
|
||||
|
||||
---
|
||||
|
||||
## Архитектура
|
||||
@@ -16,11 +42,14 @@
|
||||
### Раскладка экрана (80×32, текст mode 0x03)
|
||||
|
||||
```
|
||||
Row 0: ┃ mdview.md L 1-30 / 142 21% ┃ ← status bar (BG=blue, FG=white)
|
||||
Row 1: ┃ ┃
|
||||
... ┃ document viewport (30 rows) ┃
|
||||
Row 30: ┃ ┃
|
||||
Row 31: ┃ F1 Help F10 Exit┃ ← menu bar (BG=blue, FG=cyan)
|
||||
Row 0: ┃ MDVIEW │ mdview.md │ L 1-30 / 142 │ 21% ┃ ← status bar (BG=blue, FG=white)
|
||||
▲ ▲
|
||||
│ └── filename @ col 10
|
||||
└────────── spinner slot @ col 8 (anim. while busy)
|
||||
Row 1: ┃ ┃
|
||||
... ┃ document viewport (30 rows) ┃
|
||||
Row 30: ┃ ┃
|
||||
Row 31: ┃ F1 Help F2 Wrap F10 Exit ┃ ← menu bar (BG=blue, FG=cyan)
|
||||
```
|
||||
|
||||
- Viewport = 30 строк × 80 столбцов.
|
||||
@@ -34,15 +63,16 @@ Memory mode: **`small`** — DSS отводит под наш образ **дв
|
||||
W0 (0x0000-0x3FFF): ESTEX (system, untouchable)
|
||||
W1 (0x4000-0x7FFF): CODE (small mode page 1)
|
||||
W2 (0x8000-0xBFFF): DATA + STACK + HEAP (small mode page 2)
|
||||
W3 (0xC000-0xFFFF): paged window — переключается между EMM-страницами:
|
||||
├── file page: исходный текст .md файла (16 KB)
|
||||
└── cache page: кэш отформатированных строк (Phase 3+)
|
||||
W3 (0xC000-0xFFFF): paged window — лениво переключается между EMM-страницами
|
||||
файла (до 8 страниц = 128 KB). `cur_page` кэширует
|
||||
текущую mapping, `fb(p)` маппит нужную страницу при
|
||||
первом обращении.
|
||||
```
|
||||
|
||||
Почему small + W3:
|
||||
- 32 KB на код+данные с большим запасом → нет банкинга
|
||||
- W3 — стандартный paged window, под него у нас уже есть `bank_io_w3` API
|
||||
- v2-расширение (multi-page файлы >16 KB): просто `mem_alloc_pages(N)` и переключение страниц в W3 через `sprinter_page_w3()`
|
||||
- Файлы до 128 KB поддерживаются нативно: `mem_alloc_pages(pages_needed)` под весь файл; `map_page()` через `sprinter_page_w3()`; `fb(p)` — единая точка доступа из индексатора и рендера.
|
||||
|
||||
Статики (в W2):
|
||||
- `line_offset[MAX_LINES]` — uint16_t смещение каждой строки в файловой странице (4 KB на 2048 строк)
|
||||
@@ -65,7 +95,7 @@ main → open() → read() chunks 1KB → write to W1 (mapped EMM page) → clos
|
||||
|
||||
## Реализация — поэтапная
|
||||
|
||||
### Phase 1 — Plain text viewer (MVP)
|
||||
### Phase 1 — Plain text viewer (MVP) ✓
|
||||
|
||||
**Что работает:**
|
||||
- Загрузка файла (`open/read/close`) в W1-страницу
|
||||
@@ -81,7 +111,7 @@ main → open() → read() chunks 1KB → write to W1 (mapped EMM page) → clos
|
||||
- `examples/mdview/Makefile`
|
||||
- `examples/mdview/SAMPLE.MD` — тестовый markdown файл
|
||||
|
||||
### Phase 2 — Headers и горизонтальная линия
|
||||
### Phase 2 — Headers и горизонтальная линия ✓
|
||||
|
||||
**MD фичи:**
|
||||
- `# H1` → ярко-жёлтый (COLOR_YELLOW = 14) на чёрном
|
||||
@@ -90,7 +120,7 @@ main → open() → read() chunks 1KB → write to W1 (mapped EMM page) → clos
|
||||
- `#### H4+` → серый (COLOR_GREY = 8)
|
||||
- `---` / `***` на отдельной строке → линия 0xC4 (горизонтальная рамка ASCII) во всю ширину
|
||||
|
||||
### Phase 3 — Inline emphasis
|
||||
### Phase 3 — Inline emphasis ✓
|
||||
|
||||
**Парсер inline (per-line, runs в одну строку):**
|
||||
- `**bold**` → ATTR_TEXT_BOLD
|
||||
@@ -99,12 +129,23 @@ main → open() → read() chunks 1KB → write to W1 (mapped EMM page) → clos
|
||||
- `` `code` `` → ATTR_TEXT_CODE
|
||||
- Маркеры `**`/`*`/`_`/`` ` `` НЕ рендерятся (съедаются)
|
||||
|
||||
State machine: один активный стиль одновременно (без вложенности); конфликтующий маркер при чужом активном стиле уходит литералом. Состояние сбрасывается на каждой строке.
|
||||
State machine: один активный стиль одновременно (без вложенности); конфликтующий маркер при чужом активном стиле всё равно консьюмится (zero-width) для синхронизации ширины с index_lines. Состояние сбрасывается на каждой строке.
|
||||
|
||||
**Flanking-правило (CommonMark intraword, реализовано после изначального плана):**
|
||||
- `*` / `**` / `_` считаются markdown-маркером только если whitespace/EOL
|
||||
ровно с ОДНОЙ стороны (XOR).
|
||||
- Случаи "оба whitespace" (`2 * 3`, `2 ** 3`) → литералы (арифметика).
|
||||
- Случаи "ни одного whitespace" (`COLOR_YELLOW`, `FILE*/fread`, `foo*bar*baz`)
|
||||
→ литералы (intraword).
|
||||
- Backtick (`` ` ``) flanking НЕ требует — `` `code` `` работает без пробелов.
|
||||
- Правило применено симметрично в 4 местах (`index_lines`, cont-render,
|
||||
основной inline-парсер, truncation peek), иначе wrap-индексатор и
|
||||
рендер разъедутся по ширине.
|
||||
|
||||
> **Кэш отформатированных строк** — отложен в самый конец, см. "Phase ∞: оптимизации".
|
||||
> Скорости текущего наивного рендера хватает на 80×30 = 2400 wrchar / кадр; PgUp/PgDn визуально мгновенен.
|
||||
|
||||
### Phase 4 — Block elements
|
||||
### Phase 4 — Block elements ✓ (без таблиц)
|
||||
|
||||
- Маркированные списки: `- foo`, `* foo`, `+ foo` → префикс `•` (0x07) + пробел; цвет маркера ярче основного
|
||||
- Нумерованные списки: `1. foo`, `2. foo` → как есть (число оставляем)
|
||||
@@ -138,10 +179,11 @@ State machine: один активный стиль одновременно (б
|
||||
≥ content_col родителя, иначе считается breakout. Нужен мини-stack
|
||||
активных списков при индексации.
|
||||
|
||||
### Phase 5 — Wrap / Unwrap длинных строк
|
||||
### Phase 5 — Wrap / Unwrap длинных строк ✓
|
||||
|
||||
Дефолт: **wrap on**. F2 переключает; в меню-баре подпись отражает действие
|
||||
("Unwrap" когда wrap включён, "Wrap" когда выключен).
|
||||
("Unwrap" когда wrap включён, "Wrap" когда выключен). Во время реиндексации
|
||||
крутится спиннер на title bar.
|
||||
|
||||
**v1 — реализовано:**
|
||||
- Один массив `line_offset[2048]` хранит ВИДИМЫЕ сегменты (а не логические
|
||||
@@ -519,9 +561,10 @@ Cache tags (W2 static): uint16_t cache_tag[100] = 200 bytes
|
||||
|
||||
## Что отложено в v2
|
||||
|
||||
- Файлы >16 KB: многостраничное хранение через `mem_alloc_pages(N)`, ленивая загрузка страниц в W3 при доступе.
|
||||
- ~~Файлы >16 KB~~ — **сделано в v1.5** (до 128 KB через 1–8 EMM-страниц + lazy map в W3).
|
||||
- ~~Word wrap~~ — **сделано** (Phase 5, F2 toggle).
|
||||
- Search (Find / Find next) — F3 / F4.
|
||||
- Toggle highlight on/off — F2.
|
||||
- Word wrap.
|
||||
- Image alt-text rendering.
|
||||
- Tables.
|
||||
- F8 Raw / Render toggle — спецификация в Phase 8.
|
||||
- Links `[text](url)` + image alt — Phase 7.
|
||||
- Tables — Phase 6 (полный layout).
|
||||
- Toggle highlight on/off — частный случай F8 Raw.
|
||||
|
||||
Reference in New Issue
Block a user