This commit is contained in:
Raven Scott
2026-04-03 19:13:20 -04:00
parent 8002a66f6e
commit 04d903beb8
24 changed files with 564 additions and 74 deletions
+18 -7
View File
@@ -78,13 +78,14 @@ async function run(ctx, argv) {
let suppressErrors = false
let forceFilename = false
let noFilename = false
let word = false
const args = argv.slice(1)
let i = 0
function usage() {
ctx.console.error(
'usage: grep [-E|-F] [-i] [-v] [-n] [-c] [-l] [-q] [-s] [-H|-h] [-e pat] ... [-f file] ... [pattern] [file...]'
'usage: grep [-E|-F] [-i] [-v] [-w] [-n] [-c] [-l] [-q] [-s] [-H|-h] [-e pat] ... [-f file] ... [pattern] [file...]'
)
ctx.exitCode = 2
}
@@ -169,6 +170,9 @@ async function run(ctx, argv) {
case 'h':
noFilename = true
break
case 'w':
word = true
break
default:
ctx.console.error('grep: invalid option -- ' + c)
ctx.exitCode = 2
@@ -217,7 +221,7 @@ async function run(ctx, argv) {
let matchers
try {
matchers = buildMatchers(patterns, { fixed, icase })
matchers = buildMatchers(patterns, { fixed, icase, word })
} catch (e) {
ctx.console.error('grep: ' + (e.message || e))
ctx.exitCode = 2
@@ -304,7 +308,7 @@ async function run(ctx, argv) {
/**
* @param {string[]} patterns
* @param {{ fixed: boolean, icase: boolean }} o
* @param {{ fixed: boolean, icase: boolean, word?: boolean }} o
*/
function buildMatchers(patterns, o) {
if (patterns.length === 0) throw new Error('no pattern')
@@ -312,15 +316,22 @@ function buildMatchers(patterns, o) {
const pats = o.icase
? patterns.map((p) => p.toLowerCase())
: patterns.slice()
return pats.map(
(p) => (line) =>
return pats.map((p) => {
if (o.word) {
const esc = p.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&')
const flags = o.icase ? 'i' : ''
const re = new RegExp('(?:^|[^0-9A-Za-z_])' + esc + '(?:$|[^0-9A-Za-z_])', flags)
return (line) => re.test(line)
}
return (line) =>
o.icase ? line.toLowerCase().includes(p) : line.includes(p)
)
})
}
const flags = o.icase ? 'i' : ''
return patterns.map((p) => {
try {
const re = new RegExp(p, flags)
const body = o.word ? '\\b(?:' + p + ')\\b' : p
const re = new RegExp(body, flags)
return (line) => re.test(line)
} catch (e) {
throw new Error('invalid regex: ' + (e.message || e))