diff --git a/README.md b/README.md index e88d8de..dd369cc 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,33 @@ const results = await replaceRegex({ from: /foo/g, to: 'bar', dry: false, - countMatches: true, }) console.log(results) ``` +### CLI Usage + +You can use the `replace-regex` CLI to find and replace text in files using regular expressions right from the terminal. + +```sh +Usage + $ replace-regex + +Options + --from Regex pattern or string to find (Can be set multiple times) + --to Replacement string or function (Required) + --dry Dry run (do not actually replace, just show what would be replaced) + --no-glob Disable globbing + --ignore Ignore files matching this pattern (Can be set multiple times) + --ignore-case Search case-insensitively + +Examples + $ replace-regex --from='fox' --to='🦊' foo.md + $ replace-regex --from='v\\d+\\.\\d+\\.\\d+' --to='v$npm_package_version' foo.css + $ replace-regex --from='blob' --to='blog' 'some/**/[gb]lob/*' '!some/glob/foo' +``` + ### Options - `files` (string or string[]): Glob patterns or file paths to process. @@ -44,9 +65,40 @@ console.log(results) - `ignore` (string[], optional): An array of glob patterns to exclude matches. - `disableGlobs` (boolean, optional): If true, disables glob pattern matching. Default is `false`. - `fastGlobOptions` (object, optional): Options to pass to fast-glob. -- `countMatches` (boolean, optional): If true, counts the number of matches and replacements. Default is `false`. -### Examples +### CLI Examples + +To replace all occurrences of the word `fox` with `🦊` in the file `foo.md`: + +```sh +replace-regex --from='fox' --to='🦊' foo.md +``` + +To replace version numbers in a CSS file with the version from your `package.json`: + +```sh +replace-regex --from='v\\d+\\.\\d+\\.\\d+' --to='v$npm_package_version' foo.css +``` + +To replace the word `blob` with `blog` in files matching a glob pattern, while ignoring certain files: + +```sh +replace-regex --from='blob' --to='blog' 'some/**/[gb]lob/*' '!some/glob/foo' +``` + +To perform a dry run (no files will be overwritten): + +```sh +replace-regex --from='fox' --to='🦊' --dry foo.md +``` + +To perform a case-insensitive search and replace: + +```sh +replace-regex --from='fox' --to='🦊' --ignore-case foo.md +``` + +### API Examples **Replace text in JavaScript files** @@ -56,7 +108,6 @@ replaceRegex({ from: /console\.log/g, to: 'logger.log', dry: false, - countMatches: true, }) ``` @@ -68,7 +119,6 @@ const result = await replaceRegex({ from: /foo/g, to: 'bar', dry: true, // No files will be overwritten - countMatches: true, }) console.log(`result β†’ `, result) @@ -82,6 +132,5 @@ replaceRegex({ from: /foo/g, to: (match, file) => `${match.toUpperCase()} in ${file}`, dry: false, - countMatches: true, }) ``` diff --git a/cli.js b/cli.js index ddfdecc..b402c88 100755 --- a/cli.js +++ b/cli.js @@ -14,7 +14,6 @@ const cli = meow( --to Replacement string or function (Required) --dry Dry run (do not actually replace, just show what would be replaced) --no-glob Disable globbing - --count-matches Count matches and replacements --ignore Ignore files matching this pattern (Can be set multiple times) --ignore-case Search case-insensitively @@ -42,10 +41,6 @@ const cli = meow( type: 'boolean', default: true, }, - countMatches: { - type: 'boolean', - default: false, - }, ignore: { type: 'string', isMultiple: true, @@ -74,7 +69,6 @@ const replaceOptions = { to: cli.flags.to, dry: cli.flags.dry, disableGlobs: !cli.flags.glob, - countMatches: cli.flags.countMatches, ignore: cli.flags.ignore, ignoreCase: cli.flags.ignoreCase, } diff --git a/src/index.ts b/src/index.ts index dcbd546..a9cd40b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,7 +12,6 @@ export type ReplaceRegexOptions = { ignore?: string[] disableGlobs?: boolean fastGlobOptions?: Parameters[1] - countMatches?: boolean /** * when passing a `string` to `from` you can make it ignore case with this flag. * otherwise, you need to embed `i` into your regex @@ -34,12 +33,12 @@ async function getPathsAsync( patterns: MaybeArr, options: ReplaceRegexOptions, ): Promise { - const { ignore, disableGlobs, fastGlobOptions: cfg } = options + const { ignore, disableGlobs, fastGlobOptions } = options // disable globs, just ensure file(s) name if (disableGlobs) return isString(patterns) ? [patterns] : patterns - return await fastGlob(patterns, { ignore, ...cfg }) + return await fastGlob(patterns, { ignore, ...fastGlobOptions }) } /** @@ -50,13 +49,12 @@ function replaceFactory(options: { file: string from: string | RegExp | ((file: string) => string | RegExp) to: ReplaceRegexOptions['to'] - countMatches?: ReplaceRegexOptions['countMatches'] ignoreCase?: ReplaceRegexOptions['ignoreCase'] }): { result: ReplaceRegexResult newContents: string } { - const { contents, from, to, file, countMatches, ignoreCase } = options + const { contents, from, to, file, ignoreCase } = options const result: ReplaceRegexResult = { file, changed: false, @@ -68,13 +66,11 @@ function replaceFactory(options: { const flags = ignoreCase ? 'gi' : 'g' const fromRegex = isString(_from) ? new RegExp(_from, flags) : _from - if (countMatches) { - const matches = contents.match(fromRegex) - if (matches) { - const replacements = matches.filter((match) => match !== to) - result.matchCount = matches.length - result.replaceCount = replacements.length - } + const matches = contents.match(fromRegex) + if (matches) { + const replacements = matches.filter((match) => match !== to) + result.matchCount = matches.length + result.replaceCount = replacements.length } const newContents = isFunction(to) @@ -96,11 +92,10 @@ async function replaceFileAsync(options: { file: string from: string | RegExp | ((file: string) => string | RegExp) to: ReplaceRegexOptions['to'] - countMatches: ReplaceRegexOptions['countMatches'] dry: ReplaceRegexOptions['dry'] ignoreCase?: ReplaceRegexOptions['ignoreCase'] }): Promise { - const { file, from, to, dry, countMatches, ignoreCase } = options + const { file, from, to, dry, ignoreCase } = options const contents = await fs.readFile(file) @@ -110,7 +105,6 @@ async function replaceFileAsync(options: { from, to, file, - countMatches, ignoreCase, }) @@ -125,7 +119,7 @@ async function replaceFileAsync(options: { * Uses fast-glob to find and replace text in files. Supports RegExp. */ export async function replaceRegex(options: ReplaceRegexOptions): Promise { - const { files, from, dry, countMatches, to, ignoreCase } = options + const { files, from, dry, to, ignoreCase } = options // dry mode, do not replace if (dry) console.log('[dry mode] no files will be overwritten') @@ -137,7 +131,7 @@ export async function replaceRegex(options: ReplaceRegexOptions): Promise { to: 'TEST', disableGlobs: false, dry: false, - countMatches: true, } const results = await replaceRegex(options) @@ -54,7 +53,6 @@ describe('replaceRegex', () => { to: 'TEST', disableGlobs: false, dry: true, - countMatches: true, } const results = await replaceRegex(options) @@ -89,7 +87,6 @@ describe('replaceRegex', () => { to: 'TEST', disableGlobs: false, dry: false, - countMatches: true, } const results = await replaceRegex(options)