diff options
| author | eunhhu <[email protected]> | 2026-09-25 15:24:05 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-25 15:24:05 +0100 |
| commit | 12c377ea70c8928f96d02d0885744bd6818c10c6 (patch) | |
| tree | e2ba24cb2cd61394ff84f605daa54d8c8e36a0d1 /docs/design/001-first-component.md | |
| parent | d9dbe8a1dbdd30f3e336dc1445d852ede3de3930 (diff) | |
| download | vega-12c377ea70c8928f96d02d0885744bd6818c10c6.tar.gz vega-12c377ea70c8928f96d02d0885744bd6818c10c6.zip | |
Add the first component and three surfaces
Vega reads a verified Pure module by convention: a table view with a
label column is a list (with optional badge, detail and tone), any other
table is a table, <table>_focus is its focused row, a title view is the
title and other views are fields. lib/vega.aup gives aup apps the tones,
which say what a row means; each surface decides how it looks or sounds.
vega tui draws the screen in a terminal, keeps the focused row in view
and evaluates only the cells on screen; vega cli prints plain lines for
pipes; vega say speaks the screen and each focus change as sentences.
Display width handles Hangul, CJK, emoji, combining marks and controls.
tests/check.py compares the CLI and NUI output with a reference model of
examples/todo.aup line for line, checks 9,600 TUI frames for scrolling,
focus, badge alignment and the number of cells evaluated, drives the
interactive TUI on a pseudo-terminal, and runs every aup example on every
surface.
Diffstat (limited to 'docs/design/001-first-component.md')
| -rw-r--r-- | docs/design/001-first-component.md | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/docs/design/001-first-component.md b/docs/design/001-first-component.md new file mode 100644 index 0000000..434c0fe --- /dev/null +++ b/docs/design/001-first-component.md @@ -0,0 +1,66 @@ +# 001 — 첫 컴포넌트: 목록·표·포커스·톤, 표면 셋 + +2026-09-25. 상태: 구현(`src/`, `lib/vega.aup`, `examples/`). + +## 결정 + +Vega의 명세는 **새 언어나 위젯 트리가 아니라 aup 규약**이다. 앱은 aup로 상태와 보기를 선언하고, +Vega는 검증된 Pure 모듈의 보기를 이름과 타입으로 읽어 인터페이스 부품으로 해석한다. 인터페이스용 +화면 모델을 따로 만들지 않고, 표면은 Pure에 보이는 칸만 물어 그린다. + +| 모듈에 있는 것 | Vega가 읽는 부품 | +|---|---| +| text 보기 `title` | 화면 제목 | +| `label` text 열이 있는 표 보기 | **목록**. 행마다 `label`, 선택적으로 `badge`(text), `detail`(text), `tone`(수) | +| `label` 열이 없는 표 보기 | **표**. `tone`을 뺀 모든 열이 차례로 보인다 | +| 수 보기 `<표 이름>_focus` | 그 목록·표의 포커스 행(0부터) | +| 그 밖의 수·text 보기 | **필드**. 이름과 값 | +| 키 입력과 그 핸들러 | 표면이 보여 주는 키 목록 | +| 첫 text 입력 | 입력 줄(TUI), 스크립트의 `text` 명령 | + +톤은 의미다(`lib/vega.aup`: `normal muted accent good warning danger`, `vega.when(조건, 톤)`). 색과 소리는 표면이 +정한다. 지원하지 않는 표현은 다른 의미로 바꾸지 않고 드러낸다. 색이 없는 CLI는 톤을 `(danger)`처럼 글자로 적는다. + +```text +use vega +view tasks_list = each task in tasks { + label = task.title + badge = if task.done { "done" } else if task.urgent { "urgent" } else { "" } + tone = if task.done { vega.muted } else { vega.when(task.urgent, vega.danger) } +} +view tasks_list_focus = at.position +``` + +## 표면 + +| 표면 | 명령 | 하는 일 | +|---|---|---| +| TUI | `vega tui app.pmod` | 대체 화면, 원시 입력. 제목·필드·목록·표·키 목록·입력 줄. 포커스 행을 최소 스크롤로 화면에 두고 **보이는 행의 칸만** 계산한다. 크기 변경(SIGWINCH), frame 핸들러가 있으면 60 Hz | +| CLI | `vega cli app.pmod < script` | 파이프용 평문. 목록은 `> ` 표시와 `[badge]`, 표는 표시 폭으로 정렬한 열. 터미널이고 `NO_COLOR`가 없을 때만 색 | +| NUI | `vega say app.pmod < script` | 문장. 이벤트마다 포커스 항목을 말하고(`Item 2 of 3: danger, milk, urgent.`), 실패하면 `Could not toggle.`, `show`에서 화면 전체 | + +TUI 입력: 앱에 text 입력이 있으면 처음에는 글자가 입력 줄로 가고 Enter가 확정한다(IME 확정분과 같은 의미). +Tab이 키 모드로 바꾸면 글자·숫자·Space가 `KeyA`·`Digit0`·`Space` 입력이 된다(앱이 Tab을 쓰면 Tab은 앱의 것). +화살표·Delete·Home 같은 키는 두 모드 모두 앱으로 간다. Ctrl-C나 Ctrl-Q로 끝내고 터미널을 되돌린다. + +표시 폭은 Vega가 맡는다. 한글·CJK·그림 이모지는 두 칸, 결합 문자·변이 선택자·ZWJ는 0칸, 제어 문자는 +제어 그림(U+2400대)으로 보인다. grapheme 단위 자르기는 아직 없어 ZWJ 이모지 묶음은 근사다. + +## 검증 (`make check`) + +- `examples/todo.aup`에 무작위 추가·이동·토글·긴급·삭제 스크립트를 주고, CLI 출력과 NUI 문장이 앱과 Vega 규약의 + Python 참조 모델과 줄 단위로 같다(8시드, 약 8,000줄, 빈 목록에서 실패하는 이벤트 약 200건 포함). +- TUI 프레임 9,600개(40×12, 24×9, 80×30, 16×6)에서 보이는 행 범위와 최소 스크롤, 포커스 행, 마지막 열에서 끝나는 배지, + 말줄임, 행 톤이 모델과 같다. 프레임마다 계산한 칸 수가 `제목 + 필드 + 포커스 2회 + 보이는 행 × 3`과 정확히 같다. + 2,000항목 목록도 한 프레임에 25칸만 계산한다. +- `examples/scores.aup`의 표가 표시 폭으로 정렬되고(한글·결합 문자 포함) 행 톤이 표시된다. +- 가상 터미널에서 대화형 TUI를 실제로 띄워 입력·확정·키 모드·종료·터미널 복원을 확인한다. +- aup와 Vega의 예제 11개를 세 표면에 무작위 입력으로 돌려 비정상 종료가 없다. sanitizer 빌드로도 같은 검사를 통과한다. + +## 남은 것 + +- 규약 오류를 조용히 넘기지 않기: `label`이 수인 목록, 표에 없는 `_focus` 같은 것을 `vega check`로 알린다. +- 포커스를 표면에서 바꾸기(GUI 클릭, TUI 마우스). 지금은 앱의 키 핸들러만 포커스를 옮긴다. Pure에 표의 인덱스를 + 이벤트로 바꾸는 호스트 API가 필요하다. +- 셀 단위 갱신(TUI는 매 변경마다 전체를 다시 그린다), GUI 표면, 음성 합성으로 가는 NUI. +- 문장의 언어. 지금 NUI의 틀 문장은 영어이고 값은 앱의 text 그대로다. |
