<commit_before>#! /usr/bin/env node
/* @flow */

import 'babel-polyfill'
import _ from 'lodash'
import chalk from 'chalk'
import path from 'path'
import program from 'commander'
import cliui from 'cliui'

import { Ouroboros, File } from 'ouroboros'

const ui = cliui({ width: 80 })

function parseStrings (value) {
  return value.split(/\s*,\s*/)
}

function parseNumber (value) {
  return parseInt(value, 10)
}

function parseNumbers (value) {
  return parseStrings(value).map(x => parseNumber(x))
}

function cloneOptions (options) {
  const newOptions = {}

  for (const property in options) {
    const value = options[property]
    if (value !== undefined) {
      newOptions[property] = value
    }
  }

  return newOptions
}

const command = async (inputs, env) => {
  const commands = env.name().split(',')
  const { saveEvents = [], verbose = false, ...options } = cloneOptions(env.opts())
  commands.unshift('load')
  commands.push('save')

  for (const filePath of inputs) {
    const events = []
    const ouroboros = await Ouroboros.create(path.resolve(filePath), options)
    ouroboros
      .on('log', event => {
        const nameText = event.name ? `[${event.name}] ` : ''
        const typeText = event.category ? `${event.category}: ` : ''
        const text = `${nameText}${typeText}${event.text.replace('\n', ' ')}`
        switch (event.severity) {
          case 'error':
            console.error(chalk.red(text))
            break
          case 'warning':
            console.warn(chalk.yellow(text))
            break
          case 'trace':
            console.warn(chalk.blue(text))
            break
          default:
            console.info(text)
            break
        }
      })
      .on('action', event => {
        if (verbose) {
          const triggerText = event.triggers.length !== 0 ? ` triggered by updates to ${event.triggers}` : ''
          console.log(`[${event.rule}] Evaluating ${event.action} action${triggerText}`)
        }
      })
      .on('command', event => {
        console.log(`[${event.rule}] Executing \`${event.command}\``)
      })
      .on('fileDeleted', event => {
        console.log(`Deleting \`${event.file}\``)
      })

    for (const type of saveEvents) {
      ouroboros.on(type, event => { events.push(event) })
    }

    await ouroboros.run(...commands)

    if (saveEvents.length !== 0) {
      const eventFilePath = ouroboros.resolvePath('$dir/$name-events.yaml')
      await File.safeDump(eventFilePath, { types: saveEvents, events })
    }
  }
}

program
  .version('0.0.0')
  .description('An experimental circular builder for LaTeX')

