Skip to content

Commit f2396f5

Browse files
disconcisionclaude
andcommitted
ProbeProj: add Pin enclosing call for non-application probes
When a probe is inside a function body but not on a call site, there was no way to restrict samples to a single invocation. Add focus_call which uses the sample call_stack directly as the pinned_stack (vs pin_call which prepends the ap_id). Available via context menu (Pin enclosing call), meta-click, or p key. Existing pin on application probes renamed to Pin this call. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fa150c1 commit f2396f5

File tree

1 file changed

+49
-5
lines changed

1 file changed

+49
-5
lines changed

src/haz3lcore/projectors/implementations/ProbeProj.re

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,13 @@ let pin_call = (ctx: probe_ctx) =>
354354
| _ => Effect.Ignore
355355
};
356356

357+
let focus_call = (ctx: probe_ctx) =>
358+
switch (Dynamics.Info.is_in(ctx.dynamics)) {
359+
| Some(sample) when sample.call_stack != [] =>
360+
ctx.parent(SampleCursor(TogglePin(sample.call_stack)))
361+
| _ => Effect.Ignore
362+
};
363+
357364
/* Find the largest budget whose rendered width fits within target_width.
358365
* width_at(b) returns the rendered width for budget b. */
359366
let find_best_budget = (width_at: int => int, target_width: int): int => {
@@ -444,7 +451,9 @@ let value_view =
444451
),
445452
Attr.on_double_click(_ => local(ToggleWindowMode)),
446453
Attr.on_pointerdown(evt =>
447-
Key.meta_held(evt) ? pin_call(ctx) : val_pointerdown(evt)
454+
Key.meta_held(evt)
455+
? Option.is_some(ctx.ap_id) ? pin_call(ctx) : focus_call(ctx)
456+
: val_pointerdown(evt)
448457
),
449458
Attr.on_pointerup(val_pointerup),
450459
Attr.on_mousemove(val_mousemove),
@@ -483,8 +492,17 @@ let show_pin = (ctx: probe_ctx, sample: Sample.t) => {
483492
};
484493
};
485494

495+
let show_focus = (ctx: probe_ctx, sample: Sample.t) =>
496+
switch (ctx.ap_id, ctx.dynamics.sample_cursor.pinned_stack) {
497+
| (None, Some(pinned_stack)) =>
498+
Sample.ids_of_stack(pinned_stack)
499+
== Sample.ids_of_stack(sample.call_stack)
500+
| _ => false
501+
};
502+
486503
let pin_view = (ctx: probe_ctx, sample: Sample.t) =>
487-
show_pin(ctx, sample) ? [div(~attrs=[Attr.classes(["pin"])], [])] : [];
504+
show_pin(ctx, sample) || show_focus(ctx, sample)
505+
? [div(~attrs=[Attr.classes(["pin"])], [])] : [];
488506

489507
/* Generate unique dropdown ID for a sample */
490508
let dropdown_id = (sample_id: int): string =>
@@ -518,7 +536,24 @@ let pin_action = (ctx: probe_ctx, sample: Sample.t) => {
518536
],
519537
[
520538
div(~attrs=[Attr.classes(["pin-icon"])], []),
521-
text(is_pinned ? "Unpin" : "Pin"),
539+
text(is_pinned ? "Unpin this call" : "Pin this call"),
540+
span(~attrs=[Attr.classes(["shortcut"])], [text("P")]),
541+
],
542+
);
543+
};
544+
545+
let focus_action = (ctx: probe_ctx, sample: Sample.t) => {
546+
let is_focused = show_focus(ctx, sample);
547+
div(
548+
~attrs=[
549+
Attr.classes(
550+
["action-item", "pin-action"] @ (is_focused ? ["pinned"] : []),
551+
),
552+
Attr.on_pointerdown(_ => focus_call(ctx)),
553+
],
554+
[
555+
div(~attrs=[Attr.classes(["pin-icon"])], []),
556+
text(is_focused ? "Unpin enclosing call" : "Pin enclosing call"),
522557
span(~attrs=[Attr.classes(["shortcut"])], [text("P")]),
523558
],
524559
);
@@ -557,6 +592,12 @@ let sample_context_actions =
557592
@ (can_step_into ? [step_into_action(ctx, sample, ap_id)] : []),
558593
),
559594
]
595+
| None when sample.call_stack != [] => [
596+
div(
597+
~attrs=[Attr.classes(["context-actions"])],
598+
[focus_action(ctx, sample)],
599+
),
600+
]
560601
| None => []
561602
};
562603

@@ -788,7 +829,8 @@ let hide_env = (statics: Language.Statics.Info.t): bool =>
788829
let sample_view =
789830
(ctx: probe_ctx, ~num_total, view_seg, local, sample: Sample.t) => {
790831
let hide_env = hide_env(ctx.statics);
791-
let has_dropdown = !(hide_env && ctx.ap_id == None);
832+
let has_dropdown =
833+
!(hide_env && ctx.ap_id == None) || sample.call_stack != [];
792834
div(
793835
~attrs=
794836
[Attr.classes(["sample"])]
@@ -1027,10 +1069,12 @@ let key_handler = (ctx: probe_ctx, ~id: Id.t, local, evt) => {
10271069
| D(" ") =>
10281070
Many([local(ToggleWindowMode), Stop_propagation, Prevent_default])
10291071
| D("p") =>
1030-
/* Pin/Unpin the indicated sample */
1072+
/* Pin/Unpin the indicated sample, or Focus/Unfocus for non-ap probes */
10311073
switch (indicated_sample(ctx), ap_id) {
10321074
| (Some(_), Some(_)) =>
10331075
Many([pin_call(ctx), Stop_propagation, Prevent_default])
1076+
| (Some(_), None) =>
1077+
Many([focus_call(ctx), Stop_propagation, Prevent_default])
10341078
| _ => Many([Stop_propagation, Prevent_default])
10351079
}
10361080
| D("Enter") =>

0 commit comments

Comments
 (0)