✨ Added tab type selection
This commit is contained in:
@@ -26,7 +26,10 @@ const editorStore = useEditorStore();
|
||||
<input type="checkbox" :checked="editorStore.enableTabIndent" @change="editorStore.toggleTabIndent"/>
|
||||
<span>Tab</span>
|
||||
</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>
|
||||
<span>{{ editorStore.tabSize }}</span>
|
||||
<button class="tab-btn" @click="editorStore.increaseTabSize" :disabled="editorStore.tabSize >= 8">+</button>
|
||||
@@ -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;
|
||||
|
@@ -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)
|
||||
}])
|
||||
: [];
|
||||
|
||||
|
@@ -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(() => {
|
||||
// 创建编辑器
|
||||
|
@@ -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',
|
||||
|
@@ -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<DocumentStats>({
|
||||
@@ -30,6 +33,8 @@ export const useEditorStore = defineStore('editor', () => {
|
||||
const enableTabIndent = ref(true);
|
||||
// Tab键大小
|
||||
const tabSize = ref(DEFAULT_TAB_SIZE);
|
||||
// Tab类型:空格或制表符
|
||||
const tabType = ref<TabType>('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']
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user