feat: change evaluation now adds case transformation for capture groups

This commit is contained in:
Emmaline Autumn 2025-05-20 10:22:49 -06:00
parent 19eaf2d664
commit e5b173155a
2 changed files with 80 additions and 10 deletions

View File

@ -7,6 +7,7 @@ import { colorize } from "../cli/style.ts";
import { cliAlert, cliLog, cliPrompt } from "../cli/prompts.ts";
import { multiSelectMenuInteractive } from "../cli/selectMenu.ts";
import type { callback, ITool } from "../types.ts";
import { toCase } from "util/caseManagement.ts";
async function renameFields(
path: string,
@ -69,13 +70,42 @@ function applyRename(
}
}
/***
* Evaluates the change string with the match array
*
* @description The change string can include the following variables:
*
* - $<int> - capture groups, indexed from 1
* - $<int>i - capture groups, indexed from 1, transforming an integer to an index
* - $<int>s - capture groups, indexed from 1, transforming a string to snake case
* - $<int>c - capture groups, indexed from 1, transforming a string to camel case
* - $<int>l - capture groups, indexed from 1, transforming a string to lower case
* - $<int>u - capture groups, indexed from 1, transforming a string to upper case
* - $<int>t - capture groups, indexed from 1, transforming a string to title case
*/
function evaluateChange(change: string, match: RegExpExecArray) {
return change.replace(
/\$(\d+)(i?)/g,
(_, i, indexed) =>
indexed
? (parseInt(match[i]) ? (parseInt(match[i]) - 1).toString() : match[i])
: match[i],
/\$(\d+)([icslut]?)/g,
(_, i, indexed) => {
switch (indexed) {
case "i":
return (parseInt(match[i])
? (parseInt(match[i]) - 1).toString()
: match[i]);
case "s":
return toCase(match[i], "snake");
case "c":
return toCase(match[i], "camel");
case "t":
return toCase(match[i], "title");
case "l":
return match[i].toLowerCase();
case "u":
return match[i].toUpperCase();
default:
return match[i];
}
},
);
}

View File

@ -11,9 +11,45 @@ function lowerToTrainCase(str: string) {
);
}
function lowerToCamelCase(str: string) {
return str.trim().replace(/(?:\s)\w/g, (match) => match.toUpperCase())
.replaceAll(" ", "");
/**
* @param str
* @returns camelCased string (single letter words are lower cased, e.g. SSN -> ssn)
*/
function lowerToCamelCase(str: string): string {
const words = str.trim().split(/\s+/);
const result: string[] = [];
let i = 0;
while (i < words.length) {
if (words[i].length === 1) {
// Weve hit the start of a chain of single-letter words
let j = i;
while (j < words.length && words[j].length === 1) {
j++;
}
const chainIsAtStart = i === 0;
// Process that entire chain
for (let k = i; k < j; k++) {
result[k] = chainIsAtStart
? words[k].toLowerCase()
: words[k].toUpperCase();
}
i = j;
} else {
// Normal multi-letter word
if (i === 0) {
// first word: all lower
result[i] = words[i].toLowerCase();
} else {
// subsequent words: capitalize first letter
result[i] = words[i][0].toUpperCase() +
words[i].slice(1).toLowerCase();
}
i++;
}
}
return result.join("");
}
function lowerToSnakeCase(str: string) {
@ -88,10 +124,10 @@ function coerceCaseToLower(str: string, caseType: CaseType) {
case "macro":
case "snake":
case "upper":
return str.replace("_", " ").toLowerCase();
return str.replaceAll("_", " ").toLowerCase();
case "train":
case "kebab":
return str.replace("-", " ").toLowerCase();
return str.replaceAll("-", " ").toLowerCase();
default:
return str.toLowerCase();
}
@ -124,3 +160,7 @@ export function toCase(str: string, toCase: CaseType) {
return str;
}
}
if (import.meta.main) {
console.log(toCase("SSN", "camel"));
}