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

const fs = require('fs-extra');
const p = require('path');

const spawn = require('cross-spawn');

const yargs = require('yargs');
const inquirer = require('inquirer');
const chalk = require('chalk');
const ora = require('ora');

const TEMPLATES_DIR = p.join(
  p.dirname(require.resolve('idyll-template-projects')),
  'templates'
);

const colors = {
  progress: chalk.hex('#6122fb'),
  success: chalk.green,
  failure: chalk.red
};

exports.command = 'create [post-name]';
exports.description = 'Create a new post';
exports.builder = builder;
exports.handler = main;

let _template;

function builder(yargs) {
  return yargs
    .usage('Usage: $0 create <post-name>')
    .example('$0 create example-post');
}

function main(argv) {
  let projectDir = argv._[1];

  getAllTemplates()
    .then(askQuestions)
    .then(ensureDefaults)
    .then(createProject);

  async function askQuestions(templates) {
    _template = templates[0];
    let questions = [];
    if (!projectDir) {
      questions.push({
        name: 'post-dir',
        message: 'In which directory would you like to install your post?',
        default: 'my-idyll-post'
      });
    }
    questions.push({
      name: 'package-name',
      message: 'What would you like to name your post?',
      default: answers => answers['post-dir'] || projectDir
    });
    // questions.push({
    //   name: 'template',
    //   type: 'list',
    //   message: 'Which project template would you like to use?',
    //   choices: templates
    // });
    console.log();
    return inquirer.prompt(questions);
  }

  async function ensureDefaults(answers) {
    if (!answers['post-dir']) answers['post-dir'] = projectDir;
    return answers;
  }
}

async function createProject(answers) {
  let name = answers['package-name'];
  let template = _template.value; // answers['template'];
  let dir = answers['post-dir'];

  let startMessage = `\nCreating a new Idyll post in ${dir} using the ${template} template...`;
  let successMessage = 'Finished creating the post!';
  let doneInstructionsText = `To start developing, run the following commands in your terminal:`;
  let doneInstructionsCommand = `    cd ${dir}\n    idyll`;
  let dirExistsMessage =
    'That directory already exists. Please ensure that your target directory\
 does not exist.';
  let errorMessage = `Could not create Idyll post in ${dir}`;

  let stages = [
    ['Ensuring that the target directory is valid', ensureEmptyProject],
    [
      'Copying files from template directory into the target directory',
      copyFiles
    ],
    ['Configuring post', fillTemplates],
    ['Installing dependencies', installDependencies]
  ];

  console.log(colors.success(startMessage));
  var spinner;
  try {
    for (var i = 0; i < stages.length; i++) {
      let stage = stages[i];
      spinner = ora({
        text: colors.progress(' ' + stage[0])
      });
      spinner.start();
      await stage[1]();
      spinner.succeed();
    }
  } catch (err) {
    if (spinner) spinner.fail(colors.failure(err));
    return;
  }
  console.log();
  console.log(colors.success(successMessage));
  console.log(doneInstructionsText);
  console.log(colors.progress(doneInstructionsCommand));

  async function ensureEmptyProject() {
    return fs.pathExists(dir).then(exists => {
      if (exists) {
        throw new Error(dirExistsMessage);
      }
      return true;
    });
  }

  async function copyFiles(proceed) {
    await fs.copy(getTemplatePath(template), dir);
    await fs.move(p.join(dir, 'gitignore'), p.join(dir, '.gitignore'));
  }

  async function fillTemplates() {
    let packagePath = p.join(dir, 'package.json');
    let indexPath = p.join(dir, 'index.idyll');

    let packageJson = JSON.parse(await fs.readFile(packagePath));
    let indexIdyll = await fs.readFile(indexPath, { encoding: 'utf-8' });

    packageJson.name = name
      .split(' ')
      .join('-')
      .toLowerCase();
    var title = name
      .split('-')
      .join(' ')
      .replace(/\b\w/g, l => l.toUpperCase());

    await fs.writeFile(packagePath, JSON.stringify(packageJson, null, 2));
    // TODO: could add more templating.
    await fs.writeFile(indexPath, indexIdyll.replace(/\{\{title\}\}/g, title));
  }

  async function installDependencies() {
    return new Promise((resolve, reject) => {
      let installer = spawn('npm', ['install'], {
        cwd: p.isAbsolute(dir) ? dir : p.join(process.cwd(), dir),
        stdio: 'ignore'
      });
      installer.on('close', code => {
        if (code !== 0) {
          return reject(new Error('Could not install Idyll dependencies.'));
        }
        return resolve();
      });
    });
  }
}

async function getAllTemplates() {
  let templateNames = await fs.readdir(TEMPLATES_DIR);
  return templateNames.map(path => {
    return {
      name: path.split('-').map(c => c[0].toUpperCase() + c.slice(1)),
      value: path
    };
  });
}

function getTemplatePath(templateName) {
  return p.join(TEMPLATES_DIR, templateName);
}

if (require.main === module) {
  builder(yargs);
  main(yargs.argv);
}
<commit_msg>Add template option to idyll create command<commit_after>#! /usr/bin/env node

const fs = require('fs-extra');
const p = require('path');

const spawn = require('cross-spawn');

const yargs = require('yargs');
const inquirer = require('inquirer');
const chalk = require('chalk');
const ora = require('ora');

const TEMPLATES_DIR = p.join(
  p.dirname(require.resolve('idyll-template-projects')),
  'templates'
);

const colors = {
  progress: chalk.hex('#6122fb'),
  success: chalk.green,
  failure: chalk.red
};

