✨ Unified management of keymap
This commit is contained in:
@@ -456,18 +456,13 @@ export class KeyBinding {
|
|||||||
/**
|
/**
|
||||||
* 快捷键动作
|
* 快捷键动作
|
||||||
*/
|
*/
|
||||||
"action": KeyBindingAction;
|
"command": KeyBindingCommand;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 快捷键分类
|
* 快捷键分类
|
||||||
*/
|
*/
|
||||||
"category": KeyBindingCategory;
|
"category": KeyBindingCategory;
|
||||||
|
|
||||||
/**
|
|
||||||
* 快捷键作用域
|
|
||||||
*/
|
|
||||||
"scope": KeyBindingScope;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 快捷键组合(如 "Mod-f", "Ctrl-Shift-p")
|
* 快捷键组合(如 "Mod-f", "Ctrl-Shift-p")
|
||||||
*/
|
*/
|
||||||
@@ -485,15 +480,12 @@ export class KeyBinding {
|
|||||||
|
|
||||||
/** Creates a new KeyBinding instance. */
|
/** Creates a new KeyBinding instance. */
|
||||||
constructor($$source: Partial<KeyBinding> = {}) {
|
constructor($$source: Partial<KeyBinding> = {}) {
|
||||||
if (!("action" in $$source)) {
|
if (!("command" in $$source)) {
|
||||||
this["action"] = ("" as KeyBindingAction);
|
this["command"] = ("" as KeyBindingCommand);
|
||||||
}
|
}
|
||||||
if (!("category" in $$source)) {
|
if (!("category" in $$source)) {
|
||||||
this["category"] = ("" as KeyBindingCategory);
|
this["category"] = ("" as KeyBindingCategory);
|
||||||
}
|
}
|
||||||
if (!("scope" in $$source)) {
|
|
||||||
this["scope"] = ("" as KeyBindingScope);
|
|
||||||
}
|
|
||||||
if (!("key" in $$source)) {
|
if (!("key" in $$source)) {
|
||||||
this["key"] = "";
|
this["key"] = "";
|
||||||
}
|
}
|
||||||
@@ -516,212 +508,6 @@ export class KeyBinding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* KeyBindingAction 快捷键动作类型
|
|
||||||
*/
|
|
||||||
export enum KeyBindingAction {
|
|
||||||
/**
|
|
||||||
* The Go zero value for the underlying type of the enum.
|
|
||||||
*/
|
|
||||||
$zero = "",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 搜索相关
|
|
||||||
* 显示搜索
|
|
||||||
*/
|
|
||||||
ActionShowSearch = "showSearch",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 隐藏搜索
|
|
||||||
*/
|
|
||||||
ActionHideSearch = "hideSearch",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找下一个
|
|
||||||
*/
|
|
||||||
ActionFindNext = "findNext",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找上一个
|
|
||||||
*/
|
|
||||||
ActionFindPrevious = "findPrevious",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示替换
|
|
||||||
*/
|
|
||||||
ActionShowReplace = "showReplace",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换下一个
|
|
||||||
*/
|
|
||||||
ActionReplaceNext = "replaceNext",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 替换全部
|
|
||||||
*/
|
|
||||||
ActionReplaceAll = "replaceAll",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换大小写匹配
|
|
||||||
*/
|
|
||||||
ActionToggleCase = "toggleCase",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换全词匹配
|
|
||||||
*/
|
|
||||||
ActionToggleWholeWord = "toggleWholeWord",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换正则表达式
|
|
||||||
*/
|
|
||||||
ActionToggleRegex = "toggleRegex",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编辑相关
|
|
||||||
* 全选
|
|
||||||
*/
|
|
||||||
ActionSelectAll = "selectAll",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制
|
|
||||||
*/
|
|
||||||
ActionCopy = "copy",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 剪切
|
|
||||||
*/
|
|
||||||
ActionCut = "cut",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 粘贴
|
|
||||||
*/
|
|
||||||
ActionPaste = "paste",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 撤销
|
|
||||||
*/
|
|
||||||
ActionUndo = "undo",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重做
|
|
||||||
*/
|
|
||||||
ActionRedo = "redo",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制行
|
|
||||||
*/
|
|
||||||
ActionDuplicateLine = "duplicateLine",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除行
|
|
||||||
*/
|
|
||||||
ActionDeleteLine = "deleteLine",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上移行
|
|
||||||
*/
|
|
||||||
ActionMoveLineUp = "moveLineUp",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下移行
|
|
||||||
*/
|
|
||||||
ActionMoveLineDown = "moveLineDown",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换注释
|
|
||||||
*/
|
|
||||||
ActionToggleComment = "toggleComment",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缩进
|
|
||||||
*/
|
|
||||||
ActionIndent = "indent",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消缩进
|
|
||||||
*/
|
|
||||||
ActionOutdent = "outdent",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 代码块相关
|
|
||||||
* 新建代码块
|
|
||||||
*/
|
|
||||||
ActionNewCodeBlock = "newCodeBlock",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除代码块
|
|
||||||
*/
|
|
||||||
ActionDeleteCodeBlock = "deleteCodeBlock",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 选择代码块
|
|
||||||
*/
|
|
||||||
ActionSelectCodeBlock = "selectCodeBlock",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化代码
|
|
||||||
*/
|
|
||||||
ActionFormatCode = "formatCode",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更改语言
|
|
||||||
*/
|
|
||||||
ActionChangeLanguage = "changeLanguage",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导航相关
|
|
||||||
* 跳转到行
|
|
||||||
*/
|
|
||||||
ActionGoToLine = "goToLine",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 折叠所有
|
|
||||||
*/
|
|
||||||
ActionFoldAll = "foldAll",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 展开所有
|
|
||||||
*/
|
|
||||||
ActionUnfoldAll = "unfoldAll",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换折叠
|
|
||||||
*/
|
|
||||||
ActionToggleFold = "toggleFold",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视图相关
|
|
||||||
* 放大
|
|
||||||
*/
|
|
||||||
ActionZoomIn = "zoomIn",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缩小
|
|
||||||
*/
|
|
||||||
ActionZoomOut = "zoomOut",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置缩放
|
|
||||||
*/
|
|
||||||
ActionResetZoom = "resetZoom",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换小地图
|
|
||||||
*/
|
|
||||||
ActionToggleMinimap = "toggleMinimap",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换行号
|
|
||||||
*/
|
|
||||||
ActionToggleLineNumbers = "toggleLineNumbers",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件相关
|
|
||||||
* 保存
|
|
||||||
*/
|
|
||||||
ActionSave = "save",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* KeyBindingCategory 快捷键分类
|
* KeyBindingCategory 快捷键分类
|
||||||
*/
|
*/
|
||||||
@@ -744,27 +530,302 @@ export enum KeyBindingCategory {
|
|||||||
/**
|
/**
|
||||||
* 代码块相关
|
* 代码块相关
|
||||||
*/
|
*/
|
||||||
CategoryCodeBlock = "codeblock",
|
CategoryCodeBlock = "block",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导航相关
|
* 历史记录相关
|
||||||
*/
|
*/
|
||||||
CategoryNavigation = "navigation",
|
CategoryHistory = "history",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视图相关
|
* 代码折叠相关
|
||||||
*/
|
*/
|
||||||
CategoryView = "view",
|
CategoryFold = "fold",
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyBindingCommand 快捷键命令
|
||||||
|
*/
|
||||||
|
export enum KeyBindingCommand {
|
||||||
|
/**
|
||||||
|
* The Go zero value for the underlying type of the enum.
|
||||||
|
*/
|
||||||
|
$zero = "",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件相关
|
* 搜索相关
|
||||||
|
* 显示搜索
|
||||||
*/
|
*/
|
||||||
CategoryFile = "file",
|
ShowSearchCommand = "showSearch",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用相关
|
* 隐藏搜索
|
||||||
*/
|
*/
|
||||||
CategoryApp = "app",
|
HideSearchCommand = "hideSearch",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索切换大小写
|
||||||
|
*/
|
||||||
|
SearchToggleCaseCommand = "searchToggleCase",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索切换整词
|
||||||
|
*/
|
||||||
|
SearchToggleWordCommand = "searchToggleWord",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索切换正则
|
||||||
|
*/
|
||||||
|
SearchToggleRegexCommand = "searchToggleRegex",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示替换
|
||||||
|
*/
|
||||||
|
SearchShowReplaceCommand = "searchShowReplace",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换全部
|
||||||
|
*/
|
||||||
|
SearchReplaceAllCommand = "searchReplaceAll",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码块相关
|
||||||
|
* 块内选择全部
|
||||||
|
*/
|
||||||
|
BlockSelectAllCommand = "blockSelectAll",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在当前块后添加新块
|
||||||
|
*/
|
||||||
|
BlockAddAfterCurrentCommand = "blockAddAfterCurrent",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在最后添加新块
|
||||||
|
*/
|
||||||
|
BlockAddAfterLastCommand = "blockAddAfterLast",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在当前块前添加新块
|
||||||
|
*/
|
||||||
|
BlockAddBeforeCurrentCommand = "blockAddBeforeCurrent",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到上一个块
|
||||||
|
*/
|
||||||
|
BlockGotoPreviousCommand = "blockGotoPrevious",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到下一个块
|
||||||
|
*/
|
||||||
|
BlockGotoNextCommand = "blockGotoNext",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择上一个块
|
||||||
|
*/
|
||||||
|
BlockSelectPreviousCommand = "blockSelectPrevious",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择下一个块
|
||||||
|
*/
|
||||||
|
BlockSelectNextCommand = "blockSelectNext",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除当前块
|
||||||
|
*/
|
||||||
|
BlockDeleteCommand = "blockDelete",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向上移动当前块
|
||||||
|
*/
|
||||||
|
BlockMoveUpCommand = "blockMoveUp",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向下移动当前块
|
||||||
|
*/
|
||||||
|
BlockMoveDownCommand = "blockMoveDown",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除行
|
||||||
|
*/
|
||||||
|
BlockDeleteLineCommand = "blockDeleteLine",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向上移动行
|
||||||
|
*/
|
||||||
|
BlockMoveLineUpCommand = "blockMoveLineUp",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向下移动行
|
||||||
|
*/
|
||||||
|
BlockMoveLineDownCommand = "blockMoveLineDown",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符转置
|
||||||
|
*/
|
||||||
|
BlockTransposeCharsCommand = "blockTransposeChars",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化代码块
|
||||||
|
*/
|
||||||
|
BlockFormatCommand = "blockFormat",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制
|
||||||
|
*/
|
||||||
|
BlockCopyCommand = "blockCopy",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剪切
|
||||||
|
*/
|
||||||
|
BlockCutCommand = "blockCut",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 粘贴
|
||||||
|
*/
|
||||||
|
BlockPasteCommand = "blockPaste",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 历史记录相关
|
||||||
|
* 撤销
|
||||||
|
*/
|
||||||
|
HistoryUndoCommand = "historyUndo",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重做
|
||||||
|
*/
|
||||||
|
HistoryRedoCommand = "historyRedo",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销选择
|
||||||
|
*/
|
||||||
|
HistoryUndoSelectionCommand = "historyUndoSelection",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重做选择
|
||||||
|
*/
|
||||||
|
HistoryRedoSelectionCommand = "historyRedoSelection",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码折叠相关
|
||||||
|
* 折叠代码
|
||||||
|
*/
|
||||||
|
FoldCodeCommand = "foldCode",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展开代码
|
||||||
|
*/
|
||||||
|
UnfoldCodeCommand = "unfoldCode",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 折叠全部
|
||||||
|
*/
|
||||||
|
FoldAllCommand = "foldAll",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展开全部
|
||||||
|
*/
|
||||||
|
UnfoldAllCommand = "unfoldAll",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑相关
|
||||||
|
* 光标按语法左移
|
||||||
|
*/
|
||||||
|
CursorSyntaxLeftCommand = "cursorSyntaxLeft",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 光标按语法右移
|
||||||
|
*/
|
||||||
|
CursorSyntaxRightCommand = "cursorSyntaxRight",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按语法选择左侧
|
||||||
|
*/
|
||||||
|
SelectSyntaxLeftCommand = "selectSyntaxLeft",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按语法选择右侧
|
||||||
|
*/
|
||||||
|
SelectSyntaxRightCommand = "selectSyntaxRight",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向上复制行
|
||||||
|
*/
|
||||||
|
CopyLineUpCommand = "copyLineUp",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向下复制行
|
||||||
|
*/
|
||||||
|
CopyLineDownCommand = "copyLineDown",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入空行
|
||||||
|
*/
|
||||||
|
InsertBlankLineCommand = "insertBlankLine",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择行
|
||||||
|
*/
|
||||||
|
SelectLineCommand = "selectLine",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择父级语法
|
||||||
|
*/
|
||||||
|
SelectParentSyntaxCommand = "selectParentSyntax",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 减少缩进
|
||||||
|
*/
|
||||||
|
IndentLessCommand = "indentLess",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加缩进
|
||||||
|
*/
|
||||||
|
IndentMoreCommand = "indentMore",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缩进选择
|
||||||
|
*/
|
||||||
|
IndentSelectionCommand = "indentSelection",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 光标到匹配括号
|
||||||
|
*/
|
||||||
|
CursorMatchingBracketCommand = "cursorMatchingBracket",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换注释
|
||||||
|
*/
|
||||||
|
ToggleCommentCommand = "toggleComment",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换块注释
|
||||||
|
*/
|
||||||
|
ToggleBlockCommentCommand = "toggleBlockComment",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入新行并缩进
|
||||||
|
*/
|
||||||
|
InsertNewlineAndIndentCommand = "insertNewlineAndIndent",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向后删除字符
|
||||||
|
*/
|
||||||
|
DeleteCharBackwardCommand = "deleteCharBackward",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向前删除字符
|
||||||
|
*/
|
||||||
|
DeleteCharForwardCommand = "deleteCharForward",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向后删除组
|
||||||
|
*/
|
||||||
|
DeleteGroupBackwardCommand = "deleteGroupBackward",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向前删除组
|
||||||
|
*/
|
||||||
|
DeleteGroupForwardCommand = "deleteGroupForward",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -837,31 +898,6 @@ export class KeyBindingMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* KeyBindingScope 快捷键作用域
|
|
||||||
*/
|
|
||||||
export enum KeyBindingScope {
|
|
||||||
/**
|
|
||||||
* The Go zero value for the underlying type of the enum.
|
|
||||||
*/
|
|
||||||
$zero = "",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局作用域
|
|
||||||
*/
|
|
||||||
ScopeGlobal = "global",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编辑器作用域
|
|
||||||
*/
|
|
||||||
ScopeEditor = "editor",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 搜索面板作用域
|
|
||||||
*/
|
|
||||||
ScopeSearch = "search",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LanguageType 语言类型定义
|
* LanguageType 语言类型定义
|
||||||
*/
|
*/
|
||||||
|
@@ -17,16 +17,16 @@ import * as models$0 from "../models/models.js";
|
|||||||
/**
|
/**
|
||||||
* DisableKeyBinding 禁用快捷键
|
* DisableKeyBinding 禁用快捷键
|
||||||
*/
|
*/
|
||||||
export function DisableKeyBinding(action: models$0.KeyBindingAction): Promise<void> & { cancel(): void } {
|
export function DisableKeyBinding(command: models$0.KeyBindingCommand): Promise<void> & { cancel(): void } {
|
||||||
let $resultPromise = $Call.ByID(1594003006, action) as any;
|
let $resultPromise = $Call.ByID(1594003006, command) as any;
|
||||||
return $resultPromise;
|
return $resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EnableKeyBinding 启用快捷键
|
* EnableKeyBinding 启用快捷键
|
||||||
*/
|
*/
|
||||||
export function EnableKeyBinding(action: models$0.KeyBindingAction): Promise<void> & { cancel(): void } {
|
export function EnableKeyBinding(command: models$0.KeyBindingCommand): Promise<void> & { cancel(): void } {
|
||||||
let $resultPromise = $Call.ByID(1462644129, action) as any;
|
let $resultPromise = $Call.ByID(1462644129, command) as any;
|
||||||
return $resultPromise;
|
return $resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,10 +55,10 @@ export function GetAllKeyBindings(): Promise<models$0.KeyBinding[]> & { cancel()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GetKeyBindingByAction 根据动作获取快捷键
|
* GetKeyBindingByCommand 根据命令获取快捷键
|
||||||
*/
|
*/
|
||||||
export function GetKeyBindingByAction(action: models$0.KeyBindingAction): Promise<models$0.KeyBinding | null> & { cancel(): void } {
|
export function GetKeyBindingByCommand(command: models$0.KeyBindingCommand): Promise<models$0.KeyBinding | null> & { cancel(): void } {
|
||||||
let $resultPromise = $Call.ByID(752637777, action) as any;
|
let $resultPromise = $Call.ByID(3066982544, command) as any;
|
||||||
let $typingPromise = $resultPromise.then(($result: any) => {
|
let $typingPromise = $resultPromise.then(($result: any) => {
|
||||||
return $$createType2($result);
|
return $$createType2($result);
|
||||||
}) as any;
|
}) as any;
|
||||||
@@ -90,18 +90,6 @@ export function GetKeyBindingConfig(): Promise<models$0.KeyBindingConfig | null>
|
|||||||
return $typingPromise;
|
return $typingPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* GetKeyBindingScopes 获取所有快捷键作用域
|
|
||||||
*/
|
|
||||||
export function GetKeyBindingScopes(): Promise<models$0.KeyBindingScope[]> & { cancel(): void } {
|
|
||||||
let $resultPromise = $Call.ByID(2984736455) as any;
|
|
||||||
let $typingPromise = $resultPromise.then(($result: any) => {
|
|
||||||
return $$createType6($result);
|
|
||||||
}) as any;
|
|
||||||
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
|
|
||||||
return $typingPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GetKeyBindingsByCategory 根据分类获取快捷键
|
* GetKeyBindingsByCategory 根据分类获取快捷键
|
||||||
*/
|
*/
|
||||||
@@ -114,18 +102,6 @@ export function GetKeyBindingsByCategory(category: models$0.KeyBindingCategory):
|
|||||||
return $typingPromise;
|
return $typingPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* GetKeyBindingsByScope 根据作用域获取快捷键
|
|
||||||
*/
|
|
||||||
export function GetKeyBindingsByScope(scope: models$0.KeyBindingScope): Promise<models$0.KeyBinding[]> & { cancel(): void } {
|
|
||||||
let $resultPromise = $Call.ByID(1179712594, scope) as any;
|
|
||||||
let $typingPromise = $resultPromise.then(($result: any) => {
|
|
||||||
return $$createType1($result);
|
|
||||||
}) as any;
|
|
||||||
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
|
|
||||||
return $typingPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImportKeyBindings 导入快捷键配置
|
* ImportKeyBindings 导入快捷键配置
|
||||||
*/
|
*/
|
||||||
@@ -145,16 +121,16 @@ export function ResetAllKeyBindings(): Promise<void> & { cancel(): void } {
|
|||||||
/**
|
/**
|
||||||
* ResetKeyBinding 重置快捷键到默认值
|
* ResetKeyBinding 重置快捷键到默认值
|
||||||
*/
|
*/
|
||||||
export function ResetKeyBinding(action: models$0.KeyBindingAction): Promise<void> & { cancel(): void } {
|
export function ResetKeyBinding(command: models$0.KeyBindingCommand): Promise<void> & { cancel(): void } {
|
||||||
let $resultPromise = $Call.ByID(3466323405, action) as any;
|
let $resultPromise = $Call.ByID(3466323405, command) as any;
|
||||||
return $resultPromise;
|
return $resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UpdateKeyBinding 更新快捷键
|
* UpdateKeyBinding 更新快捷键
|
||||||
*/
|
*/
|
||||||
export function UpdateKeyBinding(action: models$0.KeyBindingAction, newKey: string): Promise<void> & { cancel(): void } {
|
export function UpdateKeyBinding(command: models$0.KeyBindingCommand, newKey: string): Promise<void> & { cancel(): void } {
|
||||||
let $resultPromise = $Call.ByID(1469368983, action, newKey) as any;
|
let $resultPromise = $Call.ByID(1469368983, command, newKey) as any;
|
||||||
return $resultPromise;
|
return $resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,4 +141,3 @@ const $$createType2 = $Create.Nullable($$createType0);
|
|||||||
const $$createType3 = $Create.Array($Create.Any);
|
const $$createType3 = $Create.Array($Create.Any);
|
||||||
const $$createType4 = models$0.KeyBindingConfig.createFrom;
|
const $$createType4 = models$0.KeyBindingConfig.createFrom;
|
||||||
const $$createType5 = $Create.Nullable($$createType4);
|
const $$createType5 = $Create.Nullable($$createType4);
|
||||||
const $$createType6 = $Create.Array($Create.Any);
|
|
||||||
|
@@ -2,17 +2,20 @@
|
|||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
import { useConfigStore } from '@/stores/configStore';
|
import { useConfigStore } from '@/stores/configStore';
|
||||||
import { useSystemStore } from '@/stores/systemStore';
|
import { useSystemStore } from '@/stores/systemStore';
|
||||||
|
import { useKeybindingStore } from '@/stores/keybindingStore';
|
||||||
import WindowTitleBar from '@/components/titlebar/WindowTitleBar.vue';
|
import WindowTitleBar from '@/components/titlebar/WindowTitleBar.vue';
|
||||||
|
|
||||||
const configStore = useConfigStore();
|
const configStore = useConfigStore();
|
||||||
const systemStore = useSystemStore();
|
const systemStore = useSystemStore();
|
||||||
|
const keybindingStore = useKeybindingStore();
|
||||||
|
|
||||||
// 应用启动时加载配置和初始化系统信息
|
// 应用启动时加载配置和初始化系统信息
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// 并行初始化配置和系统信息
|
// 并行初始化配置、系统信息和快捷键配置
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
configStore.initConfig(),
|
configStore.initConfig(),
|
||||||
systemStore.initializeSystemInfo(),
|
systemStore.initializeSystemInfo(),
|
||||||
|
keybindingStore.loadKeyBindings(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await configStore.initializeLanguage();
|
await configStore.initializeLanguage();
|
||||||
|
@@ -73,6 +73,73 @@ export default {
|
|||||||
completed: 'Migration Completed',
|
completed: 'Migration Completed',
|
||||||
failed: 'Migration Failed'
|
failed: 'Migration Failed'
|
||||||
},
|
},
|
||||||
|
keybindings: {
|
||||||
|
headers: {
|
||||||
|
shortcut: 'Shortcut',
|
||||||
|
category: 'Category',
|
||||||
|
description: 'Description'
|
||||||
|
},
|
||||||
|
commands: {
|
||||||
|
showSearch: 'Show search panel',
|
||||||
|
hideSearch: 'Hide search panel',
|
||||||
|
searchToggleCase: 'Toggle case-sensitive matching',
|
||||||
|
searchToggleWord: 'Toggle whole word matching',
|
||||||
|
searchToggleRegex: 'Toggle regular expression matching',
|
||||||
|
searchShowReplace: 'Show replace functionality',
|
||||||
|
searchFindNext: 'Find next match',
|
||||||
|
searchFindPrev: 'Find previous match',
|
||||||
|
searchReplaceAll: 'Replace all matches',
|
||||||
|
searchSelectAll: 'Select all content',
|
||||||
|
blockSelectAll: 'Select all in block',
|
||||||
|
blockAddAfterCurrent: 'Add new block after current',
|
||||||
|
blockAddAfterLast: 'Add new block at end',
|
||||||
|
blockAddBeforeCurrent: 'Add new block before current',
|
||||||
|
blockGotoPrevious: 'Go to previous block',
|
||||||
|
blockGotoNext: 'Go to next block',
|
||||||
|
blockSelectPrevious: 'Select previous block',
|
||||||
|
blockSelectNext: 'Select next block',
|
||||||
|
blockDelete: 'Delete current block',
|
||||||
|
blockMoveUp: 'Move current block up',
|
||||||
|
blockMoveDown: 'Move current block down',
|
||||||
|
blockDeleteLine: 'Delete line',
|
||||||
|
blockMoveLineUp: 'Move line up',
|
||||||
|
blockMoveLineDown: 'Move line down',
|
||||||
|
blockTransposeChars: 'Transpose characters',
|
||||||
|
blockFormat: 'Format code block',
|
||||||
|
blockCopy: 'Copy',
|
||||||
|
blockCut: 'Cut',
|
||||||
|
blockPaste: 'Paste',
|
||||||
|
historyUndo: 'Undo',
|
||||||
|
historyRedo: 'Redo',
|
||||||
|
historyUndoSelection: 'Undo selection',
|
||||||
|
historyRedoSelection: 'Redo selection',
|
||||||
|
foldCode: 'Fold code',
|
||||||
|
unfoldCode: 'Unfold code',
|
||||||
|
foldAll: 'Fold all',
|
||||||
|
unfoldAll: 'Unfold all',
|
||||||
|
cursorSyntaxLeft: 'Cursor syntax left',
|
||||||
|
cursorSyntaxRight: 'Cursor syntax right',
|
||||||
|
selectSyntaxLeft: 'Select syntax left',
|
||||||
|
selectSyntaxRight: 'Select syntax right',
|
||||||
|
copyLineUp: 'Copy line up',
|
||||||
|
copyLineDown: 'Copy line down',
|
||||||
|
simplifySelection: 'Simplify selection',
|
||||||
|
insertBlankLine: 'Insert blank line',
|
||||||
|
selectLine: 'Select line',
|
||||||
|
selectParentSyntax: 'Select parent syntax',
|
||||||
|
indentLess: 'Indent less',
|
||||||
|
indentMore: 'Indent more',
|
||||||
|
indentSelection: 'Indent selection',
|
||||||
|
cursorMatchingBracket: 'Cursor matching bracket',
|
||||||
|
toggleComment: 'Toggle comment',
|
||||||
|
toggleBlockComment: 'Toggle block comment',
|
||||||
|
insertNewlineAndIndent: 'Insert newline and indent',
|
||||||
|
deleteCharBackward: 'Delete character backward',
|
||||||
|
deleteCharForward: 'Delete character forward',
|
||||||
|
deleteGroupBackward: 'Delete group backward',
|
||||||
|
deleteGroupForward: 'Delete group forward',
|
||||||
|
}
|
||||||
|
},
|
||||||
settings: {
|
settings: {
|
||||||
title: 'Settings',
|
title: 'Settings',
|
||||||
backToEditor: 'Back to Editor',
|
backToEditor: 'Back to Editor',
|
||||||
|
@@ -73,6 +73,73 @@ export default {
|
|||||||
completed: '迁移已完成',
|
completed: '迁移已完成',
|
||||||
failed: '迁移失败'
|
failed: '迁移失败'
|
||||||
},
|
},
|
||||||
|
keybindings: {
|
||||||
|
headers: {
|
||||||
|
shortcut: '快捷键',
|
||||||
|
category: '分类',
|
||||||
|
description: '描述'
|
||||||
|
},
|
||||||
|
commands: {
|
||||||
|
showSearch: '显示搜索面板',
|
||||||
|
hideSearch: '隐藏搜索面板',
|
||||||
|
searchToggleCase: '切换大小写敏感匹配',
|
||||||
|
searchToggleWord: '切换整词匹配',
|
||||||
|
searchToggleRegex: '切换正则表达式匹配',
|
||||||
|
searchShowReplace: '显示替换功能',
|
||||||
|
searchFindNext: '查找下一个匹配项',
|
||||||
|
searchFindPrev: '查找上一个匹配项',
|
||||||
|
searchReplaceAll: '替换全部匹配项',
|
||||||
|
searchSelectAll: '选择全部内容',
|
||||||
|
blockSelectAll: '块内选择全部',
|
||||||
|
blockAddAfterCurrent: '在当前块后添加新块',
|
||||||
|
blockAddAfterLast: '在最后添加新块',
|
||||||
|
blockAddBeforeCurrent: '在当前块前添加新块',
|
||||||
|
blockGotoPrevious: '跳转到上一个块',
|
||||||
|
blockGotoNext: '跳转到下一个块',
|
||||||
|
blockSelectPrevious: '选择上一个块',
|
||||||
|
blockSelectNext: '选择下一个块',
|
||||||
|
blockDelete: '删除当前块',
|
||||||
|
blockMoveUp: '向上移动当前块',
|
||||||
|
blockMoveDown: '向下移动当前块',
|
||||||
|
blockDeleteLine: '删除行',
|
||||||
|
blockMoveLineUp: '向上移动行',
|
||||||
|
blockMoveLineDown: '向下移动行',
|
||||||
|
blockTransposeChars: '字符转置',
|
||||||
|
blockFormat: '格式化代码块',
|
||||||
|
blockCopy: '复制',
|
||||||
|
blockCut: '剪切',
|
||||||
|
blockPaste: '粘贴',
|
||||||
|
historyUndo: '撤销',
|
||||||
|
historyRedo: '重做',
|
||||||
|
historyUndoSelection: '撤销选择',
|
||||||
|
historyRedoSelection: '重做选择',
|
||||||
|
foldCode: '折叠代码',
|
||||||
|
unfoldCode: '展开代码',
|
||||||
|
foldAll: '折叠全部',
|
||||||
|
unfoldAll: '展开全部',
|
||||||
|
cursorSyntaxLeft: '光标按语法左移',
|
||||||
|
cursorSyntaxRight: '光标按语法右移',
|
||||||
|
selectSyntaxLeft: '按语法选择左侧',
|
||||||
|
selectSyntaxRight: '按语法选择右侧',
|
||||||
|
copyLineUp: '向上复制行',
|
||||||
|
copyLineDown: '向下复制行',
|
||||||
|
simplifySelection: '简化选择',
|
||||||
|
insertBlankLine: '插入空行',
|
||||||
|
selectLine: '选择行',
|
||||||
|
selectParentSyntax: '选择父级语法',
|
||||||
|
indentLess: '减少缩进',
|
||||||
|
indentMore: '增加缩进',
|
||||||
|
indentSelection: '缩进选择',
|
||||||
|
cursorMatchingBracket: '光标到匹配括号',
|
||||||
|
toggleComment: '切换注释',
|
||||||
|
toggleBlockComment: '切换块注释',
|
||||||
|
insertNewlineAndIndent: '插入新行并缩进',
|
||||||
|
deleteCharBackward: '向后删除字符',
|
||||||
|
deleteCharForward: '向前删除字符',
|
||||||
|
deleteGroupBackward: '向后删除组',
|
||||||
|
deleteGroupForward: '向前删除组',
|
||||||
|
}
|
||||||
|
},
|
||||||
settings: {
|
settings: {
|
||||||
title: '设置',
|
title: '设置',
|
||||||
backToEditor: '返回编辑器',
|
backToEditor: '返回编辑器',
|
||||||
|
@@ -15,6 +15,7 @@ import {
|
|||||||
createSaveShortcutPlugin,
|
createSaveShortcutPlugin,
|
||||||
createFontExtensionFromBackend,
|
createFontExtensionFromBackend,
|
||||||
updateFontConfig,
|
updateFontConfig,
|
||||||
|
createDynamicKeymapExtension,
|
||||||
} from '@/views/editor/extensions';
|
} from '@/views/editor/extensions';
|
||||||
import { createThemeExtension, updateEditorTheme } from '@/views/editor/extensions/themeExtension';
|
import { createThemeExtension, updateEditorTheme } from '@/views/editor/extensions/themeExtension';
|
||||||
import { useThemeStore } from './themeStore';
|
import { useThemeStore } from './themeStore';
|
||||||
@@ -169,8 +170,12 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 创建动态快捷键扩展
|
||||||
|
const keymapExtension = await createDynamicKeymapExtension();
|
||||||
|
|
||||||
// 组合所有扩展
|
// 组合所有扩展
|
||||||
const extensions: Extension[] = [
|
const extensions: Extension[] = [
|
||||||
|
keymapExtension,
|
||||||
themeExtension,
|
themeExtension,
|
||||||
...basicExtensions,
|
...basicExtensions,
|
||||||
...tabExtensions,
|
...tabExtensions,
|
||||||
|
52
frontend/src/stores/keybindingStore.ts
Normal file
52
frontend/src/stores/keybindingStore.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import {defineStore} from 'pinia'
|
||||||
|
import {computed, ref} from 'vue'
|
||||||
|
import {KeyBinding, KeyBindingCommand} from '@/../bindings/voidraft/internal/models/models'
|
||||||
|
import {GetAllKeyBindings} from '@/../bindings/voidraft/internal/services/keybindingservice'
|
||||||
|
|
||||||
|
export const useKeybindingStore = defineStore('keybinding', () => {
|
||||||
|
// 快捷键配置数据
|
||||||
|
const keyBindings = ref<KeyBinding[]>([])
|
||||||
|
|
||||||
|
|
||||||
|
// 获取启用的快捷键
|
||||||
|
const enabledKeyBindings = computed(() =>
|
||||||
|
keyBindings.value.filter(kb => kb.enabled)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 按命令获取快捷键
|
||||||
|
const getKeyBindingByCommand = computed(() =>
|
||||||
|
(command: KeyBindingCommand) =>
|
||||||
|
keyBindings.value.find(kb => kb.command === command)
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从后端加载快捷键配置
|
||||||
|
*/
|
||||||
|
const loadKeyBindings = async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
keyBindings.value = await GetAllKeyBindings()
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否存在指定命令的快捷键
|
||||||
|
*/
|
||||||
|
const hasCommand = (command: KeyBindingCommand): boolean => {
|
||||||
|
return keyBindings.value.some(kb => kb.command === command && kb.enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// 状态
|
||||||
|
keyBindings,
|
||||||
|
enabledKeyBindings,
|
||||||
|
|
||||||
|
// 计算属性
|
||||||
|
getKeyBindingByCommand,
|
||||||
|
|
||||||
|
// 方法
|
||||||
|
loadKeyBindings,
|
||||||
|
hasCommand
|
||||||
|
}
|
||||||
|
})
|
@@ -15,15 +15,13 @@ import {
|
|||||||
bracketMatching,
|
bracketMatching,
|
||||||
defaultHighlightStyle,
|
defaultHighlightStyle,
|
||||||
foldGutter,
|
foldGutter,
|
||||||
foldKeymap,
|
|
||||||
indentOnInput,
|
indentOnInput,
|
||||||
syntaxHighlighting,
|
syntaxHighlighting,
|
||||||
} from '@codemirror/language';
|
} from '@codemirror/language';
|
||||||
import {defaultKeymap, history, historyKeymap,} from '@codemirror/commands';
|
import {history} from '@codemirror/commands';
|
||||||
import {highlightSelectionMatches} from '@codemirror/search';
|
import {highlightSelectionMatches} from '@codemirror/search';
|
||||||
import {autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap} from '@codemirror/autocomplete';
|
import {autocompletion, closeBrackets, closeBracketsKeymap} from '@codemirror/autocomplete';
|
||||||
import {lintKeymap} from '@codemirror/lint';
|
import {searchVisibilityField, vscodeSearch} from './vscodeSearch';
|
||||||
import {customSearchKeymap, searchVisibilityField, vscodeSearch} from './vscodeSearch';
|
|
||||||
|
|
||||||
import {hyperLink} from './hyperlink';
|
import {hyperLink} from './hyperlink';
|
||||||
import {color} from './colorSelector';
|
import {color} from './colorSelector';
|
||||||
@@ -91,13 +89,7 @@ export const createBasicSetup = (): Extension[] => {
|
|||||||
|
|
||||||
// 键盘映射
|
// 键盘映射
|
||||||
keymap.of([
|
keymap.of([
|
||||||
...customSearchKeymap,
|
|
||||||
...closeBracketsKeymap,
|
...closeBracketsKeymap,
|
||||||
...defaultKeymap,
|
|
||||||
...historyKeymap,
|
|
||||||
...foldKeymap,
|
|
||||||
...completionKeymap,
|
|
||||||
...lintKeymap
|
|
||||||
]),
|
]),
|
||||||
];
|
];
|
||||||
};
|
};
|
@@ -208,27 +208,4 @@ export function getCopyPasteExtensions() {
|
|||||||
return [
|
return [
|
||||||
codeBlockCopyCut,
|
codeBlockCopyCut,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取复制粘贴键盘映射
|
|
||||||
*/
|
|
||||||
export function getCopyPasteKeymap() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
key: 'Mod-c',
|
|
||||||
run: copyCommand,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Mod-x',
|
|
||||||
run: cutCommand,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Mod-v',
|
|
||||||
run: pasteCommand,
|
|
||||||
preventDefault: true
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
@@ -13,17 +13,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Extension} from '@codemirror/state';
|
import {Extension} from '@codemirror/state';
|
||||||
import {keymap, lineNumbers} from '@codemirror/view';
|
import {lineNumbers} from '@codemirror/view';
|
||||||
|
|
||||||
// 导入核心模块
|
// 导入核心模块
|
||||||
import {blockState} from './state';
|
import {blockState} from './state';
|
||||||
import {getBlockDecorationExtensions} from './decorations';
|
import {getBlockDecorationExtensions} from './decorations';
|
||||||
import * as commands from './commands';
|
import {getBlockSelectExtensions} from './selectAll';
|
||||||
import {getBlockSelectExtensions, selectAll} from './selectAll';
|
import {getCopyPasteExtensions} from './copyPaste';
|
||||||
import {getCopyPasteExtensions, getCopyPasteKeymap} from './copyPaste';
|
|
||||||
import {deleteLineCommand} from './deleteLine';
|
|
||||||
import {moveLineDown, moveLineUp} from './moveLines';
|
import {moveLineDown, moveLineUp} from './moveLines';
|
||||||
import {transposeChars} from './transposeChars';
|
|
||||||
import {getCodeBlockLanguageExtension} from './lang-parser';
|
import {getCodeBlockLanguageExtension} from './lang-parser';
|
||||||
import {createLanguageDetection} from './language-detection';
|
import {createLanguageDetection} from './language-detection';
|
||||||
import {EditorOptions, SupportedLanguage} from './types';
|
import {EditorOptions, SupportedLanguage} from './types';
|
||||||
@@ -92,13 +89,7 @@ export function createCodeBlockExtension(options: CodeBlockOptions = {}): Extens
|
|||||||
defaultAutoDetect = true,
|
defaultAutoDetect = true,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
// 将简化的配置转换为内部使用的EditorOptions
|
return [
|
||||||
const editorOptions: EditorOptions = {
|
|
||||||
defaultBlockToken: defaultLanguage,
|
|
||||||
defaultBlockAutoDetect: defaultAutoDetect,
|
|
||||||
};
|
|
||||||
|
|
||||||
const extensions: Extension[] = [
|
|
||||||
// 核心状态管理
|
// 核心状态管理
|
||||||
blockState,
|
blockState,
|
||||||
|
|
||||||
@@ -126,105 +117,7 @@ export function createCodeBlockExtension(options: CodeBlockOptions = {}): Extens
|
|||||||
// 复制粘贴功能
|
// 复制粘贴功能
|
||||||
...getCopyPasteExtensions(),
|
...getCopyPasteExtensions(),
|
||||||
|
|
||||||
// 键盘映射
|
|
||||||
keymap.of([
|
|
||||||
// 复制粘贴命令
|
|
||||||
...getCopyPasteKeymap(),
|
|
||||||
|
|
||||||
// 块隔离选择命令
|
|
||||||
{
|
|
||||||
key: 'Mod-a',
|
|
||||||
run: selectAll,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
// 块创建命令
|
|
||||||
{
|
|
||||||
key: 'Mod-Enter',
|
|
||||||
run: commands.addNewBlockAfterCurrent(editorOptions),
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Mod-Shift-Enter',
|
|
||||||
run: commands.addNewBlockAfterLast(editorOptions),
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-Enter',
|
|
||||||
run: commands.addNewBlockBeforeCurrent(editorOptions),
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// 块导航命令
|
|
||||||
{
|
|
||||||
key: 'Mod-ArrowUp',
|
|
||||||
run: commands.gotoPreviousBlock,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Mod-ArrowDown',
|
|
||||||
run: commands.gotoNextBlock,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Mod-Shift-ArrowUp',
|
|
||||||
run: commands.selectPreviousBlock,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Mod-Shift-ArrowDown',
|
|
||||||
run: commands.selectNextBlock,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// 块编辑命令
|
|
||||||
{
|
|
||||||
key: 'Mod-Shift-d',
|
|
||||||
run: commands.deleteBlock(editorOptions),
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-Mod-ArrowUp',
|
|
||||||
run: commands.moveCurrentBlockUp,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-Mod-ArrowDown',
|
|
||||||
run: commands.moveCurrentBlockDown,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// 行编辑命令
|
|
||||||
{
|
|
||||||
key: 'Mod-Shift-k', // 删除行
|
|
||||||
run: deleteLineCommand,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-ArrowUp', // 向上移动行
|
|
||||||
run: moveLineUp,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-ArrowDown', // 向下移动行
|
|
||||||
run: moveLineDown,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Ctrl-t', // 字符转置
|
|
||||||
run: transposeChars,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// 代码格式化命令
|
|
||||||
{
|
|
||||||
key: 'Mod-Shift-f', // 格式化代码
|
|
||||||
run: commands.formatCurrentBlock,
|
|
||||||
preventDefault: true
|
|
||||||
},
|
|
||||||
])
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return extensions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -271,7 +164,6 @@ export {
|
|||||||
cutCommand,
|
cutCommand,
|
||||||
pasteCommand,
|
pasteCommand,
|
||||||
getCopyPasteExtensions,
|
getCopyPasteExtensions,
|
||||||
getCopyPasteKeymap
|
|
||||||
} from './copyPaste';
|
} from './copyPaste';
|
||||||
|
|
||||||
// 删除行功能
|
// 删除行功能
|
||||||
|
@@ -218,7 +218,5 @@ function isInDelimiter(state: any, pos: number) {
|
|||||||
export function getBlockSelectExtensions() {
|
export function getBlockSelectExtensions() {
|
||||||
return [
|
return [
|
||||||
emptyBlockSelected,
|
emptyBlockSelected,
|
||||||
// 禁用块边界检查以避免递归更新问题
|
|
||||||
// blockAwareSelection,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
@@ -6,4 +6,5 @@ export * from './autoSaveExtension';
|
|||||||
export * from './fontExtension';
|
export * from './fontExtension';
|
||||||
export * from './themeExtension';
|
export * from './themeExtension';
|
||||||
export * from './codeblast';
|
export * from './codeblast';
|
||||||
export * from './codeblock';
|
export * from './codeblock';
|
||||||
|
export * from './keymap';
|
298
frontend/src/views/editor/extensions/keymap/commandRegistry.ts
Normal file
298
frontend/src/views/editor/extensions/keymap/commandRegistry.ts
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
import {KeyBindingCommand} from '@/../bindings/voidraft/internal/models/models'
|
||||||
|
import {
|
||||||
|
hideSearchVisibilityCommand,
|
||||||
|
searchReplaceAll,
|
||||||
|
searchShowReplace,
|
||||||
|
searchToggleCase,
|
||||||
|
searchToggleRegex,
|
||||||
|
searchToggleWholeWord,
|
||||||
|
showSearchVisibilityCommand
|
||||||
|
} from '../vscodeSearch/commands'
|
||||||
|
import {
|
||||||
|
addNewBlockAfterCurrent,
|
||||||
|
addNewBlockAfterLast,
|
||||||
|
addNewBlockBeforeCurrent,
|
||||||
|
deleteBlock,
|
||||||
|
formatCurrentBlock,
|
||||||
|
gotoNextBlock,
|
||||||
|
gotoPreviousBlock,
|
||||||
|
moveCurrentBlockDown,
|
||||||
|
moveCurrentBlockUp,
|
||||||
|
selectNextBlock,
|
||||||
|
selectPreviousBlock
|
||||||
|
} from '../codeblock/commands'
|
||||||
|
import { selectAll } from '../codeblock/selectAll'
|
||||||
|
import { deleteLineCommand } from '../codeblock/deleteLine'
|
||||||
|
import { moveLineUp, moveLineDown } from '../codeblock/moveLines'
|
||||||
|
import { transposeChars } from '@/views/editor/extensions'
|
||||||
|
import { copyCommand, cutCommand, pasteCommand } from '../codeblock/copyPaste'
|
||||||
|
import { undo, redo, undoSelection, redoSelection, cursorSyntaxLeft, cursorSyntaxRight, selectSyntaxLeft, selectSyntaxRight, copyLineUp, copyLineDown, insertBlankLine, selectLine, selectParentSyntax, indentLess, indentMore, indentSelection, cursorMatchingBracket, toggleComment, toggleBlockComment, insertNewlineAndIndent, deleteCharBackward, deleteCharForward, deleteGroupBackward, deleteGroupForward } from '@codemirror/commands'
|
||||||
|
import { foldCode, unfoldCode, foldAll, unfoldAll } from '@codemirror/language'
|
||||||
|
import i18n from '@/i18n'
|
||||||
|
|
||||||
|
// 默认编辑器选项
|
||||||
|
const defaultEditorOptions = {
|
||||||
|
defaultBlockToken: 'text',
|
||||||
|
defaultBlockAutoDetect: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端命令注册表
|
||||||
|
* 将后端定义的command字段映射到具体的前端方法和翻译键
|
||||||
|
*/
|
||||||
|
export const commandRegistry = {
|
||||||
|
[KeyBindingCommand.ShowSearchCommand]: {
|
||||||
|
handler: showSearchVisibilityCommand,
|
||||||
|
descriptionKey: 'keybindings.commands.showSearch'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.HideSearchCommand]: {
|
||||||
|
handler: hideSearchVisibilityCommand,
|
||||||
|
descriptionKey: 'keybindings.commands.hideSearch'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SearchToggleCaseCommand]: {
|
||||||
|
handler: searchToggleCase,
|
||||||
|
descriptionKey: 'keybindings.commands.searchToggleCase'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SearchToggleWordCommand]: {
|
||||||
|
handler: searchToggleWholeWord,
|
||||||
|
descriptionKey: 'keybindings.commands.searchToggleWord'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SearchToggleRegexCommand]: {
|
||||||
|
handler: searchToggleRegex,
|
||||||
|
descriptionKey: 'keybindings.commands.searchToggleRegex'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SearchShowReplaceCommand]: {
|
||||||
|
handler: searchShowReplace,
|
||||||
|
descriptionKey: 'keybindings.commands.searchShowReplace'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SearchReplaceAllCommand]: {
|
||||||
|
handler: searchReplaceAll,
|
||||||
|
descriptionKey: 'keybindings.commands.searchReplaceAll'
|
||||||
|
},
|
||||||
|
|
||||||
|
// 代码块操作命令
|
||||||
|
[KeyBindingCommand.BlockSelectAllCommand]: {
|
||||||
|
handler: selectAll,
|
||||||
|
descriptionKey: 'keybindings.commands.blockSelectAll'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockAddAfterCurrentCommand]: {
|
||||||
|
handler: addNewBlockAfterCurrent(defaultEditorOptions),
|
||||||
|
descriptionKey: 'keybindings.commands.blockAddAfterCurrent'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockAddAfterLastCommand]: {
|
||||||
|
handler: addNewBlockAfterLast(defaultEditorOptions),
|
||||||
|
descriptionKey: 'keybindings.commands.blockAddAfterLast'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockAddBeforeCurrentCommand]: {
|
||||||
|
handler: addNewBlockBeforeCurrent(defaultEditorOptions),
|
||||||
|
descriptionKey: 'keybindings.commands.blockAddBeforeCurrent'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockGotoPreviousCommand]: {
|
||||||
|
handler: gotoPreviousBlock,
|
||||||
|
descriptionKey: 'keybindings.commands.blockGotoPrevious'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockGotoNextCommand]: {
|
||||||
|
handler: gotoNextBlock,
|
||||||
|
descriptionKey: 'keybindings.commands.blockGotoNext'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockSelectPreviousCommand]: {
|
||||||
|
handler: selectPreviousBlock,
|
||||||
|
descriptionKey: 'keybindings.commands.blockSelectPrevious'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockSelectNextCommand]: {
|
||||||
|
handler: selectNextBlock,
|
||||||
|
descriptionKey: 'keybindings.commands.blockSelectNext'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockDeleteCommand]: {
|
||||||
|
handler: deleteBlock(defaultEditorOptions),
|
||||||
|
descriptionKey: 'keybindings.commands.blockDelete'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockMoveUpCommand]: {
|
||||||
|
handler: moveCurrentBlockUp,
|
||||||
|
descriptionKey: 'keybindings.commands.blockMoveUp'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockMoveDownCommand]: {
|
||||||
|
handler: moveCurrentBlockDown,
|
||||||
|
descriptionKey: 'keybindings.commands.blockMoveDown'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockDeleteLineCommand]: {
|
||||||
|
handler: deleteLineCommand,
|
||||||
|
descriptionKey: 'keybindings.commands.blockDeleteLine'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockMoveLineUpCommand]: {
|
||||||
|
handler: moveLineUp,
|
||||||
|
descriptionKey: 'keybindings.commands.blockMoveLineUp'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockMoveLineDownCommand]: {
|
||||||
|
handler: moveLineDown,
|
||||||
|
descriptionKey: 'keybindings.commands.blockMoveLineDown'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockTransposeCharsCommand]: {
|
||||||
|
handler: transposeChars,
|
||||||
|
descriptionKey: 'keybindings.commands.blockTransposeChars'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockFormatCommand]: {
|
||||||
|
handler: formatCurrentBlock,
|
||||||
|
descriptionKey: 'keybindings.commands.blockFormat'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockCopyCommand]: {
|
||||||
|
handler: copyCommand,
|
||||||
|
descriptionKey: 'keybindings.commands.blockCopy'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockCutCommand]: {
|
||||||
|
handler: cutCommand,
|
||||||
|
descriptionKey: 'keybindings.commands.blockCut'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.BlockPasteCommand]: {
|
||||||
|
handler: pasteCommand,
|
||||||
|
descriptionKey: 'keybindings.commands.blockPaste'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.HistoryUndoCommand]: {
|
||||||
|
handler: undo,
|
||||||
|
descriptionKey: 'keybindings.commands.historyUndo'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.HistoryRedoCommand]: {
|
||||||
|
handler: redo,
|
||||||
|
descriptionKey: 'keybindings.commands.historyRedo'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.HistoryUndoSelectionCommand]: {
|
||||||
|
handler: undoSelection,
|
||||||
|
descriptionKey: 'keybindings.commands.historyUndoSelection'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.HistoryRedoSelectionCommand]: {
|
||||||
|
handler: redoSelection,
|
||||||
|
descriptionKey: 'keybindings.commands.historyRedoSelection'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.FoldCodeCommand]: {
|
||||||
|
handler: foldCode,
|
||||||
|
descriptionKey: 'keybindings.commands.foldCode'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.UnfoldCodeCommand]: {
|
||||||
|
handler: unfoldCode,
|
||||||
|
descriptionKey: 'keybindings.commands.unfoldCode'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.FoldAllCommand]: {
|
||||||
|
handler: foldAll,
|
||||||
|
descriptionKey: 'keybindings.commands.foldAll'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.UnfoldAllCommand]: {
|
||||||
|
handler: unfoldAll,
|
||||||
|
descriptionKey: 'keybindings.commands.unfoldAll'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.CursorSyntaxLeftCommand]: {
|
||||||
|
handler: cursorSyntaxLeft,
|
||||||
|
descriptionKey: 'keybindings.commands.cursorSyntaxLeft'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.CursorSyntaxRightCommand]: {
|
||||||
|
handler: cursorSyntaxRight,
|
||||||
|
descriptionKey: 'keybindings.commands.cursorSyntaxRight'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SelectSyntaxLeftCommand]: {
|
||||||
|
handler: selectSyntaxLeft,
|
||||||
|
descriptionKey: 'keybindings.commands.selectSyntaxLeft'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SelectSyntaxRightCommand]: {
|
||||||
|
handler: selectSyntaxRight,
|
||||||
|
descriptionKey: 'keybindings.commands.selectSyntaxRight'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.CopyLineUpCommand]: {
|
||||||
|
handler: copyLineUp,
|
||||||
|
descriptionKey: 'keybindings.commands.copyLineUp'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.CopyLineDownCommand]: {
|
||||||
|
handler: copyLineDown,
|
||||||
|
descriptionKey: 'keybindings.commands.copyLineDown'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.InsertBlankLineCommand]: {
|
||||||
|
handler: insertBlankLine,
|
||||||
|
descriptionKey: 'keybindings.commands.insertBlankLine'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SelectLineCommand]: {
|
||||||
|
handler: selectLine,
|
||||||
|
descriptionKey: 'keybindings.commands.selectLine'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.SelectParentSyntaxCommand]: {
|
||||||
|
handler: selectParentSyntax,
|
||||||
|
descriptionKey: 'keybindings.commands.selectParentSyntax'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.IndentLessCommand]: {
|
||||||
|
handler: indentLess,
|
||||||
|
descriptionKey: 'keybindings.commands.indentLess'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.IndentMoreCommand]: {
|
||||||
|
handler: indentMore,
|
||||||
|
descriptionKey: 'keybindings.commands.indentMore'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.IndentSelectionCommand]: {
|
||||||
|
handler: indentSelection,
|
||||||
|
descriptionKey: 'keybindings.commands.indentSelection'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.CursorMatchingBracketCommand]: {
|
||||||
|
handler: cursorMatchingBracket,
|
||||||
|
descriptionKey: 'keybindings.commands.cursorMatchingBracket'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.ToggleCommentCommand]: {
|
||||||
|
handler: toggleComment,
|
||||||
|
descriptionKey: 'keybindings.commands.toggleComment'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.ToggleBlockCommentCommand]: {
|
||||||
|
handler: toggleBlockComment,
|
||||||
|
descriptionKey: 'keybindings.commands.toggleBlockComment'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.InsertNewlineAndIndentCommand]: {
|
||||||
|
handler: insertNewlineAndIndent,
|
||||||
|
descriptionKey: 'keybindings.commands.insertNewlineAndIndent'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.DeleteCharBackwardCommand]: {
|
||||||
|
handler: deleteCharBackward,
|
||||||
|
descriptionKey: 'keybindings.commands.deleteCharBackward'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.DeleteCharForwardCommand]: {
|
||||||
|
handler: deleteCharForward,
|
||||||
|
descriptionKey: 'keybindings.commands.deleteCharForward'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.DeleteGroupBackwardCommand]: {
|
||||||
|
handler: deleteGroupBackward,
|
||||||
|
descriptionKey: 'keybindings.commands.deleteGroupBackward'
|
||||||
|
},
|
||||||
|
[KeyBindingCommand.DeleteGroupForwardCommand]: {
|
||||||
|
handler: deleteGroupForward,
|
||||||
|
descriptionKey: 'keybindings.commands.deleteGroupForward'
|
||||||
|
},
|
||||||
|
} as const
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取命令处理函数
|
||||||
|
* @param command 命令名称
|
||||||
|
* @returns 对应的处理函数,如果不存在则返回 undefined
|
||||||
|
*/
|
||||||
|
export const getCommandHandler = (command: KeyBindingCommand) => {
|
||||||
|
return commandRegistry[command]?.handler
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取命令描述
|
||||||
|
* @param command 命令名称
|
||||||
|
* @returns 对应的描述,如果不存在则返回 undefined
|
||||||
|
*/
|
||||||
|
export const getCommandDescription = (command: KeyBindingCommand) => {
|
||||||
|
const descriptionKey = commandRegistry[command]?.descriptionKey
|
||||||
|
return descriptionKey ? i18n.global.t(descriptionKey) : undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查命令是否已注册
|
||||||
|
* @param command 命令名称
|
||||||
|
* @returns 是否已注册
|
||||||
|
*/
|
||||||
|
export const isCommandRegistered = (command: KeyBindingCommand): boolean => {
|
||||||
|
return command in commandRegistry
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有已注册的命令
|
||||||
|
* @returns 已注册的命令列表
|
||||||
|
*/
|
||||||
|
export const getRegisteredCommands = (): KeyBindingCommand[] => {
|
||||||
|
return Object.keys(commandRegistry) as KeyBindingCommand[]
|
||||||
|
}
|
23
frontend/src/views/editor/extensions/keymap/index.ts
Normal file
23
frontend/src/views/editor/extensions/keymap/index.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { Extension } from '@codemirror/state'
|
||||||
|
import { useKeybindingStore } from '@/stores/keybindingStore'
|
||||||
|
import { KeymapManager } from './keymapManager'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步创建快捷键扩展
|
||||||
|
* 确保快捷键配置已加载
|
||||||
|
*/
|
||||||
|
export const createDynamicKeymapExtension = async (): Promise<Extension> => {
|
||||||
|
const keybindingStore = useKeybindingStore()
|
||||||
|
|
||||||
|
// 确保快捷键配置已加载
|
||||||
|
if (keybindingStore.keyBindings.length === 0) {
|
||||||
|
await keybindingStore.loadKeyBindings()
|
||||||
|
}
|
||||||
|
|
||||||
|
return KeymapManager.createKeymapExtension(keybindingStore.enabledKeyBindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出相关模块
|
||||||
|
export { KeymapManager } from './keymapManager'
|
||||||
|
export { commandRegistry, getCommandHandler, getCommandDescription, isCommandRegistered, getRegisteredCommands } from './commandRegistry'
|
||||||
|
export type { KeyBinding, CommandHandler, CommandDefinition, KeymapResult } from './types'
|
84
frontend/src/views/editor/extensions/keymap/keymapManager.ts
Normal file
84
frontend/src/views/editor/extensions/keymap/keymapManager.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import {keymap} from '@codemirror/view'
|
||||||
|
import {Extension} from '@codemirror/state'
|
||||||
|
import {KeyBinding as KeyBindingConfig} from '@/../bindings/voidraft/internal/models/models'
|
||||||
|
import {KeyBinding, KeymapResult} from './types'
|
||||||
|
import {getCommandHandler, isCommandRegistered} from './commandRegistry'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快捷键管理器
|
||||||
|
* 负责将后端配置转换为CodeMirror快捷键扩展
|
||||||
|
*/
|
||||||
|
export class KeymapManager {
|
||||||
|
/**
|
||||||
|
* 将后端快捷键配置转换为CodeMirror快捷键绑定
|
||||||
|
* @param keyBindings 后端快捷键配置列表
|
||||||
|
* @returns 转换结果
|
||||||
|
*/
|
||||||
|
static convertToKeyBindings(keyBindings: KeyBindingConfig[]): KeymapResult {
|
||||||
|
const result: KeyBinding[] = []
|
||||||
|
|
||||||
|
for (const binding of keyBindings) {
|
||||||
|
// 跳过禁用的快捷键
|
||||||
|
if (!binding.enabled) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查命令是否已注册
|
||||||
|
if (!isCommandRegistered(binding.command)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取命令处理函数
|
||||||
|
const handler = getCommandHandler(binding.command)
|
||||||
|
if (!handler) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为CodeMirror快捷键格式
|
||||||
|
const keyBinding: KeyBinding = {
|
||||||
|
key: binding.key,
|
||||||
|
run: handler,
|
||||||
|
preventDefault: true
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push(keyBinding)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {keyBindings: result}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建CodeMirror快捷键扩展
|
||||||
|
* @param keyBindings 后端快捷键配置列表
|
||||||
|
* @returns CodeMirror扩展
|
||||||
|
*/
|
||||||
|
static createKeymapExtension(keyBindings: KeyBindingConfig[]): Extension {
|
||||||
|
const {keyBindings: cmKeyBindings} =
|
||||||
|
this.convertToKeyBindings(keyBindings)
|
||||||
|
|
||||||
|
return keymap.of(cmKeyBindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证快捷键配置
|
||||||
|
* @param keyBindings 快捷键配置列表
|
||||||
|
* @returns 验证结果
|
||||||
|
*/
|
||||||
|
static validateKeyBindings(keyBindings: KeyBindingConfig[]): {
|
||||||
|
valid: KeyBindingConfig[]
|
||||||
|
invalid: KeyBindingConfig[]
|
||||||
|
} {
|
||||||
|
const valid: KeyBindingConfig[] = []
|
||||||
|
const invalid: KeyBindingConfig[] = []
|
||||||
|
|
||||||
|
for (const binding of keyBindings) {
|
||||||
|
if (binding.enabled && binding.key && isCommandRegistered(binding.command)) {
|
||||||
|
valid.push(binding)
|
||||||
|
} else {
|
||||||
|
invalid.push(binding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {valid, invalid}
|
||||||
|
}
|
||||||
|
}
|
30
frontend/src/views/editor/extensions/keymap/types.ts
Normal file
30
frontend/src/views/editor/extensions/keymap/types.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import {Command} from '@codemirror/view'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CodeMirror快捷键绑定格式
|
||||||
|
*/
|
||||||
|
export interface KeyBinding {
|
||||||
|
key: string
|
||||||
|
run: Command
|
||||||
|
preventDefault?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令处理函数类型
|
||||||
|
*/
|
||||||
|
export type CommandHandler = Command
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令定义接口
|
||||||
|
*/
|
||||||
|
export interface CommandDefinition {
|
||||||
|
handler: CommandHandler
|
||||||
|
descriptionKey: string // 翻译键
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快捷键转换结果
|
||||||
|
*/
|
||||||
|
export interface KeymapResult {
|
||||||
|
keyBindings: KeyBinding[]
|
||||||
|
}
|
@@ -1,5 +1,4 @@
|
|||||||
export { VSCodeSearch, vscodeSearch} from "./plugin";
|
export { VSCodeSearch, vscodeSearch} from "./plugin";
|
||||||
export { searchVisibilityField, SearchVisibilityEffect } from "./state";
|
export { searchVisibilityField, SearchVisibilityEffect } from "./state";
|
||||||
export { customSearchKeymap } from "./keymap";
|
|
||||||
export { searchBaseTheme } from "./theme"
|
export { searchBaseTheme } from "./theme"
|
||||||
export * from "./commands"
|
export * from "./commands"
|
@@ -1,81 +0,0 @@
|
|||||||
import { KeyBinding } from "@codemirror/view";
|
|
||||||
import { deleteCharacterBackwards, deleteCharacterFowards, hideSearchVisibilityCommand, searchFindPrevious, searchFindReplaceMatch, searchMoveCursorLeft, searchMoveCursorRight, searchReplaceAll, searchShowReplace, searchToggleCase, searchToggleRegex, searchToggleWholeWord, selectAllCommand, showSearchVisibilityCommand } from "./commands";
|
|
||||||
|
|
||||||
export const customSearchKeymap: KeyBinding[] = [
|
|
||||||
// 全局快捷键 - 不需要 scope 限制
|
|
||||||
{
|
|
||||||
key: 'Mod-f',
|
|
||||||
run: showSearchVisibilityCommand,
|
|
||||||
},
|
|
||||||
// 添加备用快捷键绑定,确保兼容性
|
|
||||||
{
|
|
||||||
key: 'Ctrl-f',
|
|
||||||
run: showSearchVisibilityCommand,
|
|
||||||
},
|
|
||||||
// 搜索面板内的快捷键 - 需要 scope 限制
|
|
||||||
{
|
|
||||||
key: 'Mod-a',
|
|
||||||
run: selectAllCommand,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Escape',
|
|
||||||
run: hideSearchVisibilityCommand,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-c',
|
|
||||||
run: searchToggleCase,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-w',
|
|
||||||
run: searchToggleWholeWord,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-r',
|
|
||||||
run: searchToggleRegex,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Mod-h',
|
|
||||||
run: searchShowReplace,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Enter',
|
|
||||||
run: searchFindReplaceMatch,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Shift-Enter',
|
|
||||||
run: searchFindPrevious,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Mod-Alt-Enter',
|
|
||||||
run: searchReplaceAll,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Backspace',
|
|
||||||
run: deleteCharacterBackwards,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Delete',
|
|
||||||
run: deleteCharacterFowards,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "ArrowLeft",
|
|
||||||
run: searchMoveCursorLeft,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "ArrowRight",
|
|
||||||
run: searchMoveCursorRight,
|
|
||||||
scope: 'search'
|
|
||||||
},
|
|
||||||
];
|
|
@@ -1,74 +1,196 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { ref } from 'vue';
|
import { onMounted, computed } from 'vue';
|
||||||
import SettingSection from '../components/SettingSection.vue';
|
import SettingSection from '../components/SettingSection.vue';
|
||||||
|
import { useKeybindingStore } from '@/stores/keybindingStore';
|
||||||
|
import { useSystemStore } from '@/stores/systemStore';
|
||||||
|
import { getCommandDescription } from '@/views/editor/extensions/keymap/commandRegistry';
|
||||||
|
import {KeyBindingCommand} from "@/../bindings/voidraft/internal/models";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const keybindingStore = useKeybindingStore();
|
||||||
|
const systemStore = useSystemStore();
|
||||||
|
|
||||||
interface KeyBinding {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
keys: string[];
|
|
||||||
isEditing: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 示例快捷键列表(仅用于界面展示)
|
// 从store中获取快捷键数据并转换为显示格式
|
||||||
const keyBindings = ref<KeyBinding[]>([
|
const keyBindings = computed(() => {
|
||||||
{ id: 'save', name: '保存文档', keys: ['Ctrl', 'S'], isEditing: false },
|
return keybindingStore.keyBindings
|
||||||
{ id: 'new', name: '新建文档', keys: ['Ctrl', 'N'], isEditing: false },
|
.filter(kb => kb.enabled)
|
||||||
{ id: 'open', name: '打开文档', keys: ['Ctrl', 'O'], isEditing: false },
|
.map(kb => ({
|
||||||
{ id: 'find', name: '查找', keys: ['Ctrl', 'F'], isEditing: false },
|
id: kb.command,
|
||||||
{ id: 'replace', name: '替换', keys: ['Ctrl', 'H'], isEditing: false },
|
keys: parseKeyBinding(kb.key, kb.command),
|
||||||
]);
|
category: kb.category,
|
||||||
|
description: getCommandDescription(kb.command) || kb.command
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
// 切换编辑状态
|
// 解析快捷键字符串为显示数组
|
||||||
const toggleEdit = (binding: KeyBinding) => {
|
const parseKeyBinding = (keyStr: string, command?: string): string[] => {
|
||||||
// 先关闭其他所有编辑中的项
|
if (!keyStr) return [];
|
||||||
keyBindings.value.forEach(item => {
|
|
||||||
if (item.id !== binding.id) {
|
// 特殊处理重做快捷键的操作系统差异
|
||||||
item.isEditing = false;
|
if (command === KeyBindingCommand.HistoryRedoCommand && keyStr === 'Mod-Shift-z') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', '⇧', 'Z']; // macOS: Cmd+Shift+Z
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', 'Y']; // Windows/Linux: Ctrl+Y
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// 切换当前项
|
|
||||||
binding.isEditing = !binding.isEditing;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 编辑模式下按键事件处理
|
|
||||||
const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
|
|
||||||
if (!binding.isEditing) return;
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
const newKeys: string[] = [];
|
|
||||||
if (event.ctrlKey) newKeys.push('Ctrl');
|
|
||||||
if (event.shiftKey) newKeys.push('Shift');
|
|
||||||
if (event.altKey) newKeys.push('Alt');
|
|
||||||
|
|
||||||
// 获取按键
|
|
||||||
let keyName = event.key;
|
|
||||||
if (keyName === ' ') keyName = 'Space';
|
|
||||||
if (keyName.length === 1) keyName = keyName.toUpperCase();
|
|
||||||
|
|
||||||
// 如果有修饰键,就添加主键
|
|
||||||
if (event.ctrlKey || event.shiftKey || event.altKey) {
|
|
||||||
if (!['Control', 'Shift', 'Alt'].includes(keyName)) {
|
|
||||||
newKeys.push(keyName);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 没有修饰键,直接使用主键
|
|
||||||
newKeys.push(keyName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 唯一按键,不增加空字段
|
// 特殊处理重做选择快捷键的操作系统差异
|
||||||
if (newKeys.length > 0) {
|
if (command === KeyBindingCommand.HistoryRedoSelectionCommand && keyStr === 'Mod-Shift-u') {
|
||||||
binding.keys = [...new Set(newKeys)];
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', '⇧', 'U']; // macOS: Cmd+Shift+U
|
||||||
|
} else {
|
||||||
|
return ['Alt', 'U']; // Windows/Linux: Alt+U
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 完成编辑
|
// 特殊处理代码折叠快捷键的操作系统差异
|
||||||
binding.isEditing = false;
|
if (command === KeyBindingCommand.FoldCodeCommand && keyStr === 'Ctrl-Shift-[') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', '⌥', '[']; // macOS: Cmd+Alt+[
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', '⇧', '[']; // Windows/Linux: Ctrl+Shift+[
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.UnfoldCodeCommand && keyStr === 'Ctrl-Shift-]') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', '⌥', ']']; // macOS: Cmd+Alt+]
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', '⇧', ']']; // Windows/Linux: Ctrl+Shift+]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊处理编辑快捷键的操作系统差异
|
||||||
|
if (command === KeyBindingCommand.CursorSyntaxLeftCommand && keyStr === 'Alt-ArrowLeft') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['Ctrl', '←']; // macOS: Ctrl+ArrowLeft
|
||||||
|
} else {
|
||||||
|
return ['Alt', '←']; // Windows/Linux: Alt+ArrowLeft
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.CursorSyntaxRightCommand && keyStr === 'Alt-ArrowRight') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['Ctrl', '→']; // macOS: Ctrl+ArrowRight
|
||||||
|
} else {
|
||||||
|
return ['Alt', '→']; // Windows/Linux: Alt+ArrowRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.InsertBlankLineCommand && keyStr === 'Ctrl-Enter') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', 'Enter']; // macOS: Cmd+Enter
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', 'Enter']; // Windows/Linux: Ctrl+Enter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.SelectLineCommand && keyStr === 'Alt-l') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['Ctrl', 'L']; // macOS: Ctrl+l
|
||||||
|
} else {
|
||||||
|
return ['Alt', 'L']; // Windows/Linux: Alt+l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.SelectParentSyntaxCommand && keyStr === 'Ctrl-i') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', 'I']; // macOS: Cmd+i
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', 'I']; // Windows/Linux: Ctrl+i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.IndentLessCommand && keyStr === 'Ctrl-[') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', '[']; // macOS: Cmd+[
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', '[']; // Windows/Linux: Ctrl+[
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.IndentMoreCommand && keyStr === 'Ctrl-]') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', ']']; // macOS: Cmd+]
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', ']']; // Windows/Linux: Ctrl+]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.IndentSelectionCommand && keyStr === 'Ctrl-Alt-\\') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', '⌥', '\\']; // macOS: Cmd+Alt+\
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', 'Alt', '\\']; // Windows/Linux: Ctrl+Alt+\
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.CursorMatchingBracketCommand && keyStr === 'Shift-Ctrl-\\') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⇧', '⌘', '\\']; // macOS: Shift+Cmd+\
|
||||||
|
} else {
|
||||||
|
return ['⇧', 'Ctrl', '\\']; // Windows/Linux: Shift+Ctrl+\
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.ToggleCommentCommand && keyStr === 'Ctrl-/') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', '/']; // macOS: Cmd+/
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', '/']; // Windows/Linux: Ctrl+/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊处理删除快捷键的操作系统差异
|
||||||
|
if (command === KeyBindingCommand.DeleteGroupBackwardCommand && keyStr === 'Ctrl-Backspace') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', 'Backspace']; // macOS: Cmd+Backspace
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', 'Backspace']; // Windows/Linux: Ctrl+Backspace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command === KeyBindingCommand.DeleteGroupForwardCommand && keyStr === 'Ctrl-Delete') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return ['⌘', 'Delete']; // macOS: Cmd+Delete
|
||||||
|
} else {
|
||||||
|
return ['Ctrl', 'Delete']; // Windows/Linux: Ctrl+Delete
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理常见的快捷键格式
|
||||||
|
const parts = keyStr.split(/[-+]/);
|
||||||
|
return parts.map(part => {
|
||||||
|
// 根据操作系统将 Mod 替换为相应的键
|
||||||
|
if (part === 'Mod') {
|
||||||
|
if (systemStore.isMacOS) {
|
||||||
|
return '⌘'; // macOS 使用 Command 键符号
|
||||||
|
} else {
|
||||||
|
return 'Ctrl'; // Windows/Linux 使用 Ctrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理其他键名的操作系统差异
|
||||||
|
if (part === 'Alt' && systemStore.isMacOS) {
|
||||||
|
return '⌥'; // macOS 使用 Option 键符号
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part === 'Shift') {
|
||||||
|
return systemStore.isMacOS ? '⇧' : 'Shift'; // macOS 使用符号
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首字母大写
|
||||||
|
return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
||||||
|
}).filter(part => part.length > 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 组件挂载时加载快捷键数据
|
||||||
|
onMounted(async () => {
|
||||||
|
await keybindingStore.loadKeyBindings();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -76,42 +198,27 @@ const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
|
|||||||
<SettingSection :title="t('settings.keyBindings')">
|
<SettingSection :title="t('settings.keyBindings')">
|
||||||
<div class="key-bindings-container">
|
<div class="key-bindings-container">
|
||||||
<div class="key-bindings-header">
|
<div class="key-bindings-header">
|
||||||
<div class="command-col">命令</div>
|
<div class="keybinding-col">{{ t('keybindings.headers.shortcut') }}</div>
|
||||||
<div class="keybinding-col">快捷键</div>
|
<div class="category-col">{{ t('keybindings.headers.category') }}</div>
|
||||||
<div class="action-col">操作</div>
|
<div class="description-col">{{ t('keybindings.headers.description') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-for="binding in keyBindings"
|
v-for="binding in keyBindings"
|
||||||
:key="binding.id"
|
:key="binding.id"
|
||||||
class="key-binding-row"
|
class="key-binding-row"
|
||||||
:class="{ 'is-editing': binding.isEditing }"
|
|
||||||
@keydown="(e) => handleKeyDown(e, binding)"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div class="command-col">{{ binding.name }}</div>
|
<div class="keybinding-col">
|
||||||
<div class="keybinding-col" :class="{ 'is-editing': binding.isEditing }">
|
<span
|
||||||
<template v-if="binding.isEditing">
|
v-for="(key, index) in binding.keys"
|
||||||
按下快捷键...
|
:key="index"
|
||||||
</template>
|
class="key-badge"
|
||||||
<template v-else>
|
|
||||||
<span
|
|
||||||
v-for="(key, index) in binding.keys"
|
|
||||||
:key="index"
|
|
||||||
class="key-badge"
|
|
||||||
>
|
|
||||||
{{ key }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<div class="action-col">
|
|
||||||
<button
|
|
||||||
class="edit-button"
|
|
||||||
@click="toggleEdit(binding)"
|
|
||||||
>
|
>
|
||||||
{{ binding.isEditing ? '取消' : '编辑' }}
|
{{ key }}
|
||||||
</button>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="category-col">{{ binding.category }}</div>
|
||||||
|
<div class="description-col">{{ binding.description }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SettingSection>
|
</SettingSection>
|
||||||
@@ -143,36 +250,17 @@ const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
transition: background-color 0.2s ease;
|
transition: background-color 0.2s ease;
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--settings-hover);
|
background-color: var(--settings-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-editing {
|
|
||||||
background-color: rgba(74, 158, 255, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.command-col {
|
|
||||||
flex: 1;
|
|
||||||
padding-right: 10px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--settings-text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.keybinding-col {
|
.keybinding-col {
|
||||||
width: 200px;
|
width: 150px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
padding: 0 10px;
|
padding: 0 10px 0 0;
|
||||||
|
color: var(--settings-text);
|
||||||
&.is-editing {
|
|
||||||
font-style: italic;
|
|
||||||
color: var(--text-muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-badge {
|
.key-badge {
|
||||||
background-color: var(--settings-input-bg);
|
background-color: var(--settings-input-bg);
|
||||||
@@ -184,29 +272,18 @@ const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-col {
|
.category-col {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
text-align: right;
|
padding: 0 10px 0 0;
|
||||||
|
font-size: 13px;
|
||||||
.edit-button {
|
color: var(--settings-text);
|
||||||
padding: 5px 10px;
|
text-transform: capitalize;
|
||||||
background-color: var(--settings-input-bg);
|
}
|
||||||
border: 1px solid var(--settings-input-border);
|
|
||||||
border-radius: 4px;
|
.description-col {
|
||||||
color: var(--settings-text);
|
flex: 1;
|
||||||
cursor: pointer;
|
font-size: 13px;
|
||||||
font-size: 12px;
|
color: var(--settings-text);
|
||||||
transition: all 0.2s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--settings-hover);
|
|
||||||
border-color: var(--settings-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
transform: translateY(1px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,9 +4,8 @@ import "time"
|
|||||||
|
|
||||||
// KeyBinding 单个快捷键绑定
|
// KeyBinding 单个快捷键绑定
|
||||||
type KeyBinding struct {
|
type KeyBinding struct {
|
||||||
Action KeyBindingAction `json:"action"` // 快捷键动作
|
Command KeyBindingCommand `json:"command"` // 快捷键动作
|
||||||
Category KeyBindingCategory `json:"category"` // 快捷键分类
|
Category KeyBindingCategory `json:"category"` // 快捷键分类
|
||||||
Scope KeyBindingScope `json:"scope"` // 快捷键作用域
|
|
||||||
Key string `json:"key"` // 快捷键组合(如 "Mod-f", "Ctrl-Shift-p")
|
Key string `json:"key"` // 快捷键组合(如 "Mod-f", "Ctrl-Shift-p")
|
||||||
Enabled bool `json:"enabled"` // 是否启用
|
Enabled bool `json:"enabled"` // 是否启用
|
||||||
IsDefault bool `json:"isDefault"` // 是否为默认快捷键
|
IsDefault bool `json:"isDefault"` // 是否为默认快捷键
|
||||||
@@ -16,77 +15,80 @@ type KeyBinding struct {
|
|||||||
type KeyBindingCategory string
|
type KeyBindingCategory string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CategorySearch KeyBindingCategory = "search" // 搜索相关
|
CategorySearch KeyBindingCategory = "search" // 搜索相关
|
||||||
CategoryEdit KeyBindingCategory = "edit" // 编辑相关
|
CategoryEdit KeyBindingCategory = "edit" // 编辑相关
|
||||||
CategoryCodeBlock KeyBindingCategory = "codeblock" // 代码块相关
|
CategoryCodeBlock KeyBindingCategory = "block" // 代码块相关
|
||||||
CategoryNavigation KeyBindingCategory = "navigation" // 导航相关
|
CategoryHistory KeyBindingCategory = "history" // 历史记录相关
|
||||||
CategoryView KeyBindingCategory = "view" // 视图相关
|
CategoryFold KeyBindingCategory = "fold" // 代码折叠相关
|
||||||
CategoryFile KeyBindingCategory = "file" // 文件相关
|
|
||||||
CategoryApp KeyBindingCategory = "app" // 应用相关
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyBindingScope 快捷键作用域
|
// KeyBindingCommand 快捷键命令
|
||||||
type KeyBindingScope string
|
type KeyBindingCommand string
|
||||||
|
|
||||||
const (
|
|
||||||
ScopeGlobal KeyBindingScope = "global" // 全局作用域
|
|
||||||
ScopeEditor KeyBindingScope = "editor" // 编辑器作用域
|
|
||||||
ScopeSearch KeyBindingScope = "search" // 搜索面板作用域
|
|
||||||
)
|
|
||||||
|
|
||||||
// KeyBindingAction 快捷键动作类型
|
|
||||||
type KeyBindingAction string
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// 搜索相关
|
// 搜索相关
|
||||||
ActionShowSearch KeyBindingAction = "showSearch" // 显示搜索
|
ShowSearchCommand KeyBindingCommand = "showSearch" // 显示搜索
|
||||||
ActionHideSearch KeyBindingAction = "hideSearch" // 隐藏搜索
|
HideSearchCommand KeyBindingCommand = "hideSearch" // 隐藏搜索
|
||||||
ActionFindNext KeyBindingAction = "findNext" // 查找下一个
|
SearchToggleCaseCommand KeyBindingCommand = "searchToggleCase" // 搜索切换大小写
|
||||||
ActionFindPrevious KeyBindingAction = "findPrevious" // 查找上一个
|
SearchToggleWordCommand KeyBindingCommand = "searchToggleWord" // 搜索切换整词
|
||||||
ActionShowReplace KeyBindingAction = "showReplace" // 显示替换
|
SearchToggleRegexCommand KeyBindingCommand = "searchToggleRegex" // 搜索切换正则
|
||||||
ActionReplaceNext KeyBindingAction = "replaceNext" // 替换下一个
|
SearchShowReplaceCommand KeyBindingCommand = "searchShowReplace" // 显示替换
|
||||||
ActionReplaceAll KeyBindingAction = "replaceAll" // 替换全部
|
SearchReplaceAllCommand KeyBindingCommand = "searchReplaceAll" // 替换全部
|
||||||
ActionToggleCase KeyBindingAction = "toggleCase" // 切换大小写匹配
|
|
||||||
ActionToggleWholeWord KeyBindingAction = "toggleWholeWord" // 切换全词匹配
|
|
||||||
ActionToggleRegex KeyBindingAction = "toggleRegex" // 切换正则表达式
|
|
||||||
|
|
||||||
// 编辑相关
|
|
||||||
ActionSelectAll KeyBindingAction = "selectAll" // 全选
|
|
||||||
ActionCopy KeyBindingAction = "copy" // 复制
|
|
||||||
ActionCut KeyBindingAction = "cut" // 剪切
|
|
||||||
ActionPaste KeyBindingAction = "paste" // 粘贴
|
|
||||||
ActionUndo KeyBindingAction = "undo" // 撤销
|
|
||||||
ActionRedo KeyBindingAction = "redo" // 重做
|
|
||||||
ActionDuplicateLine KeyBindingAction = "duplicateLine" // 复制行
|
|
||||||
ActionDeleteLine KeyBindingAction = "deleteLine" // 删除行
|
|
||||||
ActionMoveLineUp KeyBindingAction = "moveLineUp" // 上移行
|
|
||||||
ActionMoveLineDown KeyBindingAction = "moveLineDown" // 下移行
|
|
||||||
ActionToggleComment KeyBindingAction = "toggleComment" // 切换注释
|
|
||||||
ActionIndent KeyBindingAction = "indent" // 缩进
|
|
||||||
ActionOutdent KeyBindingAction = "outdent" // 取消缩进
|
|
||||||
|
|
||||||
// 代码块相关
|
// 代码块相关
|
||||||
ActionNewCodeBlock KeyBindingAction = "newCodeBlock" // 新建代码块
|
BlockSelectAllCommand KeyBindingCommand = "blockSelectAll" // 块内选择全部
|
||||||
ActionDeleteCodeBlock KeyBindingAction = "deleteCodeBlock" // 删除代码块
|
BlockAddAfterCurrentCommand KeyBindingCommand = "blockAddAfterCurrent" // 在当前块后添加新块
|
||||||
ActionSelectCodeBlock KeyBindingAction = "selectCodeBlock" // 选择代码块
|
BlockAddAfterLastCommand KeyBindingCommand = "blockAddAfterLast" // 在最后添加新块
|
||||||
ActionFormatCode KeyBindingAction = "formatCode" // 格式化代码
|
BlockAddBeforeCurrentCommand KeyBindingCommand = "blockAddBeforeCurrent" // 在当前块前添加新块
|
||||||
ActionChangeLanguage KeyBindingAction = "changeLanguage" // 更改语言
|
BlockGotoPreviousCommand KeyBindingCommand = "blockGotoPrevious" // 跳转到上一个块
|
||||||
|
BlockGotoNextCommand KeyBindingCommand = "blockGotoNext" // 跳转到下一个块
|
||||||
|
BlockSelectPreviousCommand KeyBindingCommand = "blockSelectPrevious" // 选择上一个块
|
||||||
|
BlockSelectNextCommand KeyBindingCommand = "blockSelectNext" // 选择下一个块
|
||||||
|
BlockDeleteCommand KeyBindingCommand = "blockDelete" // 删除当前块
|
||||||
|
BlockMoveUpCommand KeyBindingCommand = "blockMoveUp" // 向上移动当前块
|
||||||
|
BlockMoveDownCommand KeyBindingCommand = "blockMoveDown" // 向下移动当前块
|
||||||
|
BlockDeleteLineCommand KeyBindingCommand = "blockDeleteLine" // 删除行
|
||||||
|
BlockMoveLineUpCommand KeyBindingCommand = "blockMoveLineUp" // 向上移动行
|
||||||
|
BlockMoveLineDownCommand KeyBindingCommand = "blockMoveLineDown" // 向下移动行
|
||||||
|
BlockTransposeCharsCommand KeyBindingCommand = "blockTransposeChars" // 字符转置
|
||||||
|
BlockFormatCommand KeyBindingCommand = "blockFormat" // 格式化代码块
|
||||||
|
BlockCopyCommand KeyBindingCommand = "blockCopy" // 复制
|
||||||
|
BlockCutCommand KeyBindingCommand = "blockCut" // 剪切
|
||||||
|
BlockPasteCommand KeyBindingCommand = "blockPaste" // 粘贴
|
||||||
|
|
||||||
// 导航相关
|
// 历史记录相关
|
||||||
ActionGoToLine KeyBindingAction = "goToLine" // 跳转到行
|
HistoryUndoCommand KeyBindingCommand = "historyUndo" // 撤销
|
||||||
ActionFoldAll KeyBindingAction = "foldAll" // 折叠所有
|
HistoryRedoCommand KeyBindingCommand = "historyRedo" // 重做
|
||||||
ActionUnfoldAll KeyBindingAction = "unfoldAll" // 展开所有
|
HistoryUndoSelectionCommand KeyBindingCommand = "historyUndoSelection" // 撤销选择
|
||||||
ActionToggleFold KeyBindingAction = "toggleFold" // 切换折叠
|
HistoryRedoSelectionCommand KeyBindingCommand = "historyRedoSelection" // 重做选择
|
||||||
|
|
||||||
// 视图相关
|
// 代码折叠相关
|
||||||
ActionZoomIn KeyBindingAction = "zoomIn" // 放大
|
FoldCodeCommand KeyBindingCommand = "foldCode" // 折叠代码
|
||||||
ActionZoomOut KeyBindingAction = "zoomOut" // 缩小
|
UnfoldCodeCommand KeyBindingCommand = "unfoldCode" // 展开代码
|
||||||
ActionResetZoom KeyBindingAction = "resetZoom" // 重置缩放
|
FoldAllCommand KeyBindingCommand = "foldAll" // 折叠全部
|
||||||
ActionToggleMinimap KeyBindingAction = "toggleMinimap" // 切换小地图
|
UnfoldAllCommand KeyBindingCommand = "unfoldAll" // 展开全部
|
||||||
ActionToggleLineNumbers KeyBindingAction = "toggleLineNumbers" // 切换行号
|
|
||||||
|
|
||||||
// 文件相关
|
// 编辑相关
|
||||||
ActionSave KeyBindingAction = "save" // 保存
|
CursorSyntaxLeftCommand KeyBindingCommand = "cursorSyntaxLeft" // 光标按语法左移
|
||||||
|
CursorSyntaxRightCommand KeyBindingCommand = "cursorSyntaxRight" // 光标按语法右移
|
||||||
|
SelectSyntaxLeftCommand KeyBindingCommand = "selectSyntaxLeft" // 按语法选择左侧
|
||||||
|
SelectSyntaxRightCommand KeyBindingCommand = "selectSyntaxRight" // 按语法选择右侧
|
||||||
|
CopyLineUpCommand KeyBindingCommand = "copyLineUp" // 向上复制行
|
||||||
|
CopyLineDownCommand KeyBindingCommand = "copyLineDown" // 向下复制行
|
||||||
|
InsertBlankLineCommand KeyBindingCommand = "insertBlankLine" // 插入空行
|
||||||
|
SelectLineCommand KeyBindingCommand = "selectLine" // 选择行
|
||||||
|
SelectParentSyntaxCommand KeyBindingCommand = "selectParentSyntax" // 选择父级语法
|
||||||
|
IndentLessCommand KeyBindingCommand = "indentLess" // 减少缩进
|
||||||
|
IndentMoreCommand KeyBindingCommand = "indentMore" // 增加缩进
|
||||||
|
IndentSelectionCommand KeyBindingCommand = "indentSelection" // 缩进选择
|
||||||
|
CursorMatchingBracketCommand KeyBindingCommand = "cursorMatchingBracket" // 光标到匹配括号
|
||||||
|
ToggleCommentCommand KeyBindingCommand = "toggleComment" // 切换注释
|
||||||
|
ToggleBlockCommentCommand KeyBindingCommand = "toggleBlockComment" // 切换块注释
|
||||||
|
InsertNewlineAndIndentCommand KeyBindingCommand = "insertNewlineAndIndent" // 插入新行并缩进
|
||||||
|
DeleteCharBackwardCommand KeyBindingCommand = "deleteCharBackward" // 向后删除字符
|
||||||
|
DeleteCharForwardCommand KeyBindingCommand = "deleteCharForward" // 向前删除字符
|
||||||
|
DeleteGroupBackwardCommand KeyBindingCommand = "deleteGroupBackward" // 向后删除组
|
||||||
|
DeleteGroupForwardCommand KeyBindingCommand = "deleteGroupForward" // 向前删除组
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyBindingMetadata 快捷键配置元数据
|
// KeyBindingMetadata 快捷键配置元数据
|
||||||
@@ -115,308 +117,388 @@ func NewDefaultKeyBindings() []KeyBinding {
|
|||||||
return []KeyBinding{
|
return []KeyBinding{
|
||||||
// 搜索相关快捷键
|
// 搜索相关快捷键
|
||||||
{
|
{
|
||||||
Action: ActionShowSearch,
|
Command: ShowSearchCommand,
|
||||||
Category: CategorySearch,
|
Category: CategorySearch,
|
||||||
Scope: ScopeGlobal,
|
|
||||||
Key: "Mod-f",
|
Key: "Mod-f",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionHideSearch,
|
Command: HideSearchCommand,
|
||||||
Category: CategorySearch,
|
Category: CategorySearch,
|
||||||
Scope: ScopeSearch,
|
|
||||||
Key: "Escape",
|
Key: "Escape",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionFindNext,
|
Command: SearchToggleCaseCommand,
|
||||||
Category: CategorySearch,
|
Category: CategorySearch,
|
||||||
Scope: ScopeSearch,
|
|
||||||
Key: "Enter",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionFindPrevious,
|
|
||||||
Category: CategorySearch,
|
|
||||||
Scope: ScopeSearch,
|
|
||||||
Key: "Shift-Enter",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionShowReplace,
|
|
||||||
Category: CategorySearch,
|
|
||||||
Scope: ScopeSearch,
|
|
||||||
Key: "Mod-h",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionReplaceAll,
|
|
||||||
Category: CategorySearch,
|
|
||||||
Scope: ScopeSearch,
|
|
||||||
Key: "Mod-Alt-Enter",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionToggleCase,
|
|
||||||
Category: CategorySearch,
|
|
||||||
Scope: ScopeSearch,
|
|
||||||
Key: "Alt-c",
|
Key: "Alt-c",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionToggleWholeWord,
|
Command: SearchToggleWordCommand,
|
||||||
Category: CategorySearch,
|
Category: CategorySearch,
|
||||||
Scope: ScopeSearch,
|
|
||||||
Key: "Alt-w",
|
Key: "Alt-w",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionToggleRegex,
|
Command: SearchToggleRegexCommand,
|
||||||
Category: CategorySearch,
|
Category: CategorySearch,
|
||||||
Scope: ScopeSearch,
|
|
||||||
Key: "Alt-r",
|
Key: "Alt-r",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 编辑相关快捷键
|
|
||||||
{
|
{
|
||||||
Action: ActionSelectAll,
|
Command: SearchShowReplaceCommand,
|
||||||
Category: CategoryEdit,
|
Category: CategorySearch,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-h",
|
||||||
Key: "Mod-a",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionCopy,
|
Command: SearchReplaceAllCommand,
|
||||||
Category: CategoryEdit,
|
Category: CategorySearch,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-Alt-Enter",
|
||||||
Key: "Mod-c",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionCut,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Mod-x",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionPaste,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Mod-v",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionUndo,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Mod-z",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionRedo,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Mod-y",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionDuplicateLine,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Mod-d",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionDeleteLine,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Mod-Shift-k",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionMoveLineUp,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Alt-ArrowUp",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionMoveLineDown,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Alt-ArrowDown",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionToggleComment,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Mod-/",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionIndent,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Tab",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionOutdent,
|
|
||||||
Category: CategoryEdit,
|
|
||||||
Scope: ScopeEditor,
|
|
||||||
Key: "Shift-Tab",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 代码块相关快捷键
|
// 代码块相关快捷键
|
||||||
{
|
{
|
||||||
Action: ActionNewCodeBlock,
|
Command: BlockSelectAllCommand,
|
||||||
Category: CategoryCodeBlock,
|
Category: CategoryCodeBlock,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-a",
|
||||||
Key: "Mod-Alt-n",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionDeleteCodeBlock,
|
Command: BlockAddAfterCurrentCommand,
|
||||||
Category: CategoryCodeBlock,
|
Category: CategoryCodeBlock,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-Enter",
|
||||||
Key: "Mod-Alt-d",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionSelectCodeBlock,
|
Command: BlockAddAfterLastCommand,
|
||||||
Category: CategoryCodeBlock,
|
Category: CategoryCodeBlock,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-Shift-Enter",
|
||||||
Key: "Mod-Alt-a",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionFormatCode,
|
Command: BlockAddBeforeCurrentCommand,
|
||||||
Category: CategoryCodeBlock,
|
Category: CategoryCodeBlock,
|
||||||
Scope: ScopeEditor,
|
Key: "Alt-Enter",
|
||||||
Key: "Mod-Alt-f",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionChangeLanguage,
|
Command: BlockGotoPreviousCommand,
|
||||||
Category: CategoryCodeBlock,
|
Category: CategoryCodeBlock,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-ArrowUp",
|
||||||
Key: "Mod-Alt-l",
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockGotoNextCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-ArrowDown",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockSelectPreviousCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-Shift-ArrowUp",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockSelectNextCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-Shift-ArrowDown",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockDeleteCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-Shift-d",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockMoveUpCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Alt-Mod-ArrowUp",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockMoveDownCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Alt-Mod-ArrowDown",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockDeleteLineCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-Shift-k",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockMoveLineUpCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Alt-ArrowUp",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockMoveLineDownCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Alt-ArrowDown",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockTransposeCharsCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Ctrl-t",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockFormatCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-Shift-f",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockCopyCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-c",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockCutCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-x",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: BlockPasteCommand,
|
||||||
|
Category: CategoryCodeBlock,
|
||||||
|
Key: "Mod-v",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 导航相关快捷键
|
// 历史记录相关快捷键
|
||||||
{
|
{
|
||||||
Action: ActionGoToLine,
|
Command: HistoryUndoCommand,
|
||||||
Category: CategoryNavigation,
|
Category: CategoryHistory,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-z",
|
||||||
Key: "Mod-g",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionFoldAll,
|
Command: HistoryRedoCommand,
|
||||||
Category: CategoryNavigation,
|
Category: CategoryHistory,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-Shift-z",
|
||||||
Key: "Mod-k Mod-0",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionUnfoldAll,
|
Command: HistoryUndoSelectionCommand,
|
||||||
Category: CategoryNavigation,
|
Category: CategoryHistory,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-u",
|
||||||
Key: "Mod-k Mod-j",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionToggleFold,
|
Command: HistoryRedoSelectionCommand,
|
||||||
Category: CategoryNavigation,
|
Category: CategoryHistory,
|
||||||
Scope: ScopeEditor,
|
Key: "Mod-Shift-u",
|
||||||
Key: "Mod-k Mod-l",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 视图相关快捷键
|
// 代码折叠相关快捷键
|
||||||
{
|
{
|
||||||
Action: ActionZoomIn,
|
Command: FoldCodeCommand,
|
||||||
Category: CategoryView,
|
Category: CategoryFold,
|
||||||
Scope: ScopeGlobal,
|
Key: "Ctrl-Shift-[",
|
||||||
Key: "Mod-=",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionZoomOut,
|
Command: UnfoldCodeCommand,
|
||||||
Category: CategoryView,
|
Category: CategoryFold,
|
||||||
Scope: ScopeGlobal,
|
Key: "Ctrl-Shift-]",
|
||||||
Key: "Mod--",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionResetZoom,
|
Command: FoldAllCommand,
|
||||||
Category: CategoryView,
|
Category: CategoryFold,
|
||||||
Scope: ScopeGlobal,
|
Key: "Ctrl-Alt-[",
|
||||||
Key: "Mod-0",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: ActionToggleMinimap,
|
Command: UnfoldAllCommand,
|
||||||
Category: CategoryView,
|
Category: CategoryFold,
|
||||||
Scope: ScopeGlobal,
|
Key: "Ctrl-Alt-]",
|
||||||
Key: "Mod-m",
|
|
||||||
Enabled: true,
|
|
||||||
IsDefault: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: ActionToggleLineNumbers,
|
|
||||||
Category: CategoryView,
|
|
||||||
Scope: ScopeGlobal,
|
|
||||||
Key: "Mod-l",
|
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 文件相关快捷键
|
// 编辑相关快捷键 (避免冲突的快捷键)
|
||||||
{
|
{
|
||||||
Action: ActionSave,
|
Command: CursorSyntaxLeftCommand,
|
||||||
Category: CategoryFile,
|
Category: CategoryEdit,
|
||||||
Scope: ScopeGlobal,
|
Key: "Alt-ArrowLeft",
|
||||||
Key: "Mod-s",
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: CursorSyntaxRightCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Alt-ArrowRight",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: SelectSyntaxLeftCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Shift-Alt-ArrowLeft",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: SelectSyntaxRightCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Shift-Alt-ArrowRight",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: CopyLineUpCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Shift-Alt-ArrowUp",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: CopyLineDownCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Shift-Alt-ArrowDown",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: InsertBlankLineCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Ctrl-Enter",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: SelectLineCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Alt-l",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: SelectParentSyntaxCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Ctrl-i",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: IndentLessCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Ctrl-[",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: IndentMoreCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Ctrl-]",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: IndentSelectionCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Ctrl-Alt-\\",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: CursorMatchingBracketCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Shift-Ctrl-\\",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: ToggleCommentCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Ctrl-/",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: ToggleBlockCommentCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Shift-Alt-a",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: InsertNewlineAndIndentCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Enter",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: DeleteCharBackwardCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Backspace",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: DeleteCharForwardCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Delete",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: DeleteGroupBackwardCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Ctrl-Backspace",
|
||||||
|
Enabled: true,
|
||||||
|
IsDefault: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Command: DeleteGroupForwardCommand,
|
||||||
|
Category: CategoryEdit,
|
||||||
|
Key: "Ctrl-Delete",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
},
|
},
|
||||||
|
@@ -26,14 +26,14 @@ type KeyBindingService struct {
|
|||||||
// KeyBindingError 快捷键错误
|
// KeyBindingError 快捷键错误
|
||||||
type KeyBindingError struct {
|
type KeyBindingError struct {
|
||||||
Operation string // 操作名称
|
Operation string // 操作名称
|
||||||
Action string // 快捷键Action
|
Command string // 快捷键Command
|
||||||
Err error // 原始错误
|
Err error // 原始错误
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error 实现error接口
|
// Error 实现error接口
|
||||||
func (e *KeyBindingError) Error() string {
|
func (e *KeyBindingError) Error() string {
|
||||||
if e.Action != "" {
|
if e.Command != "" {
|
||||||
return fmt.Sprintf("keybinding error during %s for action %s: %v", e.Operation, e.Action, e.Err)
|
return fmt.Sprintf("keybinding error during %s for command %s: %v", e.Operation, e.Command, e.Err)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("keybinding error during %s: %v", e.Operation, e.Err)
|
return fmt.Sprintf("keybinding error during %s: %v", e.Operation, e.Err)
|
||||||
}
|
}
|
||||||
@@ -225,28 +225,8 @@ func (kbs *KeyBindingService) GetKeyBindingsByCategory(category models.KeyBindin
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetKeyBindingsByScope 根据作用域获取快捷键
|
// GetKeyBindingByCommand 根据命令获取快捷键
|
||||||
func (kbs *KeyBindingService) GetKeyBindingsByScope(scope models.KeyBindingScope) ([]models.KeyBinding, error) {
|
func (kbs *KeyBindingService) GetKeyBindingByCommand(command models.KeyBindingCommand) (*models.KeyBinding, error) {
|
||||||
kbs.mu.RLock()
|
|
||||||
defer kbs.mu.RUnlock()
|
|
||||||
|
|
||||||
allKeyBindings, err := kbs.GetAllKeyBindings()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var result []models.KeyBinding
|
|
||||||
for _, kb := range allKeyBindings {
|
|
||||||
if kb.Scope == scope && kb.Enabled {
|
|
||||||
result = append(result, kb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyBindingByAction 根据动作获取快捷键
|
|
||||||
func (kbs *KeyBindingService) GetKeyBindingByAction(action models.KeyBindingAction) (*models.KeyBinding, error) {
|
|
||||||
kbs.mu.RLock()
|
kbs.mu.RLock()
|
||||||
defer kbs.mu.RUnlock()
|
defer kbs.mu.RUnlock()
|
||||||
|
|
||||||
@@ -256,19 +236,19 @@ func (kbs *KeyBindingService) GetKeyBindingByAction(action models.KeyBindingActi
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, kb := range allKeyBindings {
|
for _, kb := range allKeyBindings {
|
||||||
if kb.Action == action && kb.Enabled {
|
if kb.Command == command && kb.Enabled {
|
||||||
return &kb, nil
|
return &kb, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, &KeyBindingError{
|
return nil, &KeyBindingError{
|
||||||
Operation: "get_keybinding_by_action",
|
Operation: "get_keybinding_by_command",
|
||||||
Err: fmt.Errorf("keybinding for action %s not found", action),
|
Err: fmt.Errorf("keybinding for command %s not found", command),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateKeyBinding 更新快捷键
|
// UpdateKeyBinding 更新快捷键
|
||||||
func (kbs *KeyBindingService) UpdateKeyBinding(action models.KeyBindingAction, newKey string) error {
|
func (kbs *KeyBindingService) UpdateKeyBinding(command models.KeyBindingCommand, newKey string) error {
|
||||||
kbs.mu.Lock()
|
kbs.mu.Lock()
|
||||||
defer kbs.mu.Unlock()
|
defer kbs.mu.Unlock()
|
||||||
|
|
||||||
@@ -276,16 +256,16 @@ func (kbs *KeyBindingService) UpdateKeyBinding(action models.KeyBindingAction, n
|
|||||||
if err := kbs.validateKeyFormat(newKey); err != nil {
|
if err := kbs.validateKeyFormat(newKey); err != nil {
|
||||||
return &KeyBindingError{
|
return &KeyBindingError{
|
||||||
Operation: "update_keybinding",
|
Operation: "update_keybinding",
|
||||||
Action: string(action),
|
Command: string(command),
|
||||||
Err: fmt.Errorf("invalid key format: %v", err),
|
Err: fmt.Errorf("invalid key format: %v", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查快捷键冲突
|
// 检查快捷键冲突
|
||||||
if err := kbs.checkKeyConflict(action, newKey); err != nil {
|
if err := kbs.checkKeyConflict(command, newKey); err != nil {
|
||||||
return &KeyBindingError{
|
return &KeyBindingError{
|
||||||
Operation: "update_keybinding",
|
Operation: "update_keybinding",
|
||||||
Action: string(action),
|
Command: string(command),
|
||||||
Err: fmt.Errorf("key conflict: %v", err),
|
Err: fmt.Errorf("key conflict: %v", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,13 +273,13 @@ func (kbs *KeyBindingService) UpdateKeyBinding(action models.KeyBindingAction, n
|
|||||||
// 获取当前配置
|
// 获取当前配置
|
||||||
config, err := kbs.GetKeyBindingConfig()
|
config, err := kbs.GetKeyBindingConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &KeyBindingError{Operation: "update_keybinding", Action: string(action), Err: err}
|
return &KeyBindingError{Operation: "update_keybinding", Command: string(command), Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找并更新快捷键
|
// 查找并更新快捷键
|
||||||
found := false
|
found := false
|
||||||
for i, kb := range config.KeyBindings {
|
for i, kb := range config.KeyBindings {
|
||||||
if kb.Action == action {
|
if kb.Command == command {
|
||||||
config.KeyBindings[i].Key = newKey
|
config.KeyBindings[i].Key = newKey
|
||||||
config.KeyBindings[i].IsDefault = false // 标记为非默认
|
config.KeyBindings[i].IsDefault = false // 标记为非默认
|
||||||
found = true
|
found = true
|
||||||
@@ -310,7 +290,7 @@ func (kbs *KeyBindingService) UpdateKeyBinding(action models.KeyBindingAction, n
|
|||||||
if !found {
|
if !found {
|
||||||
return &KeyBindingError{
|
return &KeyBindingError{
|
||||||
Operation: "update_keybinding",
|
Operation: "update_keybinding",
|
||||||
Action: string(action),
|
Command: string(command),
|
||||||
Err: errors.New("keybinding not found"),
|
Err: errors.New("keybinding not found"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,38 +300,38 @@ func (kbs *KeyBindingService) UpdateKeyBinding(action models.KeyBindingAction, n
|
|||||||
|
|
||||||
// 保存配置
|
// 保存配置
|
||||||
if err := kbs.saveConfig(config); err != nil {
|
if err := kbs.saveConfig(config); err != nil {
|
||||||
return &KeyBindingError{Operation: "update_keybinding", Action: string(action), Err: err}
|
return &KeyBindingError{Operation: "update_keybinding", Command: string(command), Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
kbs.logger.Info("KeyBinding: Updated keybinding", "action", action, "newKey", newKey)
|
kbs.logger.Info("KeyBinding: Updated keybinding", "command", command, "newKey", newKey)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableKeyBinding 启用快捷键
|
// EnableKeyBinding 启用快捷键
|
||||||
func (kbs *KeyBindingService) EnableKeyBinding(action models.KeyBindingAction) error {
|
func (kbs *KeyBindingService) EnableKeyBinding(command models.KeyBindingCommand) error {
|
||||||
return kbs.setKeyBindingEnabled(action, true)
|
return kbs.setKeyBindingEnabled(command, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisableKeyBinding 禁用快捷键
|
// DisableKeyBinding 禁用快捷键
|
||||||
func (kbs *KeyBindingService) DisableKeyBinding(action models.KeyBindingAction) error {
|
func (kbs *KeyBindingService) DisableKeyBinding(command models.KeyBindingCommand) error {
|
||||||
return kbs.setKeyBindingEnabled(action, false)
|
return kbs.setKeyBindingEnabled(command, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setKeyBindingEnabled 设置快捷键启用状态
|
// setKeyBindingEnabled 设置快捷键启用状态
|
||||||
func (kbs *KeyBindingService) setKeyBindingEnabled(action models.KeyBindingAction, enabled bool) error {
|
func (kbs *KeyBindingService) setKeyBindingEnabled(command models.KeyBindingCommand, enabled bool) error {
|
||||||
kbs.mu.Lock()
|
kbs.mu.Lock()
|
||||||
defer kbs.mu.Unlock()
|
defer kbs.mu.Unlock()
|
||||||
|
|
||||||
// 获取当前配置
|
// 获取当前配置
|
||||||
config, err := kbs.GetKeyBindingConfig()
|
config, err := kbs.GetKeyBindingConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &KeyBindingError{Operation: "set_keybinding_enabled", Action: string(action), Err: err}
|
return &KeyBindingError{Operation: "set_keybinding_enabled", Command: string(command), Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找并更新快捷键
|
// 查找并更新快捷键
|
||||||
found := false
|
found := false
|
||||||
for i, kb := range config.KeyBindings {
|
for i, kb := range config.KeyBindings {
|
||||||
if kb.Action == action {
|
if kb.Command == command {
|
||||||
config.KeyBindings[i].Enabled = enabled
|
config.KeyBindings[i].Enabled = enabled
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
@@ -361,7 +341,7 @@ func (kbs *KeyBindingService) setKeyBindingEnabled(action models.KeyBindingActio
|
|||||||
if !found {
|
if !found {
|
||||||
return &KeyBindingError{
|
return &KeyBindingError{
|
||||||
Operation: "set_keybinding_enabled",
|
Operation: "set_keybinding_enabled",
|
||||||
Action: string(action),
|
Command: string(command),
|
||||||
Err: errors.New("keybinding not found"),
|
Err: errors.New("keybinding not found"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -371,19 +351,19 @@ func (kbs *KeyBindingService) setKeyBindingEnabled(action models.KeyBindingActio
|
|||||||
|
|
||||||
// 保存配置
|
// 保存配置
|
||||||
if err := kbs.saveConfig(config); err != nil {
|
if err := kbs.saveConfig(config); err != nil {
|
||||||
return &KeyBindingError{Operation: "set_keybinding_enabled", Action: string(action), Err: err}
|
return &KeyBindingError{Operation: "set_keybinding_enabled", Command: string(command), Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
status := "enabled"
|
status := "enabled"
|
||||||
if !enabled {
|
if !enabled {
|
||||||
status = "disabled"
|
status = "disabled"
|
||||||
}
|
}
|
||||||
kbs.logger.Info("KeyBinding: "+status+" keybinding", "action", action)
|
kbs.logger.Info("KeyBinding: "+status+" keybinding", "command", command)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetKeyBinding 重置快捷键到默认值
|
// ResetKeyBinding 重置快捷键到默认值
|
||||||
func (kbs *KeyBindingService) ResetKeyBinding(action models.KeyBindingAction) error {
|
func (kbs *KeyBindingService) ResetKeyBinding(command models.KeyBindingCommand) error {
|
||||||
kbs.mu.Lock()
|
kbs.mu.Lock()
|
||||||
defer kbs.mu.Unlock()
|
defer kbs.mu.Unlock()
|
||||||
|
|
||||||
@@ -391,7 +371,7 @@ func (kbs *KeyBindingService) ResetKeyBinding(action models.KeyBindingAction) er
|
|||||||
defaultKeyBindings := models.NewDefaultKeyBindings()
|
defaultKeyBindings := models.NewDefaultKeyBindings()
|
||||||
var defaultKeyBinding *models.KeyBinding
|
var defaultKeyBinding *models.KeyBinding
|
||||||
for _, kb := range defaultKeyBindings {
|
for _, kb := range defaultKeyBindings {
|
||||||
if kb.Action == action {
|
if kb.Command == command {
|
||||||
defaultKeyBinding = &kb
|
defaultKeyBinding = &kb
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -400,7 +380,7 @@ func (kbs *KeyBindingService) ResetKeyBinding(action models.KeyBindingAction) er
|
|||||||
if defaultKeyBinding == nil {
|
if defaultKeyBinding == nil {
|
||||||
return &KeyBindingError{
|
return &KeyBindingError{
|
||||||
Operation: "reset_keybinding",
|
Operation: "reset_keybinding",
|
||||||
Action: string(action),
|
Command: string(command),
|
||||||
Err: errors.New("default keybinding not found"),
|
Err: errors.New("default keybinding not found"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -408,13 +388,13 @@ func (kbs *KeyBindingService) ResetKeyBinding(action models.KeyBindingAction) er
|
|||||||
// 获取当前配置
|
// 获取当前配置
|
||||||
config, err := kbs.GetKeyBindingConfig()
|
config, err := kbs.GetKeyBindingConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &KeyBindingError{Operation: "reset_keybinding", Action: string(action), Err: err}
|
return &KeyBindingError{Operation: "reset_keybinding", Command: string(command), Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找并重置快捷键
|
// 查找并重置快捷键
|
||||||
found := false
|
found := false
|
||||||
for i, kb := range config.KeyBindings {
|
for i, kb := range config.KeyBindings {
|
||||||
if kb.Action == action {
|
if kb.Command == command {
|
||||||
config.KeyBindings[i].Key = defaultKeyBinding.Key
|
config.KeyBindings[i].Key = defaultKeyBinding.Key
|
||||||
config.KeyBindings[i].Enabled = defaultKeyBinding.Enabled
|
config.KeyBindings[i].Enabled = defaultKeyBinding.Enabled
|
||||||
config.KeyBindings[i].IsDefault = true
|
config.KeyBindings[i].IsDefault = true
|
||||||
@@ -426,7 +406,7 @@ func (kbs *KeyBindingService) ResetKeyBinding(action models.KeyBindingAction) er
|
|||||||
if !found {
|
if !found {
|
||||||
return &KeyBindingError{
|
return &KeyBindingError{
|
||||||
Operation: "reset_keybinding",
|
Operation: "reset_keybinding",
|
||||||
Action: string(action),
|
Command: string(command),
|
||||||
Err: errors.New("keybinding not found"),
|
Err: errors.New("keybinding not found"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,10 +416,10 @@ func (kbs *KeyBindingService) ResetKeyBinding(action models.KeyBindingAction) er
|
|||||||
|
|
||||||
// 保存配置
|
// 保存配置
|
||||||
if err := kbs.saveConfig(config); err != nil {
|
if err := kbs.saveConfig(config); err != nil {
|
||||||
return &KeyBindingError{Operation: "reset_keybinding", Action: string(action), Err: err}
|
return &KeyBindingError{Operation: "reset_keybinding", Command: string(command), Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
kbs.logger.Info("KeyBinding: Reset keybinding to default", "action", action, "key", defaultKeyBinding.Key)
|
kbs.logger.Info("KeyBinding: Reset keybinding to default", "command", command, "key", defaultKeyBinding.Key)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,15 +495,15 @@ func (kbs *KeyBindingService) validateKeyFormat(key string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// checkKeyConflict 检查快捷键冲突
|
// checkKeyConflict 检查快捷键冲突
|
||||||
func (kbs *KeyBindingService) checkKeyConflict(excludeAction models.KeyBindingAction, key string) error {
|
func (kbs *KeyBindingService) checkKeyConflict(excludeCommand models.KeyBindingCommand, key string) error {
|
||||||
allKeyBindings, err := kbs.GetAllKeyBindings()
|
allKeyBindings, err := kbs.GetAllKeyBindings()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, kb := range allKeyBindings {
|
for _, kb := range allKeyBindings {
|
||||||
if kb.Action != excludeAction && kb.Key == key && kb.Enabled {
|
if kb.Command != excludeCommand && kb.Key == key && kb.Enabled {
|
||||||
return fmt.Errorf("key %s is already used by %s", key, kb.Action)
|
return fmt.Errorf("key %s is already used by %s", key, kb.Command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,19 +516,8 @@ func (kbs *KeyBindingService) GetKeyBindingCategories() []models.KeyBindingCateg
|
|||||||
models.CategorySearch,
|
models.CategorySearch,
|
||||||
models.CategoryEdit,
|
models.CategoryEdit,
|
||||||
models.CategoryCodeBlock,
|
models.CategoryCodeBlock,
|
||||||
models.CategoryNavigation,
|
models.CategoryHistory,
|
||||||
models.CategoryView,
|
models.CategoryFold,
|
||||||
models.CategoryFile,
|
|
||||||
models.CategoryApp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyBindingScopes 获取所有快捷键作用域
|
|
||||||
func (kbs *KeyBindingService) GetKeyBindingScopes() []models.KeyBindingScope {
|
|
||||||
return []models.KeyBindingScope{
|
|
||||||
models.ScopeGlobal,
|
|
||||||
models.ScopeEditor,
|
|
||||||
models.ScopeSearch,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,23 +539,23 @@ func (kbs *KeyBindingService) ImportKeyBindings(keyBindings []models.KeyBinding)
|
|||||||
if err := kbs.validateKeyFormat(kb.Key); err != nil {
|
if err := kbs.validateKeyFormat(kb.Key); err != nil {
|
||||||
return &KeyBindingError{
|
return &KeyBindingError{
|
||||||
Operation: "import_keybindings",
|
Operation: "import_keybindings",
|
||||||
Action: string(kb.Action),
|
Command: string(kb.Command),
|
||||||
Err: fmt.Errorf("invalid key format for %s: %v", kb.Action, err),
|
Err: fmt.Errorf("invalid key format for %s: %v", kb.Command, err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查重复的快捷键
|
// 检查重复的快捷键
|
||||||
keyMap := make(map[string]models.KeyBindingAction)
|
keyMap := make(map[string]models.KeyBindingCommand)
|
||||||
for _, kb := range keyBindings {
|
for _, kb := range keyBindings {
|
||||||
if kb.Enabled {
|
if kb.Enabled {
|
||||||
if existingAction, exists := keyMap[kb.Key]; exists {
|
if existingCommand, exists := keyMap[kb.Key]; exists {
|
||||||
return &KeyBindingError{
|
return &KeyBindingError{
|
||||||
Operation: "import_keybindings",
|
Operation: "import_keybindings",
|
||||||
Err: fmt.Errorf("duplicate key %s found in %s and %s", kb.Key, existingAction, kb.Action),
|
Err: fmt.Errorf("duplicate key %s found in %s and %s", kb.Key, existingCommand, kb.Command),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyMap[kb.Key] = kb.Action
|
keyMap[kb.Key] = kb.Command
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user