diff --git a/editors/code/src/snippets.ts b/editors/code/src/snippets.ts index fb12125bcd842..b3982bdf2be41 100644 --- a/editors/code/src/snippets.ts +++ b/editors/code/src/snippets.ts @@ -13,7 +13,7 @@ export async function applySnippetWorkspaceEdit( const [uri, edits] = unwrapUndefinable(editEntries[0]); const editor = await editorFromUri(uri); if (editor) { - edit.set(uri, edits); + edit.set(uri, removeLeadingWhitespace(editor, edits)); await vscode.workspace.applyEdit(edit); } return; @@ -48,7 +48,8 @@ async function editorFromUri(uri: vscode.Uri): Promise { + if (edit instanceof vscode.SnippetTextEdit) { + const snippetEdit: vscode.SnippetTextEdit = edit; + const firstLineEnd = snippetEdit.snippet.value.indexOf("\n"); + + if (firstLineEnd !== -1) { + // Is a multi-line snippet, remove the indentation which + // would be added back in by vscode. + const startLine = editor.document.lineAt(snippetEdit.range.start.line); + const leadingWhitespace = getLeadingWhitespace( + startLine.text, + 0, + startLine.firstNonWhitespaceCharacterIndex, + ); + + const [firstLine, rest] = splitAt(snippetEdit.snippet.value, firstLineEnd + 1); + const unindentedLines = rest + .split("\n") + .map((line) => line.replace(leadingWhitespace, "")) + .join("\n"); + + snippetEdit.snippet.value = firstLine + unindentedLines; + } + + return snippetEdit; + } else { + return edit; + } + }); +} + +// based on https://github.com/microsoft/vscode/blob/main/src/vs/base/common/strings.ts#L284 +function getLeadingWhitespace(str: string, start: number = 0, end: number = str.length): string { + for (let i = start; i < end; i++) { + const chCode = str.charCodeAt(i); + if (chCode !== " ".charCodeAt(0) && chCode !== " ".charCodeAt(0)) { + return str.substring(start, i); + } + } + return str.substring(start, end); +} + +function splitAt(str: string, index: number): [string, string] { + return [str.substring(0, index), str.substring(index)]; +}