aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-18 22:11:19 +0100
committereunhhu <[email protected]>2026-10-18 22:11:19 +0100
commitda79f1e2b8d49dabe2290f5d795f8809c8b15c0f (patch)
treeb20972e242544a22bd77e22f1eb5bcd65ff5b928
parent4d9598e7d0d6d45bf3db9305d365bd2967481bcd (diff)
downloadvega-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.c36
-rw-r--r--tests/check.py50
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))