createWatcher = (
  mocha,
  {watchFiles, watchIgnore, beforeRun, fileCollectParams}
) => {
  if (!watchFiles) {
    watchFiles = fileCollectParams.extension.map(ext => `**/*.${ext}`);
  }

  debug('ignoring files matching: %s', watchIgnore);
  let globalFixtureContext;

  // we handle global fixtures manually
  mocha.enableGlobalSetup(false).enableGlobalTeardown(false);

  const tracker = new GlobFilesTracker(watchFiles, watchIgnore);
  tracker.regenerate();

  const watcher = chokidar.watch('.', {
    ignoreInitial: true
  });

  const rerunner = createRerunner(mocha, watcher, {
    beforeRun
  });

  watcher.on('ready', async () => {
    if (!globalFixtureContext) {
      debug('triggering global setup');
      globalFixtureContext = await mocha.runGlobalSetup();
    }
    rerunner.run();
  });

  watcher.on('all', (event, filePath) => {
    if (event === 'add') {
      tracker.regenerate();
    }
    if (tracker.has(filePath)) {
      rerunner.scheduleRun();
    }
  });

  hideCursor();
  process.on('exit', () => {
    showCursor();
  });

  // this is for testing.
  // win32 cannot gracefully shutdown via a signal from a parent
  // process; a `SIGINT` from a parent will cause the process
  // to immediately exit.  during normal course of operation, a user
  // will type Ctrl-C and the listener will be invoked, but this
  // is not possible in automated testing.
  // there may be another way to solve this, but it too will be a hack.
  // for our watch tests on win32 we must _fork_ mocha with an IPC channel
  if (process.connected) {
    process.on('message', msg => {
      if (msg === 'SIGINT') {
        process.emit('SIGINT');
      }
    });
  }

  let exiting = false;
  process.on('SIGINT', async () => {
    showCursor();
    console.error(`${logSymbols.warning} [mocha] cleaning up, please wait...`);
    if (!exiting) {
      exiting = true;
      if (mocha.hasGlobalTeardownFixtures()) {
        debug('running global teardown');
        try {
          await mocha.runGlobalTeardown(globalFixtureContext);
        } catch (err) {
          console.error(err);
        }
      }
      process.exit(130);
    }
  });

  // Keyboard shortcut for restarting when "rs\n" is typed (ala Nodemon)
  process.stdin.resume();
  process.stdin.setEncoding('utf8');
  process.stdin.on('data', data => {
    const str = data.toString().trim().toLowerCase();
    if (str === 'rs') rerunner.scheduleRun();
  });

  return watcher;
}
Bootstraps a chokidar watcher. Handles keyboard input & signals
@param {Mocha} mocha - Mocha instance
@param {Object} opts
@param {BeforeWatchRun} [opts.beforeRun] - Function to call before
`mocha.run()`
@param {string[]} [opts.watchFiles] - List of paths and patterns to watch. If
  not provided all files with an extension included in
  `fileCollectionParams.extension` are watched. See first argument of
  `chokidar.watch`.
@param {string[]} [opts.watchIgnore] - List of paths and patterns to exclude
  from watching. See `ignored` option of `chokidar`.
@param {FileCollectionOptions} opts.fileCollectParams - List of extensions to watch if `opts.watchFiles` is not given.
@returns {FSWatcher}
@ignore
@private