diff options
| author | eunhhu <[email protected]> | 2026-10-18 22:11:19 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-18 22:11:19 +0100 |
| commit | da79f1e2b8d49dabe2290f5d795f8809c8b15c0f (patch) | |
| tree | b20972e242544a22bd77e22f1eb5bcd65ff5b928 | |
| parent | 4d9598e7d0d6d45bf3db9305d365bd2967481bcd (diff) | |
| download | vega-da79f1e2b8d49dabe2290f5d795f8809c8b15c0f.tar.gz vega-da79f1e2b8d49dabe2290f5d795f8809c8b15c0f.zip | |
Show views of any value (Pure 027's 4e): a list view is a list or a table (a list state as it is a table of its record's fields), a list in a cell shows how many items it holds, bytes their hex digits, on every surface
| -rw-r--r-- | surfaces/screen.c | 36 | ||||
| -rw-r--r-- | tests/check.py | 50 |
2 files changed, 82 insertions, 4 deletions
diff --git a/surfaces/screen.c b/surfaces/screen.c index 6f5aeb7..eeaaa8d 100644 --- a/surfaces/screen.c +++ b/surfaces/screen.c @@ -61,7 +61,7 @@ void vega_screen(VegaScreen *screen, const PureModule *m) { /* A <table>_focus view belongs to its table, not to the fields. */ bool focus_view[PURE_MODULE_VIEWS] = {false}; for (uint32_t i = 0; i < m->views; ++i) { - if (m->view_type[i] != PURE_VIEW_TABLE) continue; + if (m->view_type[i] != PURE_VIEW_LIST || m->view_table[i]) continue; char name[PURE_MODULE_NAME + 8]; snprintf(name, sizeof(name), "%s_focus", m->view_names[i]); int focus = pure_module_view(m, name); @@ -72,7 +72,7 @@ void vega_screen(VegaScreen *screen, const PureModule *m) { VegaPart *part = &screen->parts[screen->count++]; *part = (VegaPart){.kind = VEGA_FIELD, .view = i, .focus = -1, .pointer = -1, .label = -1, .tone = -1, .detail = -1, .badge = -1}; - if (m->view_type[i] != PURE_VIEW_TABLE) continue; + if (m->view_type[i] != PURE_VIEW_LIST) continue; char name[PURE_MODULE_NAME + 8]; snprintf(name, sizeof(name), "%s_focus", m->view_names[i]); part->focus = pure_module_view(m, name); @@ -111,11 +111,11 @@ unsigned vega_check(const PureModule *m, void (*report)(void *, const char *name char table[PURE_MODULE_NAME]; snprintf(table, sizeof(table), "%.*s", (int)(length - 6), view); int owner = pure_module_view(m, table); - if (!is_view(m, owner, PURE_VIEW_TABLE)) + if (!is_view(m, owner, PURE_VIEW_LIST)) FIND("names no list or table %s; it shows as a field", table); else if (m->view_type[i] != PURE_VIEW_NUM) FIND("the focused row is a number; %s shows no focus", table); } - if (m->view_type[i] != PURE_VIEW_TABLE) continue; + if (m->view_type[i] != PURE_VIEW_LIST) continue; int label = pure_module_column(m, i, "label"), tone = pure_module_column(m, i, "tone"); bool list = is_view(m, label, PURE_VIEW_TEXT); unsigned shown = 0; @@ -149,6 +149,15 @@ unsigned vega_check(const PureModule *m, void (*report)(void *, const char *name typedef struct { char *out; size_t used; } Collect; +/* Bytes, as many as their hex digits fit in a value's text. */ +static bool collect_bytes(void *context, PureSpan span) { + Collect *c = context; + size_t room = (VEGA_TEXT - 1) / 2 - c->used, take = span.size < room ? span.size : room; + if (take) memcpy(c->out + c->used, span.data, take); + c->used += take; + return true; +} + static bool collect(void *context, PureSpan span) { Collect *c = context; size_t room = VEGA_TEXT - 1 - c->used; @@ -172,6 +181,25 @@ bool vega_text(PureApp *app, uint32_t view, size_t row, char out[VEGA_TEXT], siz *length = (size_t)snprintf(out, VEGA_TEXT, "%" PRId64, value); return true; } + if (m->view_type[view] == PURE_VIEW_LIST) { /* a list cell (027's 4e): how many items it holds */ + PureSpan items; + PureCell cells[PURE_RECORD_FIELDS]; + size_t count = 0, at = 0; + if (!column || pure_app_cell_items(app, view, row, &items) != PURE_OK) return false; + while (pure_items_next(m, m->view_record[view] - 1u, items, &at, cells)) ++count; + *length = (size_t)snprintf(out, VEGA_TEXT, "%zu item%s", count, count == 1 ? "" : "s"); + return true; + } + if (m->view_type[view] == PURE_VIEW_BYTES) { /* as hex digits, as Pure's tools write bytes */ + char bytes[VEGA_TEXT / 2]; + Collect c = {bytes, 0}; + PureResult result = column ? pure_app_cell_text(app, view, row, collect_bytes, &c) + : pure_app_view_text(app, view, collect_bytes, &c); + for (size_t i = 0; i < c.used; ++i) snprintf(out + 2 * i, 3, "%02x", (unsigned char)bytes[i]); + *length = 2 * c.used; + out[*length] = 0; + return result == PURE_OK; + } if (m->view_type[view] == PURE_VIEW_NUM || m->view_type[view] == PURE_VIEW_BOOL) { double value; if (!(column ? pure_app_cell(app, view, row, &value) : pure_app_view(app, view, &value))) return false; diff --git a/tests/check.py b/tests/check.py index b9f9572..6093556 100644 --- a/tests/check.py +++ b/tests/check.py @@ -1989,6 +1989,55 @@ def integers(vega, aup, work): return len(out) + len(dump) + len(said) +LISTS_APP = """use vega +record Tag { + v: i64 +} +record Note { + name: text + raw: bytes + tags: list of Tag +} +state notes: list of Note +input add = key Space +on add.down { + let tags: list of Tag + for i in 0 .. notes.count + 1 { + tags.append(Tag { v: i64(i) }) + } + notes.append(Note { name: "n{notes.count}", raw: bytes("a{notes.count}"), tags: tags }) +} +view mark = bytes("zz") +view all = notes +""" + + +def lists_and_bytes(vega, aup, work): + """Views of any value (Pure 027's 4e) on every surface: a list state as it + is is a table of its record's fields, a list in a cell shows how many + items it holds, bytes their hex digits.""" + source, module = work / 'lists.aup', work / 'lists.pmod' + source.write_text(LISTS_APP) + built = run(aup, 'build', source, '-o', module, env=dict(os.environ, AUP_PATH=str(ROOT / 'lib'))) + assert built.returncode == 0, built.stderr + script = 'key Space\nkey Space\nshow\n' + out = run(vega, 'cli', module, stdin=script).stdout.splitlines() + assert out == ['mark: 7a7a', 'all (2)', ' name raw tags', '> n0 6130 1 item', ' n1 6131 2 items'], out + dump = run(vega, 'tui', module, '--dump', '40x8', stdin=script).stdout.splitlines() + assert all(line in dump for line in ['|mark 7a7a\tmuted', '>> n0 6130 1 item', '| n1 6131 2 items']), dump + said = run(vega, 'say', module, stdin=script).stdout.splitlines() + assert all(line in said for line in ['mark: 7a7a.', 'Item 1 of 2: name n0, raw 6130, tags 1 item.']), said + surface = WebSurface(vega, module) + try: + for _ in range(2): surface.call('POST', '/key', 'Space') + screen = json.loads(surface.call('GET', '/screen?rows=5')[1]) + finally: + surface.stop() + assert screen['fields'] == [{'name': 'mark', 'text': '7a7a'}], screen['fields'] + assert [item['cells'] for item in screen['parts'][0]['items']] == [['n0', '6130', '1 item'], ['n1', '6131', '2 items']], screen + return len(out) + len(dump) + len(said) + + def main(): parser = argparse.ArgumentParser() parser.add_argument('--vega', type=Path, required=True) @@ -2021,6 +2070,7 @@ def main(): report['split_list_lines'] = split(vega, modules['today'], work, range(args.seeds)) report['bool_lines'] = bools(vega, aup, work) report['i64_lines'] = integers(vega, aup, work) + report['list_and_bytes_lines'] = lists_and_bytes(vega, aup, work) report['painted_frames'], report['first_paint_bytes'], report['later_paint_bytes'] = \ painting(vega, modules['todo'], range(args.seeds), [(40, 12), (24, 9), (80, 30)]) report['web_screens'] = web(vega, modules['todo'], work, range(args.seeds)) |
