diff --git a/packages/core/src/processor/completer/Completer.ts b/packages/core/src/processor/completer/Completer.ts index a07028697..d156bb9e7 100644 --- a/packages/core/src/processor/completer/Completer.ts +++ b/packages/core/src/processor/completer/Completer.ts @@ -92,6 +92,13 @@ export namespace CompletionItem { export function escape(textToInsert: string): string { return textToInsert.replace(/([\\$}])/g, '\\$1') } + + /** + * Un-escape `$`, `\`, and `}` in `textToInsert` + */ + export function unescape(textToInsert: string): string { + return textToInsert.replace(/\\([\\$}])/g, '$1') + } } export class InsertTextBuilder { diff --git a/packages/core/src/processor/completer/builtin.ts b/packages/core/src/processor/completer/builtin.ts index bed9fa9de..cee08a53a 100644 --- a/packages/core/src/processor/completer/builtin.ts +++ b/packages/core/src/processor/completer/builtin.ts @@ -283,7 +283,10 @@ export function escapeString(value: string, quote?: Quote) { if (!quote) { return value } - return value.replaceAll('\\', '\\\\').replaceAll(quote, '\\"') + // Un-escape and then re-escape completion + value = CompletionItem.unescape(value) + value = value.replaceAll('\\', '\\\\').replaceAll(quote, '\\"') + return CompletionItem.escape(value) } export const symbol: Completer = (node, ctx) => {