this repo has no description
1(** Individual code cell within an x-ocaml page.
2
3 A cell is a single code editor + output region embedded in the page. Each
4 cell has a {!mode} that controls its appearance and behaviour:
5
6 - {b Interactive}: visible, editable. The default for cells without a
7 [mode] attribute. Edits are ephemeral (lost on page refresh).
8 - {b Exercise}: visible, editable. The reader writes or modifies code here.
9 - {b Test}: visible, read-only. Contains assertions that validate exercise
10 code. Linked to an exercise cell and run automatically after it.
11 - {b Hidden}: invisible. Provides definitions (types, helpers) available to
12 subsequent cells without cluttering the page.
13
14 Cells form a linear chain via {!set_prev}. When a cell is run, all
15 preceding cells that haven't completed are run first, ensuring definitions
16 are available. The chain determines line-number offsets so error locations
17 map correctly to the page.
18
19 {2 Test linking}
20
21 A {!Test} cell can be linked to an {!Exercise} cell in two ways:
22
23 - {b Positional}: if no [data-for] is set, a test cell links to the nearest
24 preceding exercise cell.
25 - {b Explicit}: [data-for="some-id"] links to the exercise cell whose
26 [data-id] is ["some-id"], regardless of position.
27
28 Linking is established by the page-level orchestrator ({!Page}), not by the
29 cell itself. The cell exposes {!set_on_completed} so the page can register
30 a callback that triggers linked test cells after a successful run. *)
31
32(** {1 Mode} *)
33
34type mode =
35 | Interactive (** Visible, editable. Edits are ephemeral. *)
36 | Exercise (** Visible, editable. *)
37 | Test (** Visible, read-only. Linked to an exercise cell. *)
38 | Hidden (** Invisible. Provides definitions to later cells. *)
39
40val mode_of_string : string -> mode
41(** [mode_of_string s] parses a mode from an HTML attribute value.
42 Returns {!Interactive} for unrecognised strings. *)
43
44val string_of_mode : mode -> string
45(** [string_of_mode m] returns the canonical lowercase string for a mode. *)
46
47(** {1 Cell type} *)
48
49type t
50(** An individual code cell. Mutable: tracks execution status, editor state,
51 and position in the cell chain. *)
52
53(** {1 Creation} *)
54
55val init :
56 id:int ->
57 mode:mode ->
58 run_on:[ `Click | `Load ] ->
59 ?cell_id:string ->
60 ?cell_for:string ->
61 ?cell_env:string ->
62 ?filename:string ->
63 ?merlin:bool ->
64 ?extra_style:Jstr.t ->
65 ?inline_style:Jstr.t ->
66 eval_fn:(id:int -> line_number:int -> string -> unit) ->
67 fmt_fn:(id:int -> string -> unit) ->
68 post_fn:(X_protocol.request -> unit) ->
69 Webcomponent.t ->
70 t
71(** Create and initialise a cell.
72
73 Attaches a shadow DOM to the given web component, creates the CodeMirror
74 editor (unless the mode is {!Hidden}), and sets up the merlin integration
75 (unless [~merlin:false] is passed).
76
77 @param id Unique numeric identifier (typically the cell's position on page).
78 @param mode Determines editability and visibility.
79 @param run_on Whether to run automatically on page load or only on click.
80 @param cell_id Optional [data-id] attribute for test-linking targets.
81 @param cell_for Optional [data-for] attribute linking a test to an exercise.
82 @param cell_env Optional [data-env] for future environment scoping.
83 @param filename Optional filename for merlin and error reporting.
84 @param merlin Whether to enable merlin integration. Default [true];
85 set to [false] to disable completions and type-on-hover for this cell.
86 Has no effect on {!Hidden} cells, which never have merlin regardless.
87 @param extra_style URL to an external stylesheet to load.
88 @param inline_style Inline CSS for the [:host] selector.
89 @param eval_fn Called to evaluate code. Receives the cell [~id],
90 [~line_number] offset, and the source code string.
91 @param fmt_fn Called to format code. Receives the cell [~id] and source.
92 @param post_fn Called to send raw protocol messages (for merlin). *)
93
94(** {1 Accessors} *)
95
96val id : t -> int
97(** The cell's numeric identifier. *)
98
99val mode : t -> mode
100(** The cell's mode. *)
101
102val cell_id : t -> string option
103(** The [data-id] attribute, if set. Used as a target for [data-for] linking. *)
104
105val cell_for : t -> string option
106(** The [data-for] attribute, if set. Links a test cell to an exercise cell. *)
107
108val cell_env : t -> string option
109(** The [data-env] attribute, if set. Reserved for environment scoping. *)
110
111val source : t -> string
112(** The current source code. Reads from the CodeMirror editor if present,
113 otherwise from the internal text buffer (for hidden cells). *)
114
115val has_completed : t -> bool
116(** [true] if the cell has been run and completed successfully since the last
117 invalidation. *)
118
119(** {1 Execution} *)
120
121val run : t -> unit
122(** Run this cell. If preceding cells in the chain have not completed, they
123 are run first (cascading). Does nothing if the cell is already running. *)
124
125val loadable : t -> bool
126(** [true] if the cell's [run_on] is [`Load]. *)
127
128val completed_run : t -> X_protocol.output list -> unit
129(** Called by the backend when evaluation completes. Displays the output and
130 marks the cell as successfully run. If the next cell in the chain was
131 waiting, triggers it.
132
133 After marking the cell complete, fires any callback registered via
134 {!set_on_completed}. The callback fires after every completed run,
135 regardless of whether the output contains errors. *)
136
137val set_on_completed : t -> (t -> unit) -> unit
138(** [set_on_completed cell f] registers [f] to be called each time [cell]
139 completes a run. Used by {!Page} to trigger linked test cells after
140 an exercise cell finishes.
141
142 Replaces any previously registered callback. *)
143
144val set_stop_fn : t -> (unit -> unit) -> unit
145(** [set_stop_fn cell f] registers [f] to be called when the user clicks
146 "Stop" while the cell is running. Typically [f] resets the backend
147 and all cells. *)
148
149val reset_status : t -> unit
150(** Reset the cell to {!Not_run} state: clears output messages, restores
151 the "Run" button text, and resets test-result tracking flags.
152 Does {e not} invalidate the cell chain. *)
153
154(** {1 Chain management} *)
155
156val set_prev : prev:t option -> t -> unit
157(** [set_prev ~prev cell] sets [cell]'s predecessor in the execution chain.
158 Updates line-number offsets for all subsequent cells. The previous cell's
159 [next] pointer is updated as well. *)
160
161(** {1 Content and display} *)
162
163val set_source : t -> string -> unit
164(** Replace the cell's source code. Updates the editor if present. *)
165
166val add_message : t -> int -> X_protocol.output list -> unit
167(** [add_message cell loc msgs] adds output messages at character offset
168 [loc] in the cell's editor. No-op for hidden cells. *)
169
170val start : t -> Webcomponent.t -> unit
171(** [start cell element] reads the initial source from the element's
172 [textContent] and loads it into the cell. Called once after the
173 WebComponent's [connectedCallback]. *)
174
175(** {1 Merlin integration} *)
176
177val receive_merlin : t -> Protocol.answer -> unit
178(** Handle a merlin response for this cell. No-op if the cell has no
179 merlin worker. *)