From 30224cfeb6d6d056cd74007eb3db89f456d91b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E5=B0=8F=E5=A2=A8?= <2291200076@qq.com> Date: Wed, 3 Apr 2024 00:07:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E8=A1=8C=E5=86=85=E5=AE=B9=E9=80=90?= =?UTF-8?q?=E8=A1=8C=E5=A4=84=E7=90=86=EF=BC=9B=E6=9B=B4=E6=96=B0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B=EF=BC=9B=E6=B5=8B=E8=AF=95=E7=94=A8?= =?UTF-8?q?=E4=BE=8B=E5=8F=AF=E4=BB=A5=E6=8C=87=E5=AE=9AEOL=E6=8D=A2?= =?UTF-8?q?=E8=A1=8C=E7=AC=A6=EF=BC=9BtransformMutliLineText=20=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E6=89=80=E6=9C=89=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/extension.ts | 6 +- src/main-code/text-conversion.ts | 65 ++++-- src/main-code/text-transform.ts | 12 + src/test/extension.test.ts | 24 +- src/test/test-case.ts | 218 ++++++++++++++----- src/type-definition/convert-function-type.ts | 3 + src/type-definition/test-case-type.ts | 5 +- src/type-definition/text-transform-type.ts | 1 + 8 files changed, 244 insertions(+), 90 deletions(-) create mode 100644 src/type-definition/convert-function-type.ts diff --git a/src/extension.ts b/src/extension.ts index fea19bd..50084c3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,8 +2,7 @@ // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; import * as TextConversion from './main-code/text-conversion'; - -type ConvertFunction = (selectionText: string) => string; +import { ConvertFunction, EOL } from './type-definition/convert-function-type'; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed @@ -32,12 +31,13 @@ export function activate(context: vscode.ExtensionContext) { console.log('============ start convert ============'); let document = editor.document; let selection = editor.selection; + let eol: EOL = document.eol === vscode.EndOfLine.CRLF ? '\r\n' : '\n'; // 获取选中的文本 let text = document.getText(selection); // 转换文本 - const converted = convertFunction(text); + const converted = convertFunction(text, eol); console.log('converted', converted); // 无法转换时,跳过转换 diff --git a/src/main-code/text-conversion.ts b/src/main-code/text-conversion.ts index c6f24fb..8e3b4de 100644 --- a/src/main-code/text-conversion.ts +++ b/src/main-code/text-conversion.ts @@ -1,4 +1,6 @@ -import { transformText } from './text-transform'; +import { ConvertFunction, EOL } from '../type-definition/convert-function-type'; +import { TransformTextResult } from '../type-definition/text-transform-type'; +import { transformMutliLineText, transformText } from './text-transform'; /** * 转小驼峰 to Camel Case @@ -7,26 +9,41 @@ import { transformText } from './text-transform'; * @returns * @since 2024-03-28 */ -export function toCamelCase(str: string): string { +export const toCamelCase: ConvertFunction = (str: string, eol: EOL): string => { // Cut text 切割文本 - let result = transformText(str); - console.log('result', result); + const results: Array = transformMutliLineText(str); + console.log('results', results); - // Post Process 后置处理 - const words = result.trimResult.split('|'); - const camelCaseWords = words.map((word, index) => { - if (index === 0) { - // 第一个单词保持不变 - return word; - } else { - // 其他单词首字母大写 - return word.charAt(0).toUpperCase() + word.slice(1); + const transformedLines: Array = []; + for (const result of results) { + // Post Process 后置处理 + const words = result.trimResult.split('|'); + let isFirstWord: boolean = true;// 用于判断首词小写 + const camelCaseWords: Array = []; + for (let index = 0; index < words.length; index++) { + const word = words[index]; + const firstLetter = word.charAt(0); + const pascalCaseWord = firstLetter.toUpperCase() + word.slice(1); + if (isFirstWord) { + camelCaseWords.push(word); + if (firstLetter !== firstLetter.toUpperCase()) { + // 是大写 (A-Z), 再后面的词句不再是首词 + isFirstWord = false; + } + } else { + camelCaseWords.push(pascalCaseWord); + } + + if (word === '\n' || word === '\r\n') { + isFirstWord = true; // 换行后,重新计算首词 + } } - }); - return result.leadingSpace + camelCaseWords.join('') + result.trailingSpace; - + const transformedLine = result.leadingSpace + camelCaseWords.join('') + result.trailingSpace; + transformedLines.push(transformedLine); + } + return transformedLines.join(eol); // return str.replace(/_([a-z])/g, (g) => g[1].toUpperCase()); -} +}; /** * 转大驼峰 to Pascal Case @@ -35,7 +52,7 @@ export function toCamelCase(str: string): string { * @returns * @since 2024-03-28 */ -export function toPascalCase(str: string): string { +export const toPascalCase: ConvertFunction = (str: string, eol: EOL): string => { // Cut text 切割文本 let result = transformText(str); console.log('result', result); @@ -49,7 +66,7 @@ export function toPascalCase(str: string): string { return result.leadingSpace + pascalCaseWords.join('') + result.trailingSpace; // return str.replace(/(^\w|_\w)/g, (g) => g.toUpperCase().replace('_', '')); -} +}; /** * 转大写 to Upper Case @@ -57,10 +74,10 @@ export function toPascalCase(str: string): string { * @param {string} str user selection * @returns * @since 2024-03-28 - */ -export function toUpperCase(str: string): string { +*/ +export const toUpperCase: ConvertFunction = (str: string, eol: EOL): string => { return str.toUpperCase(); -} +}; /** * 转小写 to Lower Case @@ -69,6 +86,6 @@ export function toUpperCase(str: string): string { * @returns * @since 2024-03-28 */ -export function toLowerCase(str: string): string { +export const toLowerCase: ConvertFunction = (str: string, eol: EOL): string => { return str.toLowerCase(); -} +}; diff --git a/src/main-code/text-transform.ts b/src/main-code/text-transform.ts index 40925eb..33b7294 100644 --- a/src/main-code/text-transform.ts +++ b/src/main-code/text-transform.ts @@ -2,6 +2,15 @@ import { TransformTextResult } from "../type-definition/text-transform-type"; const logDebugInfo = false; +export function transformMutliLineText(multilineInput: string): Array { + const results: Array = []; + const lines = multilineInput.split(/\r?\n/); + for (const line of lines) { + // console.log('line', '->' + line + '<-'); + results.push(transformText(line)); + } + return results; +} /** * 分词 * @@ -17,6 +26,8 @@ export function transformText(input: string): TransformTextResult { ? '' // 字符串全为空格时,将尾空格置为空字符串 : input.match(/ +$/); + // const debug = { input, leadingSpaces, trailingSpaces }; + // 去除首尾空格 // 不可以使用 input = input.trim(); 否则换行会被替换掉 input = input.replace(/^ +| +$/g, ''); @@ -61,5 +72,6 @@ export function transformText(input: string): TransformTextResult { trailingSpace: trailingSpaceStr, result: noTrimResult, trimResult: result, + // debug: debug }; } diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index cce8eb2..ef6e3b1 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -5,8 +5,9 @@ import * as assert from 'assert'; import * as vscode from 'vscode'; import testGroups from './test-case'; import { TestCase, TestCaseGroup } from '../type-definition/test-case-type'; -import { transformText } from '../main-code/text-transform'; +import { transformMutliLineText, transformText } from '../main-code/text-transform'; import { toCamelCase, toPascalCase } from '../main-code/text-conversion'; +import { TransformTextResult } from '../type-definition/text-transform-type'; // import * as myExtension from '../../extension'; /* @@ -31,15 +32,28 @@ suite('Extension Test: run test case', () => { const testTitle = testGroup.testTitle; const testCases: Array = testGroup.cases; for (const testCase of testCases) { + // // 临时 + // if (testCase.title !== '') { + // continue; + // } test(testTitle + ' - ' + testCase.title, () => { const inputList = Array.isArray(testCase.input) ? testCase.input : [testCase.input]; + const eolList = Array.isArray(testCase.eol) ? testCase.eol : [testCase.eol]; for (const input of inputList) { + // console.log('input', '->' + input + '<-'); // 验证 transformText - const transformTextResult = transformText(input); - assert.strictEqual(testCase.transformText, transformTextResult.result); + const transformTextResult: Array = transformMutliLineText(input); + const results = transformTextResult.map(res => res.result); + for (let index = 0; index < testCase.transformText.length; index++) { + const correctValue = testCase.transformText[index]; + const currentValue = results[index]; + assert.strictEqual(correctValue, currentValue); + } // 验证转换 - assert.strictEqual(testCase.output.camelCase, toCamelCase(input)); - assert.strictEqual(testCase.output.pascalCase, toPascalCase(input)); + for (let eol of eolList) { + assert.strictEqual(testCase.output.camelCase, toCamelCase(input, eol)); + assert.strictEqual(testCase.output.pascalCase, toPascalCase(input, eol)); + } } }); } diff --git a/src/test/test-case.ts b/src/test/test-case.ts index ed83c65..1e3fb6c 100644 --- a/src/test/test-case.ts +++ b/src/test/test-case.ts @@ -1,5 +1,8 @@ import { TestCaseGroup } from "../type-definition/test-case-type"; +const LF = '\n'; +const CRLF = '\r\n'; + const testGroups: Array = [ { group: 'Input validation', @@ -9,7 +12,10 @@ const testGroups: Array = [ { title: 'empty input', input: '', - transformText: '', + eol: [LF, CRLF], + transformText: [ + '', + ], output: { camelCase: '', pascalCase: '', @@ -18,28 +24,65 @@ const testGroups: Array = [ { title: 'empty input (contains space)', input: ' ', - transformText: ' ', + eol: [LF, CRLF], + transformText: [ + ' ', + ], output: { camelCase: ' ', pascalCase: ' ', }, }, { - title: 'empty input (contains space and enter 1)', + title: 'empty input (contains space and crlf enter 1)', + input: ' \r\n ', + eol: [CRLF], + transformText: [ + ' ', + ' ', + ], + output: { + camelCase: ' \r\n ', + pascalCase: ' \r\n ', + }, + }, + { + title: 'empty input (contains space and crlf enter 2)', + input: ' x \r\ny ', + eol: [CRLF], + transformText: [ + ' x ', + 'y ', + ], + output: { + camelCase: ' x \r\ny ', + pascalCase: ' X \r\nY ', + }, + }, + { + title: 'empty input (contains space and lf enter 1)', input: ' \n ', - transformText: ' \n ', + eol: [LF], + transformText: [ + ' ', + ' ', + ], output: { camelCase: ' \n ', pascalCase: ' \n ', }, }, { - title: 'empty input (contains space and enter 2)', + title: 'empty input (contains space and lf enter 2)', input: ' a\nb ', - transformText: ' a|\n|b ', + eol: [LF], + transformText: [ + ' a', + 'b ', + ], output: { camelCase: ' a\nb ', - pascalCase: ' a\nb ', + pascalCase: ' A\nB ', }, }, // 输入长文本 @@ -48,35 +91,46 @@ const testGroups: Array = [ input: `China's factory activity expanded in March after five consecutive months of contraction, an official survey revealed on Sunday, adding to a run of indicators that suggest the stabilization of the world's second-largest economy.` , - transformText: + eol: [LF, CRLF], + transformText: [ "china|'|s|factory|activity|expanded|in|march|after|five|consecutive|months|of|contraction|,|an|official|survey|revealed|on|sunday|,|adding|to|a|run|of|indicators|that|suggest|the|stabilization|of|the|world|'|s|second|largest|economy|." - , + ], output: { - camelCase: '', - pascalCase: '', + camelCase: + "china'SFactoryActivityExpandedInMarchAfterFiveConsecutiveMonthsOfContraction,AnOfficialSurveyRevealedOnSunday,AddingToARunOfIndicatorsThatSuggestTheStabilizationOfTheWorld'SSecondLargestEconomy." + , + pascalCase: + "China'SFactoryActivityExpandedInMarchAfterFiveConsecutiveMonthsOfContraction,AnOfficialSurveyRevealedOnSunday,AddingToARunOfIndicatorsThatSuggestTheStabilizationOfTheWorld'SSecondLargestEconomy." + , }, }, // 输入包含数字 { title: 'text and number input', input: 'entity2Map', - transformText: 'entity|2|map', + eol: [LF, CRLF], + transformText: [ + 'entity|2|map', + ], output: { - camelCase: '', - pascalCase: '', + camelCase: 'entity2Map', + pascalCase: 'Entity2Map', }, }, // 输入包含换行 { title: 'enter input', input: - `How do you\bdo? - How do you\tdo!` + 'How do you\bdo?\n How do you\tdo!' , - transformText: 'how|do|you|\b|do|?\n|how|do|you|\t|do|!', + eol: [LF, CRLF], + transformText: [ + 'how|do|you|\b|do|?', + ' how|do|you|\t|do|!', + ], output: { - camelCase: '', - pascalCase: '', + camelCase: 'howDoYou\bDo?\n HowDoYou\tDo!', + pascalCase: 'HowDoYou\bDo?\n HowDoYou\tDo!', }, }, // 非英文字符,特殊字符 @@ -85,7 +139,10 @@ const testGroups: Array = [ input: '今天是星期日' , - transformText: '今天是星期日', + eol: [LF, CRLF], + transformText: [ + '今天是星期日', + ], output: { camelCase: '今天是星期日', pascalCase: '今天是星期日', @@ -96,10 +153,13 @@ const testGroups: Array = [ input: '🥰 a-cup/_of Coffee🍻,-_please!. ' , - transformText: '🥰|a|cup|/|of|coffee|🍻,|please|!. ', + eol: [LF, CRLF], + transformText: [ + '🥰|a|cup|/|of|coffee|🍻,|please|!. ', + ], output: { - camelCase: '', - pascalCase: '', + camelCase: '🥰aCup/OfCoffee🍻,Please!. ', + pascalCase: '🥰ACup/OfCoffee🍻,Please!. ', }, }, { @@ -107,10 +167,13 @@ const testGroups: Array = [ input: ' NHDAs--+90-usz&* ' , - transformText: ' n|h|d|as|+90|usz|&* ', + eol: [LF, CRLF], + transformText: [ + ' n|h|d|as|+90|usz|&* ', + ], output: { - camelCase: '', - pascalCase: '', + camelCase: ' nHDAs+90Usz&* ', + pascalCase: ' NHDAs+90Usz&* ', }, }, { @@ -118,10 +181,13 @@ const testGroups: Array = [ input: '--担心你鸿dAf_=coffee—_— ' , - transformText: '担心你鸿|d|af|=|coffee|—|— ', + eol: [LF, CRLF], + transformText: [ + '担心你鸿|d|af|=|coffee|—|— ', + ], output: { - camelCase: '', - pascalCase: '', + camelCase: '担心你鸿dAf=Coffee—— ', + pascalCase: '担心你鸿DAf=Coffee—— ', }, }, { @@ -129,10 +195,13 @@ const testGroups: Array = [ input: 'fsdi_sdacsaf+desd' , - transformText: 'fsdi|sdacsaf|+|desd', + eol: [LF, CRLF], + transformText: [ + 'fsdi|sdacsaf|+|desd', + ], output: { - camelCase: '', - pascalCase: '', + camelCase: 'fsdiSdacsaf+Desd', + pascalCase: 'FsdiSdacsaf+Desd', }, }, // add more cases... @@ -150,7 +219,10 @@ const testGroups: Array = [ '-foo -bar', '__foo - _bar-__', ], - transformText: 'foo|bar', + eol: [LF, CRLF], + transformText: [ + 'foo|bar', + ], output: { camelCase: 'fooBar', pascalCase: 'FooBar', @@ -166,7 +238,10 @@ const testGroups: Array = [ 'TestCase', 'TEST_CASE', ], - transformText: 'test|case', + eol: [LF, CRLF], + transformText: [ + 'test|case', + ], output: { camelCase: 'testCase', pascalCase: 'TestCase', @@ -177,7 +252,10 @@ const testGroups: Array = [ input: [ 'pineApple', ], - transformText: 'pine|apple', + eol: [LF, CRLF], + transformText: [ + 'pine|apple', + ], output: { camelCase: 'pineApple', pascalCase: 'PineApple', @@ -197,7 +275,10 @@ const testGroups: Array = [ 'HaveANiceDay!', 'haveANiceDay!', ], - transformText: 'have|a|nice|day|!', + eol: [LF, CRLF], + transformText: [ + 'have|a|nice|day|!', + ], output: { camelCase: 'haveANiceDay!', pascalCase: 'HaveANiceDay!', @@ -215,7 +296,10 @@ const testGroups: Array = [ // ' A----NiCe_Day_-_!-- ', ' A----NICE_Day_-_!-- ', ], - transformText: ' a|nice|day|! ', + eol: [LF, CRLF], + transformText: [ + ' a|nice|day|! ', + ], output: { camelCase: ' aNiceDay! ', pascalCase: ' ANiceDay! ', @@ -227,22 +311,28 @@ const testGroups: Array = [ ' A NICE-Day-', ' A niceDay', ], - transformText: ' a|nice|day', + eol: [LF, CRLF], + transformText: [ + ' a|nice|day', + ], output: { - camelCase: ' a niceDay', - pascalCase: ' A NiceDay', + camelCase: ' aNiceDay', + pascalCase: ' ANiceDay', }, }, { - title: 'Normal input (foo-bar)', + title: 'Normal input (apple-2-Tree)', input: [ - ' app2-Trrre ', - ' app2Trrre ', + ' apple2-Tree ', + ' apple2Tree ', + ], + eol: [LF, CRLF], + transformText: [ + ' apple|2|tree ', ], - transformText: ' app|2|trrre ', output: { - camelCase: '', - pascalCase: '', + camelCase: ' apple2Tree ', + pascalCase: ' Apple2Tree ', }, }, { @@ -250,24 +340,35 @@ const testGroups: Array = [ input: ' Julius_Caesar, William_Shakespeare, Albert_Einstein, Marie_Curie, WolfgangAmadeusMozart, Vincent-van-Gogh. ' , - transformText: ' julius|caesar|,|william|shakespeare|,|albert|einstein|,|marie|curie|,|wolfgang|amadeus|mozart|,|vincent|van|gogh|. ', + eol: [LF, CRLF], + transformText: [ + ' julius|caesar|,|william|shakespeare|,|albert|einstein|,|marie|curie|,|wolfgang|amadeus|mozart|,|vincent|van|gogh|. ', + ], output: { - camelCase: '', - pascalCase: '', + camelCase: ' juliusCaesar,WilliamShakespeare,AlbertEinstein,MarieCurie,WolfgangAmadeusMozart,VincentVanGogh. ', + pascalCase: ' JuliusCaesar,WilliamShakespeare,AlbertEinstein,MarieCurie,WolfgangAmadeusMozart,VincentVanGogh. ', }, }, { title: 'Normal input ("You" (or "Your") ...)', input: - [ - ` "You" (or "Your") shall mean an individual or Legal Entity`, - ` exercising permissions granted by this License.` - ].join('\n') + ' "You" (or "Your") shall mean an individual or Legal Entity\n' + + ' exercising permissions granted by this License.' , - transformText: ' &|quot|;|you|&|quot|;|(|or|&|quot|;|your|&|quot|;)|shall|mean|an|individual|or|legal|entity|\n|exercising|permissions|granted|by|this|license|.', + eol: [LF], + transformText: [ + ' &|quot|;|you|&|quot|;|(|or|&|quot|;|your|&|quot|;)|shall|mean|an|individual|or|legal|entity', + ' exercising|permissions|granted|by|this|license|.', + ], output: { - camelCase: ' "You" (or "Your") shall mean an individual or Legal Entity\n exercising permissions granted by this License.', - pascalCase: ' "You" (or "Your") shall mean an individual or Legal Entity\n exercising permissions granted by this License.', + camelCase: + ' "You&Quot;(Or&Quot;Your&Quot;)ShallMeanAnIndividualOrLegalEntity\n' + + ' exercisingPermissionsGrantedByThisLicense.' + , + pascalCase: + ' "You" (or "Your") shall mean an individual or Legal Entity\n' + + ' exercising permissions granted by this License.' + , }, }, // add more cases... @@ -290,7 +391,10 @@ const testGroups: Array = [ // { // title: 'Normal input ( ...)', // input: '', - // transformText: '', + // eol: [LF, CRLF], + // transformText: [ + // '', + // ], // output: { // camelCase: '', // pascalCase: '' diff --git a/src/type-definition/convert-function-type.ts b/src/type-definition/convert-function-type.ts new file mode 100644 index 0000000..831471d --- /dev/null +++ b/src/type-definition/convert-function-type.ts @@ -0,0 +1,3 @@ +export type EOL = '\n' | '\r\n'; + +export type ConvertFunction = (selectionText: string, eol: EOL) => string; \ No newline at end of file diff --git a/src/type-definition/test-case-type.ts b/src/type-definition/test-case-type.ts index 2df4b51..b90fe9e 100644 --- a/src/type-definition/test-case-type.ts +++ b/src/type-definition/test-case-type.ts @@ -1,3 +1,5 @@ +import { EOL } from "./convert-function-type"; + export type TestCaseGroup = { group: string testTitle: string @@ -7,7 +9,8 @@ export type TestCaseGroup = { export type TestCase = { title: string input: string | Array - transformText: string + eol: EOL | Array + transformText: Array output: { camelCase: string pascalCase: string diff --git a/src/type-definition/text-transform-type.ts b/src/type-definition/text-transform-type.ts index 68b4cb2..81221fc 100644 --- a/src/type-definition/text-transform-type.ts +++ b/src/type-definition/text-transform-type.ts @@ -3,4 +3,5 @@ export type TransformTextResult = { trailingSpace: string result: string trimResult: string + // debug?: any };