exports.command = 'create [post-name]';
exports.description = 'Create a new post';
exports.builder = builder;
exports.handler = main;

let _template;
let _customTemplate;

function buildOptions(yargs) {
  return yargs
    .alias({
      t: 'template'
    })
    .describe('template', 'Path to custom template');
}

function builder(yargs) {
  return buildOptions(yargs)
    .usage('Usage: $0 create <post-name>')
    .example('$0 create example-post');
}

function main(argv) {
  let projectDir = argv._[1];
  _customTemplate = argv['t'];

  getAllTemplates(_customTemplate)
    .then(askQuestions)
    .then(ensureDefaults)
    .then(createProject);

  async function askQuestions(templates) {
    _template = templates[0];
    let questions = [];
    if (!projectDir) {
      questions.push({
        name: 'post-dir',
        message: 'In which directory would you like to install your post?',
        default: 'my-idyll-post'
      });
    }
    questions.push({
      name: 'package-name',
      message: 'What would you like to name your post?',
      default: answers => answers['post-dir'] || projectDir
    });
    // questions.push({
    //   name: 'template',
    //   type: 'list',
    //   message: 'Which project template would you like to use?',
    //   choices: templates
    // });
    console.log();
    return inquirer.prompt(questions);
  }

  async function ensureDefaults(answers) {
    if (!answers['post-dir']) answers['post-dir'] = projectDir;
    return answers;
  }
}

async function createProject(answers) {
  let name = answers['package-name'];
  let template = _template.value; // answers['template'];
  let dir = answers['post-dir'];

  let startMessage = `\nCreating a new Idyll post in ${dir} using the ${template} template...`;
  let successMessage = 'Finished creating the post!';
  let doneInstructionsText = `To start developing, run the following commands in your terminal:`;
  let doneInstructionsCommand = `    cd ${dir}\n    idyll`;
  let dirExistsMessage =
    'That directory already exists. Please ensure that your target directory\
 does not exist.';
  let errorMessage = `Could not create Idyll post in ${dir}`;

  let stages = [
    ['Ensuring that the target directory is valid', ensureEmptyProject],
    [
      'Copying files from template directory into the target directory',
      copyFiles
    ],
    ['Configuring post', fillTemplates],
    ['Installing dependencies', installDependencies]
  ];

  console.log(colors.success(startMessage));
  var spinner;
  try {
    for (var i = 0; i < stages.length; i++) {
      let stage = stages[i];
      spinner = ora({
        text: colors.progress(' ' + stage[0])
      });
      spinner.start();
      await stage[1]();
      spinner.succeed();
    }
  } catch (err) {
    if (spinner) spinner.fail(colors.failure(err));
    return;
  }
  console.log();
  console.log(colors.success(successMessage));
  console.log(doneInstructionsText);
  console.log(colors.progress(doneInstructionsCommand));

  async function ensureEmptyProject() {
    return fs.pathExists(dir).then(exists => {
      if (exists) {
        throw new Error(dirExistsMessage);
      }
      return true;
    });
  }

  async function copyFiles(proceed) {
    const filterFunction = path => {
      return path.indexOf('node_modules') === -1;
    };
    await fs.copy(getTemplatePath(template, Boolean(_customTemplate)), dir, {
      filter: filterFunction
    });
    if (!Boolean(_customTemplate)) {
      await fs.move(p.join(dir, 'gitignore'), p.join(dir, '.gitignore'));
    }
  }

  async function fillTemplates() {
    let packagePath = p.join(dir, 'package.json');
    let indexPath = p.join(dir, 'index.idyll');

    let packageJson = JSON.parse(await fs.readFile(packagePath));
    let indexIdyll = await fs.readFile(indexPath, { encoding: 'utf-8' });

    packageJson.name = name
      .split(' ')
      .join('-')
      .toLowerCase();
    var title = name
      .split('-')
      .join(' ')
      .replace(/\b\w/g, l => l.toUpperCase());

    await fs.writeFile(packagePath, JSON.stringify(packageJson, null, 2));
    // TODO: could add more templating.
    await fs.writeFile(indexPath, indexIdyll.replace(/\{\{title\}\}/g, title));
  }

  async function installDependencies() {
    return new Promise((resolve, reject) => {
      let installer = spawn('npm', ['install'], {
        cwd: p.isAbsolute(dir) ? dir : p.join(process.cwd(), dir),
        stdio: 'ignore'
      });
      installer.on('close', code => {
        if (code !== 0) {
          return reject(new Error('Could not install Idyll dependencies.'));
        }
        return resolve();
      });
    });
  }
}

async function getAllTemplates(templateDir = TEMPLATES_DIR) {
  let templateNames;
  if (templateDir !== TEMPLATES_DIR) {
    templateNames = [templateDir];
  } else {
    templateNames = await fs.readdir(templateDir);
  }
  return templateNames.map(path => {
    return {
      name: path.split('-').map(c => c[0].toUpperCase() + c.slice(1)),
      value: path
    };
  });
}

function getTemplatePath(templateName, isCustomTemplate = false) {
  if (isCustomTemplate) {
    return p.resolve(templateName);
  }
  return p.join(TEMPLATES_DIR, templateName);
}

if (require.main === module) {
  builder(yargs);
  main(yargs.argv);
}

{'fraction_non_alphanumeric': 0.149798682284041, 'fraction_numerical': 0.003019765739385066, 'mean_word_length': 3.131947069943289, 'pattern_counts': {'":': 0, '<': 7, '<?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': '404998', 'n_tokens_mistral': 3439, 'n_tokens_neox': 3362, 'n_words': 849}