diff --git a/src/vs/editor/browser/config/migrateOptions.ts b/src/vs/editor/browser/config/migrateOptions.ts index 84abd167ef6a3..968f5281afb9e 100644 --- a/src/vs/editor/browser/config/migrateOptions.ts +++ b/src/vs/editor/browser/config/migrateOptions.ts @@ -89,6 +89,7 @@ registerSimpleEditorSettingMigration('hover', [[true, { enabled: true }], [false registerSimpleEditorSettingMigration('parameterHints', [[true, { enabled: true }], [false, { enabled: false }]]); registerSimpleEditorSettingMigration('autoIndent', [[false, 'advanced'], [true, 'full']]); registerSimpleEditorSettingMigration('matchBrackets', [[true, 'always'], [false, 'never']]); +registerSimpleEditorSettingMigration('renderFinalNewline', [[true, 'on'], [false, 'off']]); registerEditorSettingMigration('autoClosingBrackets', (value, read, write) => { if (value === false) { diff --git a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts index 6b0f1277a2e7c..92537ee51db94 100644 --- a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts +++ b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.ts @@ -11,6 +11,8 @@ import { Position } from 'vs/editor/common/core/position'; import { RenderingContext } from 'vs/editor/browser/view/renderingContext'; import { ViewContext } from 'vs/editor/common/viewModel/viewContext'; import * as viewEvents from 'vs/editor/common/viewEvents'; +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { editorDimmedLineNumber, editorLineNumbers } from 'vs/editor/common/core/editorColorRegistry'; export class LineNumbersOverlay extends DynamicViewOverlay { @@ -21,7 +23,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay { private _lineHeight!: number; private _renderLineNumbers!: RenderLineNumbersType; private _renderCustomLineNumbers!: ((lineNumber: number) => string) | null; - private _renderFinalNewline!: boolean; + private _renderFinalNewline!: 'off' | 'on' | 'dimmed'; private _lineNumbersLeft!: number; private _lineNumbersWidth!: number; private _lastCursorModelPosition: Position; @@ -140,40 +142,38 @@ export class LineNumbersOverlay extends DynamicViewOverlay { const lineHeightClassName = (platform.isLinux ? (this._lineHeight % 2 === 0 ? ' lh-even' : ' lh-odd') : ''); const visibleStartLineNumber = ctx.visibleRange.startLineNumber; const visibleEndLineNumber = ctx.visibleRange.endLineNumber; - const common = '
'; const lineCount = this._context.viewModel.getLineCount(); const output: string[] = []; for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) { const lineIndex = lineNumber - visibleStartLineNumber; - if (!this._renderFinalNewline) { - if (lineNumber === lineCount && this._context.viewModel.getLineLength(lineNumber) === 0) { - // Do not render last (empty) line - output[lineIndex] = ''; - continue; - } + const renderLineNumber = this._getLineRenderLineNumber(lineNumber); + + if (!renderLineNumber) { + output[lineIndex] = ''; + continue; } - const renderLineNumber = this._getLineRenderLineNumber(lineNumber); + let extraClassName = ''; - if (renderLineNumber) { - if (lineNumber === this._activeLineNumber) { - output[lineIndex] = ( - '
' - + renderLineNumber - + '
' - ); - } else { - output[lineIndex] = ( - common - + renderLineNumber - + '
' - ); + if (lineNumber === lineCount && this._context.viewModel.getLineLength(lineNumber) === 0) { + // this is the last line + if (this._renderFinalNewline === 'off') { + output[lineIndex] = ''; + continue; } - } else { - output[lineIndex] = ''; + if (this._renderFinalNewline === 'dimmed') { + extraClassName = ' dimmed-line-number'; + } + } + if (lineNumber === this._activeLineNumber) { + extraClassName = ' active-line-number'; } + + output[lineIndex] = ( + `
${renderLineNumber}
` + ); } this._renderResult = output; @@ -190,3 +190,13 @@ export class LineNumbersOverlay extends DynamicViewOverlay { return this._renderResult[lineIndex]; } } + +registerThemingParticipant((theme, collector) => { + const editorLineNumbersColor = theme.getColor(editorLineNumbers); + const editorDimmedLineNumberColor = theme.getColor(editorDimmedLineNumber); + if (editorDimmedLineNumberColor) { + collector.addRule(`.monaco-editor .line-numbers.dimmed-line-number { color: ${editorDimmedLineNumberColor}; }`); + } else if (editorLineNumbersColor) { + collector.addRule(`.monaco-editor .line-numbers.dimmed-line-number { color: ${editorLineNumbersColor.transparent(0.4)}; }`); + } +}); diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 86c4620bc9b44..5ffd8827bee45 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -97,9 +97,9 @@ export interface IEditorOptions { cursorSurroundingLinesStyle?: 'default' | 'all'; /** * Render last line number when the file ends with a newline. - * Defaults to true. + * Defaults to 'on' for Windows and macOS and 'dimmed' for Linux. */ - renderFinalNewline?: boolean; + renderFinalNewline?: 'on' | 'off' | 'dimmed'; /** * Remove unusual line terminators like LINE SEPARATOR (LS), PARAGRAPH SEPARATOR (PS). * Defaults to 'prompt'. @@ -5262,8 +5262,10 @@ export const EditorOptions = { EditorOption.renderControlCharacters, 'renderControlCharacters', true, { description: nls.localize('renderControlCharacters', "Controls whether the editor should render control characters."), restricted: true } )), - renderFinalNewline: register(new EditorBooleanOption( - EditorOption.renderFinalNewline, 'renderFinalNewline', true, + renderFinalNewline: register(new EditorStringEnumOption( + EditorOption.renderFinalNewline, 'renderFinalNewline', + (platform.isLinux ? 'dimmed' : 'on') as 'off' | 'on' | 'dimmed', + ['off', 'on', 'dimmed'] as const, { description: nls.localize('renderFinalNewline', "Render last line number when the file ends with a newline.") } )), renderLineHighlight: register(new EditorStringEnumOption( diff --git a/src/vs/editor/common/core/editorColorRegistry.ts b/src/vs/editor/common/core/editorColorRegistry.ts index b122075cc4d95..b5adcabcfc0fe 100644 --- a/src/vs/editor/common/core/editorColorRegistry.ts +++ b/src/vs/editor/common/core/editorColorRegistry.ts @@ -27,6 +27,7 @@ export const editorLineNumbers = registerColor('editorLineNumber.foreground', { const deprecatedEditorActiveLineNumber = registerColor('editorActiveLineNumber.foreground', { dark: '#c6c6c6', light: '#0B216F', hcDark: activeContrastBorder, hcLight: activeContrastBorder }, nls.localize('editorActiveLineNumber', 'Color of editor active line number'), false, nls.localize('deprecatedEditorActiveLineNumber', 'Id is deprecated. Use \'editorLineNumber.activeForeground\' instead.')); export const editorActiveLineNumber = registerColor('editorLineNumber.activeForeground', { dark: deprecatedEditorActiveLineNumber, light: deprecatedEditorActiveLineNumber, hcDark: deprecatedEditorActiveLineNumber, hcLight: deprecatedEditorActiveLineNumber }, nls.localize('editorActiveLineNumber', 'Color of editor active line number')); +export const editorDimmedLineNumber = registerColor('editorLineNumber.dimmedForeground', { dark: null, light: null, hcDark: null, hcLight: null }, nls.localize('editorDimmedLineNumber', 'Color of the final editor line when editor.renderFinalNewline is set to dimmed.')); export const editorRuler = registerColor('editorRuler.foreground', { dark: '#5A5A5A', light: Color.lightgrey, hcDark: Color.white, hcLight: '#292929' }, nls.localize('editorRuler', 'Color of the editor rulers.')); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index abff06786635c..b02fc612e4670 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -3058,9 +3058,9 @@ declare namespace monaco.editor { cursorSurroundingLinesStyle?: 'default' | 'all'; /** * Render last line number when the file ends with a newline. - * Defaults to true. + * Defaults to 'on' for Windows and macOS and 'dimmed' for Linux. */ - renderFinalNewline?: boolean; + renderFinalNewline?: 'on' | 'off' | 'dimmed'; /** * Remove unusual line terminators like LINE SEPARATOR (LS), PARAGRAPH SEPARATOR (PS). * Defaults to 'prompt'. @@ -4787,7 +4787,7 @@ declare namespace monaco.editor { readOnly: IEditorOption; renameOnType: IEditorOption; renderControlCharacters: IEditorOption; - renderFinalNewline: IEditorOption; + renderFinalNewline: IEditorOption; renderLineHighlight: IEditorOption; renderLineHighlightOnlyWhenFocus: IEditorOption; renderValidationDecorations: IEditorOption;