diff options
| author | eunhhu <[email protected]> | 2026-09-26 10:54:12 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-26 10:54:12 +0100 |
| commit | b230b70252f09cf3425a8b4b959b3dfd72075b31 (patch) | |
| tree | 6ddae95ead87fa1905e133dbabf0f2d6a595efde /prototypes | |
| parent | d58e1d29cc3cbd5f1c9b271c0b7e25b9962fad4f (diff) | |
| download | pure-b230b70252f09cf3425a8b4b959b3dfd72075b31.tar.gz pure-b230b70252f09cf3425a8b4b959b3dfd72075b31.zip | |
Let a host point an index at an item
pure_app_point moves an index state to an item, as a user pointing at a
row would: an event with no handler, saved like a key event, joining the
burst when saving is deferred; past the last item it is not_found. A host
learns which index to move from the view that shows it:
pure_module_position gives the state behind a number view that is just
`at.position`. An interface can so turn a click on a list row into its
focus without any code in the app.
Diffstat (limited to 'prototypes')
| -rw-r--r-- | prototypes/connections/module.c | 20 | ||||
| -rw-r--r-- | prototypes/connections/module.h | 7 | ||||
| -rw-r--r-- | prototypes/connections/test-module.c | 32 |
3 files changed, 58 insertions, 1 deletions
diff --git a/prototypes/connections/module.c b/prototypes/connections/module.c index ebb746f..5e2b98f 100644 --- a/prototypes/connections/module.c +++ b/prototypes/connections/module.c @@ -522,6 +522,13 @@ int pure_module_view(const PureModule *m, const char *name) { return -1; } +int pure_module_position(const PureModule *m, uint32_t view) { + if (view >= m->views || m->view_type[view] != PURE_VIEW_NUM || m->view_table[view]) return -1; + const PureBlock *block = &m->view_code[view]; + const PureOp *code = &m->code[block->start]; + return block->length == 2 && code[0].op == PURE_OP_INDEX_LOAD && code[1].op == PURE_OP_INDEX_NUM ? (int)code[0].arg : -1; +} + int pure_module_column(const PureModule *m, uint32_t table, const char *name) { for (uint32_t i = 0; i < m->views; ++i) if (m->view_table[i] == table + 1 && !strcmp(m->view_names[i], name)) return (int)i; @@ -1121,6 +1128,19 @@ PureResult pure_app_input(PureApp *app, uint32_t input, PureEdge edge) { return dispatch(app, 1 + 2 * input + (edge == PURE_EDGE_UP), &ev); } +PureResult pure_app_point(PureApp *app, uint32_t state, size_t position) { + const PureModule *m = app->module; + pure_app_finish(app); + if (state >= m->states || m->state_type[state] != PURE_STATE_INDEX) return PURE_INVALID; + if (position >= pure_list_count(app->lists[m->state_ref[state]])) return PURE_NOT_FOUND; + open_burst(app); /* what a failed save returns to */ + app->fault = PURE_FAULT_NONE; + app->fault_pc = UINT32_MAX; + app->values[state] = (double)position; + ++app->events; + return app->deferred ? PURE_OK : pure_app_save(app); +} + PureResult pure_app_text(PureApp *app, uint32_t input, PureSpan text) { pure_app_finish(app); if (input >= app->module->inputs || app->module->input[input].kind != PURE_KIND_TEXT || diff --git a/prototypes/connections/module.h b/prototypes/connections/module.h index c9fb606..16b755c 100644 --- a/prototypes/connections/module.h +++ b/prototypes/connections/module.h @@ -106,6 +106,9 @@ int pure_module_state(const PureModule *, const char *name); int pure_module_input(const PureModule *, const char *name); int pure_module_view(const PureModule *, const char *name); int pure_module_column(const PureModule *, uint32_t table, const char *name); +/* The index state a number view shows as its position (a view that is just + * `at.position`), or -1: what a host moves with pure_app_point. */ +int pure_module_position(const PureModule *, uint32_t view); /* Keyed collections live in a data host (for example the tree store). One * event opens at most one document, the message's key, at its current @@ -189,6 +192,10 @@ bool pure_app_defer(PureApp *, bool deferred); void pure_app_stop(PureApp *); PureResult pure_app_frame(PureApp *); PureResult pure_app_input(PureApp *, uint32_t input, PureEdge); +/* Point an index state at the item at position (0 first), as a user pointing + * at a row: an event with no handler, saved like a key event. NOT_FOUND past + * the last item, INVALID for a state that is not an index. */ +PureResult pure_app_point(PureApp *, uint32_t state, size_t position); /* Deliver committed text (for example from an input method). Not UTF-8: invalid. */ PureResult pure_app_text(PureApp *, uint32_t input, PureSpan text); /* Deliver a message. base is the revision the sender edited, or -1 for none; diff --git a/prototypes/connections/test-module.c b/prototypes/connections/test-module.c index 6f48bc8..b0666fe 100644 --- a/prototypes/connections/test-module.c +++ b/prototypes/connections/test-module.c @@ -1714,6 +1714,35 @@ static void deferred(void) { deferred_messages(); } +/* A host points at an item: the index a view shows as its position moves + * there, as an event with no handler, saved like a key event; deferred, it + * joins the burst and a failed save undoes it with the rest. */ +static void pointing(void) { + CHECK(load(list_spec, &module_a) == PURE_OK); + CHECK(pure_module_position(&module_a, 1) == 2); /* position = at.position */ + CHECK(pure_module_position(&module_a, 0) == -1 && pure_module_position(&module_a, 2) == -1 && + pure_module_position(&module_a, 3) == -1 && pure_module_position(&module_a, 99) == -1); + char path[] = "/tmp/pure-point-XXXXXX"; + CHECK(mkdtemp(path) && pure_store_init(path) == PURE_OK); + PureApp app; + CHECK(pure_app_start(&app, &module_a, pure_tree_data(path)) == PURE_OK); + CHECK(pure_app_point(&app, 2, 0) == PURE_NOT_FOUND); /* nothing to point at */ + for (int i = 0; i < 3; ++i) CHECK(pure_app_text(&app, 0, (PureSpan){(const unsigned char *)"a", 1}) == PURE_OK); + uint64_t events = app.events; + CHECK(app.values[2] == 2 && pure_app_point(&app, 2, 0) == PURE_OK && app.values[2] == 0 && app.events == events + 1); + CHECK(pure_app_point(&app, 2, 3) == PURE_NOT_FOUND && app.values[2] == 0); + CHECK(pure_app_point(&app, 0, 1) == PURE_INVALID && pure_app_point(&app, 1, 1) == PURE_INVALID); /* a number, a list */ + CHECK(pure_app_point(&app, 2, 1) == PURE_OK); + pure_app_stop(&app); + CHECK(pure_app_start(&app, &module_a, pure_tree_data(path)) == PURE_OK && app.values[2] == 1); + CHECK(pure_app_defer(&app, true) && pure_app_point(&app, 2, 2) == PURE_OK && app.open && app.values[2] == 2); + CHECK(pure_app_save(&app) == PURE_OK); + pure_app_stop(&app); + CHECK(pure_app_start(&app, &module_a, pure_tree_data(path)) == PURE_OK && app.values[2] == 2); + pure_app_stop(&app); + remove_store(path); +} + int main(void) { behaviour(); faults(); @@ -1724,12 +1753,13 @@ int main(void) { texts(); text_mutations(); lists(); + pointing(); list_mutations(); tables(); table_mutations(); stored_states(); deferred(); printf("{\"sizeof_module\":%zu,\"sizeof_app\":%zu}\n", sizeof(PureModule), sizeof(PureApp)); - puts("{\"module_tests\":\"verified-load-atomic-events-faults-signed-zero-if-else-replace-by-name-rejections-mutations-messages-documents-typed-verification-text-cursors-utf8-views-rollback-replace-lists-indices-undo-migration-joins-tables-columns-pick-slide-stored-equivalence-crashes-frames-messages-migration-deferred-bursts\"}"); + puts("{\"module_tests\":\"verified-load-atomic-events-faults-signed-zero-if-else-replace-by-name-rejections-mutations-messages-documents-typed-verification-text-cursors-utf8-views-rollback-replace-lists-indices-undo-migration-joins-tables-columns-pick-slide-stored-equivalence-crashes-frames-messages-migration-deferred-bursts-pointing\"}"); return 0; } |
