<commit_before>#!/usr/bin/env node

/*globals require, console*/

'use strict'

const chalk = require('chalk'),
  process   = require('process'),
  args      = require('command-line-args'),
  cp        = require('child_process'),
  R         = require('ramda')

const error = chalk.bold.red

const header = `${chalk.blue('Penkki')}. Run a command ${chalk.italic('n')} times and measure how long it takes.`

const cli = args([
  { name:          'command',
    type:          String,
    multiple:      true,
    defaultOption: true,
    description:   'The command to run.'
  },
  { name:          'formatter',
    alias:         'f',
    type:          String,
    defaultValue:  'json',
    description:   'The formatter to use. Either "json", "sparkly", "chart", or "html". Default: "json".'
  },
  { name:          'times',
    alias:         't',
    type:          Number,
    description:   'The number of times to run the command.'
  },
  { name:          'help',
    alias:         'h',
    type:          Boolean,
    description:   'Show this help.'
  }
])

const options = cli.parse()

// Every method is a function that returns the options for the given formatter.
const formatterOptions = {
  chart: () => { return { width: 80, height: 25 } },
  html:  R.identity
}

if (!options.command || options.help) {
  console.log(header)
  console.log(cli.getUsage())
  process.exit(1)
}

function time(command) {
  let before = Date.now()
  cp.execSync(command)
  let after = Date.now()

  return after - before
}

// Get the output formatter.
//
// Try to load the given formatter in the "formatters" directory. If not found,
// try the dependencies. If still not found, throw an error.
function loadFormatter(name) {
  try {
    return require('./formatters/' + name)
  } catch (_) {
    try {
      return require(name)
    } catch (e) {
      console.error(`${error('ERROR:')} Couldn't load formatter "${name}":`)
      console.error(e)
      process.exit(1)
    }
  }
}

function main() {
  const command = options.command.join(' ')
  const data = R.times(R.partial(time, [command]), options.times)
  let formatter = loadFormatter(options.formatter)
  return formatter(data, formatterOptions[formatter.name](command))
}

console.log(main())<commit_msg>Fix "sparkly" and "json" formatters<commit_after>#!/usr/bin/env node

/*globals require, console*/

'use strict'

const chalk = require('chalk'),
  process   = require('process'),
  args      = require('command-line-args'),
  cp        = require('child_process'),
  R         = require('ramda')

const error = chalk.bold.red

const header = `${chalk.blue('Penkki')}. Run a command ${chalk.italic('n')} times and measure how long it takes.`

const cli = args([
  { name:          'command',
    type:          String,
    multiple:      true,
    defaultOption: true,
    description:   'The command to run.'
  },
  { name:          'formatter',
    alias:         'f',
    type:          String,
    defaultValue:  'json',
    description:   'The formatter to use. Either "json", "sparkly", "chart", or "html". Default: "json".'
  },
  { name:          'times',
    alias:         't',
    type:          Number,
    description:   'The number of times to run the command.'
  },
  { name:          'help',
    alias:         'h',
    type:          Boolean,
    description:   'Show this help.'
  }
])

const options = cli.parse()

// Every method is a function that returns the options for the given formatter.
const formatterOptions = {
  chart:   () => { return { width: 80, height: 25 } }
}

if (!options.command || options.help) {
  console.log(header)
  console.log(cli.getUsage())
  process.exit(1)
}

function time(command) {
  let before = Date.now()
  cp.execSync(command)
  let after = Date.now()

  return after - before
}

// Get the output formatter.
//
// Try to load the given formatter in the "formatters" directory. If not found,
// try the dependencies. If still not found, throw an error.
function loadFormatter(name) {
  try {
    return require('./formatters/' + name)
  } catch (_) {
    try {
      return require(name)
    } catch (e) {
      console.error(`${error('ERROR:')} Couldn't load formatter "${name}":`)
      console.error(e)
      process.exit(1)
    }
  }
}

function getFormatterOptions(name) {
  return R.has(name, formatterOptions) ? formatterOptions[name] : R.identity
}

function main() {
  const command = options.command.join(' ')
  const data = R.times(R.partial(time, [command]), options.times)
  let formatter = loadFormatter(options.formatter)
  return formatter(data, getFormatterOptions(formatter.name)(command))
}

console.log(main())
{'fraction_non_alphanumeric': 0.14583781458378145, 'fraction_numerical': 0.002581200258120026, 'mean_word_length': 2.6992840095465396, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 5, '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': '697892', 'n_tokens_mistral': 1481, 'n_tokens_neox': 1453, 'n_words': 416}