diff --git a/frontend/bindings/voidraft/internal/models/models.ts b/frontend/bindings/voidraft/internal/models/models.ts index ac13b81..de5ea94 100644 --- a/frontend/bindings/voidraft/internal/models/models.ts +++ b/frontend/bindings/voidraft/internal/models/models.ts @@ -433,11 +433,6 @@ export enum ExtensionID { */ ExtensionSearch = "search", - /** - * 代码块 - */ - ExtensionCodeBlock = "codeBlock", - /** * 核心扩展 * 编辑器核心功能 @@ -918,6 +913,12 @@ export enum KeyBindingCommand { * 重做选择 */ HistoryRedoSelectionCommand = "historyRedoSelection", + + /** + * 文本高亮扩展相关 + * 切换文本高亮 + */ + TextHighlightToggleCommand = "textHighlightToggle", }; /** diff --git a/frontend/src/i18n/locales/en-US.ts b/frontend/src/i18n/locales/en-US.ts index 0729d65..dce8e58 100644 --- a/frontend/src/i18n/locales/en-US.ts +++ b/frontend/src/i18n/locales/en-US.ts @@ -89,6 +89,7 @@ export default { deleteCharForward: 'Delete character forward', deleteGroupBackward: 'Delete group backward', deleteGroupForward: 'Delete group forward', + textHighlightToggle: 'Toggle text highlight', } }, settings: { @@ -182,17 +183,16 @@ export default { name: 'Search', description: 'Text search and replace functionality' }, - codeBlock: { - name: 'Code Block', - description: 'Code block syntax highlighting and formatting' - }, + fold: { name: 'Code Folding', description: 'Collapse and expand code sections for better readability' }, textHighlight: { name: 'Text Highlight', - description: 'Highlight text selections and search matches' + description: 'Highlight selected text content (Ctrl+Shift+H to toggle highlight)', + backgroundColor: 'Background Color', + opacity: 'Opacity' } } }; \ No newline at end of file diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index 0ffc23d..293adc2 100644 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -89,6 +89,7 @@ export default { deleteCharForward: '向前删除字符', deleteGroupBackward: '向后删除组', deleteGroupForward: '向前删除组', + textHighlightToggle: '切换文本高亮', } }, settings: { @@ -182,17 +183,16 @@ export default { name: '搜索功能', description: '文本搜索和替换功能' }, - codeBlock: { - name: '代码块', - description: '代码块语法高亮和格式化' - }, + fold: { name: '代码折叠', description: '折叠和展开代码段以提高代码可读性' }, textHighlight: { name: '文本高亮', - description: '高亮显示文本选择和搜索匹配项' + description: '高亮选中的文本内容 (Ctrl+Shift+H 切换高亮)', + backgroundColor: '背景颜色', + opacity: '透明度' } } }; \ No newline at end of file diff --git a/frontend/src/stores/editorStore.ts b/frontend/src/stores/editorStore.ts index 3ca6acc..b615f7c 100644 --- a/frontend/src/stores/editorStore.ts +++ b/frontend/src/stores/editorStore.ts @@ -18,6 +18,7 @@ import {createAutoSavePlugin, createSaveShortcutPlugin} from '@/views/editor/bas import {createDynamicKeymapExtension, updateKeymapExtension} from '@/views/editor/keymap'; import {createDynamicExtensions, getExtensionManager, setExtensionManagerView} from '@/views/editor/manager'; import {useExtensionStore} from './extensionStore'; +import createCodeBlockExtension from "@/views/editor/extensions/codeblock"; export interface DocumentStats { lines: number; @@ -142,6 +143,11 @@ export const useEditorStore = defineStore('editor', () => { } } }); + // 代码块功能 + const codeBlockExtension = createCodeBlockExtension({ + showBackground: true, + enableAutoDetection: true + }); // 创建动态快捷键扩展 const keymapExtension = await createDynamicKeymapExtension(); @@ -159,6 +165,7 @@ export const useEditorStore = defineStore('editor', () => { statsExtension, saveShortcutExtension, autoSaveExtension, + codeBlockExtension, ...dynamicExtensions ]; diff --git a/frontend/src/views/editor/extensions/textHighlight/textHighlightExtension.ts b/frontend/src/views/editor/extensions/textHighlight/textHighlightExtension.ts index f4883e2..5de186f 100644 --- a/frontend/src/views/editor/extensions/textHighlight/textHighlightExtension.ts +++ b/frontend/src/views/editor/extensions/textHighlight/textHighlightExtension.ts @@ -1,120 +1,108 @@ -import { EditorState, StateEffect, StateField, Transaction, Range } from "@codemirror/state"; -import { Decoration, DecorationSet, EditorView, ViewPlugin, ViewUpdate } from "@codemirror/view"; -import { keymap } from "@codemirror/view"; +import { EditorState, StateEffect, StateField, Facet } from "@codemirror/state"; +import { Decoration, DecorationSet, EditorView } from "@codemirror/view"; -// 全局高亮存储 - 以文档ID为键,高亮范围数组为值 -interface HighlightInfo { - from: number; - to: number; +// 高亮配置接口 +export interface TextHighlightConfig { + backgroundColor?: string; + opacity?: number; } -class GlobalHighlightStore { - private static instance: GlobalHighlightStore; - private highlightMap: Map = new Map(); - - private constructor() {} - - public static getInstance(): GlobalHighlightStore { - if (!GlobalHighlightStore.instance) { - GlobalHighlightStore.instance = new GlobalHighlightStore(); - } - return GlobalHighlightStore.instance; - } - - // 保存文档的高亮 - saveHighlights(documentId: string, highlights: HighlightInfo[]): void { - this.highlightMap.set(documentId, [...highlights]); - } - - // 获取文档的高亮 - getHighlights(documentId: string): HighlightInfo[] { - return this.highlightMap.get(documentId) || []; - } - - // 添加高亮 - addHighlight(documentId: string, highlight: HighlightInfo): void { - const highlights = this.getHighlights(documentId); - highlights.push(highlight); - this.saveHighlights(documentId, highlights); - } - - // 移除高亮 - removeHighlights(documentId: string, from: number, to: number): void { - const highlights = this.getHighlights(documentId); - const filtered = highlights.filter(h => !(h.from < to && h.to > from)); - this.saveHighlights(documentId, filtered); - } - - // 清除文档的所有高亮 - clearHighlights(documentId: string): void { - this.highlightMap.delete(documentId); - } -} - -// 获取全局高亮存储实例 -const highlightStore = GlobalHighlightStore.getInstance(); +// 默认配置 +const DEFAULT_CONFIG: Required = { + backgroundColor: '#FFD700', // 金黄色 + opacity: 0.3 +}; // 定义添加和移除高亮的状态效果 -const addHighlight = StateEffect.define<{from: number, to: number, documentId: string}>({ - map: ({from, to, documentId}, change) => ({ +const addHighlight = StateEffect.define<{from: number, to: number}>({ + map: ({from, to}, change) => ({ from: change.mapPos(from), - to: change.mapPos(to), - documentId + to: change.mapPos(to) }) }); -const removeHighlight = StateEffect.define<{from: number, to: number, documentId: string}>({ - map: ({from, to, documentId}, change) => ({ +const removeHighlight = StateEffect.define<{from: number, to: number}>({ + map: ({from, to}, change) => ({ from: change.mapPos(from), - to: change.mapPos(to), - documentId + to: change.mapPos(to) }) }); -// 初始化高亮效果 - 用于页面加载时恢复高亮 -const initHighlights = StateEffect.define<{highlights: HighlightInfo[], documentId: string}>(); -// 高亮样式 -const highlightMark = Decoration.mark({ - attributes: {style: `background-color: rgba(255, 215, 0, 0.3)`} + +// 配置facet +const highlightConfigFacet = Facet.define>({ + combine: (configs) => { + let result = { ...DEFAULT_CONFIG }; + for (const config of configs) { + if (config.backgroundColor !== undefined) { + result.backgroundColor = config.backgroundColor; + } + if (config.opacity !== undefined) { + result.opacity = config.opacity; + } + } + return result; + } }); -// 存储高亮范围的状态字段 +// 创建高亮装饰 +function createHighlightMark(config: Required): Decoration { + const { backgroundColor, opacity } = config; + const rgbaColor = hexToRgba(backgroundColor, opacity); + + return Decoration.mark({ + attributes: { + style: `background-color: ${rgbaColor}; border-radius: 2px;` + } + }); +} + +// 将十六进制颜色转换为RGBA +function hexToRgba(hex: string, opacity: number): string { + // 移除 # 符号 + hex = hex.replace('#', ''); + + // 处理短格式 (如 #FFF -> #FFFFFF) + if (hex.length === 3) { + hex = hex.split('').map(char => char + char).join(''); + } + + const r = parseInt(hex.substr(0, 2), 16); + const g = parseInt(hex.substr(2, 2), 16); + const b = parseInt(hex.substr(4, 2), 16); + + return `rgba(${r}, ${g}, ${b}, ${opacity})`; +} + +// 存储高亮范围的状态字段 - 支持撤销 const highlightState = StateField.define({ create() { return Decoration.none; }, update(decorations, tr) { - // 先映射现有的装饰,以适应文档变化 + // 映射现有装饰以适应文档变化 decorations = decorations.map(tr.changes); - // 处理添加和移除高亮的效果 + // 处理效果 for (const effect of tr.effects) { if (effect.is(addHighlight)) { - const { from, to, documentId } = effect.value; + const { from, to } = effect.value; + const config = tr.state.facet(highlightConfigFacet); + const highlightMark = createHighlightMark(config); + decorations = decorations.update({ add: [highlightMark.range(from, to)] }); - // 同步到全局存储 - highlightStore.addHighlight(documentId, { from, to }); } else if (effect.is(removeHighlight)) { - const { from, to, documentId } = effect.value; + const { from, to } = effect.value; decorations = decorations.update({ filter: (rangeFrom, rangeTo) => { // 移除与指定范围重叠的装饰 return !(rangeFrom < to && rangeTo > from); } }); - // 同步到全局存储 - highlightStore.removeHighlights(documentId, from, to); - } - else if (effect.is(initHighlights)) { - const { highlights } = effect.value; - const ranges = highlights.map(h => highlightMark.range(h.from, h.to)); - if (ranges.length > 0) { - decorations = decorations.update({ add: ranges }); - } } } @@ -123,51 +111,32 @@ const highlightState = StateField.define({ provide: field => EditorView.decorations.from(field) }); -// 定义高亮范围接口 -interface HighlightRange { - from: number; - to: number; - decoration: Decoration; -} - -// 查找指定位置包含的高亮 -function findHighlightsAt(state: EditorState, pos: number): HighlightRange[] { - const highlights: HighlightRange[] = []; - - state.field(highlightState).between(pos, pos, (from, to, deco) => { - highlights.push({ from, to, decoration: deco }); - }); - - return highlights; -} - // 查找与给定范围重叠的所有高亮 -function findHighlightsInRange(state: EditorState, from: number, to: number): HighlightRange[] { - const highlights: HighlightRange[] = []; +function findHighlightsInRange(state: EditorState, from: number, to: number): Array<{from: number, to: number}> { + const highlights: Array<{from: number, to: number}> = []; - state.field(highlightState).between(from, to, (rangeFrom, rangeTo, deco) => { - // 只添加与指定范围有重叠的高亮 + state.field(highlightState).between(from, to, (rangeFrom, rangeTo) => { if (rangeFrom < to && rangeTo > from) { - highlights.push({ from: rangeFrom, to: rangeTo, decoration: deco }); + highlights.push({ from: rangeFrom, to: rangeTo }); } }); return highlights; } -// 收集当前所有高亮信息 -function collectAllHighlights(state: EditorState): HighlightInfo[] { - const highlights: HighlightInfo[] = []; +// 查找指定位置包含的高亮 +function findHighlightsAt(state: EditorState, pos: number): Array<{from: number, to: number}> { + const highlights: Array<{from: number, to: number}> = []; - state.field(highlightState).between(0, state.doc.length, (from, to) => { + state.field(highlightState).between(pos, pos, (from, to) => { highlights.push({ from, to }); }); return highlights; } -// 添加高亮 -function addHighlightRange(view: EditorView, from: number, to: number, documentId: string): boolean { +// 添加高亮范围 +function addHighlightRange(view: EditorView, from: number, to: number): boolean { if (from === to) return false; // 不高亮空选择 // 检查是否已经完全高亮 @@ -179,27 +148,27 @@ function addHighlightRange(view: EditorView, from: number, to: number, documentI if (isFullyHighlighted) return false; view.dispatch({ - effects: addHighlight.of({from, to, documentId}) + effects: addHighlight.of({from, to}) }); return true; } -// 移除高亮 -function removeHighlightRange(view: EditorView, from: number, to: number, documentId: string): boolean { +// 移除高亮范围 +function removeHighlightRange(view: EditorView, from: number, to: number): boolean { const highlights = findHighlightsInRange(view.state, from, to); if (highlights.length === 0) return false; view.dispatch({ - effects: removeHighlight.of({from, to, documentId}) + effects: removeHighlight.of({from, to}) }); return true; } // 切换高亮状态 -function toggleHighlight(view: EditorView, documentId: string): boolean { +function toggleHighlight(view: EditorView): boolean { const selection = view.state.selection.main; // 如果有选择文本 @@ -211,10 +180,10 @@ function toggleHighlight(view: EditorView, documentId: string): boolean { if (highlights.length > 0) { // 如果已有高亮,则移除 - return removeHighlightRange(view, from, to, documentId); + return removeHighlightRange(view, from, to); } else { // 如果没有高亮,则添加 - return addHighlightRange(view, from, to, documentId); + return addHighlightRange(view, from, to); } } // 如果是光标 @@ -225,135 +194,20 @@ function toggleHighlight(view: EditorView, documentId: string): boolean { if (highlightsAtCursor.length > 0) { // 移除光标位置的高亮 const highlight = highlightsAtCursor[0]; - return removeHighlightRange(view, highlight.from, highlight.to, documentId); + return removeHighlightRange(view, highlight.from, highlight.to); } } return false; } -// 创建高亮快捷键,需要文档ID -function createHighlightKeymap(documentId: string) { - return keymap.of([ - {key: "Mod-h", run: (view) => toggleHighlight(view, documentId)} - ]); -} +// 导出文本高亮切换命令,供快捷键系统使用 +export const textHighlightToggleCommand = toggleHighlight; -// 高亮刷新管理器类 -class HighlightRefreshManager { - private view: EditorView; - private refreshPending = false; - private initialSetupDone = false; - private rafId: number | null = null; - private documentId: string; - - constructor(view: EditorView, documentId: string) { - this.view = view; - this.documentId = documentId; - } - - /** - * 使用requestAnimationFrame安排视图更新 - */ - scheduleRefresh(): void { - if (this.refreshPending) return; - - this.refreshPending = true; - - this.rafId = requestAnimationFrame(() => { - this.executeRefresh(); - }); - } - - /** - * 执行视图更新 - */ - private executeRefresh(): void { - this.refreshPending = false; - this.rafId = null; - - if (!this.view.state) return; - - try { - // 触发一个空的更新,确保视图刷新 - this.view.dispatch({}); - } catch (e) { - console.debug("highlight refresh error:", e); - } - } - - /** - * 初始化高亮 - 应用保存的高亮 - */ - initHighlights(): void { - const savedHighlights = highlightStore.getHighlights(this.documentId); - if (savedHighlights.length > 0) { - this.view.dispatch({ - effects: initHighlights.of({ - highlights: savedHighlights, - documentId: this.documentId - }) - }); - } - } - - /** - * 执行初始化设置 - */ - performInitialSetup(): void { - if (this.initialSetupDone) return; - - Promise.resolve().then(() => { - this.initHighlights(); - this.scheduleRefresh(); - }); - - this.initialSetupDone = true; - } - - /** - * 清理资源 - */ - dispose(): void { - if (this.rafId !== null) { - cancelAnimationFrame(this.rafId); - } - } -} - -// 创建高亮扩展 -export function createTextHighlighter(documentId: string) { - // 视图插件 - const highlightSetupPlugin = ViewPlugin.define((view) => { - // 创建刷新管理器实例 - const refreshManager = new HighlightRefreshManager(view, documentId); - - // 执行初始化设置 - refreshManager.performInitialSetup(); - - return { - update(update: ViewUpdate) { - // 页面有内容变化时,保存最新的高亮状态 - if (update.docChanged || update.transactions.some(tr => - tr.effects.some(e => e.is(addHighlight) || e.is(removeHighlight)) - )) { - // 延迟收集高亮信息,确保所有效果都已应用 - setTimeout(() => { - const allHighlights = collectAllHighlights(view.state); - highlightStore.saveHighlights(documentId, allHighlights); - }, 0); - } - }, - destroy() { - // 清理资源 - refreshManager.dispose(); - } - }; - }); - +// 创建文本高亮扩展 +export function createTextHighlighter(config: TextHighlightConfig = {}) { return [ - highlightState, - createHighlightKeymap(documentId), - highlightSetupPlugin + highlightConfigFacet.of(config), + highlightState ]; } \ No newline at end of file diff --git a/frontend/src/views/editor/keymap/commandRegistry.ts b/frontend/src/views/editor/keymap/commandRegistry.ts index ab811f8..bc788cb 100644 --- a/frontend/src/views/editor/keymap/commandRegistry.ts +++ b/frontend/src/views/editor/keymap/commandRegistry.ts @@ -26,6 +26,7 @@ import {deleteLineCommand} from '../extensions/codeblock/deleteLine' import {moveLineDown, moveLineUp} from '../extensions/codeblock/moveLines' import {transposeChars} from '../extensions/codeblock' import {copyCommand, cutCommand, pasteCommand} from '../extensions/codeblock/copyPaste' +import {textHighlightToggleCommand} from '../extensions/textHighlight/textHighlightExtension' import { copyLineDown, copyLineUp, @@ -284,6 +285,12 @@ export const commandRegistry = { handler: deleteGroupForward, descriptionKey: 'keybindings.commands.deleteGroupForward' }, + + // 文本高亮扩展命令 + [KeyBindingCommand.TextHighlightToggleCommand]: { + handler: textHighlightToggleCommand, + descriptionKey: 'keybindings.commands.textHighlightToggle' + }, } as const /** diff --git a/frontend/src/views/editor/manager/factories.ts b/frontend/src/views/editor/manager/factories.ts index 8932462..47cbefb 100644 --- a/frontend/src/views/editor/manager/factories.ts +++ b/frontend/src/views/editor/manager/factories.ts @@ -10,7 +10,7 @@ import {color} from '../extensions/colorSelector' import {hyperLink} from '../extensions/hyperlink' import {minimap} from '../extensions/minimap' import {vscodeSearch} from '../extensions/vscodeSearch' -import {createCodeBlockExtension} from '../extensions/codeblock' + import {foldingOnIndent} from '../extensions/fold/foldExtension' /** @@ -33,16 +33,21 @@ export const rainbowBracketsFactory: ExtensionFactory = { */ export const textHighlightFactory: ExtensionFactory = { create(config: any) { - return createTextHighlighter('default') + return createTextHighlighter({ + backgroundColor: config.backgroundColor || '#FFD700', + opacity: config.opacity || 0.3 + }) }, getDefaultConfig() { return { - highlightClass: 'hl' + backgroundColor: '#FFD700', // 金黄色 + opacity: 0.3 // 透明度 } }, validateConfig(config: any) { return typeof config === 'object' && - (!config.highlightClass || typeof config.highlightClass === 'string') + (!config.backgroundColor || typeof config.backgroundColor === 'string') && + (!config.opacity || (typeof config.opacity === 'number' && config.opacity >= 0 && config.opacity <= 1)) } } @@ -120,29 +125,7 @@ export const searchFactory: ExtensionFactory = { } } -/** - * 代码块扩展工厂 - */ -export const codeBlockFactory: ExtensionFactory = { - create(config: any) { - const options = { - showBackground: config.showBackground !== false, - enableAutoDetection: config.enableAutoDetection !== false - } - return createCodeBlockExtension(options) - }, - getDefaultConfig() { - return { - showBackground: true, - enableAutoDetection: true - } - }, - validateConfig(config: any) { - return typeof config === 'object' && - (!config.showBackground || typeof config.showBackground === 'boolean') && - (!config.enableAutoDetection || typeof config.enableAutoDetection === 'boolean') - } -} + export const foldFactory: ExtensionFactory = { create(config: any) { @@ -193,11 +176,7 @@ const EXTENSION_CONFIGS = { displayNameKey: 'extensions.search.name', descriptionKey: 'extensions.search.description' }, - [ExtensionID.ExtensionCodeBlock]: { - factory: codeBlockFactory, - displayNameKey: 'extensions.codeBlock.name', - descriptionKey: 'extensions.codeBlock.description' - }, + [ExtensionID.ExtensionFold]: { factory: foldFactory, displayNameKey: 'extensions.fold.name', diff --git a/frontend/src/views/settings/pages/ExtensionsPage.vue b/frontend/src/views/settings/pages/ExtensionsPage.vue index c42ae88..248307c 100644 --- a/frontend/src/views/settings/pages/ExtensionsPage.vue +++ b/frontend/src/views/settings/pages/ExtensionsPage.vue @@ -7,11 +7,11 @@ import {ExtensionService} from '@/../bindings/voidraft/internal/services' import {ExtensionID} from '@/../bindings/voidraft/internal/models/models' import {getExtensionManager} from '@/views/editor/manager' import { - getAllExtensionIds, - getExtensionDescription, + getAllExtensionIds, + getExtensionDefaultConfig, + getExtensionDescription, getExtensionDisplayName, - hasExtensionConfig, - getExtensionDefaultConfig + hasExtensionConfig } from '@/views/editor/manager/factories' import SettingSection from '../components/SettingSection.vue' import SettingItem from '../components/SettingItem.vue' @@ -67,10 +67,10 @@ const updateExtensionConfig = async (extensionId: ExtensionID, configKey: string if (!extension) return // 更新配置 - const updatedConfig = { ...extension.config, [configKey]: value } + const updatedConfig = {...extension.config, [configKey]: value} await editorStore.updateExtension(extensionId, extension.enabled, updatedConfig) - + } catch (error) { console.error('Failed to update extension config:', error) } @@ -80,7 +80,7 @@ const updateExtensionConfig = async (extensionId: ExtensionID, configKey: string const resetExtension = async (extensionId: ExtensionID) => { try { await ExtensionService.ResetExtensionToDefault(extensionId) - + // 重新加载扩展状态以获取最新配置 await extensionStore.loadExtensions() @@ -114,25 +114,23 @@ const extensionConfigMeta: Partial { :class="{ expanded: expandedExtensions.has(extension.id) }" :title="t('settings.extensionsPage.configuration')" > - - + + @@ -194,7 +194,7 @@ const getSelectOptions = (extensionId: ExtensionID, configKey: string) => { -
@@ -209,8 +209,8 @@ const getSelectOptions = (extensionId: ExtensionID, configKey: string) => { {{ t('settings.reset') }}
- -
{ :model-value="extension.config[configKey] ?? configValue" @update:model-value="updateExtensionConfig(extension.id, configKey, $event)" /> - + - + - + { .extension-item { border-bottom: 1px solid var(--settings-input-border); - + &:last-child { border-bottom: none; } @@ -301,17 +304,17 @@ const getSelectOptions = (extensionId: ExtensionID, configKey: string) => { display: flex; align-items: center; justify-content: center; - + &:hover { background-color: var(--settings-hover); color: var(--settings-text); } - + &.expanded { color: var(--settings-accent); background-color: var(--settings-hover); } - + svg { transition: all 0.2s ease; } @@ -368,12 +371,12 @@ const getSelectOptions = (extensionId: ExtensionID, configKey: string) => { &:not(:last-child) { margin-bottom: 12px; } - + /* 配置项标题和描述字体大小 */ :deep(.setting-item-title) { font-size: 12px; } - + :deep(.setting-item-description) { font-size: 11px; } @@ -387,7 +390,7 @@ const getSelectOptions = (extensionId: ExtensionID, configKey: string) => { background-color: var(--settings-input-bg); color: var(--settings-text); font-size: 11px; /* 调整字体大小 */ - + &:focus { outline: none; border-color: var(--settings-accent); diff --git a/internal/models/extensions.go b/internal/models/extensions.go index 678a891..547d027 100644 --- a/internal/models/extensions.go +++ b/internal/models/extensions.go @@ -25,8 +25,7 @@ const ( ExtensionMinimap ExtensionID = "minimap" // 小地图 // 工具扩展 - ExtensionSearch ExtensionID = "search" // 搜索功能 - ExtensionCodeBlock ExtensionID = "codeBlock" // 代码块 + ExtensionSearch ExtensionID = "search" // 搜索功能 // 核心扩展 ExtensionEditor ExtensionID = "editor" // 编辑器核心功能 @@ -90,7 +89,10 @@ func NewDefaultExtensions() []Extension { ID: ExtensionTextHighlight, Enabled: true, IsDefault: true, - Config: ExtensionConfig{}, + Config: ExtensionConfig{ + "backgroundColor": "#FFD700", + "opacity": 0.3, + }, }, // UI增强扩展 @@ -112,15 +114,6 @@ func NewDefaultExtensions() []Extension { IsDefault: true, Config: ExtensionConfig{}, }, - { - ID: ExtensionCodeBlock, - Enabled: true, - IsDefault: true, - Config: ExtensionConfig{ - "showBackground": true, - "enableAutoDetection": true, - }, - }, // 核心扩展 { diff --git a/internal/models/key_bindings.go b/internal/models/key_bindings.go index 79c755d..ce313f5 100644 --- a/internal/models/key_bindings.go +++ b/internal/models/key_bindings.go @@ -78,6 +78,9 @@ const ( HistoryRedoCommand KeyBindingCommand = "historyRedo" // 重做 HistoryUndoSelectionCommand KeyBindingCommand = "historyUndoSelection" // 撤销选择 HistoryRedoSelectionCommand KeyBindingCommand = "historyRedoSelection" // 重做选择 + + // 文本高亮扩展相关 + TextHighlightToggleCommand KeyBindingCommand = "textHighlightToggle" // 切换文本高亮 ) // KeyBindingMetadata 快捷键配置元数据 @@ -157,115 +160,115 @@ func NewDefaultKeyBindings() []KeyBinding { IsDefault: true, }, - // 代码块扩展快捷键 + // 代码块核心功能快捷键 { Command: BlockSelectAllCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-a", Enabled: true, IsDefault: true, }, { Command: BlockAddAfterCurrentCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-Enter", Enabled: true, IsDefault: true, }, { Command: BlockAddAfterLastCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-Shift-Enter", Enabled: true, IsDefault: true, }, { Command: BlockAddBeforeCurrentCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Alt-Enter", Enabled: true, IsDefault: true, }, { Command: BlockGotoPreviousCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-ArrowUp", Enabled: true, IsDefault: true, }, { Command: BlockGotoNextCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-ArrowDown", Enabled: true, IsDefault: true, }, { Command: BlockSelectPreviousCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-Shift-ArrowUp", Enabled: true, IsDefault: true, }, { Command: BlockSelectNextCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-Shift-ArrowDown", Enabled: true, IsDefault: true, }, { Command: BlockDeleteCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-Shift-d", Enabled: true, IsDefault: true, }, { Command: BlockMoveUpCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Alt-Mod-ArrowUp", Enabled: true, IsDefault: true, }, { Command: BlockMoveDownCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Alt-Mod-ArrowDown", Enabled: true, IsDefault: true, }, { Command: BlockDeleteLineCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-Shift-k", Enabled: true, IsDefault: true, }, { Command: BlockMoveLineUpCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Alt-ArrowUp", Enabled: true, IsDefault: true, }, { Command: BlockMoveLineDownCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Alt-ArrowDown", Enabled: true, IsDefault: true, }, { Command: BlockTransposeCharsCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Ctrl-t", Enabled: true, IsDefault: true, }, { Command: BlockFormatCommand, - Extension: ExtensionCodeBlock, + Extension: ExtensionEditor, Key: "Mod-Shift-f", Enabled: true, IsDefault: true, @@ -493,6 +496,15 @@ func NewDefaultKeyBindings() []KeyBinding { Enabled: true, IsDefault: true, }, + + // 文本高亮扩展快捷键 + { + Command: TextHighlightToggleCommand, + Extension: ExtensionTextHighlight, + Key: "Mod-Shift-h", + Enabled: true, + IsDefault: true, + }, } }