diff --git a/packages/filesystem/src/browser/filesystem-preferences.ts b/packages/filesystem/src/browser/filesystem-preferences.ts index 2a363946610b1..706511f1a6d9d 100644 --- a/packages/filesystem/src/browser/filesystem-preferences.ts +++ b/packages/filesystem/src/browser/filesystem-preferences.ts @@ -96,6 +96,12 @@ export const filesystemPreferenceSchema: PreferenceSchema = { description: nls.localizeByDefault('When enabled, will trim trailing whitespace when saving a file.'), scope: 'language-overridable' }, + 'files.insertFinalNewline': { + type: 'boolean', + default: false, + description: nls.localizeByDefault('When enabled, insert a final new line at the end of the file when saving it.'), + scope: 'language-overridable' + }, 'files.maxConcurrentUploads': { type: 'integer', default: 1, @@ -117,6 +123,7 @@ export interface FileSystemConfiguration { 'files.participants.timeout': number 'files.maxFileSizeMB': number 'files.trimTrailingWhitespace': boolean + 'files.insertFinalNewline': boolean 'files.maxConcurrentUploads': number } diff --git a/packages/monaco/src/browser/monaco-editor-provider.ts b/packages/monaco/src/browser/monaco-editor-provider.ts index 75fa4dbcb049a..30412e5a1342e 100644 --- a/packages/monaco/src/browser/monaco-editor-provider.ts +++ b/packages/monaco/src/browser/monaco-editor-provider.ts @@ -268,6 +268,10 @@ export class MonacoEditorProvider { if (shouldRemoveWhiteSpace) { await editor.runAction('editor.action.trimTrailingWhitespace'); } + const insertFinalNewline = this.filePreferences.get({ preferenceName: 'files.insertFinalNewline', overrideIdentifier }, undefined, uri); + if (insertFinalNewline) { + this.insertFinalNewline(editor); + } return []; } @@ -452,4 +456,33 @@ export class MonacoEditorProvider { ) ) as MonacoDiffEditor; } + + protected insertFinalNewline(editor: MonacoEditor): void { + const model = editor.document && editor.document.textEditorModel; + if (!model) { + return; + } + + const lines = model?.getLineCount(); + if (lines === 0) { + return; + } + + const lastLine = model?.getLineContent(lines); + if (lastLine.trim() === '') { + return; + } + + const lastLineMaxColumn = model?.getLineMaxColumn(lines); + const range = { + startLineNumber: lines, + startColumn: lastLineMaxColumn, + endLineNumber: lines, + endColumn: lastLineMaxColumn + }; + model?.applyEdits([{ + range, + text: model?.getEOL() + }]); + } }