<commit_before>import path from 'path'
import xtend from 'xtend'
import { spawn } from 'child_process'
import { parse } from 'shell-quote'

const PATH_SEP = process.platform === 'win32' ? ';' : ':'
const PATH_KEY = process.platform === 'win32' && !(process.env.PATH && !process.env.Path) ? 'Path' : 'PATH'
const ESCAPE_CHAR = process.platform === 'win32' ? '^' : '\\'
const ELECTRON_LIB = `electron ${path.join(__dirname, 'electron.bundle.js')}`

const commandToString = (cmd) => cmd.pattern || cmd.op || handleQuotes(cmd)

const handleQuotes = (s) => {
  if (/["'\s]/.test(s)) return '"' + s.replace(/(["\\$`!])/g, '\\$1') + '"'
  if (/["\s]/.test(s) && !/'/.test(s)) return "'" + s.replace(/(['\\])/g, '\\$1') + "'"
  return String(s).replace(/([\\$`()!#&*|])/g, '\\$1')
}

const NPMBinPath = (cwd, PATH) => {
  const result = []
  let parent

  while (true) {
    parent = path.join(cwd, '..')
    result.push(path.join(cwd, 'node_modules/.bin'))
    if (parent === cwd) return result.concat(PATH).join(PATH_SEP)
    cwd = parent
  }
}

const formatAndSpawn = (command, opts) => {
  const options = xtend({}, opts)
  let file
  let args

  if (process.platform === 'win32') {
    file = process.env.comspec || 'cmd.exe'
    args = [ '/s', '/c', '"' + command + '"' ]
    options.windowsVerbatimArguments = true
  } else {
    file = '/bin/sh'
    args = [ '-c', command ]
    options.windowsVerbatimArguments = false
  }

  if (options && options.shell) {
    file = options.shell
    delete options.shell
  }

  return spawn(file, args, options)
}

module.exports = () => {
  const cwd = process.cwd()
  const env = process.env
  const parsed = parse(ELECTRON_LIB, xtend({ '': '$' }), { escape: ESCAPE_CHAR }).map(commandToString).join(' ')

  const override = {
    [ PATH_KEY ]: NPMBinPath(path.resolve(cwd, '.'), env[PATH_KEY] || process.env[PATH_KEY])
  }

  const child = formatAndSpawn(parsed, { env: xtend(env, override) })
  let out = child.stdin.write.bind(child.stdin)

  child.stdin.setEncoding('utf-8')
  child.stdout.pipe(process.stdout)

  child.on('exit', () => {
    out = console.log.bind(console)
  })

  return (log) => out(log)
}
<commit_msg>* Fix node_module/.bin path resolution * Spawn only one Quark process for multi-process app * Add electron's IPC communication<commit_after>import path from 'path'
import xtend from 'xtend'
import { spawn } from 'child_process'
import { parse } from 'shell-quote'

const { platform, env } = process

const PATH_SEP = platform === 'win32' ? ';' : ':'
const PATH_KEY = platform === 'win32' && !(env.PATH && !env.Path) ? 'Path' : 'PATH'
const ESCAPE_CHAR = platform === 'win32' ? '^' : '\\'
const ELECTRON_LIB = `electron ${path.join(__dirname, 'electron.bundle.js')}`

const commandToString = (cmd) => cmd.pattern || cmd.op || handleQuotes(cmd)

const handleQuotes = (s) => {
  if (/["'\s]/.test(s)) return '"' + s.replace(/(["\\$`!])/g, '\\$1') + '"'
  if (/["\s]/.test(s) && !/'/.test(s)) return "'" + s.replace(/(['\\])/g, '\\$1') + "'"
  return String(s).replace(/([\\$`()!#&*|])/g, '\\$1')
}

const pathToNPMBinDirectory = () => path.resolve(__dirname, '..', 'node_modules/.bin')

const formatAndSpawn = (command, opts) => {
  const options = xtend({}, opts)
  let file
  let args

  if (platform === 'win32') {
    file = env.comspec || 'cmd.exe'
    args = [ '/s', '/c', '"' + command + '"' ]
    options.windowsVerbatimArguments = true
  } else {
    file = '/bin/sh'
    args = [ '-c', command ]
    options.windowsVerbatimArguments = false
  }

  if (options && options.shell) {
    file = options.shell
    delete options.shell
  }

  return spawn(file, args, options)
}

const handleSpawningInMainProcess = () => {
  let out
  const parsed = parse(ELECTRON_LIB, xtend({ '': '$' }), { escape: ESCAPE_CHAR }).map(commandToString).join(' ')

  const overridePATH = {
    [ PATH_KEY ]: [ pathToNPMBinDirectory(), env[PATH_KEY] ].join(PATH_SEP)
  }

  const child = formatAndSpawn(parsed, { env: xtend(env, overridePATH) })
  out = child.stdin.write.bind(child.stdin)

  child.stdin.setEncoding('utf-8')
  child.stdout.pipe(process.stdout)

  child.on('exit', () => {
    out = console.log.bind(console)
  })

  return (log) => out(log)
}

module.exports = () => {
  if (typeof process === 'undefined') {
    // Web browser

    return console.log.bind(console)
  } else {
    if (process.type === 'renderer') {
      // Renderer process
      const { ipcRenderer } = require('electron')

      return (log) => ipcRenderer.send('quark-logger:ipc', log)
    } else {
      if (process.versions.electron) {
        // Electron
        const { ipcMain } = require('electron')

        let logger = handleSpawningInMainProcess()

        ipcMain.on('quark-logger:ipc', (event, arg) => {
          logger(arg)
        })

        return logger
      } else {
        // Node.js

        return handleSpawningInMainProcess()
      }
    }
  }
}

{'fraction_non_alphanumeric': 0.20224032586558044, 'fraction_numerical': 0.004887983706720978, 'mean_word_length': 3.186700767263427, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1945072', 'n_tokens_mistral': 1807, 'n_tokens_neox': 1747, 'n_words': 363}