From 8d19f9e0ba519f94ddece66394d70f67ccdb33c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=8D=9A=E5=87=AF?= Date: Sat, 14 Dec 2024 23:56:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=B7=AF=E5=BE=84=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E5=8F=B3=E9=94=AE=E8=8F=9C=E5=8D=95=EF=BC=9B=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E8=B7=AF=E5=BE=84=E8=BD=AC=E6=8D=A2=20QuickPick=20?= =?UTF-8?q?=E5=BF=AB=E9=80=9F=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +- package-comment.jsonc | 83 +++++++++- package.json | 61 +++++++- src/core/path-convert/conversion.ts | 3 +- src/core/path-convert/cyclic-conversion.ts | 4 +- .../types/SupportPathFormatType.ts | 65 +++++++- src/extension.ts | 52 +++++-- .../path-convert/editor-submenu-handler.ts | 59 +++++++ .../path-convert/quick-pick-handler.ts | 144 ++++++++++++++++++ .../editor-submenu-handler.ts | 8 +- .../quick-pick-handler.ts | 16 +- 11 files changed, 466 insertions(+), 38 deletions(-) create mode 100644 src/handler/path-convert/editor-submenu-handler.ts create mode 100644 src/handler/path-convert/quick-pick-handler.ts rename src/handler/{ => variable-convert}/editor-submenu-handler.ts (87%) rename src/handler/{ => variable-convert}/quick-pick-handler.ts (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index cebf010..8ae6249 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,18 +25,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 2.0.0 -### Improvement - -- Adjust the project code directory structure. (项目代码目录结构调整) - ### Added - New: Support path conversions via shortcut keys `Ctrl + Alt + /` and `Ctrl + Shift + Alt + /` (also supports multi-selection conversion). (支持通过 `Ctrl + Alt + /`, `Ctrl + Shift + Alt + /` 快捷键进行路径转换 (同时支持多选区转换)) +- New: Support following path conversion type: QuickPick menu conversion, context menu conversion, status bar button conversion, shortcut key conversion. (支持以下路径转换方式:QuickPick 菜单转换、右键菜单转换、状态栏按钮转换、快捷键转换) ### Changed - Do not display the editor context menu `Variable Conversion` option when text is not selected. (当未选中文本时,不显示右键菜单 `变量转换` 选项) +### Improvement + +- Adjust the project code directory structure. (项目代码目录结构调整) + ## 1.1.0 ### Added diff --git a/package-comment.jsonc b/package-comment.jsonc index 83f42a4..e3f9abe 100644 --- a/package-comment.jsonc +++ b/package-comment.jsonc @@ -196,7 +196,7 @@ { "command": "variable-conversion.toUpperCase", "title": "全大写 (Upper Case) [ FOOBAR ]" - } + }, // 隐藏命令 // { // "command": "editor.action.transformToCamelcase", @@ -227,26 +227,61 @@ // "command": "editor.action.transformToSnakecase", // "title": "[VSCode 自带] 转换为蛇形命名法 (Snake Case) [ foo_bar ]", // "enablement": "false" - // } + // }, + /** + * 右键菜单 + */ + { + "command": "variable-conversion.convertPath", + "title": "路径转换" + }, + /** + * 右键菜单 - 子菜单 + */ + // group-1-common-style + { + "command": "variable-conversion.pathFormat.toWindowsStyle", + "title": "Windows 风格 [ C:\\Windows\\System32 ]" + }, + { + "command": "variable-conversion.pathFormat.toUnixStyle", + "title": "Unix 风格 [ /usr/bin ]" + } ], // docs: https://code.visualstudio.com/api/references/contribution-points#contributes.menus "menus": { // 编辑器右键菜单 "editor/context": [ + // 变量转换 { // "when": "editorTextFocus", // 2024.12.07 当未选中文字时,隐藏 [变量转换] 右键菜单 "when": "editorTextFocus && _textSelectionLength >= 1", "command": "variable-conversion.convertCase", // "group": "1_modification@9" - "group": "navigation@9" + "group": "navigation@10" }, + // 将变量转换为... { "when": "editorTextFocus && _textSelectionLength >= 1", "submenu": "variable-conversion.stringConversionMenu", // docs: https://code.visualstudio.com/api/references/contribution-points#Sorting-of-groups // "group": "1_modification@9" - "group": "navigation@9" + "group": "navigation@11" + }, + // 路径转换 + { + // "when": "editorTextFocus", + // 2024.12.07 当未选中文字时,隐藏 [变量转换] 右键菜单 + "when": "editorTextFocus && _textSelectionLength >= 1", + "command": "variable-conversion.convertPath", + "group": "navigation@12" + }, + // 将路径转换为... + { + "when": "editorTextFocus && _textSelectionLength >= 1", + "submenu": "variable-conversion.pathConversionMenu", + "group": "navigation@13" } ], "variable-conversion.stringConversionMenu": [ @@ -387,6 +422,21 @@ // "group": "group-vscode", // "when": "false" // } + ], + "variable-conversion.pathConversionMenu": [ + // group-1-common-style + { + // Windows 风格 + "when": "!_isHideSubMenuItem_windows_style", + "command": "variable-conversion.pathFormat.toWindowsStyle", + "group": "group-1-common-style@1" + }, + { + // Unix 风格 + "when": "!_isHideSubMenuItem_unix_style", + "command": "variable-conversion.pathFormat.toUnixStyle", + "group": "group-1-common-style@2" + } ] }, // docs: https://code.visualstudio.com/api/references/contribution-points#contributes.submenus @@ -394,6 +444,10 @@ { "id": "variable-conversion.stringConversionMenu", "label": "将变量转换为..." + }, + { + "id": "variable-conversion.pathConversionMenu", + "label": "将路径转换为..." } ], // docs: https://code.visualstudio.com/api/references/contribution-points#contributes.configuration @@ -432,7 +486,7 @@ "variable-conversion.disableFormat": { "order": 1, // markdownDescription 最多配置 11 行 - "markdownDescription": "定义哪些格式是禁用的\n\nDefine which formats are disabled.\n\n若您感觉以下配置比较麻烦,也可以选择在 `settings.json` 中编辑:\n\nIf you find the following configuration troublesome, you can also edit this configuration item in `settings.json`:\n\n`\"variable-conversion.disableFormat\": [ ... ],`\n\n[在 settings.json 中编辑 (Edit in settings.json)](command:workbench.action.openSettingsJson)\n\n配置后,您可能需要*重启扩展宿主*,或*重启当前窗口*才可使该配置完全生效(二选一即可):\n\nYou may need to *restart extension host* or *reload window* after configuration to take full effect (either):\n\n[重启扩展宿主 (Restart Extension Host)](command:workbench.action.restartExtensionHost), [重启当前窗口 (Reload Window)](command:workbench.action.reloadWindow)", + "markdownDescription": "定义哪些变量命名方式是禁用的\n\nDefine which variable formats are disabled.\n\n若您感觉以下配置比较麻烦,也可以选择在 `settings.json` 中编辑:\n\nIf you find the following configuration troublesome, you can also edit this configuration item in `settings.json`:\n\n`\"variable-conversion.disableFormat\": [ ... ],`\n\n[在 settings.json 中编辑 (Edit in settings.json)](command:workbench.action.openSettingsJson)\n\n配置后,您可能需要*重启扩展宿主*,或*重启当前窗口*才可使该配置完全生效(二选一即可):\n\nYou may need to *restart extension host* or *reload window* after configuration to take full effect (either):\n\n[重启扩展宿主 (Restart Extension Host)](command:workbench.action.restartExtensionHost), [重启当前窗口 (Reload Window)](command:workbench.action.reloadWindow)", "type": "array", "items": { "type": "string", @@ -562,6 +616,25 @@ "lower_case", "upper_case" ] + }, + // TODO + "variable-conversion.disablePathFormat": { + "order": 3, + // markdownDescription 最多配置 11 行 + "markdownDescription": "定义哪些路径风格是禁用的\n\nDefine which path formats are disabled.\n\n若您感觉以下配置比较麻烦,也可以选择在 `settings.json` 中编辑:\n\nIf you find the following configuration troublesome, you can also edit this configuration item in `settings.json`:\n\n`\"variable-conversion.disablePathFormat\": [ ... ],`\n\n[在 settings.json 中编辑 (Edit in settings.json)](command:workbench.action.openSettingsJson)\n\n配置后,您可能需要*重启扩展宿主*,或*重启当前窗口*才可使该配置完全生效(二选一即可):\n\nYou may need to *restart extension host* or *reload window* after configuration to take full effect (either):\n\n[重启扩展宿主 (Restart Extension Host)](command:workbench.action.restartExtensionHost), [重启当前窗口 (Reload Window)](command:workbench.action.reloadWindow)", + "type": "array", + "items": { + "type": "string", + "enum": [ + "windows_style", + "unix_style" + ], + "enumDescriptions": [ + "Windows 风格", + "Unix 风格" + ] + }, + "default": [] } } } diff --git a/package.json b/package.json index ff50309..05b7f4a 100644 --- a/package.json +++ b/package.json @@ -159,6 +159,18 @@ { "command": "variable-conversion.toUpperCase", "title": "全大写 (Upper Case) [ FOOBAR ]" + }, + { + "command": "variable-conversion.convertPath", + "title": "路径转换" + }, + { + "command": "variable-conversion.pathFormat.toWindowsStyle", + "title": "Windows 风格 [ C:\\Windows\\System32 ]" + }, + { + "command": "variable-conversion.pathFormat.toUnixStyle", + "title": "Unix 风格 [ /usr/bin ]" } ], "menus": { @@ -166,12 +178,22 @@ { "when": "editorTextFocus && _textSelectionLength >= 1", "command": "variable-conversion.convertCase", - "group": "navigation@9" + "group": "navigation@10" }, { "when": "editorTextFocus && _textSelectionLength >= 1", "submenu": "variable-conversion.stringConversionMenu", - "group": "navigation@9" + "group": "navigation@11" + }, + { + "when": "editorTextFocus && _textSelectionLength >= 1", + "command": "variable-conversion.convertPath", + "group": "navigation@12" + }, + { + "when": "editorTextFocus && _textSelectionLength >= 1", + "submenu": "variable-conversion.pathConversionMenu", + "group": "navigation@13" } ], "variable-conversion.stringConversionMenu": [ @@ -275,12 +297,28 @@ "command": "variable-conversion.toUpperCase", "group": "group-6-upper-lower@2" } + ], + "variable-conversion.pathConversionMenu": [ + { + "when": "!_isHideSubMenuItem_windows_style", + "command": "variable-conversion.pathFormat.toWindowsStyle", + "group": "group-1-common-style@1" + }, + { + "when": "!_isHideSubMenuItem_unix_style", + "command": "variable-conversion.pathFormat.toUnixStyle", + "group": "group-1-common-style@2" + } ] }, "submenus": [ { "id": "variable-conversion.stringConversionMenu", "label": "将变量转换为..." + }, + { + "id": "variable-conversion.pathConversionMenu", + "label": "将路径转换为..." } ], "configuration": { @@ -288,7 +326,7 @@ "properties": { "variable-conversion.disableFormat": { "order": 1, - "markdownDescription": "定义哪些格式是禁用的\n\nDefine which formats are disabled.\n\n若您感觉以下配置比较麻烦,也可以选择在 `settings.json` 中编辑:\n\nIf you find the following configuration troublesome, you can also edit this configuration item in `settings.json`:\n\n`\"variable-conversion.disableFormat\": [ ... ],`\n\n[在 settings.json 中编辑 (Edit in settings.json)](command:workbench.action.openSettingsJson)\n\n配置后,您可能需要*重启扩展宿主*,或*重启当前窗口*才可使该配置完全生效(二选一即可):\n\nYou may need to *restart extension host* or *reload window* after configuration to take full effect (either):\n\n[重启扩展宿主 (Restart Extension Host)](command:workbench.action.restartExtensionHost), [重启当前窗口 (Reload Window)](command:workbench.action.reloadWindow)", + "markdownDescription": "定义哪些变量命名方式是禁用的\n\nDefine which variable formats are disabled.\n\n若您感觉以下配置比较麻烦,也可以选择在 `settings.json` 中编辑:\n\nIf you find the following configuration troublesome, you can also edit this configuration item in `settings.json`:\n\n`\"variable-conversion.disableFormat\": [ ... ],`\n\n[在 settings.json 中编辑 (Edit in settings.json)](command:workbench.action.openSettingsJson)\n\n配置后,您可能需要*重启扩展宿主*,或*重启当前窗口*才可使该配置完全生效(二选一即可):\n\nYou may need to *restart extension host* or *reload window* after configuration to take full effect (either):\n\n[重启扩展宿主 (Restart Extension Host)](command:workbench.action.restartExtensionHost), [重启当前窗口 (Reload Window)](command:workbench.action.reloadWindow)", "type": "array", "items": { "type": "string", @@ -338,6 +376,23 @@ ] }, "default": [] + }, + "variable-conversion.disablePathFormat": { + "order": 3, + "markdownDescription": "定义哪些路径风格是禁用的\n\nDefine which path formats are disabled.\n\n若您感觉以下配置比较麻烦,也可以选择在 `settings.json` 中编辑:\n\nIf you find the following configuration troublesome, you can also edit this configuration item in `settings.json`:\n\n`\"variable-conversion.disablePathFormat\": [ ... ],`\n\n[在 settings.json 中编辑 (Edit in settings.json)](command:workbench.action.openSettingsJson)\n\n配置后,您可能需要*重启扩展宿主*,或*重启当前窗口*才可使该配置完全生效(二选一即可):\n\nYou may need to *restart extension host* or *reload window* after configuration to take full effect (either):\n\n[重启扩展宿主 (Restart Extension Host)](command:workbench.action.restartExtensionHost), [重启当前窗口 (Reload Window)](command:workbench.action.reloadWindow)", + "type": "array", + "items": { + "type": "string", + "enum": [ + "windows_style", + "unix_style" + ], + "enumDescriptions": [ + "Windows 风格", + "Unix 风格" + ] + }, + "default": [] } } } diff --git a/src/core/path-convert/conversion.ts b/src/core/path-convert/conversion.ts index 4c479dc..659178f 100644 --- a/src/core/path-convert/conversion.ts +++ b/src/core/path-convert/conversion.ts @@ -1,5 +1,6 @@ import { EOL } from "../../types/EOLType"; import { SupportPathFormat } from "./types/SupportPathFormatType"; +import { TransformTextResult } from '../../types/TransformTextResultType'; /** / */ const LEFT_SLASH = '/'; @@ -8,7 +9,7 @@ const RIGHT_SLASH = '\\'; /** \\ */ const DOUBLE_RIGHT_SLASH = '\\\\'; -export function pathConversion(targetPathType: SupportPathFormat, input: string, eol: EOL): string { +export function pathConversion(targetPathType: SupportPathFormat, input: string, eol: EOL, cutText: Array | undefined = undefined): string { let resultPath; let isSeperator = false; diff --git a/src/core/path-convert/cyclic-conversion.ts b/src/core/path-convert/cyclic-conversion.ts index c5925aa..12e8b5a 100644 --- a/src/core/path-convert/cyclic-conversion.ts +++ b/src/core/path-convert/cyclic-conversion.ts @@ -67,7 +67,7 @@ function lazyConvert() { // 获取用户配置 // TODO - // const disableFormatList = getUserConfigurations>('disableFormat') || []; + // const disablePathFormatList = getUserConfigurations>('disablePathFormat') || []; const textList = userSelection.currentSelectionsText; // vscode.window.showInformationMessage('lazyConvert' + textList.join('\n')); @@ -76,7 +76,7 @@ function lazyConvert() { for (const cyclicConvertCase of cyclicConvertPathOrder) { // 跳过禁用的目标格式 // TODO - // if (disableFormatList.includes(cyclicConvertCase.settingsKey)) { + // if (disablePathFormatList.includes(cyclicConvertCase.settingsKey)) { // continue; // } diff --git a/src/core/path-convert/types/SupportPathFormatType.ts b/src/core/path-convert/types/SupportPathFormatType.ts index 6642234..1a96800 100644 --- a/src/core/path-convert/types/SupportPathFormatType.ts +++ b/src/core/path-convert/types/SupportPathFormatType.ts @@ -6,7 +6,7 @@ export enum SupportPathFormat { /** - * Windows 格式 + * Windows 风格 * * @alias: windows / Windows * @since 2024-12-07 @@ -14,7 +14,7 @@ export enum SupportPathFormat { Windows, /** - * Unix 格式 + * Unix 风格 * * @alias: unix / Unix * @since 2024-12-07 @@ -22,6 +22,67 @@ export enum SupportPathFormat { Unix, }; +const keyword = { + windows: [ + 'Windows', 'win', + ], + unix: [ + 'Unix', + 'Linux', + 'macOS', + ], +}; + +/** + * 接管的变量转换命令 + * + * @since 2024-12-14 + */ +export const commands: Array<{ command: string; targetCase: SupportPathFormat; settingsKey: string }> = [ + { + command: 'variable-conversion.pathFormat.toWindowsStyle', + targetCase: SupportPathFormat.Windows, + settingsKey: 'windows_style' + }, + { + command: 'variable-conversion.pathFormat.toUnixStyle', + targetCase: SupportPathFormat.Unix, + settingsKey: 'unix_style' + }, +]; + +/** + * @since 2024-12-14 + */ +export interface QuickPickSupportCaseItem { + type: SupportPathFormat, + name: string, + shortName: string, + keyword: string[], + settingsKey: string, +} + +/** + * 所有支持的路径风格 + * @since 2024-12-14 + */ +export const quickPickSupportCases: Array = [ + { + type: SupportPathFormat.Windows, + name: 'Microsoft Windows 风格', + shortName: 'Windows 风格', + keyword: keyword.windows, + settingsKey: 'windows_style', + }, + { + type: SupportPathFormat.Unix, + name: 'Unix / 类 Unix 风格 (Linux, macOS, ...)', + shortName: 'Unix 风格', + keyword: keyword.unix, + settingsKey: 'unix_style', + }, +]; + /** * @since 2024-12-14 */ diff --git a/src/extension.ts b/src/extension.ts index 047319e..5ce8f1e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -11,12 +11,21 @@ * @see https://code.visualstudio.com/api */ import * as vscode from 'vscode'; -import handleEditorReplace from './handler/editor-submenu-handler'; -import { handleQuickPick } from './handler/quick-pick-handler'; -import { commands } from './core/variable-convert/types/SupportVariableCaseType'; -import { createStatusBarItem, updateStatusBarItemVisable } from './handler/status-bar-handler'; + +// Variable Convert +import handleEditorReplaceVariable from './handler/variable-convert/editor-submenu-handler'; +import { handleQuickPick as handleQuickPickVariable } from './handler/variable-convert/quick-pick-handler'; +import { commands as variableCommands } from './core/variable-convert/types/SupportVariableCaseType'; import * as CyclicConversionVariable from './core/variable-convert/cyclic-conversion'; + +// Path Convert +import handleEditorReplacePath from './handler/path-convert/editor-submenu-handler'; +import { handleQuickPick as handleQuickPickPath } from './handler/path-convert/quick-pick-handler'; +import { commands as pathCommands } from './core/path-convert/types/SupportPathFormatType'; import * as CyclicConversionPath from './core/path-convert/cyclic-conversion'; + +// Common +import { createStatusBarItem, updateStatusBarItemVisable } from './handler/status-bar-handler'; import { EOL } from './types/EOLType'; import { getUserConfigurations } from './utils/user-configuration'; @@ -56,10 +65,16 @@ export function activate(context: vscode.ExtensionContext) { // issue: #1 https://github.com/coder-xiaomo/variable-conversion-vscode-extension/issues/1 // 获取用户配置 const disableFormatList = getUserConfigurations>('disableFormat') || []; + const disablePathFormatList = getUserConfigurations>('disablePathFormat') || []; // 更新右键菜单每一项是否展示 - for (const { settingsKey } of commands) { + // 变量转换右键菜单visible 2024.07.29 + for (const { settingsKey } of variableCommands) { vscode.commands.executeCommand('setContext', '_isHideSubMenuItem_' + settingsKey, disableFormatList.includes(settingsKey)); } + // 路径转换右键菜单visible 2024.12.14 + for (const { settingsKey } of pathCommands) { + vscode.commands.executeCommand('setContext', '_isHideSubMenuItem_' + settingsKey, disablePathFormatList.includes(settingsKey)); + } // 判断是否展示状态栏按钮 updateStatusBarItemVisable(selectTextLength); @@ -109,16 +124,24 @@ export function activate(context: vscode.ExtensionContext) { onTextEditorSelectionChangeCallback(editor, editor.selections); } + + /** + * 变量转换 + * + * @since 2024-04 + */ + // 逐一注册右键菜单-子菜单项 command - for (const { command, targetCase } of commands) { + for (const { command, targetCase } of variableCommands) { let disposable = vscode.commands.registerCommand(command, () => { - handleEditorReplace(targetCase); + // 变量转换右键菜单 2024.04.05 + handleEditorReplaceVariable(targetCase); }); context.subscriptions.push(disposable); } // 注册变量转换 command 状态栏/快捷键/右键[变量转换]菜单均有用到 - let convertCaseDisposable = vscode.commands.registerCommand('variable-conversion.convertCase', handleQuickPick); + let convertCaseDisposable = vscode.commands.registerCommand('variable-conversion.convertCase', handleQuickPickVariable); context.subscriptions.push(convertCaseDisposable); // 注册循环转换 command @@ -137,10 +160,21 @@ export function activate(context: vscode.ExtensionContext) { /** * 路径转换 * issue: #3 https://github.com/coder-xiaomo/variable-conversion-vscode-extension/issues/3 + * + * @since 2024-12 */ + // 逐一注册右键菜单-子菜单项 command + for (const { command, targetCase } of pathCommands) { + let disposable = vscode.commands.registerCommand(command, () => { + // 变量转换右键菜单 2024.12.14 + handleEditorReplacePath(targetCase); + }); + context.subscriptions.push(disposable); + } + // 注册路径转换 command 状态栏/快捷键/右键[路径转换]菜单均有用到 - let convertPathDisposable = vscode.commands.registerCommand('variable-conversion.convertPath', handleQuickPick); + let convertPathDisposable = vscode.commands.registerCommand('variable-conversion.convertPath', handleQuickPickPath); context.subscriptions.push(convertPathDisposable); // 注册循环转换 command diff --git a/src/handler/path-convert/editor-submenu-handler.ts b/src/handler/path-convert/editor-submenu-handler.ts new file mode 100644 index 0000000..97c0526 --- /dev/null +++ b/src/handler/path-convert/editor-submenu-handler.ts @@ -0,0 +1,59 @@ +import * as vscode from 'vscode'; +import { EOL } from '../../types/EOLType'; +import { pathConversion } from '../../core/path-convert/conversion'; +import { SupportPathFormat } from '../../core/path-convert/types/SupportPathFormatType'; +import { isStringArrayEqual } from '../../utils/utils'; + +/** + * 编辑器右键菜单 + * + * @param convertFunction + * @returns + */ +const handleEditorReplace = (targetCase: SupportPathFormat) => { + // 获取当前编辑器 + let editor = vscode.window.activeTextEditor; + if (!editor) { + return; + } + + const document = editor.document; + const selections = editor.selections; + const eol: EOL = document.eol === vscode.EndOfLine.CRLF ? '\r\n' : '\n'; + + // 获取选中的文本 + const textList = selections.map(selection => document.getText(selection)); + + if (textList.filter(text => text.length > 0).length === 0) { + vscode.window.showInformationMessage('请选择需要转换的路径后重试\nPlease select the path you want to convert and try again.'); + return; + } + + // 转换文本 + const convertedList = textList.map(text => pathConversion(targetCase, text, eol)); + console.log('convertedList', convertedList); + + // 无法转换时,跳过转换 + if (convertedList.filter(converted => converted !== undefined).length === 0) { + console.log('converted text is undefined, skip replace contents.'); + return; + } + + // 当转换后文本与转换前相同时,跳过转换,避免形成 Ctrl + Z 撤销历史记录 + if (isStringArrayEqual(convertedList, textList)) { + console.log('selection text is same to converted text, skip replace contents.'); + return; + } + + // 替换文本 + console.log('replace selection text', textList, 'to', convertedList); + editor.edit(editBuilder => { + for (let i = 0; i < selections.length; i++) { + const selection = selections[i]; + const converted = convertedList[i]; + editBuilder.replace(selection, converted); + } + }); +}; + +export default handleEditorReplace; diff --git a/src/handler/path-convert/quick-pick-handler.ts b/src/handler/path-convert/quick-pick-handler.ts new file mode 100644 index 0000000..a1c7833 --- /dev/null +++ b/src/handler/path-convert/quick-pick-handler.ts @@ -0,0 +1,144 @@ +import * as vscode from 'vscode'; +import QuickPickItemEx from "../types/QuickPickItemExType"; +import { QuickPickSupportCaseItem, quickPickSupportCases } from '../../core/path-convert/types/SupportPathFormatType'; +import { TransformTextResult } from '../../types/TransformTextResultType'; +import { transformMutliSelectionText } from '../../utils/transform'; +import { EOL } from '../../types/EOLType'; +import { pathConversion } from '../../core/path-convert/conversion'; +import { isStringArrayEqual } from '../../utils/utils'; +import { getUserConfigurations } from '../../utils/user-configuration'; + +const QuickPickLabelMaxLength = 60; + +interface RecommendItem { + conversionText: Array + transforTo: string[] + keyword: string[] +} + +/** + * 弹出的提示 + * + * @since 2024-12-14 + */ +function generateOptionsBasedOnText(textList: string[], eol: EOL, enabledQuickPickSupportCases: Array): Array { + // Cut text 切割文本 + const resultsList: Array = transformMutliSelectionText(textList); + + const mergeResultList: Array = []; + for (const quickPick of enabledQuickPickSupportCases) { + const conversionResults: Array = []; + for (let i = 0; i < textList.length; i++) { + const text = textList[i]; + const results = resultsList[i]; + const conversionResult: string = pathConversion(quickPick.type, text, eol, results); + conversionResults.push(conversionResult); + } + const recommendItem: RecommendItem | undefined = mergeResultList.find(item => isStringArrayEqual(item.conversionText, conversionResults)); + + if (recommendItem === undefined) { + let item: RecommendItem = { + conversionText: conversionResults, + transforTo: [quickPick.shortName], // quickPick.name + keyword: quickPick.keyword, + }; + mergeResultList.push(item); + continue; + } + + recommendItem.transforTo.push(quickPick.shortName); // quickPick.name + recommendItem.keyword = Array.from(new Set(recommendItem.keyword.concat(quickPick.keyword))); // 关键词去重 + } + + // 根据文本生成选项的逻辑 + const quickPickList = []; + + for (const recommendItem of mergeResultList) { + if (isStringArrayEqual(textList, recommendItem.conversionText)) { + continue; // 如果转换后与转换前相同,那么跳过这一项 + } + const conversionTextForDisplay = recommendItem.conversionText.join(' ').replace(/\s+/g, " "); // 友好展示 将连续空格 \n \t 等替换为单一空格 + let quickPickItem: QuickPickItemEx = { + label: conversionTextForDisplay.length >= QuickPickLabelMaxLength + ? (conversionTextForDisplay.substring(0, QuickPickLabelMaxLength - 3) + '...') + : conversionTextForDisplay, + description: `转换为 ${recommendItem.transforTo.join(' / ')}`, + detail: `关键词 ${recommendItem.keyword.join(' ')}`, + value: recommendItem.conversionText, + }; + quickPickList.push(quickPickItem); + } + return quickPickList; +} + +export function handleQuickPick() { + // 获取当前编辑器 + let editor = vscode.window.activeTextEditor; + if (!editor) { + return; + } + + const document = editor.document; + const selections = editor.selections; + const eol: EOL = document.eol === vscode.EndOfLine.CRLF ? '\r\n' : '\n'; + + // 获取选中的文本 + const textList = selections.map(selection => document.getText(selection)); + + if (textList.filter(text => text.length > 0).length === 0) { + vscode.window.showInformationMessage('请选择需要转换的路径后重试\nPlease select the path you want to convert and try again.'); + return; + } + + // TODO + // 获取用户配置 + const disablePathFormatList = getUserConfigurations>('disablePathFormat') || []; + // 排除禁用的选项 + const enabledQuickPickSupportCases = []; + for (const quickPick of quickPickSupportCases) { + if (disablePathFormatList.includes(quickPick.settingsKey)) { + continue; + } + enabledQuickPickSupportCases.push(quickPick); + } + if (enabledQuickPickSupportCases.length === 0) { + vscode.window.showInformationMessage('所有格式都已被配置为禁用,请修改配置 `variable-conversion.disablePathFormat` 后重试\nAll formats have been configured to disable. Modify the `variable-conversion.disablePathFormat` configuration and try again.'); + return; + } + + // 基于选中的文本生成选项 + const options = generateOptionsBasedOnText(textList, eol, enabledQuickPickSupportCases); + if (options.length === 0) { + vscode.window.showInformationMessage('所选内容暂无可选转换,请尝试重新选择\nNo conversion candidates are available for the selected content, please try to select another text.'); + return; + } + + // 显示推荐项列表 + vscode.window.showQuickPick(options, { + matchOnDetail: true, + title: '请选择需要转换的路径风格...', + placeHolder: '点击转换,输入关键词可快速选择' + }).then(pickItem => { + if (!editor || pickItem === undefined) { + return; + } + + const convertedList = pickItem.value; + + // 当转换后文本与转换前相同时,跳过转换,避免形成 Ctrl + Z 撤销历史记录 + if (isStringArrayEqual(convertedList, textList)) { + console.log('selection text is same to converted text, skip replace contents.'); + return; + } + + // 替换文本 + console.log('replace selection text', textList, 'to', convertedList); + editor.edit(editBuilder => { + for (let i = 0; i < selections.length; i++) { + const selection = selections[i]; + const converted = convertedList[i]; + editBuilder.replace(selection, converted); + } + }); + }); +} diff --git a/src/handler/editor-submenu-handler.ts b/src/handler/variable-convert/editor-submenu-handler.ts similarity index 87% rename from src/handler/editor-submenu-handler.ts rename to src/handler/variable-convert/editor-submenu-handler.ts index 7703fb6..3abf0fc 100644 --- a/src/handler/editor-submenu-handler.ts +++ b/src/handler/variable-convert/editor-submenu-handler.ts @@ -1,8 +1,8 @@ import * as vscode from 'vscode'; -import { EOL } from '../types/EOLType'; -import { caseConversion } from '../core/variable-convert/conversion'; -import { SupportVariableCase } from '../core/variable-convert/types/SupportVariableCaseType'; -import { isStringArrayEqual } from '../utils/utils'; +import { EOL } from '../../types/EOLType'; +import { caseConversion } from '../../core/variable-convert/conversion'; +import { SupportVariableCase } from '../../core/variable-convert/types/SupportVariableCaseType'; +import { isStringArrayEqual } from '../../utils/utils'; /** * 编辑器右键菜单 diff --git a/src/handler/quick-pick-handler.ts b/src/handler/variable-convert/quick-pick-handler.ts similarity index 92% rename from src/handler/quick-pick-handler.ts rename to src/handler/variable-convert/quick-pick-handler.ts index 290dd03..9cd0973 100644 --- a/src/handler/quick-pick-handler.ts +++ b/src/handler/variable-convert/quick-pick-handler.ts @@ -1,12 +1,12 @@ import * as vscode from 'vscode'; -import QuickPickItemEx from "./types/QuickPickItemExType"; -import { QuickPickSupportCaseItem, quickPickSupportCases } from '../core/variable-convert/types/SupportVariableCaseType'; -import { TransformTextResult } from '../types/TransformTextResultType'; -import { transformMutliSelectionText } from '../utils/transform'; -import { EOL } from '../types/EOLType'; -import { caseConversion } from '../core/variable-convert/conversion'; -import { isStringArrayEqual } from '../utils/utils'; -import { getUserConfigurations } from '../utils/user-configuration'; +import QuickPickItemEx from "../types/QuickPickItemExType"; +import { QuickPickSupportCaseItem, quickPickSupportCases } from '../../core/variable-convert/types/SupportVariableCaseType'; +import { TransformTextResult } from '../../types/TransformTextResultType'; +import { transformMutliSelectionText } from '../../utils/transform'; +import { EOL } from '../../types/EOLType'; +import { caseConversion } from '../../core/variable-convert/conversion'; +import { isStringArrayEqual } from '../../utils/utils'; +import { getUserConfigurations } from '../../utils/user-configuration'; const QuickPickLabelMaxLength = 60;