✨ 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"/>
|
<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>
|
||||||
@@ -98,6 +101,17 @@ const editorStore = useEditorStore();
|
|||||||
cursor: pointer;
|
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 {
|
.tab-size {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@@ -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)
|
||||||
}])
|
}])
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
|
@@ -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(() => {
|
||||||
// 创建编辑器
|
// 创建编辑器
|
||||||
|
@@ -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',
|
||||||
|
@@ -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) {
|
||||||
@@ -94,6 +99,11 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
tabSize.value -= 1;
|
tabSize.value -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 切换Tab类型(空格或制表符)
|
||||||
|
function toggleTabType() {
|
||||||
|
tabType.value = tabType.value === 'spaces' ? 'tab' : 'spaces';
|
||||||
|
}
|
||||||
|
|
||||||
// 设置按钮操作
|
// 设置按钮操作
|
||||||
function openSettings() {
|
function openSettings() {
|
||||||
@@ -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']
|
||||||
}
|
}
|
||||||
});
|
});
|
Reference in New Issue
Block a user