From 6b661e5e37945bfc96b71788e8cfff5f438e89ef Mon Sep 17 00:00:00 2001 From: zhangbk1 Date: Tue, 2 Apr 2024 15:31:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E9=A1=B9=E7=9B=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=9B=E7=A1=AE=E8=AE=A4=E9=9C=80=E8=A6=81=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GPT.md | 12 +++ package.json | 124 ++++++++++++++++++++----- src/extension.ts | 88 ++++++++++-------- src/{ => main-code}/text-conversion.ts | 4 + src/main-code/text-split.ts | 89 ++++++++++++++++++ src/type-definition/support-case.ts | 72 ++++++++++++++ 6 files changed, 326 insertions(+), 63 deletions(-) rename src/{ => main-code}/text-conversion.ts (86%) create mode 100644 src/main-code/text-split.ts create mode 100644 src/type-definition/support-case.ts diff --git a/GPT.md b/GPT.md index 81f0def..924de64 100644 --- a/GPT.md +++ b/GPT.md @@ -1,3 +1,15 @@ +docs: + +右键二级菜单 +https://fishpi.cn/article/1630641187509 +https://code.visualstudio.com/api/references/contribution-points#contributes.menus +https://code.visualstudio.com/api/references/contribution-points#contributes.submenus + +>extension.toCamelCase +>Transform to + +===== + 请帮我用js写一个小驼峰,大驼峰,下划线写法互相转换的VSCode插件。实现按shift+alt+t自动在这几种模式下切换。我完全没有写过VSCode插件,所以你可能需要详细告诉我每一步该怎么做,谢谢你 当然可以帮助您!创建一个VSCode插件涉及几个步骤,包括设置项目结构、编写代码以及打包和发布插件。以下是创建您所需插件的基本步骤: diff --git a/package.json b/package.json index b2ce16b..16870d5 100644 --- a/package.json +++ b/package.json @@ -9,27 +9,64 @@ "categories": [ "Other" ], - "activationEvents": [ - "onCommand:extension.convertCase" - ], "main": "./out/extension.js", "contributes": { "commands": [ + { + "command": "extension.convertCase", + "title": "字符串转换" + }, { "command": "extension.toCamelCase", - "title": "转小驼峰 To Camel Case" + "title": "小驼峰 / 驼峰命名 (Camel Case) [ fooBar ]" }, { "command": "extension.toPascalCase", - "title": "转大驼峰 To Pascal Case" + "title": "大驼峰 / 帕斯卡命名 (Pascal Case) [ FooBar ]" + }, + { + "command": "extension.toKebabCase", + "title": "连字符 / 脊柱式命名 (Kebab Case / Spinal Case) [ foo-bar ]" + }, + { + "command": "extension.toSnakeCase", + "title": "下划线 / 蛇形命名 (Snake Case) [ foo_bar ]" + }, + { + "command": "extension.toSnakeUpperCase", + "title": "下划线大写 (Snake Upper Case) [ FOO_BAR ]" }, { "command": "extension.toUpperCase", - "title": "转大写 To Upper Case" + "title": "全大写 (Upper Case) [ FOOBAR ]" }, { "command": "extension.toLowerCase", - "title": "转小写 To Lower Case" + "title": "全小写 (Lower Case) [ foobar ]" + }, + { + "command": "editor.action.transformToCamelcase", + "title": "[VSCode 自带] 驼峰式大小写 (Camel Case) [ fooBar ]" + }, + { + "command": "editor.action.transformToKebabcase", + "title": "[VSCode 自带] Kebab 命名 (Kebab Case) [ foo-bar ]" + }, + { + "command": "editor.action.transformToTitlecase", + "title": "[VSCode 自带] 词首字母大写 (Title Case) [ Foo Bar ]" + }, + { + "command": "editor.action.transformToLowercase", + "title": "[VSCode 自带] 转换为小写 (Lower Case) [ foo bar ]" + }, + { + "command": "editor.action.transformToUppercase", + "title": "[VSCode 自带] 转换为大写 (Upper Case) [ FOO BAR ]" + }, + { + "command": "editor.action.transformToSnakecase", + "title": "[VSCode 自带] 转换为蛇形命名法 (Snake Case) [ foo_bar ]" } ], "keybindings": [ @@ -43,22 +80,63 @@ "editor/context": [ { "when": "editorTextFocus", - "submenu": "extension.stringConversion" - } - ], - "submenus": [ - { - "id": "extension.stringConversion", - "when": "editorTextFocus", - "command": "extension.toCamelCase", - "label": "字符串转换" + "command": "extension.convertCase", + "group": "1_modification@9" }, { - "when": "editorTextFocus", - "command": "extension.toPascalCase" + "submenu": "extension.stringConversionMenu", + "group": "1_modification@9" + } + ], + "extension.stringConversionMenu": [ + { + "command": "extension.toCamelCase", + "group": "group-extension" + }, + { + "command": "extension.toPascalCase", + "group": "group-extension" + }, + { + "command": "extension.toUpperCase", + "group": "group-extension" + }, + { + "command": "extension.toLowerCase", + "group": "group-extension" + }, + { + "command": "editor.action.transformToCamelcase", + "group": "group-vscode" + }, + { + "command": "editor.action.transformToKebabcase", + "group": "group-vscode" + }, + { + "command": "editor.action.transformToTitlecase", + "group": "group-vscode" + }, + { + "command": "editor.action.transformToLowercase", + "group": "group-vscode" + }, + { + "command": "editor.action.transformToUppercase", + "group": "group-vscode" + }, + { + "command": "editor.action.transformToSnakecase", + "group": "group-vscode" } ] - } + }, + "submenus": [ + { + "id": "extension.stringConversionMenu", + "label": "将字符串转换为..." + } + ] }, "scripts": { "vscode:prepublish": "npm run compile", @@ -69,14 +147,14 @@ "test": "vscode-test" }, "devDependencies": { - "@types/vscode": "^1.87.0", "@types/mocha": "^10.0.6", "@types/node": "18.x", + "@types/vscode": "^1.87.0", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", - "eslint": "^8.57.0", - "typescript": "^5.3.3", "@vscode/test-cli": "^0.0.8", - "@vscode/test-electron": "^2.3.9" + "@vscode/test-electron": "^2.3.9", + "eslint": "^8.57.0", + "typescript": "^5.3.3" } } \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 7030366..3968e30 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,9 @@ // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; -import * as TextConversion from './text-conversion'; +import * as TextConversion from './main-code/text-conversion'; + +type ConvertFunction = (selectionText: string) => string | undefined; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed @@ -20,51 +22,57 @@ export function activate(context: vscode.ExtensionContext) { // vscode.window.showInformationMessage('Hello World from text-conversion!'); // }); - const handleEditorReplace = (convertFunction: (selectionText: string) => string) => { + const handleEditorReplace = (convertFunction: ConvertFunction) => { // 获取当前编辑器 let editor = vscode.window.activeTextEditor; - if (editor) { - let document = editor.document; - let selection = editor.selection; - - // 获取选中的文本 - let text = document.getText(selection); - // 转换文本 - let converted = convertFunction(text); - - // 当转换后文本与转换前相同时,跳过转换 - if (text === converted) { - console.log('selection text is same to converted text, skip replace contents.'); - return; - } - - // 替换文本 - console.log('replace selection text', text, 'to', converted); - editor.edit(editBuilder => { - editBuilder.replace(selection, converted); - }); + if (!editor) { + return; } + + console.log('============ start convert ============'); + let document = editor.document; + let selection = editor.selection; + + // 获取选中的文本 + let text = document.getText(selection); + + // 转换文本 + const converted = convertFunction(text); + console.log('converted', converted); + + // 无法转换时,跳过转换 + if (converted === undefined) { + console.log('converted text is undefined, skip replace contents.'); + return; + } + + // 当转换后文本与转换前相同时,跳过转换 + if (converted === text) { + console.log('selection text is same to converted text, skip replace contents.'); + return; + } + + // 替换文本 + console.log('replace selection text', text, 'to', converted); + editor.edit(editBuilder => { + editBuilder.replace(selection, converted); + }); + console.log('============ finish convert ============'); }; - let disposableCamelCase = vscode.commands.registerCommand('extension.toCamelCase', () => { - handleEditorReplace(TextConversion.toCamelCase); - }); - context.subscriptions.push(disposableCamelCase); + const commands: Array<{ command: string; convertFunction: ConvertFunction }> = [ + { command: 'extension.toCamelCase', convertFunction: TextConversion.toCamelCase }, + { command: 'extension.toPascalCase', convertFunction: TextConversion.toPascalCase }, + { command: 'extension.toUpperCase', convertFunction: TextConversion.toUpperCase }, + { command: 'extension.toLowerCase', convertFunction: TextConversion.toLowerCase }, + ]; - let disposablePascalCase = vscode.commands.registerCommand('extension.toPascalCase', () => { - handleEditorReplace(TextConversion.toPascalCase); - }); - context.subscriptions.push(disposablePascalCase); - - let disposableUpperCase = vscode.commands.registerCommand('extension.toUpperCase', () => { - handleEditorReplace(TextConversion.toUpperCase); - }); - context.subscriptions.push(disposableUpperCase); - - let disposableLowerCase = vscode.commands.registerCommand('extension.toLowerCase', () => { - handleEditorReplace(TextConversion.toLowerCase); - }); - context.subscriptions.push(disposableLowerCase); + for (const { command, convertFunction } of commands) { + let disposable = vscode.commands.registerCommand(command, () => { + handleEditorReplace(convertFunction); + }); + context.subscriptions.push(disposable); + } } diff --git a/src/text-conversion.ts b/src/main-code/text-conversion.ts similarity index 86% rename from src/text-conversion.ts rename to src/main-code/text-conversion.ts index 6a511d5..2c403a2 100644 --- a/src/text-conversion.ts +++ b/src/main-code/text-conversion.ts @@ -3,6 +3,7 @@ * * @param {string} str user selection * @returns + * @since 2024-03-28 */ export function toCamelCase(str: string): string { return str.replace(/_([a-z])/g, (g) => g[1].toUpperCase()); @@ -13,6 +14,7 @@ export function toCamelCase(str: string): string { * * @param {string} str user selection * @returns + * @since 2024-03-28 */ export function toPascalCase(str: string): string { return str.replace(/(^\w|_\w)/g, (g) => g.toUpperCase().replace('_', '')); @@ -23,6 +25,7 @@ export function toPascalCase(str: string): string { * * @param {string} str user selection * @returns + * @since 2024-03-28 */ export function toUpperCase(str: string): string { return str.toUpperCase(); @@ -33,6 +36,7 @@ export function toUpperCase(str: string): string { * * @param {string} str user selection * @returns + * @since 2024-03-28 */ export function toLowerCase(str: string): string { return str.toLowerCase(); diff --git a/src/main-code/text-split.ts b/src/main-code/text-split.ts new file mode 100644 index 0000000..52e2297 --- /dev/null +++ b/src/main-code/text-split.ts @@ -0,0 +1,89 @@ + +const handlerList = []; +/** + * 小驼峰处理中间件 + * + * @param str + * @since 2024-03-29 + */ +const camelCaseHandler = (str: string) => { + // 是否是小驼峰 + const regexp = /^$/g; // need done + // if() +}; +handlerList.push(camelCaseHandler); + +/** + * 小驼峰处理中间件 + * + * @param str + * @since 2024-03-29 + */ +const pascalCaseHandler = (str: string) => { + // 是否是小驼峰 + const regexp = /^$/g; // need done +}; +handlerList.push(pascalCaseHandler); + +type SplitFailResult = { + success: false + errMsg: string +}; + +type SplitSuccessResult = { + success: true + result: Array +}; + +type SplitResult = SplitFailResult | SplitSuccessResult; + +/** + * 分词 + * + * @param str + * @since 2024-03-29 + */ +export function splitWord(str: string): SplitResult { + // check parameter type + if (typeof str !== 'string') { + return { success: false, errMsg: `str is not string, type: ${typeof str}` }; + } + + // check parameter length + if (str.length === 0) { + return { success: false, errMsg: 'str is empty string.' }; + } + else if (str.length > 64) { + return { success: false, errMsg: 'str is too long, it does not appear to be an acceptable input.' }; + } + + // check whether the input matches the criteria + // 是否包含空格 + const isContainSpace = str.indexOf(' ') !== -1; + // 是否包含连字符 + const isContainHyphen = str.indexOf('-') !== -1; + // 是否包含下划线 + const isContainUnderline = str.indexOf('_') !== -1; + // 是否包含除空格外的其他连字符 (检查字符串是否包含 - 或 _ ,并且不包含空格) + const isContainSeparator = /^[^\s]*[-_]+[^\s]*$/.test(str); + + // 是否是小驼峰命名法 + const isCamelCase = /^[a-z][a-zA-Z]*$/; + // 是否是大驼峰命名法 + const isPascalCase = /^[A-Z][a-zA-Z]*$/; + // 是否包含大写字母 + const isContainUpperCaseLetter = /[A-Z]/.test(str); + // 是否包含小写字母 + const isContainLowerCaseLetter = /[a-z]/.test(str); + // 是否包含字母 + const isContainLetter = /[a-zA-Z]/.test(str); + + return { success: true, result: [] }; +} + +const result = splitWord('hello world'); +if (result.success) { + console.log('success!', result.result); +} else { + console.log('skip!', result.errMsg); +} \ No newline at end of file diff --git a/src/type-definition/support-case.ts b/src/type-definition/support-case.ts new file mode 100644 index 0000000..c458a79 --- /dev/null +++ b/src/type-definition/support-case.ts @@ -0,0 +1,72 @@ +export enum SupportCase { + /** + * 小驼峰 / 驼峰命名 + * Camel Case + * e.g. fooBar + * + * @alias: camelCase / CamelCase / camel_case / CAMEL_CASE + * @since 2024-04-02 + */ + CAMEL_CASE, + + /** + * 大驼峰 / 帕斯卡命名 + * Pascal Case + * e.g. FooBar + * + * @alias: pascalCase / PascalCase / pascal_case / PASCAL_CASE + * @since 2024-04-02 + */ + PASCAL_CASE, + + /** + * 连字符 / 脊柱式命名 + * Kebab Case / Spinal Case + * e.g. foo-bar + * + * @alias: kebabCase / KebabCase / kebab_case / KEBAB_CASE + * spinalCase / SpinalCase / spinal_case / SPINAL_CASE + * @since 2024-04-02 + */ + KEBAB_CASE, + + /** + * 下划线 / 蛇形命名 + * Snake Case + * e.g. foo_bar + * + * @alias: snakeCase / SnakeCase / snake_case / SNAKE_CASE + * @since 2024-04-02 + */ + SNAKE_CASE, + + /** + * 下划线大写 + * Snake Upper Case + * e.g. FOO_BAR + * + * @alias: snakeUpperCase / SnakeUpperCase / snake_upper_case / SNAKE_UPPER_CASE + * @since 2024-04-02 + */ + SNAKE_UPPER_CASE, + + /** + * 全大写 + * Upper Case + * e.g. FOO_BAR / FOOBAR + * + * @alias: upperCase / UpperCase / upper_case / UPPER_CASE + * @since 2024-04-02 + */ + UPPER_CASE, + + /** + * 全小写 + * Lower Case + * e.g. foo_bar / foobar + * + * @alias: lowerCase / LowerCase / lower_case / LOWER_CASE + * @since 2024-04-02 + */ + LOWER_CASE, +} \ No newline at end of file