grep.js 1.68 KB
const fs = require('fs')
const path = require('path')

// If running as `npm run grep`, use the current directory the command was run in
const {INIT_CWD} = process.env
if (INIT_CWD) process.chdir(INIT_CWD)

/**
 * Calls a callback function on every file inside a directory.
 * This is like fs.readdir(), but recurses on subdirectories.
 *
 * @param dir the name of the directory to search
 * @param callback the function to call on each filename found
 */
const readdirRecursive = (dir, callback) =>
  fs.readdir(dir, {withFileTypes: true}, (err, entries) => {
    // If an error occurs, we currently just skip this directory.
    // Ideally, we would report the error to the user...
    if (err) return

    for (const entry of entries) {
      const entryPath = path.join(dir, entry.name)
      if (entry.isDirectory()) readdirRecursive(entryPath, callback)
      else callback(entryPath)
    }
  })

// Parse command-line arguments
let ignoreCase = false, recursive = false, invert = false, gunzip = false
let pattern
const files = []
for (const arg of process.argv.slice(2)) {
  switch (arg) {
    case '-i':
      ignoreCase = true
      break
    case '-r':
      recursive = true
      break
    case '-v':
      invert = true
      break
    case '-z':
      gunzip = true
      break
    default:
      // The first non-flag argument is a pattern to search for.
      // The rest are files (or directories, if -r is used).
      if (pattern) files.push(arg)
      else pattern = arg
  }
}
if (!pattern) throw new Error('Syntax: npm run grep [-i] [-r] [-v] [-z] pattern ...files')

// Prevent warnings when piping many streams to `process.stdout`
process.stdout.setMaxListeners(Infinity)

// TODO: implement grep