From 3483ac4cf6cab234bf8da18f24759018235a9279 Mon Sep 17 00:00:00 2001 From: landaiqing Date: Fri, 25 Apr 2025 00:03:06 +0800 Subject: [PATCH] :sparkles: Added tab type selection --- frontend/src/components/toolbar/index.vue | 16 +++++++++- .../src/editor/extensions/tabExtension.ts | 30 +++++++++++-------- frontend/src/editor/index.vue | 7 +++-- frontend/src/editor/theme/base-dark.ts | 6 ++-- frontend/src/stores/editor.ts | 16 ++++++++-- 5 files changed, 54 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/toolbar/index.vue b/frontend/src/components/toolbar/index.vue index 1adc952..01dbbc7 100644 --- a/frontend/src/components/toolbar/index.vue +++ b/frontend/src/components/toolbar/index.vue @@ -26,7 +26,10 @@ const editorStore = useEditorStore(); Tab - + + {{ editorStore.tabType === 'spaces' ? '空格' : '制表符' }} + + {{ editorStore.tabSize }} @@ -98,6 +101,17 @@ const editorStore = useEditorStore(); cursor: pointer; } } + + .tab-type { + cursor: pointer; + padding: 0 3px; + border-radius: 3px; + background-color: rgba(255, 255, 255, 0.05); + + &:hover { + background-color: rgba(255, 255, 255, 0.1); + } + } .tab-size { display: flex; diff --git a/frontend/src/editor/extensions/tabExtension.ts b/frontend/src/editor/extensions/tabExtension.ts index abccd63..8a01317 100644 --- a/frontend/src/editor/extensions/tabExtension.ts +++ b/frontend/src/editor/extensions/tabExtension.ts @@ -2,33 +2,35 @@ import {Compartment, Extension} from '@codemirror/state'; import {EditorView, keymap} from '@codemirror/view'; import {indentSelection} from '@codemirror/commands'; import {indentUnit} from '@codemirror/language'; +import {TabType} from '@/stores/editor'; // Tab设置相关的compartment export const tabSizeCompartment = new Compartment(); export const tabKeyCompartment = new Compartment(); // 自定义Tab键处理函数 -export const tabHandler = (view: EditorView, tabSize: number): boolean => { +export const tabHandler = (view: EditorView, tabSize: number, tabType: TabType): boolean => { // 如果有选中文本,使用indentSelection if (!view.state.selection.main.empty) { return indentSelection(view); } - // 创建相应数量的空格 - const spaces = ' '.repeat(tabSize); + // 根据tabType创建缩进字符 + const indent = tabType === 'spaces' ? ' '.repeat(tabSize) : '\t'; - // 在光标位置插入空格 + // 在光标位置插入缩进字符 const {state, dispatch} = view; - dispatch(state.update(state.replaceSelection(spaces), {scrollIntoView: true})); + dispatch(state.update(state.replaceSelection(indent), {scrollIntoView: true})); return true; }; // 获取Tab相关的扩展 -export const getTabExtensions = (tabSize: number, enableTabIndent: boolean): Extension[] => { +export const getTabExtensions = (tabSize: number, enableTabIndent: boolean, tabType: TabType): Extension[] => { const extensions: Extension[] = []; - // 设置缩进单位 - extensions.push(tabSizeCompartment.of(indentUnit.of(' '.repeat(tabSize)))); + // 根据tabType设置缩进单位 + const indentStr = tabType === 'spaces' ? ' '.repeat(tabSize) : '\t'; + extensions.push(tabSizeCompartment.of(indentUnit.of(indentStr))); // 如果启用了Tab缩进,添加自定义Tab键映射 if (enableTabIndent) { @@ -36,7 +38,7 @@ export const getTabExtensions = (tabSize: number, enableTabIndent: boolean): Ext tabKeyCompartment.of( keymap.of([{ key: "Tab", - run: (view) => tabHandler(view, tabSize) + run: (view) => tabHandler(view, tabSize, tabType) }]) ) ); @@ -51,20 +53,22 @@ export const getTabExtensions = (tabSize: number, enableTabIndent: boolean): Ext export const updateTabConfig = ( view: EditorView | null, tabSize: number, - enableTabIndent: boolean + enableTabIndent: boolean, + tabType: TabType ) => { if (!view) return; - // 更新indentUnit配置 + // 根据tabType更新indentUnit配置 + const indentStr = tabType === 'spaces' ? ' '.repeat(tabSize) : '\t'; view.dispatch({ - effects: tabSizeCompartment.reconfigure(indentUnit.of(' '.repeat(tabSize))) + effects: tabSizeCompartment.reconfigure(indentUnit.of(indentStr)) }); // 更新Tab键映射 const tabKeymap = enableTabIndent ? keymap.of([{ key: "Tab", - run: (view) => tabHandler(view, tabSize) + run: (view) => tabHandler(view, tabSize, tabType) }]) : []; diff --git a/frontend/src/editor/index.vue b/frontend/src/editor/index.vue index 8e33632..2de1852 100644 --- a/frontend/src/editor/index.vue +++ b/frontend/src/editor/index.vue @@ -34,7 +34,8 @@ const createEditor = () => { // 获取Tab相关扩展 const tabExtensions = getTabExtensions( editorStore.tabSize, - editorStore.enableTabIndent + editorStore.enableTabIndent, + editorStore.tabType ); // 创建统计信息更新扩展 @@ -83,13 +84,15 @@ const reconfigureTabSettings = () => { updateTabConfig( editorStore.editorView as EditorView, editorStore.tabSize, - editorStore.enableTabIndent + editorStore.enableTabIndent, + editorStore.tabType ); }; // 监听Tab设置变化 watch(() => editorStore.tabSize, reconfigureTabSettings); watch(() => editorStore.enableTabIndent, reconfigureTabSettings); +watch(() => editorStore.tabType, reconfigureTabSettings); onMounted(() => { // 创建编辑器 diff --git a/frontend/src/editor/theme/base-dark.ts b/frontend/src/editor/theme/base-dark.ts index e2c8f37..c211e0c 100644 --- a/frontend/src/editor/theme/base-dark.ts +++ b/frontend/src/editor/theme/base-dark.ts @@ -8,12 +8,12 @@ export const config = { dark: true, background: '#252B37', foreground: '#9BB586', - selection: '#1A5888', - selectionMatch: 'rgba(26, 88, 136, 0.5)', + selection: '#3381c1', + selectionMatch: '#1A58887F', cursor: '#F8F8F2', dropdownBackground: '#282A36', dropdownBorder: '#191A21', - activeLine: 'rgba(46, 51, 63, 0.6)', + activeLine: '#2E333F99', lineNumber: '#676d7c', lineNumberActive: '#F8F8F2', lineNumberBackground: '#212731', diff --git a/frontend/src/stores/editor.ts b/frontend/src/stores/editor.ts index 2fe0f0a..b6a1784 100644 --- a/frontend/src/stores/editor.ts +++ b/frontend/src/stores/editor.ts @@ -13,6 +13,9 @@ const DEFAULT_TAB_SIZE = 4; const MIN_TAB_SIZE = 2; const MAX_TAB_SIZE = 8; +// Tab类型 +export type TabType = 'spaces' | 'tab'; + export const useEditorStore = defineStore('editor', () => { // 状态 const documentStats = ref({ @@ -30,6 +33,8 @@ export const useEditorStore = defineStore('editor', () => { const enableTabIndent = ref(true); // Tab键大小 const tabSize = ref(DEFAULT_TAB_SIZE); + // Tab类型:空格或制表符 + const tabType = ref('spaces'); // 方法 function setEditorView(view: EditorView | null) { @@ -94,6 +99,11 @@ export const useEditorStore = defineStore('editor', () => { tabSize.value -= 1; } } + + // 切换Tab类型(空格或制表符) + function toggleTabType() { + tabType.value = tabType.value === 'spaces' ? 'tab' : 'spaces'; + } // 设置按钮操作 function openSettings() { @@ -109,6 +119,7 @@ export const useEditorStore = defineStore('editor', () => { fontSize, enableTabIndent, tabSize, + tabType, // 方法 setEditorView, @@ -120,12 +131,13 @@ export const useEditorStore = defineStore('editor', () => { resetFontSize, toggleTabIndent, increaseTabSize, - decreaseTabSize + decreaseTabSize, + toggleTabType }; }, { persist: { key: 'editor', storage: localStorage, - pick: ['fontSize', 'encoding', 'enableTabIndent', 'tabSize'] + pick: ['fontSize', 'encoding', 'enableTabIndent', 'tabSize', 'tabType'] } }); \ No newline at end of file