Added tab type selection

This commit is contained in:
2025-04-25 00:03:06 +08:00
parent 8673b36f98
commit 3483ac4cf6
5 changed files with 54 additions and 21 deletions

View File

@@ -26,7 +26,10 @@ const editorStore = useEditorStore();
<input type="checkbox" :checked="editorStore.enableTabIndent" @change="editorStore.toggleTabIndent"/> <input type="checkbox" :checked="editorStore.enableTabIndent" @change="editorStore.toggleTabIndent"/>
<span>Tab</span> <span>Tab</span>
</label> </label>
<span class="tab-size" title="Tab大小"> <span class="tab-type" title="Tab类型切换" @click="editorStore.toggleTabType">
{{ editorStore.tabType === 'spaces' ? '空格' : '制表符' }}
</span>
<span class="tab-size" title="Tab大小" v-if="editorStore.tabType === 'spaces'">
<button class="tab-btn" @click="editorStore.decreaseTabSize" :disabled="editorStore.tabSize <= 2">-</button> <button class="tab-btn" @click="editorStore.decreaseTabSize" :disabled="editorStore.tabSize <= 2">-</button>
<span>{{ editorStore.tabSize }}</span> <span>{{ editorStore.tabSize }}</span>
<button class="tab-btn" @click="editorStore.increaseTabSize" :disabled="editorStore.tabSize >= 8">+</button> <button class="tab-btn" @click="editorStore.increaseTabSize" :disabled="editorStore.tabSize >= 8">+</button>
@@ -99,6 +102,17 @@ const editorStore = useEditorStore();
} }
} }
.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 { .tab-size {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -2,33 +2,35 @@ import {Compartment, Extension} from '@codemirror/state';
import {EditorView, keymap} from '@codemirror/view'; import {EditorView, keymap} from '@codemirror/view';
import {indentSelection} from '@codemirror/commands'; import {indentSelection} from '@codemirror/commands';
import {indentUnit} from '@codemirror/language'; import {indentUnit} from '@codemirror/language';
import {TabType} from '@/stores/editor';
// Tab设置相关的compartment // Tab设置相关的compartment
export const tabSizeCompartment = new Compartment(); export const tabSizeCompartment = new Compartment();
export const tabKeyCompartment = new Compartment(); export const tabKeyCompartment = new Compartment();
// 自定义Tab键处理函数 // 自定义Tab键处理函数
export const tabHandler = (view: EditorView, tabSize: number): boolean => { export const tabHandler = (view: EditorView, tabSize: number, tabType: TabType): boolean => {
// 如果有选中文本使用indentSelection // 如果有选中文本使用indentSelection
if (!view.state.selection.main.empty) { if (!view.state.selection.main.empty) {
return indentSelection(view); return indentSelection(view);
} }
// 创建相应数量的空格 // 根据tabType创建缩进字符
const spaces = ' '.repeat(tabSize); const indent = tabType === 'spaces' ? ' '.repeat(tabSize) : '\t';
// 在光标位置插入空格 // 在光标位置插入缩进字符
const {state, dispatch} = view; const {state, dispatch} = view;
dispatch(state.update(state.replaceSelection(spaces), {scrollIntoView: true})); dispatch(state.update(state.replaceSelection(indent), {scrollIntoView: true}));
return true; return true;
}; };
// 获取Tab相关的扩展 // 获取Tab相关的扩展
export const getTabExtensions = (tabSize: number, enableTabIndent: boolean): Extension[] => { export const getTabExtensions = (tabSize: number, enableTabIndent: boolean, tabType: TabType): Extension[] => {
const extensions: Extension[] = []; const extensions: Extension[] = [];
// 设置缩进单位 // 根据tabType设置缩进单位
extensions.push(tabSizeCompartment.of(indentUnit.of(' '.repeat(tabSize)))); const indentStr = tabType === 'spaces' ? ' '.repeat(tabSize) : '\t';
extensions.push(tabSizeCompartment.of(indentUnit.of(indentStr)));
// 如果启用了Tab缩进添加自定义Tab键映射 // 如果启用了Tab缩进添加自定义Tab键映射
if (enableTabIndent) { if (enableTabIndent) {
@@ -36,7 +38,7 @@ export const getTabExtensions = (tabSize: number, enableTabIndent: boolean): Ext
tabKeyCompartment.of( tabKeyCompartment.of(
keymap.of([{ keymap.of([{
key: "Tab", 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 = ( export const updateTabConfig = (
view: EditorView | null, view: EditorView | null,
tabSize: number, tabSize: number,
enableTabIndent: boolean enableTabIndent: boolean,
tabType: TabType
) => { ) => {
if (!view) return; if (!view) return;
// 更新indentUnit配置 // 根据tabType更新indentUnit配置
const indentStr = tabType === 'spaces' ? ' '.repeat(tabSize) : '\t';
view.dispatch({ view.dispatch({
effects: tabSizeCompartment.reconfigure(indentUnit.of(' '.repeat(tabSize))) effects: tabSizeCompartment.reconfigure(indentUnit.of(indentStr))
}); });
// 更新Tab键映射 // 更新Tab键映射
const tabKeymap = enableTabIndent const tabKeymap = enableTabIndent
? keymap.of([{ ? keymap.of([{
key: "Tab", key: "Tab",
run: (view) => tabHandler(view, tabSize) run: (view) => tabHandler(view, tabSize, tabType)
}]) }])
: []; : [];

View File

@@ -34,7 +34,8 @@ const createEditor = () => {
// 获取Tab相关扩展 // 获取Tab相关扩展
const tabExtensions = getTabExtensions( const tabExtensions = getTabExtensions(
editorStore.tabSize, editorStore.tabSize,
editorStore.enableTabIndent editorStore.enableTabIndent,
editorStore.tabType
); );
// 创建统计信息更新扩展 // 创建统计信息更新扩展
@@ -83,13 +84,15 @@ const reconfigureTabSettings = () => {
updateTabConfig( updateTabConfig(
editorStore.editorView as EditorView, editorStore.editorView as EditorView,
editorStore.tabSize, editorStore.tabSize,
editorStore.enableTabIndent editorStore.enableTabIndent,
editorStore.tabType
); );
}; };
// 监听Tab设置变化 // 监听Tab设置变化
watch(() => editorStore.tabSize, reconfigureTabSettings); watch(() => editorStore.tabSize, reconfigureTabSettings);
watch(() => editorStore.enableTabIndent, reconfigureTabSettings); watch(() => editorStore.enableTabIndent, reconfigureTabSettings);
watch(() => editorStore.tabType, reconfigureTabSettings);
onMounted(() => { onMounted(() => {
// 创建编辑器 // 创建编辑器

View File

@@ -8,12 +8,12 @@ export const config = {
dark: true, dark: true,
background: '#252B37', background: '#252B37',
foreground: '#9BB586', foreground: '#9BB586',
selection: '#1A5888', selection: '#3381c1',
selectionMatch: 'rgba(26, 88, 136, 0.5)', selectionMatch: '#1A58887F',
cursor: '#F8F8F2', cursor: '#F8F8F2',
dropdownBackground: '#282A36', dropdownBackground: '#282A36',
dropdownBorder: '#191A21', dropdownBorder: '#191A21',
activeLine: 'rgba(46, 51, 63, 0.6)', activeLine: '#2E333F99',
lineNumber: '#676d7c', lineNumber: '#676d7c',
lineNumberActive: '#F8F8F2', lineNumberActive: '#F8F8F2',
lineNumberBackground: '#212731', lineNumberBackground: '#212731',

View File

@@ -13,6 +13,9 @@ const DEFAULT_TAB_SIZE = 4;
const MIN_TAB_SIZE = 2; const MIN_TAB_SIZE = 2;
const MAX_TAB_SIZE = 8; const MAX_TAB_SIZE = 8;
// Tab类型
export type TabType = 'spaces' | 'tab';
export const useEditorStore = defineStore('editor', () => { export const useEditorStore = defineStore('editor', () => {
// 状态 // 状态
const documentStats = ref<DocumentStats>({ const documentStats = ref<DocumentStats>({
@@ -30,6 +33,8 @@ export const useEditorStore = defineStore('editor', () => {
const enableTabIndent = ref(true); const enableTabIndent = ref(true);
// Tab键大小 // Tab键大小
const tabSize = ref(DEFAULT_TAB_SIZE); const tabSize = ref(DEFAULT_TAB_SIZE);
// Tab类型空格或制表符
const tabType = ref<TabType>('spaces');
// 方法 // 方法
function setEditorView(view: EditorView | null) { function setEditorView(view: EditorView | null) {
@@ -95,6 +100,11 @@ export const useEditorStore = defineStore('editor', () => {
} }
} }
// 切换Tab类型空格或制表符
function toggleTabType() {
tabType.value = tabType.value === 'spaces' ? 'tab' : 'spaces';
}
// 设置按钮操作 // 设置按钮操作
function openSettings() { function openSettings() {
console.log('打开设置面板'); console.log('打开设置面板');
@@ -109,6 +119,7 @@ export const useEditorStore = defineStore('editor', () => {
fontSize, fontSize,
enableTabIndent, enableTabIndent,
tabSize, tabSize,
tabType,
// 方法 // 方法
setEditorView, setEditorView,
@@ -120,12 +131,13 @@ export const useEditorStore = defineStore('editor', () => {
resetFontSize, resetFontSize,
toggleTabIndent, toggleTabIndent,
increaseTabSize, increaseTabSize,
decreaseTabSize decreaseTabSize,
toggleTabType
}; };
}, { }, {
persist: { persist: {
key: 'editor', key: 'editor',
storage: localStorage, storage: localStorage,
pick: ['fontSize', 'encoding', 'enableTabIndent', 'tabSize'] pick: ['fontSize', 'encoding', 'enableTabIndent', 'tabSize', 'tabType']
} }
}); });