1
0
Code Issues Pull Requests Packages Projects Releases Wiki Activity GitHub Gitee

添加路径转换右键菜单;实现路径转换 QuickPick 快速选择

This commit is contained in:
2024-12-14 23:56:37 +08:00
parent 948976f7ee
commit 8d19f9e0ba
11 changed files with 466 additions and 38 deletions

View File

@@ -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<TransformTextResult> | undefined = undefined): string {
let resultPath;
let isSeperator = false;

View File

@@ -67,7 +67,7 @@ function lazyConvert() {
// 获取用户配置
// TODO
// const disableFormatList = getUserConfigurations<Array<string>>('disableFormat') || [];
// const disablePathFormatList = getUserConfigurations<Array<string>>('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;
// }

View File

@@ -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<QuickPickSupportCaseItem> = [
{
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
*/

View File

@@ -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<Array<string>>('disableFormat') || [];
const disablePathFormatList = getUserConfigurations<Array<string>>('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

View File

@@ -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;

View File

@@ -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<string>
transforTo: string[]
keyword: string[]
}
/**
* 弹出的提示
*
* @since 2024-12-14
*/
function generateOptionsBasedOnText(textList: string[], eol: EOL, enabledQuickPickSupportCases: Array<QuickPickSupportCaseItem>): Array<QuickPickItemEx> {
// Cut text 切割文本
const resultsList: Array<TransformTextResult[]> = transformMutliSelectionText(textList);
const mergeResultList: Array<RecommendItem> = [];
for (const quickPick of enabledQuickPickSupportCases) {
const conversionResults: Array<string> = [];
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<Array<string>>('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);
}
});
});
}

View File

@@ -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';
/**
*

View File

@@ -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;