Skip to content

Commit f87b859

Browse files
committed
more robust selection
1 parent aeea780 commit f87b859

File tree

6 files changed

+117
-13
lines changed

6 files changed

+117
-13
lines changed

src/haz3lcore/derived/TermData.re

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,29 @@ let get_term_rows =
9797
|> List.map(List.rev);
9898
(start.row, term_rows);
9999
};
100+
101+
let get_root_id_using_ranges =
102+
(s: Base.segment, data: t, measured: Measured.t): option(Id.t) => {
103+
let id_and_ranges =
104+
s
105+
|> List.filter_map((p: Piece.t) => {
106+
let id = Piece.id(p);
107+
let range_opt = extreme_measures(id, data, measured);
108+
Option.map(r => (id, r), range_opt);
109+
});
110+
ListUtil.max(
111+
((_, (start1, end1)), (_, (start2, end2))) =>
112+
switch (Point.comp(start1, start2)) {
113+
| Under => Direction.Left
114+
| Over => Direction.Right
115+
| Exact =>
116+
switch (Point.comp(end1, end2)) {
117+
| Under => Direction.Right
118+
| Over => Direction.Left
119+
| Exact => Direction.Right
120+
}
121+
},
122+
id_and_ranges,
123+
)
124+
|> Option.map(fst);
125+
};

src/util/ListUtil.re

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,3 +587,21 @@ let assoc_update = (key, f, assoc) => {
587587

588588
let remove_assoc = (key, assoc) =>
589589
List.filter(((k, _)) => k != key, assoc);
590+
591+
let max = (cmp: ('a, 'a) => Direction.t, xs: list('a)): option('a) => {
592+
switch (xs) {
593+
| [] => None
594+
| [x, ...xs] =>
595+
Some(
596+
List.fold_left(
597+
(current_max, candidate) =>
598+
switch (cmp(current_max, candidate)) {
599+
| Left => current_max
600+
| Right => candidate
601+
},
602+
x,
603+
xs,
604+
),
605+
)
606+
};
607+
};

src/web/app/editors/code/CodeEditable.re

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,24 @@ module View = {
227227

228228
module MouseState = Pointer.MkState();
229229

230-
let deco = (~syntax: CachedSyntax.t, ~z: Zipper.t, ~globals: Globals.t) => [
230+
let deco =
231+
(
232+
~expand_selection=false,
233+
~syntax: CachedSyntax.t,
234+
~globals: Globals.t,
235+
z: Zipper.t,
236+
) => [
231237
CaretDec.view(
232238
~measured=syntax.measured,
233239
~font_metrics=globals.font_metrics,
234240
z,
235241
),
236242
Arms.Indicated.term(~font_metrics=globals.font_metrics, ~syntax, z),
237-
Highlight.selection(
243+
(
244+
expand_selection
245+
? Highlight.selection_expanded(~term_data=syntax.term_data)
246+
: Highlight.selection
247+
)(
238248
~measured=syntax.measured,
239249
~shape_map=syntax.shape_map,
240250
~font_metrics=globals.font_metrics,
@@ -261,6 +271,7 @@ module View = {
261271
~selected: bool,
262272
~overlays: list(Node.t)=[],
263273
~dynamics: Language.Dynamics.Map.t,
274+
~expand_selection=?,
264275
model: Model.t,
265276
) => {
266277
/* Sync document-level click listener for closing context menu */
@@ -271,9 +282,10 @@ module View = {
271282
let edit_decos =
272283
selected
273284
? deco(
274-
~z=model.editor.state.zipper,
285+
~expand_selection?,
275286
~syntax=model.editor.syntax,
276287
~globals,
288+
model.editor.state.zipper,
277289
)
278290
@ [
279291
Arms.Refractors.all(

src/web/app/editors/decoration/Highlight.re

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,50 @@ let selection =
215215
),
216216
);
217217

218+
// Explands selection to make it a subtree of the exp
219+
let selection_expanded =
220+
(
221+
~measured: Measured.t,
222+
~shape_map: ProjectorCore.Shape.Map.t,
223+
~font_metrics: FontMetrics.t,
224+
~term_data: TermData.t,
225+
z: Zipper.t,
226+
) =>
227+
div_c(
228+
"selects",
229+
switch (
230+
TermData.get_root_id_using_ranges(
231+
z.selection.content,
232+
term_data,
233+
measured,
234+
)
235+
) {
236+
| None => []
237+
| Some(id) =>
238+
let seg = TermData.segment(id, term_data);
239+
switch (seg) {
240+
| None => []
241+
| Some(seg) =>
242+
of_segment(
243+
~measured,
244+
~shape_map,
245+
~font_metrics,
246+
~shape_init=Some(fst(Siblings.shapes(z.relatives.siblings))),
247+
~clss=["selected-expanded", Selection.buffer_cls(z.selection)],
248+
seg,
249+
)
250+
@ of_segment(
251+
~measured,
252+
~shape_map,
253+
~font_metrics,
254+
~shape_init=Some(fst(Siblings.shapes(z.relatives.siblings))),
255+
~clss=["selected", Selection.buffer_cls(z.selection)],
256+
z.selection.content,
257+
)
258+
};
259+
},
260+
);
261+
218262
let indicated_refractor =
219263
(
220264
~measured: Measured.t,

src/web/app/editors/result/StepperEditor.re

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ module View = {
157157
model: Model.t,
158158
) => {
159159
CodeSelectable.View.view(
160+
~expand_selection=true,
160161
~dynamics=Language.Dynamics.Map.empty,
161162
~signal=
162163
fun

src/web/app/editors/stepper/MissingStep.re

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,19 @@ module Update = {
162162
// hacky way to get a currently-selected id
163163
{
164164
let editor: CodeSelectable.Model.t = editor |> Calc.get_value;
165-
try({
166-
let zipper = editor.editor.state.zipper;
167-
let selection = zipper.selection.content;
168-
let skel = Segment.skel(selection);
169-
let root = Skel.root(skel);
170-
let idx = Aba.first_a(root);
171-
let piece = List.nth(selection, idx);
172-
let id = Piece.id(piece);
173-
Some(id);
174-
}) {
165+
try(
166+
{
167+
open OptUtil.Syntax;
168+
let zipper = editor.editor.state.zipper;
169+
let* id =
170+
TermData.get_root_id_using_ranges(
171+
zipper.selection.content,
172+
editor.editor.syntax.term_data,
173+
editor.editor.syntax.measured,
174+
);
175+
Some(id);
176+
}
177+
) {
175178
| _ => None
176179
};
177180
}

0 commit comments

Comments
 (0)