Skip to content

Commit 5b5bee8

Browse files
Feat context-help: prioritize textExpression when present and open preview; fallback to preview-only when empty (#59)
1 parent 0bf1bee commit 5b5bee8

File tree

1 file changed

+102
-39
lines changed

1 file changed

+102
-39
lines changed

src/ccs/commands/contextHelp.ts

Lines changed: 102 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ export async function resolveContextExpression(): Promise<void> {
3232
const data = response ?? {};
3333

3434
if (typeof data === "string") {
35-
await handleContextHelpDocumentationContent(data);
35+
const { previewContent, textExpression } = extractEmbeddedContextExpression(data);
36+
37+
if (textExpression && textExpression.trim()) {
38+
await applyResolvedTextExpression(editor, document, selection, contextInfo, contextExpression, textExpression);
39+
}
40+
41+
await handleContextHelpDocumentationContent(previewContent);
3642
return;
3743
}
3844

@@ -49,43 +55,14 @@ export async function resolveContextExpression(): Promise<void> {
4955
}
5056

5157
if (isSuccessfulTextExpression(data)) {
52-
const hasGifCommand = /--gif\b/i.test(contextExpression);
53-
let normalizedTextExpression = data.textExpression.replace(/\r?\n/g, "\n");
54-
let gifUri: vscode.Uri | undefined;
55-
56-
if (hasGifCommand) {
57-
const extracted = extractGifUri(normalizedTextExpression);
58-
normalizedTextExpression = extracted.textWithoutGifUri;
59-
gifUri = extracted.gifUri;
60-
}
61-
62-
if (!hasGifCommand) {
63-
const eol = document.eol === vscode.EndOfLine.CRLF ? "\r\n" : "\n";
64-
const textExpression = normalizedTextExpression.replace(/\r?\n/g, eol);
65-
const formattedTextExpression = textExpression;
66-
67-
let rangeToReplace: vscode.Range;
68-
if (selection.isEmpty) {
69-
const fallbackLine = document.lineAt(selection.active.line);
70-
rangeToReplace = fallbackLine.range;
71-
} else {
72-
const start = document.lineAt(selection.start.line).range.start;
73-
const replacementEnd = contextInfo.replacementEnd ?? document.lineAt(selection.end.line).range.end;
74-
rangeToReplace = new vscode.Range(start, replacementEnd);
75-
}
76-
77-
await editor.edit((editBuilder) => {
78-
editBuilder.replace(rangeToReplace, formattedTextExpression);
79-
});
80-
}
81-
82-
if (gifUri) {
83-
try {
84-
await showGifInWebview(gifUri);
85-
} catch (error) {
86-
handleError(error, "Failed to open GIF from context expression.");
87-
}
88-
}
58+
await applyResolvedTextExpression(
59+
editor,
60+
document,
61+
selection,
62+
contextInfo,
63+
contextExpression,
64+
data.textExpression
65+
);
8966
return;
9067
}
9168

@@ -159,8 +136,56 @@ function extractGifUri(text: string): {
159136
return { textWithoutGifUri: processedLines.join("\n"), gifUri };
160137
}
161138

139+
async function applyResolvedTextExpression(
140+
editor: vscode.TextEditor,
141+
document: vscode.TextDocument,
142+
selection: vscode.Selection,
143+
contextInfo: ContextExpressionInfo,
144+
contextExpression: string,
145+
rawTextExpression: string
146+
): Promise<void> {
147+
const hasGifCommand = /--gif\b/i.test(contextExpression);
148+
let normalizedTextExpression = rawTextExpression.replace(/\r?\n/g, "\n");
149+
let gifUri: vscode.Uri | undefined;
150+
151+
if (hasGifCommand) {
152+
const extracted = extractGifUri(normalizedTextExpression);
153+
normalizedTextExpression = extracted.textWithoutGifUri;
154+
gifUri = extracted.gifUri;
155+
}
156+
157+
if (!hasGifCommand) {
158+
const eol = document.eol === vscode.EndOfLine.CRLF ? "\r\n" : "\n";
159+
const textExpression = normalizedTextExpression.replace(/\r?\n/g, eol);
160+
const formattedTextExpression = textExpression;
161+
162+
let rangeToReplace: vscode.Range;
163+
if (selection.isEmpty) {
164+
const fallbackLine = document.lineAt(selection.active.line);
165+
rangeToReplace = fallbackLine.range;
166+
} else {
167+
const start = document.lineAt(selection.start.line).range.start;
168+
const replacementEnd = contextInfo.replacementEnd ?? document.lineAt(selection.end.line).range.end;
169+
rangeToReplace = new vscode.Range(start, replacementEnd);
170+
}
171+
172+
await editor.edit((editBuilder) => {
173+
editBuilder.replace(rangeToReplace, formattedTextExpression);
174+
});
175+
}
176+
177+
if (gifUri) {
178+
try {
179+
await showGifInWebview(gifUri);
180+
} catch (error) {
181+
handleError(error, "Failed to open GIF from context expression.");
182+
}
183+
}
184+
}
185+
162186
async function handleContextHelpDocumentationContent(rawContent: string): Promise<void> {
163-
const sanitizedContent = sanitizeContextHelpContent(rawContent);
187+
const { previewContent } = extractEmbeddedContextExpression(rawContent);
188+
const sanitizedContent = sanitizeContextHelpContent(previewContent);
164189

165190
if (!sanitizedContent.trim()) {
166191
void vscode.window.showInformationMessage("A ajuda de contexto não retornou nenhum conteúdo.");
@@ -176,6 +201,44 @@ async function handleContextHelpDocumentationContent(rawContent: string): Promis
176201
await showContextHelpPreview(sanitizedContent);
177202
}
178203

204+
function extractEmbeddedContextExpression(content: string): {
205+
previewContent: string;
206+
textExpression?: string;
207+
} {
208+
const jsonPattern = /\{[\s\S]*\}\s*$/;
209+
const match = jsonPattern.exec(content);
210+
if (!match || match.index === undefined) {
211+
return { previewContent: content };
212+
}
213+
214+
const previewWithoutJson = content.slice(0, match.index).replace(/\s+$/, "");
215+
const jsonText = content.slice(match.index).trim();
216+
217+
try {
218+
const parsed = JSON.parse(jsonText);
219+
if (!isRecord(parsed)) {
220+
return { previewContent: previewWithoutJson };
221+
}
222+
223+
const { status, textExpression } = parsed as ResolveContextExpressionResponse;
224+
if (typeof status !== "string" || status.toLowerCase() !== "success") {
225+
return { previewContent: previewWithoutJson };
226+
}
227+
228+
if (typeof textExpression !== "string") {
229+
return { previewContent: previewWithoutJson };
230+
}
231+
232+
if (!textExpression.trim()) {
233+
return { previewContent: previewWithoutJson };
234+
}
235+
236+
return { previewContent: previewWithoutJson, textExpression };
237+
} catch (_error) {
238+
return { previewContent: content };
239+
}
240+
}
241+
179242
function sanitizeContextHelpContent(content: string): string {
180243
let sanitized = content.replace(/\{"status":"success","textExpression":""\}\s*$/i, "");
181244

0 commit comments

Comments
 (0)