From 3f9f6d9727eb07c7939ee789f631490d55f516b9 Mon Sep 17 00:00:00 2001 From: pyranota <92104930+pyranota@users.noreply.github.com> Date: Wed, 20 Aug 2025 00:09:01 +0200 Subject: [PATCH] feat(frontend): add relative line numbers toggle (#6416) * feat(frontend): add relative line numbers toggle Signed-off-by: pyranota * nits Signed-off-by: pyranota --------- Signed-off-by: pyranota --- frontend/src/lib/components/Editor.svelte | 10 ++++++++-- .../src/lib/components/EditorSettings.svelte | 6 ++++++ .../lib/components/RelativeLineNumbers.svelte | 18 ++++++++++++++++++ .../src/lib/components/SimpleEditor.svelte | 9 +++++++-- .../src/lib/components/TemplateEditor.svelte | 2 +- frontend/src/lib/components/custom_ui.ts | 1 + frontend/src/lib/editorUtils.ts | 4 +++- frontend/src/lib/stores.ts | 2 ++ 8 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 frontend/src/lib/components/RelativeLineNumbers.svelte diff --git a/frontend/src/lib/components/Editor.svelte b/frontend/src/lib/components/Editor.svelte index 825b6f7f58..32b1c42809 100644 --- a/frontend/src/lib/components/Editor.svelte +++ b/frontend/src/lib/components/Editor.svelte @@ -100,7 +100,8 @@ codeCompletionSessionEnabled, lspTokenStore, formatOnSave, - vimMode + vimMode, + relativeLineNumbers } from '$lib/stores' import { editorConfig, updateOptions } from '$lib/editorUtils' @@ -1234,7 +1235,7 @@ try { editor = meditor.create(divEl as HTMLDivElement, { - ...editorConfig(code ?? '', lang, automaticLayout, fixedOverflowWidgets), + ...editorConfig(code ?? '', lang, automaticLayout, fixedOverflowWidgets, $relativeLineNumbers), model, fontSize: !small ? 14 : 12, lineNumbersMinChars, @@ -1652,6 +1653,11 @@ $effect(() => { files && model && untrack(() => onFileChanges()) }) + $effect(() => { + editor?.updateOptions({ + lineNumbers: $relativeLineNumbers ? 'relative' : 'on' + }) + }) diff --git a/frontend/src/lib/components/EditorSettings.svelte b/frontend/src/lib/components/EditorSettings.svelte index fe1bd4bdf9..88984a3a52 100644 --- a/frontend/src/lib/components/EditorSettings.svelte +++ b/frontend/src/lib/components/EditorSettings.svelte @@ -2,6 +2,7 @@ import { Settings } from 'lucide-svelte' import FormatOnSave from './FormatOnSave.svelte' import VimMode from './VimMode.svelte' + import RelativeLineNumbers from './RelativeLineNumbers.svelte' import { Button } from './common' import CodeCompletionStatus from './copilot/CodeCompletionStatus.svelte' import type { EditorBarUi } from './custom_ui' @@ -39,6 +40,11 @@ {/if} + {#if customUi?.relativeLineNumbers != false} +
+ +
+ {/if} {#if customUi?.aiCompletion != false}
diff --git a/frontend/src/lib/components/RelativeLineNumbers.svelte b/frontend/src/lib/components/RelativeLineNumbers.svelte new file mode 100644 index 0000000000..96d68764ae --- /dev/null +++ b/frontend/src/lib/components/RelativeLineNumbers.svelte @@ -0,0 +1,18 @@ + + + { + storeSetting() + }} + options={{ right: 'relative line numbers' }} +/> \ No newline at end of file diff --git a/frontend/src/lib/components/SimpleEditor.svelte b/frontend/src/lib/components/SimpleEditor.svelte index a431a341ee..5f7c6b6a4f 100644 --- a/frontend/src/lib/components/SimpleEditor.svelte +++ b/frontend/src/lib/components/SimpleEditor.svelte @@ -78,7 +78,7 @@ import domContent from '$lib/dom.d.ts.txt?raw' import { initializeVscode, keepModelAroundToAvoidDisposalOfWorkers } from './vscode' import EditorTheme from './EditorTheme.svelte' - import { vimMode } from '$lib/stores' + import { vimMode, relativeLineNumbers } from '$lib/stores' import { initVim } from './monaco_keybindings' import FakeMonacoPlaceHolder from './FakeMonacoPlaceHolder.svelte' import { editorPositionMap } from '$lib/utils' @@ -266,6 +266,11 @@ untrack(() => onVimDisable()) } }) + $effect(() => { + editor?.updateOptions({ + lineNumbers: $relativeLineNumbers ? 'relative' : 'on' + }) + }) function onVimDisable() { vimDisposable?.dispose() @@ -374,7 +379,7 @@ try { console.log('fixedOverflowWidgets', fixedOverflowWidgets) editor = meditor.create(divEl as HTMLDivElement, { - ...editorConfig(code ?? '', lang, automaticLayout, fixedOverflowWidgets), + ...editorConfig(code ?? '', lang, automaticLayout, fixedOverflowWidgets, $relativeLineNumbers), model, lineDecorationsWidth: 6, lineNumbersMinChars: 2, diff --git a/frontend/src/lib/components/TemplateEditor.svelte b/frontend/src/lib/components/TemplateEditor.svelte index 7d2d1314fb..d3579e68ae 100644 --- a/frontend/src/lib/components/TemplateEditor.svelte +++ b/frontend/src/lib/components/TemplateEditor.svelte @@ -456,7 +456,7 @@ try { editor = meditor.create(divEl as HTMLDivElement, { - ...editorConfig(code, lang, automaticLayout, fixedOverflowWidgets), + ...editorConfig(code, lang, automaticLayout, fixedOverflowWidgets, false), model, // overflowWidgetsDomNode: widgets, // lineNumbers: 'on', diff --git a/frontend/src/lib/components/custom_ui.ts b/frontend/src/lib/components/custom_ui.ts index d690386ccb..b653f6fd55 100644 --- a/frontend/src/lib/components/custom_ui.ts +++ b/frontend/src/lib/components/custom_ui.ts @@ -65,6 +65,7 @@ export type EditorBarUi = { multiplayer?: boolean autoformatting?: boolean vimMode?: boolean + relativeLineNumbers?: boolean aiGen?: boolean aiCompletion?: boolean library?: boolean diff --git a/frontend/src/lib/editorUtils.ts b/frontend/src/lib/editorUtils.ts index 4cb3b586ed..0ce0085f77 100644 --- a/frontend/src/lib/editorUtils.ts +++ b/frontend/src/lib/editorUtils.ts @@ -6,7 +6,8 @@ export function editorConfig( code: string, lang: string, automaticLayout: boolean, - fixedOverflowWidgets: boolean + fixedOverflowWidgets: boolean, + relativeLineNumbers?: boolean ) { return { value: code, @@ -16,6 +17,7 @@ export function editorConfig( fixedOverflowWidgets, lineDecorationsWidth: 10, lineNumbersMinChars: 3, + lineNumbers: (relativeLineNumbers ?? false) ? 'relative' as const : 'on' as const, scrollbar: { alwaysConsumeMouseWheel: false }, folding: false, scrollBeyondLastLine: false, diff --git a/frontend/src/lib/stores.ts b/frontend/src/lib/stores.ts index c27baa1d1c..20a44ac882 100644 --- a/frontend/src/lib/stores.ts +++ b/frontend/src/lib/stores.ts @@ -158,6 +158,7 @@ export const metadataCompletionEnabled = writable(true) export const stepInputCompletionEnabled = writable(true) export const FORMAT_ON_SAVE_SETTING_NAME = 'formatOnSave' export const VIM_MODE_SETTING_NAME = 'vimMode' +export const RELATIVE_LINE_NUMBERS_SETTING_NAME = 'relativeLineNumbers' export const CODE_COMPLETION_SETTING_NAME = 'codeCompletionSessionEnabled' export const COPILOT_SESSION_MODEL_SETTING_NAME = 'copilotSessionModel' export const COPILOT_SESSION_PROVIDER_SETTING_NAME = 'copilotSessionProvider' @@ -165,6 +166,7 @@ export const formatOnSave = writable( getLocalSetting(FORMAT_ON_SAVE_SETTING_NAME) != 'false' ) export const vimMode = writable(getLocalSetting(VIM_MODE_SETTING_NAME) == 'true') +export const relativeLineNumbers = writable(getLocalSetting(RELATIVE_LINE_NUMBERS_SETTING_NAME) == 'true') export const codeCompletionSessionEnabled = writable( getLocalSetting(CODE_COMPLETION_SETTING_NAME) != 'false' )