Ouroboros.getOptionDefinitions().then(definitions => {
  function loadOptions (pc) {
    for (const option of definitions) {
      const commands = pc.name().split(',')

      if (!option.commands.some(command => commands.includes(command))) continue

      const prefix = (option.type === 'boolean' && option.defaultValue) ? 'no-' : ''
      const flagList = [].concat((option.aliases || []).filter(alias => alias.length === 1), option.name)
        .map(name => name.length === 1 ? `-${name}` : `--${prefix}${_.kebabCase(name)}`)
        .join(', ')
      const flags = (option.type === 'boolean') ? flagList : `${flagList} <${option.name}>`

      switch (option.type) {
        case 'string':
          if (option.values) {
            pc = pc.option(flags, option.description, new RegExp(`^(${option.values.join('|')})$`), option.defaultValue)
          } else {
            pc = pc.option(flags, option.description, option.defaultValue)
          }
          break
        case 'strings':
          pc = pc.option(flags, option.description, parseStrings, option.defaultValue)
          break
        case 'number':
          pc = pc.option(flags, option.description, parseNumber, option.defaultValue)
          break
        case 'numbers':
          pc = pc.option(flags, option.description, parseNumbers, option.defaultValue)
          break
        case 'boolean':
          pc = pc.option(flags, option.description)
          break
      }
    }

    pc = pc.option('--save-events <saveEvents>', 'List of event types to save for test usage.', parseStrings, [])
    pc = pc.option('-v, --verbose', 'Be verbose in command output.')<commit_msg>Remove default values<commit_after>#! /usr/bin/env node
/* @flow */

import 'babel-polyfill'
import _ from 'lodash'
import chalk from 'chalk'
import path from 'path'
import program from 'commander'
import cliui from 'cliui'

import { Ouroboros, File } from 'ouroboros'

const ui = cliui({ width: 80 })

function parseStrings (value) {
  return value.split(/\s*,\s*/)
}

function parseNumber (value) {
  return parseInt(value, 10)
}

function parseNumbers (value) {
  return parseStrings(value).map(x => parseNumber(x))
}

function cloneOptions (options) {
  const newOptions = {}

  for (const property in options) {
    const value = options[property]
    if (value !== undefined) {
      newOptions[property] = value
    }
  }

  return newOptions
}

const command = async (inputs, env) => {
  const commands = env.name().split(',')
  const { saveEvents = [], verbose = false, ...options } = cloneOptions(env.opts())
  commands.unshift('load')
  commands.push('save')

  for (const filePath of inputs) {
    const events = []
    const ouroboros = await Ouroboros.create(path.resolve(filePath), options)
    ouroboros
      .on('log', event => {
        const nameText = event.name ? `[${event.name}] ` : ''
        const typeText = event.category ? `${event.category}: ` : ''
        const text = `${nameText}${typeText}${event.text.replace('\n', ' ')}`
        switch (event.severity) {
          case 'error':
            console.error(chalk.red(text))
            break
          case 'warning':
            console.warn(chalk.yellow(text))
            break
          case 'trace':
            console.warn(chalk.blue(text))
            break
          default:
            console.info(text)
            break
        }
      })
      .on('action', event => {
        if (verbose) {
          const triggerText = event.triggers.length !== 0 ? ` triggered by updates to ${event.triggers}` : ''
          console.log(`[${event.rule}] Evaluating ${event.action} action${triggerText}`)
        }
      })
      .on('command', event => {
        console.log(`[${event.rule}] Executing \`${event.command}\``)
      })
      .on('fileDeleted', event => {
        console.log(`Deleting \`${event.file}\``)
      })

    for (const type of saveEvents) {
      ouroboros.on(type, event => { events.push(event) })
    }

    await ouroboros.run(...commands)

    if (saveEvents.length !== 0) {
      const eventFilePath = ouroboros.resolvePath('$dir/$name-events.yaml')
      await File.safeDump(eventFilePath, { types: saveEvents, events })
    }
  }
}

program
  .version('0.0.0')
  .description('An experimental circular builder for LaTeX')

Ouroboros.getOptionDefinitions().then(definitions => {
  function loadOptions (pc) {
    for (const option of definitions) {
      const commands = pc.name().split(',')

      if (!option.commands.some(command => commands.includes(command))) continue

      const prefix = (option.type === 'boolean' && option.defaultValue) ? 'no-' : ''
      const flagList = [].concat((option.aliases || []).filter(alias => alias.length === 1), option.name)
        .map(name => name.length === 1 ? `-${name}` : `--${prefix}${_.kebabCase(name)}`)
        .join(', ')
      const flags = (option.type === 'boolean') ? flagList : `${flagList} <${option.name}>`

      switch (option.type) {
        case 'string':
          if (option.values) {
            pc = pc.option(flags, option.description, new RegExp(`^(${option.values.join('|')})$`))
          } else {
            pc = pc.option(flags, option.description)
          }
          break
        case 'strings':
          pc = pc.option(flags, option.description, parseStrings)
          break
        case 'number':
          pc = pc.option(flags, option.description, parseNumber)
          break
        case 'numbers':
          pc = pc.option(flags, option.description, parseNumbers)
          break
        case 'boolean':
          pc = pc.option(flags, option.description)
          break
      }
    }

    pc = pc.option('--save-events <saveEvents>', 'List of event types to save for test usage.', parseStrings, [])
    pc = pc.option('-v, --verbose', 'Be verbose in command output.')
{'fraction_non_alphanumeric': 0.15883536513196828, 'fraction_numerical': 0.0026038584447863654, 'mean_word_length': 2.5164377861007075, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, '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': '6795894', 'n_tokens_mistral': 2580, 'n_tokens_neox': 2536, 'n_words': 590}