| 1 | #nullable enable |
| 2 | |
| 3 | using CascadeIDE.Models; |
| 4 | using CascadeIDE.Models.Intercom; |
| 5 | |
| 6 | namespace CascadeIDE.Services; |
| 7 | |
| 8 | /// <summary> |
| 9 | /// Навигация по <see cref="AttachmentAnchor"/> в редакторе: reveal или select (ADR 0128 §8, 0130). |
| 10 | /// </summary> |
| 11 | public static class IntercomAttachmentNavigator |
| 12 | { |
| 13 | public static string Apply( |
| 14 | IIdeMcpActions actions, |
| 15 | IntercomSettings settings, |
| 16 | string? workspaceRoot, |
| 17 | AttachmentAnchor anchor, |
| 18 | bool? selectExplicit, |
| 19 | bool shiftSelect, |
| 20 | int? durationMs, |
| 21 | string? solutionPath = null) |
| 22 | { |
| 23 | var select = shiftSelect |
| 24 | || selectExplicit == true |
| 25 | || (selectExplicit is null && settings.Attachments.Code.DefaultNavigateSelects()); |
| 26 | |
| 27 | var plan = IntercomAttachmentRevealPlan.Create(anchor, workspaceRoot, solutionPath); |
| 28 | |
| 29 | if (plan.ResolveOutcome == IntercomAttachmentRevealPlan.OutcomeFileMissing) |
| 30 | return plan.Message; |
| 31 | |
| 32 | if (string.IsNullOrEmpty(plan.AbsoluteFilePath)) |
| 33 | return plan.Message; |
| 34 | |
| 35 | if (plan.Lines is { } range && !plan.OpenFileOnly) |
| 36 | { |
| 37 | if (select) |
| 38 | { |
| 39 | actions.SelectInEditor(plan.AbsoluteFilePath, range.Start.Value, 1, range.End.Value, 1); |
| 40 | return plan.Message.StartsWith("OK", StringComparison.Ordinal) |
| 41 | ? "OK (select)" |
| 42 | : plan.Message + " (select)"; |
| 43 | } |
| 44 | |
| 45 | actions.RevealEditorRange(plan.AbsoluteFilePath, range.Start.Value, range.End.Value, durationMs); |
| 46 | return plan.Message; |
| 47 | } |
| 48 | |
| 49 | actions.OpenFile(plan.AbsoluteFilePath); |
| 50 | return plan.Message; |
| 51 | } |
| 52 | } |
| 53 | |