<commit_before>// Load modules

var Fs = require('fs');
var Hoek = require('hoek');
var Package = require('../package.json');
var Path = require('path');
var Os = require('os');
var Url = require('url');
var log = require('./log');
var Yargs = require('yargs');
var Async = require('async');
var Joi = require('joi');
var Wreck = require('wreck');

// Declare internals
var internals = {
    lastIndex: 0,
    schemaName: 'good.v1',
    host: Os.hostname(),
    appVer: Package.version
};

internals.setConfig = function () {

    var buildResult = function (options, source) {

        var parsedResult = {};
        var keys = Object.keys(options);
        var schema = Joi.object({
            url: Joi.string().required(),
            interval: Joi.number().default(1000).integer().min(1000),
            path: Joi.string().required(),
            onlySendNew: Joi.boolean().default(false)
        });

        for (var i = 0, il = keys.length; i < il; ++i) {
            var key = keys[i];

            if (source[options[key].alias] != null) {
                parsedResult[options[key].alias] = source[options[key].alias];
            }
        }

        var validate = Joi.validate(parsedResult, schema);
        if (validate.error) {
            console.error('Invalid arguments: \n' + validate.error.annotate() + '\n\n');
            Yargs.showHelp();
            process.exit(1);
        }
        else {
            return validate.value;
        }
    };

    var options = {
        c: {
            alias: 'config',
            description: 'Path to configuration file'
        },
        u: {
            alias: 'url',
            description: 'Url endpoint to send data'
        },
        l: {
            alias: 'path',
            description: 'Path to log file'
        },
        i: {
            alias: 'interval',
            description: 'Broadcast interval'
        },
        n: {
            alias: 'onlySendNew',
            description: 'Only send new records',
            boolean: true
        }
    };
    var parser = Yargs.usage('good-broadcast [options]');
    parser.options(options);
    var argv = parser.argv;

    if (argv.h) {
        Yargs.showHelp();
        process.exit(0);
    }

    // Configuration file trumps command line
    if (argv.c) {
        try {
            var config = JSON.parse(Fs.readFileSync(argv.c, 'utf8'));
            internals.argv = buildResult(options, config);

        } catch (ex) {
            console.error('Invalid JSON config file: ' + argv.c);
            throw ex;
        }
    }
    else {
        internals.argv = buildResult(options, argv);
    }
    internals.argv.path = Path.resolve(internals.argv.path);
};

internals.setConfig();

internals.broadcast = function (log) {

    if (!log.length) {
        return;
    }

    var envelope = {
        schema: internals.schemaName,
        host: internals.host,
        appVer: internals.appVer,
        timestamp: Date.now(),
        events: log
    };

    var requestOptions = {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        agent: false
    };
    var payload = JSON.stringify(envelope);

    Wreck.request(requestOptions.method, internals.argv.url, {
        payload: payload
    }, function (error, res) {

        if (error) {
            console.error(error);
        } else {
            res.pipe(process.stdout);
        }
    });
};

exports.start = function () {

    var config = internals.argv;

    var getStats = function (path, callback) {

        Fs.stat(path, function (error, stats) {

            var data = {
                stats: stats || {}
            };

            return callback(error, data);
        });
    };

    process.once('SIGUSR2', function () {

        process.exit(0);
    });

    var determineStart = function (next) {
        var start;

      getStats(config.path, function (error, result) {

          start = result.stats.size || 0;
          start = start ? start - 1 : 0;

          if (!config.onlySendNew) {
              start = 0;
          }

          next(start, result);
      });
    };

    var processLog = function (start, fileResult) {

        var startIndex = start;
        var previousResult = fileResult;

        return function (callback) {

            getStats(config.path, function(error, result) {
                if (error) {
                    console.error(error);
                    return callback(null);
                }

                var previousMtime = previousResult.stats.mtime;
                var resultMtime = result.stats.mtime;

                // If the file has been truncated since the last run.
                if (result.stats.size < startIndex) {
                    startIndex = 0;
                }
                else if (parseInt(result.stats.size, 10) === parseInt(previousResult.stats.size, 10)) {
                    // If the file has been overwritten and the length happens to be the same
                    if (resultMtime.getTime() > previousMtime.getTime()) {
                        startIndex = 0;
                    }
                }

                previousResult = result;

                log.get(config.path, startIndex, function (bytesRead, logResult) {

                    startIndex += bytesRead;

                    internals.broadcast(logResult);

                    setTimeout(function () {

                        callback(null);
                    }, config.interval);
                });
            });
        };
    };

    determineStart(function (start, result) {

        Async.forever(processLog(start, result), function (error) {

            if (error) {
                console.error(error);
            }

            process.exit(1);
        });
    });
};
<commit_msg>Cleanup after merge.<commit_after>// Load modules

var Fs = require('fs');
var Package = require('../package.json');
var Path = require('path');
var Os = require('os');
var log = require('./log');
var Yargs = require('yargs');
var Async = require('async');
var Joi = require('joi');
var Wreck = require('wreck');

// Declare internals
var internals = {
    lastIndex: 0,
    schemaName: 'good.v1',
    host: Os.hostname(),
    appVer: Package.version
};

internals.setConfig = function () {

    var buildResult = function (options, source) {

        var parsedResult = {};
        var keys = Object.keys(options);
        var schema = Joi.object({
            url: Joi.string().required(),
            interval: Joi.number().default(1000).integer().min(1000),
            path: Joi.string().required(),
            onlySendNew: Joi.boolean().default(false)
        });

        for (var i = 0, il = keys.length; i < il; ++i) {
            var key = keys[i];

            if (source[options[key].alias] != null) {
                parsedResult[options[key].alias] = source[options[key].alias];
            }
        }

        var validate = Joi.validate(parsedResult, schema);
        if (validate.error) {
            console.error('Invalid arguments: \n' + validate.error.annotate() + '\n\n');
            Yargs.showHelp();
            process.exit(1);
        }
        else {
            return validate.value;
        }
    };

    var options = {
        c: {
            alias: 'config',
            description: 'Path to configuration file'
        },
        u: {
            alias: 'url',
            description: 'Url endpoint to send data'
        },
        l: {
            alias: 'path',
            description: 'Path to log file'
        },
        i: {
            alias: 'interval',
            description: 'Broadcast interval'
        },
        n: {
            alias: 'onlySendNew',
            description: 'Only send new records',
            boolean: true
        }
    };
    var parser = Yargs.usage('good-broadcast [options]');
    parser.options(options);
    var argv = parser.argv;

    if (argv.h) {
        Yargs.showHelp();
        process.exit(0);
    }

    // Configuration file trumps command line
    if (argv.c) {
        try {
            var config = JSON.parse(Fs.readFileSync(argv.c, 'utf8'));
            internals.argv = buildResult(options, config);

        } catch (ex) {
            console.error('Invalid JSON config file: ' + argv.c);
            throw ex;
        }
    }
    else {
        internals.argv = buildResult(options, argv);
    }
    internals.argv.path = Path.resolve(internals.argv.path);
};

internals.setConfig();

internals.broadcast = function (log) {

    if (!log.length) {
        return;
    }

    var envelope = {
        schema: internals.schemaName,
        host: internals.host,
        appVer: internals.appVer,
        timestamp: Date.now(),
        events: log
    };

    var requestOptions = {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        agent: false
    };
    var payload = JSON.stringify(envelope);

    Wreck.request(requestOptions.method, internals.argv.url, {
        payload: payload
    }, function (error, res) {

        if (error) {
            console.error(error);
        } else {
            res.pipe(process.stdout);
        }
    });
};

exports.start = function () {

    var config = internals.argv;

    var getStats = function (path, callback) {

        Fs.stat(path, function (error, stats) {

            var data = {
                stats: stats || {}
            };

            return callback(error, data);
        });
    };

    process.once('SIGUSR2', function () {

        process.exit(0);
    });

    var determineStart = function (next) {
        var start;

      getStats(config.path, function (error, result) {

          start = result.stats.size || 0;
          start = start ? start - 1 : 0;

          if (!config.onlySendNew) {
              start = 0;
          }

          next(start, result);
      });
    };

    var processLog = function (start, fileResult) {

        var startIndex = start;
        var previousResult = fileResult;

        return function (callback) {

            getStats(config.path, function(error, result) {
                if (error) {
                    console.error(error);
                    return callback(null);
                }

                var previousMtime = previousResult.stats.mtime;
                var resultMtime = result.stats.mtime;

                // If the file has been truncated since the last run.
                if (result.stats.size < startIndex) {
                    startIndex = 0;
                }
                else if (parseInt(result.stats.size, 10) === parseInt(previousResult.stats.size, 10)) {
                    // If the file has been overwritten and the length happens to be the same
                    if (resultMtime.getTime() > previousMtime.getTime()) {
                        startIndex = 0;
                    }
                }

                previousResult = result;

                log.get(config.path, startIndex, function (bytesRead, logResult) {

                    startIndex += bytesRead;

                    internals.broadcast(logResult);

                    setTimeout(function () {

                        callback(null);
                    }, config.interval);
                });
            });
        };
    };

    determineStart(function (start, result) {

        Async.forever(processLog(start, result), function (error) {

            if (error) {
                console.error(error);
            }

            process.exit(1);
        });
    });
};
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  client: {
    lib: {
      css: [
        'public/lib/bootstrap/dist/css/bootstrap.css',
        'public/lib/bootstrap/dist/css/bootstrap-theme.css'
      ],
      js: [
        'public/lib/angular/angular.js',
        'public/lib/angular-resource/angular-resource.js',
        'public/lib/angular-animate/angular-animate.js',
        'public/lib/angular-messages/angular-messages.js',
        'public/lib/angular-ui-router/release/angular-ui-router.js',
        'public/lib/angular-ui-utils/ui-utils.js',
        'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
        'public/lib/angular-file-upload/angular-file-upload.js',
        'public/lib/owasp-password-strength-test/owasp-password-strength-test.js'
      ],
      tests: ['public/lib/angular-mocks/angular-mocks.js']
    },
    css: [
      'modules/*/client/css/*.css'
    ],
    less: [
      'modules/*/client/less/*.less'
    ],
    sass: [
      'modules/*/client/scss/*.scss'
    ],
    js: [
      'modules/core/client/app/config.js',
      'modules/core/client/app/init.js',
      'modules/*/client/*.js',
      'modules/*/client/**/*.js'
    ],
    views: ['modules/*/client/views/**/*.html'],
    templates: ['build/templates.js']
  },
  server: {
    gruntConfig: 'gruntfile.js',
    gulpConfig: 'gulpfile.js',
    allJS: ['server.js', 'config/**/*.js', 'modules/*/server/**/*.js'],
    models: 'modules/*/server/models/**/*.js',
    routes: ['modules/!(core)/server/routes/**/*.js', 'modules/core/server/routes/**/*.js'],
    sockets: 'modules/*/server/sockets/**/*.js',
    config: 'modules/*/server/config/*.js',
    policies: 'modules/*/server/policies/*.js',
    views: 'modules/*/server/views/*.html'
  }
};
<commit_msg>Added bootsrap and jquery to project javascript files<commit_after>'use strict';

module.exports = {
  client: {
    lib: {
      css: [
        'public/lib/bootstrap/dist/css/bootstrap.css',
        'public/lib/bootstrap/dist/css/bootstrap-theme.css'
      ],
      js: [
        'public/lib/angular/angular.js',
        'public/lib/angular-resource/angular-resource.js',
        'public/lib/angular-animate/angular-animate.js',
        'public/lib/angular-messages/angular-messages.js',
        'public/lib/angular-ui-router/release/angular-ui-router.js',
        'public/lib/angular-ui-utils/ui-utils.js',
        'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
        'public/lib/angular-file-upload/angular-file-upload.js',
        'public/lib/owasp-password-strength-test/owasp-password-strength-test.js',
        'public/lib/jquery/dist/jquery.min.js',
        'public/lib/bootstrap/dist/js/bootstrap.min.js'
      ],
      tests: ['public/lib/angular-mocks/angular-mocks.js']
    },
    css: [
      'modules/*/client/css/*.css'
    ],
    less: [
      'modules/*/client/less/*.less'
    ],
    sass: [
      'modules/*/client/scss/*.scss'
    ],
    js: [
      'modules/core/client/app/config.js',
      'modules/core/client/app/init.js',
      'modules/*/client/*.js',
      'modules/*/client/**/*.js'
    ],
    views: ['modules/*/client/views/**/*.html'],
    templates: ['build/templates.js']
  },
  server: {
    gruntConfig: 'gruntfile.js',
    gulpConfig: 'gulpfile.js',
    allJS: ['server.js', 'config/**/*.js', 'modules/*/server/**/*.js'],
    models: 'modules/*/server/models/**/*.js',
    routes: ['modules/!(core)/server/routes/**/*.js', 'modules/core/server/routes/**/*.js'],
    sockets: 'modules/*/server/sockets/**/*.js',
    config: 'modules/*/server/config/*.js',
    policies: 'modules/*/server/policies/*.js',
    views: 'modules/*/server/views/*.html'
  }
};
<|endoftext|>


<commit_before>// cli.js
//

var commands  = require('./commands');
var collider  = require('./collider');
var pkg       = require('../package.json');
var questions = require('./questions');

var inquirer = require('inquirer');

module.exports = function (argv) {
  var command = argv._[0];

  switch (command) {
    case 'new':
      inquirer.prompt(questions.new)
        .then(commands.new);
      break;

    case 'open':
      collider.load('.', function (err, project) {
        if (err) throw err;
        commands.open(project);
      });

      break;

    case 'edit':
      collider.load('.', function (err, defaults) {
        if (err) throw err;
        questions.edit = questions.assignDefaults(questions.edit, defaults);

        inquirer.prompt(questions.edit)
          .then(commands.edit);
      });

      break;

    case 'generate':
      inquirer.prompt(questions.generate)
        .then(commands.generate);
      break;

    case 'update':
      inquirer.prompt(questions.update)
        .then(commands.update);
      break;

    default:
      if (argv.help) {
        console.log(getHelp());
        break;
      }

      if (argv.version) {
        console.log(getVersion());
        break;
      }

      console.error(getHelp());
  }

};

function getHelp() {
  return `
usage:
  collider new       Create a new project.
  collider open      Open the current project.
  collider edit      Edit the current project's settings.
  collider generate  Generate Matter component starting files.
  collider update    Update Collider to the latest version.

options:
  -h, --help         Show this message.
  -v, --version      Show this program's version.
  `;
}

function getVersion() {
  return `
Collider CLI v${pkg.version}
  `;
}
<commit_msg>Improve ENOENT error message on 'open'<commit_after>// cli.js
//

var commands  = require('./commands');
var collider  = require('./collider');
var pkg       = require('../package.json');
var questions = require('./questions');

var inquirer = require('inquirer');

module.exports = function (argv) {
  var command = argv._[0];

  switch (command) {
    case 'new':
      inquirer.prompt(questions.new)
        .then(commands.new);
      break;

    case 'open':
      collider.load('.', function (err, project) {
        if (err) {
          err.message = err.code === 'ENOENT' ? 'A collider.json file could not be found. Is this a Collider project?' : err.message;
          throw err;
        }

        commands.open(project);
      });

      break;

    case 'edit':
      collider.load('.', function (err, defaults) {
        if (err) throw err;
        questions.edit = questions.assignDefaults(questions.edit, defaults);

        inquirer.prompt(questions.edit)
          .then(commands.edit);
      });

      break;

    case 'generate':
      inquirer.prompt(questions.generate)
        .then(commands.generate);
      break;

    case 'update':
      inquirer.prompt(questions.update)
        .then(commands.update);
      break;

    default:
      if (argv.help) {
        console.log(getHelp());
        break;
      }

      if (argv.version) {
        console.log(getVersion());
        break;
      }

      console.error(getHelp());
  }

};

function getHelp() {
  return `
usage:
  collider new       Create a new project.
  collider open      Open the current project.
  collider edit      Edit the current project's settings.
  collider generate  Generate Matter component starting files.
  collider update    Update Collider to the latest version.

options:
  -h, --help         Show this message.
  -v, --version      Show this program's version.
  `;
}

function getVersion() {
  return `
Collider CLI v${pkg.version}
  `;
}
<|endoftext|>


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

var Jison = require('./jison.js');

function getCommandlineOptions() {
    'use strict';

    var version = require('../package.json').version;
    var opts = require('nomnom')
        .script('jison')
        .unknownOptionTreatment(false)              // do not accept unknown options!
        .options({
            file: {
                flag: true,
                position: 0,
                help: 'file containing a grammar'
            },
            lexfile: {
                flag: true,
                position: 1,
                help: 'file containing a lexical grammar'
            },
            json: {
                abbr: 'j',
                flag: true,
                default: false,
                help: 'jison will expect a grammar in either JSON/JSON5 or JISON format: the precise format is autodetected'
            },
            outfile: {
                abbr: 'o',
                metavar: 'FILE',
                help : 'Filepath and base module name of the generated parser;\nwhen terminated with a / (dir separator) it is treated as the destination directory where the generated output will be stored'
            },
            debug: {
                abbr: 't',
                flag: true,
                default: false,
                help: 'Debug mode'
            },
            dumpSourceCodeOnFailure: {
                full: 'dump-sourcecode-on-failure',
                flag: true,
                default: true,
                help: 'Dump the generated source code to a special named file when the internal generator tests fail, i.e. when the generated source code does not compile in the JavaScript engine. Enabling this option helps you to diagnose/debug crashes (thrown exceptions) in the code generator due to various reasons: you can, for example, load the dumped sourcecode in another environment (e.g. NodeJS) to get more info on the precise location and cause of the compile failure.'
            },
            throwErrorOnCompileFailure: {
                full: 'throw-on-compile-failure',
                flag: true,
                default: true,
                help: 'Throw an exception when the generated source code fails to compile in the JavaScript engine. **WARNING**: Turning this feature OFF permits the code generator to produce non-working source code and treat that as SUCCESS. This MAY be desirable code generator behaviour, but only rarely.'
            },
            reportStats: {
                full: 'info',
                abbr: 'I',
                flag: true,
                default: false,
                help: 'Report some statistics about the generated parser'
            },
            moduleType: {
                full: 'module-type',
                abbr: 'm',
                default: 'commonjs',
                metavar: 'TYPE',
                choices: ['commonjs', 'amd', 'js', 'es'],
                help: 'The type of module to generate (commonjs, amd, es, js)'
            },
            moduleName: {
                full: 'module-name',
            	abbr: 'n',
            	metavar: 'NAME',
            	help: 'The name of the generated parser object, namespace supported'
            },
            parserType: {
                full: 'parser-type',
                abbr: 'p',
                default: 'lalr',
                metavar: 'TYPE',
                help: 'The type of algorithm to use for the parser (lr0, slr, lalr, lr, ll)'
            },
            compressTables: {
                full: 'compress-tables',
                abbr: 'c',
                flag: false,
                default: 2,             // 0, 1, 2
                choices: [0, 1, 2],
                help: 'Output compressed parser tables in generated modules (0 = no compression, 1 = default compression, 2 = deep compression)'
            },
            outputDebugTables: {
                full: 'output-debug-tables',
                abbr: 'T',
                flag: true,
                default: false,
                help: 'Output extra parser tables (rules list + look-ahead analysis) in generated modules to assist debugging / diagnostics purposes'
            },
            hasDefaultResolve: {
                full: 'default-resolve',
                abbr: 'X',
                flag: true,
                default: true,
                help: 'Turn this OFF to make jison act another way when a conflict is found in the grammar'
            },
            hasPartialLrUpgradeOnConflict: {
                full: 'partial-lr-upgrade-on-conflict',
                abbr: 'Z',
                flag: true,
                default: true,
                help: 'When enabled, the grammar generator attempts to resolve LALR(1) conflicts by, at least for the conflicting rules, moving towards LR(1) behaviour'
            },
            hasDefaultAction: {
                full: 'default-action',
                flag: true,
                default: true,
                help: 'Generate a parser which includes the default "$$ = $1" action for every rule. When you turn this OFF, it will produce a slightly faster parser but then you are solely responsible for propagating rule action "$$" results.'
            },
            hasTryCatch: {
                full: 'try-catch',
                flag: true,
                default: true,
                help: 'Generate a parser which catches exceptions from the grammar action code or parseError error reporting calls using a try/catch/finally code block. When you turn this OFF, it will produce a slightly faster parser at the cost of reduced code safety.'
            },
            errorRecoveryTokenDiscardCount: {
                full: 'error-recovery-token-discard-count',
                abbr: 'Q',
                flag: false,
                default: 3,
                callback: function (count) {
                    if (count != parseInt(count)) {
                        return "count must be an integer";
                    }
                    count = parseInt(count);
                    if (count < 2) {
                        return "count must be >= 2";
                    }
                },
                help: 'Set the number of lexed tokens that may be gobbled by an error recovery process before we cry wolf (default: 3)'
            },
            exportAllTables: {
                full: 'export-all-tables',
                abbr: 'E',
                flag: true,
                default: false,
                help: 'Next to producing a grammar source file, also export the symbols, terminals, grammar and parse tables to separate JSON files for further use by other tools. The files\' names will be derived from the outputFile name by appending a suffix.'
            },
            main: {
                full: 'main',
            	abbr: 'x',
                flag: true,
                default: false,
                help: 'Include .main() entry point in generated commonjs module'
            },
            moduleMain: {
                full: 'module-main',
            	abbr: 'y',
            	metavar: 'NAME',
            	help: 'The main module function definition'
            },
            version: {
                abbr: 'V',
                flag: true,
                help: 'print version and exit',
                callback: function () {
                    return version;
                }
            }
        }).parse();

    return opts;
}

var cli = module.exports;

cli.main = function cliMain(opts) {
    'use strict';

    opts = Jison.mkStdOptions(opts);

    var fs = require('fs');
    var path = require('path');

    function isDirectory(fp) {
        try {
            return fs.lstatSync(fp).isDirectory();
        } catch (e) {
            return false;
        }
    }

    function mkdirp(fp) {
        if (!fp || fp === '.' || fp.length === 0) {
            return false;
        }
        try {
            fs.mkdirSync(fp);
            return true;
        } catch (e) {
            if (e.code === 'ENOENT') {
                var parent = path.dirname(fp);
                // Did we hit the root directory by now? If so, abort!
                // Else, create the parent; iff that fails, we fail too...
                if (parent !== fp && mkdirp(parent)) {
                    try {
                        // Retry creating the original directory: it should succeed now
                        fs.mkdirSync(fp);
                        return true;
                    } catch (e) {
                        return false;
                    }
                }
            }
        }
        return false;
    }

    function processInputFile() {
        // getting raw files
        var lex;
        var original_cwd = process.cwd();

        if (opts.lexfile) {
            lex = fs.readFileSync(path.normalize(opts.lexfile), 'utf8');
        }
        var raw = fs.readFileSync(path.normalize(opts.file), 'utf8');

        // making best guess at json mode
        opts.json = path.extname(opts.file) === '.json' || opts.json;

        // When only the directory part of the output path was specified, then we
        // do NOT have the target module name in there as well!
        var outpath = opts.outfile;
        if (/[\\\/]$/.test(outpath) || isDirectory(outpath)) {
            opts.outfile = null;
            outpath = outpath.replace(/[\\\/]$/, '');
        }
        if (outpath && outpath.length > 0) {
            outpath += '/';
        } else {
            outpath = '';
        }

        // setting output file name and module name based on input file name
        // if they aren't specified.
        var name = path.basename(opts.outfile || opts.file);

        // get the base name (i.e. the file name without extension)
        // i.e. strip off only the extension and keep any other dots in the filename
        name = path.basename(name, path.extname(name));

        opts.outfile = opts.outfile || (outpath + name + '.js');
        if (!opts.moduleName && name) {
            opts.moduleName = opts.defaultModuleName = name.replace(/-\w/g,
                function (match) {
                    return match.charAt(1).toUpperCase();
                });
        }

        // Change CWD to the directory where the source grammar resides: this helps us properly
        // %include any files mentioned in the grammar with relative paths:
        var new_cwd = path.dirname(path.normalize(opts.file));
        process.chdir(new_cwd);

        var parser = cli.generateParserString(raw, lex, opts);

        // and change back to the CWD we started out with:
        process.chdir(original_cwd);

        mkdirp(path.dirname(opts.outfile));
        fs.writeFileSync(opts.outfile, parser);
        console.log('JISON output for module [' + opts.moduleName + '] has been written to file:', opts.outfile);

        if (opts.exportAllTables) {
	        	// Determine the output file path 'template' for use by the exportAllTables
	        	// functionality:
	        	var out_ext = path.extname(opts.outfile);
	        	var out_re = new RegExp(out_ext.replace(/\./g, '\\.') + '$');			// re = /\.<ext>$/
	        	//opts.outfiletemplate = opts.outfile.replace(out_re, '@@');

	        	var t = opts.exportAllTables;

	        	for (var id in t) {
	        		if (t.hasOwnProperty(id) && id !== 'enabled') {
	        			var content = t[id];
	        			if (content) {
	        				var fname = opts.outfile.replace(out_re, '.' + id.replace(/[^a-zA-Z0-9_]/g, '_') + '.json');
					        fs.writeFileSync(fname, JSON.stringify(content, null, 2) /* .replace(/"([0-9]+)":/g, '$1:').replace(/^(\s+)"([a-z_][a-z_0-9]*)":/gmi, '$1$2:') */ );
					        console.log('JISON table export for [' + id + '] has been written to file:', fname);
	        			}
	        		}
	        	}
        }
    }

    function readin(cb) {
        var stdin = process.openStdin(),
        data = '';

        stdin.setEncoding('utf8');
        stdin.addListener('data', function (chunk) {
            data += chunk;
        });
        stdin.addListener('end', function () {
            cb(data);
        });
    }

    function processStdin() {
        readin(function processStdinReadInCallback(raw) {
            console.log(cli.generateParserString(raw, null, opts));
        });
    }

    // if an input file wasn't given, assume input on stdin
    if (opts.file) {
        processInputFile();
    } else {
        processStdin();
    }
};

cli.generateParserString = function generateParserString(grammar, optionalLexSection, opts) {
    'use strict';

    var settings = Jison.mkStdOptions(opts);

    var generator = new Jison.Generator(grammar, optionalLexSection, settings);
    var srcCode = generator.generate(settings);
    generator.reportGrammarInformation();

    // as `settings` is cloned inside `generator.generate()`, we need to fetch
    // the extra exported tables from the `options` member of the generator
    // itself:
    opts.exportAllTables = generator.options.exportAllTables;

    return srcCode;
};

if (require.main === module) {
    var opts = getCommandlineOptions();
    cli.main(opts);
}

<commit_msg>Slightly reformulate the help text for one of the command line options + whitespace police raid<commit_after>#!/usr/bin/env node

var Jison = require('./jison.js');

function getCommandlineOptions() {
    'use strict';

    var version = require('../package.json').version;
    var opts = require('nomnom')
        .script('jison')
        .unknownOptionTreatment(false)              // do not accept unknown options!
        .options({
            file: {
                flag: true,
                position: 0,
                help: 'file containing a grammar'
            },
            lexfile: {
                flag: true,
                position: 1,
                help: 'file containing a lexical grammar'
            },
            json: {
                abbr: 'j',
                flag: true,
                default: false,
                help: 'jison will expect a grammar in either JSON/JSON5 or JISON format: the precise format is autodetected'
            },
            outfile: {
                abbr: 'o',
                metavar: 'FILE',
                help : 'Filepath and base module name of the generated parser;\nwhen terminated with a / (dir separator) it is treated as the destination directory where the generated output will be stored'
            },
            debug: {
                abbr: 't',
                flag: true,
                default: false,
                help: 'Debug mode'
            },
            dumpSourceCodeOnFailure: {
                full: 'dump-sourcecode-on-failure',
                flag: true,
                default: true,
                help: 'Dump the generated source code to a special named file when the internal generator tests fail, i.e. when the generated source code does not compile in the JavaScript engine. Enabling this option helps you to diagnose/debug crashes (thrown exceptions) in the code generator due to various reasons: you can, for example, load the dumped sourcecode in another environment (e.g. NodeJS) to get more info on the precise location and cause of the compile failure.'
            },
            throwErrorOnCompileFailure: {
                full: 'throw-on-compile-failure',
                flag: true,
                default: true,
                help: 'Throw an exception when the generated source code fails to compile in the JavaScript engine. **WARNING**: Turning this feature OFF permits the code generator to produce non-working source code and treat that as SUCCESS. This MAY be desirable code generator behaviour, but only rarely.'
            },
            reportStats: {
                full: 'info',
                abbr: 'I',
                flag: true,
                default: false,
                help: 'Report some statistics about the generated parser'
            },
            moduleType: {
                full: 'module-type',
                abbr: 'm',
                default: 'commonjs',
                metavar: 'TYPE',
                choices: ['commonjs', 'amd', 'js', 'es'],
                help: 'The type of module to generate (commonjs, amd, es, js)'
            },
            moduleName: {
                full: 'module-name',
                abbr: 'n',
                metavar: 'NAME',
                help: 'The name of the generated parser object, namespace supported'
            },
            parserType: {
                full: 'parser-type',
                abbr: 'p',
                default: 'lalr',
                metavar: 'TYPE',
                help: 'The type of algorithm to use for the parser (lr0, slr, lalr, lr, ll)'
            },
            compressTables: {
                full: 'compress-tables',
                abbr: 'c',
                flag: false,
                default: 2,             // 0, 1, 2
                choices: [0, 1, 2],
                help: 'Output compressed parser tables in generated modules (0 = no compression, 1 = default compression, 2 = deep compression)'
            },
            outputDebugTables: {
                full: 'output-debug-tables',
                abbr: 'T',
                flag: true,
                default: false,
                help: 'Output extra parser tables (rules list + look-ahead analysis) in generated modules to assist debugging / diagnostics purposes'
            },
            hasDefaultResolve: {
                full: 'default-resolve',
                abbr: 'X',
                flag: true,
                default: true,
                help: 'Turn this OFF to make jison act another way when a conflict is found in the grammar'
            },
            hasPartialLrUpgradeOnConflict: {
                full: 'partial-lr-upgrade-on-conflict',
                abbr: 'Z',
                flag: true,
                default: true,
                help: 'When enabled, the grammar generator attempts to resolve LALR(1) conflicts by, at least for the conflicting rules, moving towards LR(1) behaviour'
            },
            hasDefaultAction: {
                full: 'default-action',
                flag: true,
                default: true,
                help: 'Generate a parser which includes the default "$$ = $1" action for every rule. When you turn this OFF, it will produce a slightly faster parser but then you are solely responsible for propagating rule action "$$" results.'
            },
            hasTryCatch: {
                full: 'try-catch',
                flag: true,
                default: true,
                help: 'Generate a parser which catches exceptions from the grammar action code or parseError error reporting calls using a try/catch/finally code block. When you turn this OFF, it will produce a slightly faster parser at the cost of reduced code safety.'
            },
            errorRecoveryTokenDiscardCount: {
                full: 'error-recovery-token-discard-count',
                abbr: 'Q',
                flag: false,
                default: 3,
                callback: function (count) {
                    if (count != parseInt(count)) {
                        return "count must be an integer";
                    }
                    count = parseInt(count);
                    if (count < 2) {
                        return "count must be >= 2";
                    }
                },
                help: 'Specify the number of lexed tokens that may be gobbled by an error recovery process before we cry wolf'
            },
            exportAllTables: {
                full: 'export-all-tables',
                abbr: 'E',
                flag: true,
                default: false,
                help: 'Next to producing a grammar source file, also export the symbols, terminals, grammar and parse tables to separate JSON files for further use by other tools. The files\' names will be derived from the outputFile name by appending a suffix.'
            },
            main: {
                full: 'main',
                abbr: 'x',
                flag: true,
                default: false,
                help: 'Include .main() entry point in generated commonjs module'
            },
            moduleMain: {
                full: 'module-main',
                abbr: 'y',
                metavar: 'NAME',
                help: 'The main module function definition'
            },
            version: {
                abbr: 'V',
                flag: true,
                help: 'print version and exit',
                callback: function () {
                    return version;
                }
            }
        }).parse();

    return opts;
}

var cli = module.exports;

cli.main = function cliMain(opts) {
    'use strict';

    opts = Jison.mkStdOptions(opts);

    var fs = require('fs');
    var path = require('path');

    function isDirectory(fp) {
        try {
            return fs.lstatSync(fp).isDirectory();
        } catch (e) {
            return false;
        }
    }

    function mkdirp(fp) {
        if (!fp || fp === '.' || fp.length === 0) {
            return false;
        }
        try {
            fs.mkdirSync(fp);
            return true;
        } catch (e) {
            if (e.code === 'ENOENT') {
                var parent = path.dirname(fp);
                // Did we hit the root directory by now? If so, abort!
                // Else, create the parent; iff that fails, we fail too...
                if (parent !== fp && mkdirp(parent)) {
                    try {
                        // Retry creating the original directory: it should succeed now
                        fs.mkdirSync(fp);
                        return true;
                    } catch (e) {
                        return false;
                    }
                }
            }
        }
        return false;
    }

    function processInputFile() {
        // getting raw files
        var lex;
        var original_cwd = process.cwd();

        if (opts.lexfile) {
            lex = fs.readFileSync(path.normalize(opts.lexfile), 'utf8');
        }
        var raw = fs.readFileSync(path.normalize(opts.file), 'utf8');

        // making best guess at json mode
        opts.json = path.extname(opts.file) === '.json' || opts.json;

        // When only the directory part of the output path was specified, then we
        // do NOT have the target module name in there as well!
        var outpath = opts.outfile;
        if (/[\\\/]$/.test(outpath) || isDirectory(outpath)) {
            opts.outfile = null;
            outpath = outpath.replace(/[\\\/]$/, '');
        }
        if (outpath && outpath.length > 0) {
            outpath += '/';
        } else {
            outpath = '';
        }

        // setting output file name and module name based on input file name
        // if they aren't specified.
        var name = path.basename(opts.outfile || opts.file);

        // get the base name (i.e. the file name without extension)
        // i.e. strip off only the extension and keep any other dots in the filename
        name = path.basename(name, path.extname(name));

        opts.outfile = opts.outfile || (outpath + name + '.js');
        if (!opts.moduleName && name) {
            opts.moduleName = opts.defaultModuleName = name.replace(/-\w/g,
                function (match) {
                    return match.charAt(1).toUpperCase();
                });
        }

        // Change CWD to the directory where the source grammar resides: this helps us properly
        // %include any files mentioned in the grammar with relative paths:
        var new_cwd = path.dirname(path.normalize(opts.file));
        process.chdir(new_cwd);

        var parser = cli.generateParserString(raw, lex, opts);

        // and change back to the CWD we started out with:
        process.chdir(original_cwd);

        mkdirp(path.dirname(opts.outfile));
        fs.writeFileSync(opts.outfile, parser);
        console.log('JISON output for module [' + opts.moduleName + '] has been written to file:', opts.outfile);

        if (opts.exportAllTables) {
            // Determine the output file path 'template' for use by the exportAllTables
            // functionality:
            var out_ext = path.extname(opts.outfile);
            var out_re = new RegExp(out_ext.replace(/\./g, '\\.') + '$');           // re = /\.<ext>$/
            //opts.outfiletemplate = opts.outfile.replace(out_re, '@@');

            var t = opts.exportAllTables;

            for (var id in t) {
                if (t.hasOwnProperty(id) && id !== 'enabled') {
                    var content = t[id];
                    if (content) {
                        var fname = opts.outfile.replace(out_re, '.' + id.replace(/[^a-zA-Z0-9_]/g, '_') + '.json');
                        fs.writeFileSync(fname, JSON.stringify(content, null, 2));
                        console.log('JISON table export for [' + id + '] has been written to file:', fname);
                    }
                }
            }
        }
    }

    function readin(cb) {
        var stdin = process.openStdin(),
        data = '';

        stdin.setEncoding('utf8');
        stdin.addListener('data', function (chunk) {
            data += chunk;
        });
        stdin.addListener('end', function () {
            cb(data);
        });
    }

    function processStdin() {
        readin(function processStdinReadInCallback(raw) {
            console.log(cli.generateParserString(raw, null, opts));
        });
    }

    // if an input file wasn't given, assume input on stdin
    if (opts.file) {
        processInputFile();
    } else {
        processStdin();
    }
};

cli.generateParserString = function generateParserString(grammar, optionalLexSection, opts) {
    'use strict';

    var settings = Jison.mkStdOptions(opts);

    var generator = new Jison.Generator(grammar, optionalLexSection, settings);
    var srcCode = generator.generate(settings);
    generator.reportGrammarInformation();

    // as `settings` is cloned inside `generator.generate()`, we need to fetch
    // the extra exported tables from the `options` member of the generator
    // itself:
    opts.exportAllTables = generator.options.exportAllTables;

    return srcCode;
};

if (require.main === module) {
    var opts = getCommandlineOptions();
    cli.main(opts);
}

<|endoftext|>


<commit_before>require('eventsource-polyfill');

var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true');

hotClient.subscribe(function (event) {
    if (event.action === 'reload') {
        window.location.reload();
    }
});<commit_msg>update dev client<commit_after>require('eventsource-polyfill');

const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true');

hotClient.subscribe(event => {
    if (event.action === 'reload') {
        window.location.reload();
    }
});<|endoftext|>


<commit_before>'use strict';

/**!
 * [square]
 * @copyright (c) 2012 observe.it (observe.it) <opensource@observe.it>
 * MIT Licensed
 */

/**
 * Native modules.
 */
var fs = require('fs')
  , path = require('path');

/**
 * Third party modules.
 */
var cli = require('commander')
  , colors = require('colors')
  , _ = require('lodash');

/**
 * Square's API
 */
var Square = require('./square')
  , helpers = require('./helpers');

/**
 * Expose the commandline as function so custom arguments can be fed in to the
 * system.
 *
 * @param {Array} argv
 * @api public
 */
module.exports = function commandline(argv) {
  argv = argv || process.argv;

  /**
   * Setup the command line interface for square.
   */
  cli
    .version(require('../package.json').version)
    .usage('[options] [files]')
    .option('-e, --extensions <extensions>', 'only process files with these extensions', list, [])
    .option('-p, --plugins <plugins>', 'specify the plugins to use', list, [])
    .option('-P, --platform <platform>', 'only build files for this platform', list, ['web'])
    .option('-s, --storage <storage>', 'specify the storage system', list, ['disk'])
    .option('-w, --watch [port]', 'watch the bundled files for changes', parseInt);

  cli.name = 'square';

  /**
   * Scaffold command, generate an example square.json in the given directory, if
   * the given directory does not yet exist, create it for them.
   *
   * @param {String} destination
   */
  cli
    .command('scaffold [path]')
    .description('scaffold a square.json file')
    .action(function scaffold(destination) {
      // If we were given a path, we should create it if it doesn't exist or we
      // should just default to the users current working directory.
      if (destination) require('mkdirp').sync(destination);
      else destination = process.cwd();

      // Write an example square.json file.
      fs.writeFileSync(path.join(destination, 'square.json'), JSON.stringify({
          configuration: {
            dist: '/path/to/storage/{type}/bundlename.{ext}'
          }

        , bundle: {
            'path/to/file.js': {
                description: '{string} -- a small description about the use of file.css'
              , weight: '{number} 100 -- used to override the default order of inclusion'
              , version: '{string} 0.0.0 -- the version of a third party script'
              , latest: '{string} -- remote url of the third party asset'
              , extract: [
                    '{array} of variable or function names to extract from the source'
                  , 'if you want to exclude these functions of vars, let the first item'
                  , 'be a the boolean `true`'
                ]
            },
            'example/parser.coffee': {
                description: 'config parser written in pure coffeescript'
            },
            'example/jQuery.js': {
                description: 'Cross browser DOM utility library'
              , latest: 'http://code.jquery.com/jquery.js'
              , version: '1.8.3'
            }
          }
      }, null, 2));

      [
          ''
        , 'Created a new `square.json` file at '+ destination
        , ''
        , 'To learn more about the square.json specification take a look at our'
        , 'documentation center at github: github.com/observing/square/tree/master/doc'
        , ''
        , 'Or visit us irc: irc.freenode.net#observing'
        , ''
      ].forEach(function details(line) {
        console.log(line);
      });

      process.exit(0);
    });

  /**
   * Output the square ASCII logo.
   *
   * @param {Boolean} exit exit the node process after outputting
   */
  cli.logo = function logo(exit) {
    [
        ''
      , 'o-o  o-o o  o o-o o-o o-o '.cyan
      , ' \\  |  | |  | |-| |   |- '.cyan + ('      version: ' + cli._version).white
      , 'o-o  o-O o--o o o-o   o-o '.cyan
      , '       |                  '.cyan
      , '       o                  '.cyan
      , ''
    ].forEach(function logo(line) {
      console.log('  ' + line);
    });

    if (exit) process.exit(0);
  };

  /**
   * Output some square CLI examples.
   *
   * @param {Boolean} exit exit the node process after outputting.
   */
  cli.examples = function examples(exit) {
    [
        ''
      , 'Examples:'
      , ''
      , '# Generating a build with multiple plugins'.grey
      , 'square --plugins '.white
          + 'debug,crush '.green
          + './path/to/square.json'.white
      , ''
      , '# Automatically rebuild files on changes + live reload server'.grey
      , 'square --plugins '.white
          + 'debug,crush '.green
          + '--watch'.white + ' 8080 '.green
          + './path/to/square.json'.white
    ].forEach(function log(line) {
      console.log(line);
    });

    if (exit) process.exit(0);
  };

  /**
   * Display custom help information.
   *
   * @api public
   */
  cli.on('--help', function help() {
    cli.examples(true);
  });

  /**
   * List all the available plugins and their descriptions.
   *
   * @api private
   */
  cli.on('--list', function list() {
    var plugsin = Square.plugins();
  });

  /**
   * Watching.
   *
   * @param {Number} port
   * @api public
   */
  cli.on('--watch', function watch(port) {
    // Register a signint handler so we can cleanly exit the process when
    // people press crtl+c.
    process.on('SIGINT', function sigint() {
      // Make sure we cleanly exit when we receive a SIGINT signal.
      process.exit(0);
    });

    // Show the cursor again.
    process.on('exit', function exit() {
      process.stdout.write('\u001b[?25h\n\n');
    });

    /**
     * Display a spinner in the terminal the the users receive feedback
     * and know that we are watching their files for changes.
     *
     * @param {Array} frames frames that needs to be displayd
     * @param {Number} interval frame interval
     * @api private
     */
    function spinner(frames, interval) {
      interval = interval || 100;
      frames = frames || spinner.frames;

      var len = frames.length
        , i = 0;

      spinner.interval = setInterval(function tick() {
        process.stdout.write(
            '\r'
          + frames[i++ % len]
          + 'Waiting for file changes'.white
        );
      }, interval);
    }

    /**
     * Spinner frames.
     *
     * @type {Array}
     * @api private
     */
    spinner.frames = [
        '  \u001b[96m◜ \u001b[90m'
      , '  \u001b[96m◠ \u001b[90m'
      , '  \u001b[96m◝ \u001b[90m'
      , '  \u001b[96m◞ \u001b[90m'
      , '  \u001b[96m◡ \u001b[90m'
      , '  \u001b[96m◟ \u001b[90m'
    ];

    /**
     * Stop the spinner from running.
     *
     * @api private
     */
    spinner.stop = function stop() {
      process.stdout.write('\u001b[2K');
      clearInterval(spinner.interval);
    };

    // Hide the curser.
    process.stdout.write('\u001b[?25l');

    // Everyting is parsed, and we can start listening for file changes.
    cli.once('parsed', function parsed(squares) {
      spinner();
    });
  });

  /**
   * Read out a `square.opts` file where users can specify the options they want
   * to run the cli with. This allows us to bypass all the --params and just run
   * square [files] instead.
   */
  try {
    var opts = fs.readFileSync('square.opts', 'utf8').trim().split(/\s+/);
    argv = argv.slice(0, 2).concat(opts.concat(argv.slice(2)));
  } catch (err) {}

  /**
   * Possible errors that need be displayed when we shutdown our process.
   *
   * @type {Array}
   */
  cli.errors = [];

  /**
   * Parse the command line arguments now that we have setup all the argument
   * event listeners.
   */
  cli.logo();
  cli.parse(argv);

  // Due to some weird shit in commander.js, we have to detect flags our self
  // when calling the commandline with args.
  cli.unknown = cli.parseOptions(cli.normalize(argv.slice(2))).unknown;
  if (cli.unknown.length) {
    return cli.unknownOption(cli.unknown[0]);
  }

  /**
   * We want to use an emit based pattern for triggering some commands, as
   * commander doesn't do this automatically.
   */
  [
    'watch'
  ].forEach(function emit(key) {
    if (cli[key]) cli.emit('--'+ key, cli[key]);
  });

  /**
   * Check if the dependencies exist. If we don't have any agruments we should
   * check if the current working directory has a `square.json` use that instead.
   *
   * @param {String} bundle
   */
  if (!cli.args.length && fs.existsSync('square.json')) {
    cli.args.push('square.json');
  } else {
    cli.args = cli.args.filter(function filer(bundle) {
      var valid = fs.existsSync(bundle);

      if (!valid) {
        cli.errors.push(
            'Unable to locate ' + bundle.red
          + '. Make sure file exists and that the path is specified correctly.'
        );
      }

      return valid;
    });
  }

  /**
   * It's possible to supply multipe square.json files in to the binary, we need
   * to process each one of them and apply the same plugins and storage
   * containers.
   *
   * @param {Object} memo
   * @param {String} bundle
   */
  cli.square = cli.args.reduce(function (memo, bundle) {
    var square = new Square({
        'cli': true
      , 'log level': 8
    });

    // Initialize the plugins.
    cli.plugins.forEach(function load(plugin) {
      if (square.plugin(plugin)) {
        square.logger.debug('adding plugin %s', plugin);
      }
    });

    // Initialize the storage containers.
    cli.storage.forEach(function load(storage) {
      if (square.storage(storage)) {
        square.logger.debug('attaching the %s storage engine', storage);
      }
    });

    // See if we could parse the given square file.
    if (!square.parse(bundle)) {
      square.logger.debug('failed to parse %s', bundle);
    }

    // Generage the builds.
    cli.platform.forEach(function build(platform) {
      square.build(platform, cli.extensions);
    });

    memo[bundle] = square;
    return memo;
  }, {});

  if (cli.args.length && cli.square) {
    cli.emit('parsed', cli.square);
  } else {
    [
        'Missing files argument, make sure you call square with the correct arguments'
      , ''
      , '  square [options] ' + '[files]'.green
      , ''
      , 'Thanks for flying Square ■'
    ].forEach(function errors(line) {
      cli.errors.push(line);
    });
  }

  /**
   * Output all the found errors to STDERR.
   */
  if (cli.errors) cli.errors.forEach(function error(line) {
    console.error(line);
  });

  return cli;
};

/**
 * Some helper function that will make it easier to process the command line
 * arguments.
 */

/**
 * Split the supplied argument to create a list (array).
 *
 * @param {String} val the command line flag value
 * @returns {Array}
 * @api private
 */
function list(val) {
  return val.split(',');
}
<commit_msg>[minor] Generate the square instances async, process it async so we can destroy instances<commit_after>'use strict';

/**!
 * [square]
 * @copyright (c) 2012 observe.it (observe.it) <opensource@observe.it>
 * MIT Licensed
 */

/**
 * Native modules.
 */
var fs = require('fs')
  , path = require('path');

/**
 * Third party modules.
 */
var cli = require('commander')
  , colors = require('colors')
  , async = require('async')
  , _ = require('lodash');

/**
 * Square's API
 */
var Square = require('./square');

/**
 * Expose the commandline as function so custom arguments can be fed in to the
 * system.
 *
 * @param {Array} argv
 * @api public
 */
module.exports = function commandline(argv) {
  argv = argv || process.argv;

  /**
   * Setup the command line interface for square.
   */
  cli
    .version(require('../package.json').version)
    .usage('[options] [files]')
    .option('-e, --extensions <extensions>', 'only process files with these extensions', list, [])
    .option('-p, --plugins <plugins>', 'specify the plugins to use', list, [])
    .option('-P, --platform <platform>', 'only build files for this platform', list, ['web'])
    .option('-s, --storage <storage>', 'specify the storage system', list, ['disk'])
    .option('-w, --watch [port]', 'watch the bundled files for changes', parseInt);

  cli.name = 'square';

  /**
   * Scaffold command, generate an example square.json in the given directory, if
   * the given directory does not yet exist, create it for them.
   *
   * @param {String} destination
   */
  cli
    .command('scaffold [path]')
    .description('scaffold a square.json file')
    .action(function scaffold(destination) {
      // If we were given a path, we should create it if it doesn't exist or we
      // should just default to the users current working directory.
      if (destination) require('mkdirp').sync(destination);
      else destination = process.cwd();

      // Write an example square.json file.
      fs.writeFileSync(path.join(destination, 'square.json'), JSON.stringify({
          configuration: {
            dist: '/path/to/storage/{type}/bundlename.{ext}'
          }

        , bundle: {
            'path/to/file.js': {
                description: '{string} -- a small description about the use of file.css'
              , weight: '{number} 100 -- used to override the default order of inclusion'
              , version: '{string} 0.0.0 -- the version of a third party script'
              , latest: '{string} -- remote url of the third party asset'
              , extract: [
                    '{array} of variable or function names to extract from the source'
                  , 'if you want to exclude these functions of vars, let the first item'
                  , 'be a the boolean `true`'
                ]
            },
            'example/parser.coffee': {
                description: 'config parser written in pure coffeescript'
            },
            'example/jQuery.js': {
                description: 'Cross browser DOM utility library'
              , latest: 'http://code.jquery.com/jquery.js'
              , version: '1.8.3'
            }
          }
      }, null, 2));

      [
          ''
        , 'Created a new `square.json` file at '+ destination
        , ''
        , 'To learn more about the square.json specification take a look at our'
        , 'documentation center at github: github.com/observing/square/tree/master/doc'
        , ''
        , 'Or visit us irc: irc.freenode.net#observing'
        , ''
      ].forEach(function details(line) {
        console.log(line);
      });

      process.exit(0);
    });

  /**
   * Output the square ASCII logo.
   *
   * @param {Boolean} exit exit the node process after outputting
   */
  cli.logo = function logo(exit) {
    [
        ''
      , 'o-o  o-o o  o o-o o-o o-o '.cyan
      , ' \\  |  | |  | |-| |   |- '.cyan + ('      version: ' + cli._version).white
      , 'o-o  o-O o--o o o-o   o-o '.cyan
      , '       |                  '.cyan
      , '       o                  '.cyan
      , ''
    ].forEach(function logo(line) {
      console.log('  ' + line);
    });

    if (exit) process.exit(0);
  };

  /**
   * Output some square CLI examples.
   *
   * @param {Boolean} exit exit the node process after outputting.
   */
  cli.examples = function examples(exit) {
    [
        ''
      , 'Examples:'
      , ''
      , '# Generating a build with multiple plugins'.grey
      , 'square --plugins '.white
          + 'debug,crush '.green
          + './path/to/square.json'.white
      , ''
      , '# Automatically rebuild files on changes + live reload server'.grey
      , 'square --plugins '.white
          + 'debug,crush '.green
          + '--watch'.white + ' 8080 '.green
          + './path/to/square.json'.white
    ].forEach(function log(line) {
      console.log(line);
    });

    if (exit) process.exit(0);
  };

  /**
   * Display custom help information.
   *
   * @api public
   */
  cli.on('--help', function help() {
    cli.examples(true);
  });

  /**
   * List all the available plugins and their descriptions.
   *
   * @api private
   */
  cli.on('--list', function list() {
    var plugsin = Square.plugins();
  });

  /**
   * Watching.
   *
   * @param {Number} port
   * @api public
   */
  cli.on('--watch', function watch(port) {
    // Register a signint handler so we can cleanly exit the process when
    // people press crtl+c.
    process.on('SIGINT', function sigint() {
      // Make sure we cleanly exit when we receive a SIGINT signal.
      process.exit(0);
    });

    // Show the cursor again.
    process.on('exit', function exit() {
      process.stdout.write('\u001b[?25h\n\n');
    });

    /**
     * Display a spinner in the terminal the the users receive feedback
     * and know that we are watching their files for changes.
     *
     * @param {Array} frames frames that needs to be displayd
     * @param {Number} interval frame interval
     * @api private
     */
    function spinner(frames, interval) {
      interval = interval || 100;
      frames = frames || spinner.frames;

      var len = frames.length
        , i = 0;

      spinner.interval = setInterval(function tick() {
        process.stdout.write(
            '\r'
          + frames[i++ % len]
          + 'Waiting for file changes'.white
        );
      }, interval);
    }

    /**
     * Spinner frames.
     *
     * @type {Array}
     * @api private
     */
    spinner.frames = [
        '  \u001b[96m◜ \u001b[90m'
      , '  \u001b[96m◠ \u001b[90m'
      , '  \u001b[96m◝ \u001b[90m'
      , '  \u001b[96m◞ \u001b[90m'
      , '  \u001b[96m◡ \u001b[90m'
      , '  \u001b[96m◟ \u001b[90m'
    ];

    /**
     * Stop the spinner from running.
     *
     * @api private
     */
    spinner.stop = function stop() {
      process.stdout.write('\u001b[2K');
      clearInterval(spinner.interval);
    };

    // Hide the curser.
    process.stdout.write('\u001b[?25l');

    // Everyting is parsed, and we can start listening for file changes.
    cli.once('parsed', function parsed(squares) {
      spinner();
    });
  });

  /**
   * Read out a `square.opts` file where users can specify the options they want
   * to run the cli with. This allows us to bypass all the --params and just run
   * square [files] instead.
   */
  try {
    var opts = fs.readFileSync('square.opts', 'utf8').trim().split(/\s+/);
    argv = argv.slice(0, 2).concat(opts.concat(argv.slice(2)));
  } catch (err) {}

  /**
   * Possible errors that need be displayed when we shutdown our process.
   *
   * @type {Array}
   */
  cli.errors = [];

  /**
   * Parse the command line arguments now that we have setup all the argument
   * event listeners.
   */
  cli.logo();
  cli.parse(argv);

  // Due to some weird shit in commander.js, we have to detect flags our self
  // when calling the commandline with args.
  cli.unknown = cli.parseOptions(cli.normalize(argv.slice(2))).unknown;
  if (cli.unknown.length) {
    return cli.unknownOption(cli.unknown[0]);
  }

  /**
   * We want to use an emit based pattern for triggering some commands, as
   * commander doesn't do this automatically.
   */
  [
    'watch'
  ].forEach(function emit(key) {
    if (cli[key]) cli.emit('--'+ key, cli[key]);
  });

  /**
   * Check if the dependencies exist. If we don't have any agruments we should
   * check if the current working directory has a `square.json` use that instead.
   *
   * @param {String} bundle
   */
  if (!cli.args.length && fs.existsSync('square.json')) {
    cli.args.push('square.json');
  } else {
    cli.args = cli.args.filter(function filer(bundle) {
      var valid = fs.existsSync(bundle);

      if (!valid) {
        cli.errors.push(
            'Unable to locate ' + bundle.red
          + '. Make sure file exists and that the path is specified correctly.'
        );
      }

      return valid;
    });
  }

  /**
   * It's possible to supply multipe square.json files in to the binary, we need
   * to process each one of them and apply the same plugins and storage
   * containers.
   *
   * @param {Object} memo
   * @param {String} bundle
   * @param {Function} callback
   */
  async.reduce(cli.args, {}, function (memo, bundle, callback) {
    var square = new Square({
        'cli': true
      , 'log level': 8
    });

    // Initialize the plugins.
    cli.plugins.forEach(function load(plugin) {
      if (square.plugin(plugin)) {
        square.logger.debug('adding plugin %s', plugin);
      }
    });

    // Initialize the storage containers.
    cli.storage.forEach(function load(storage) {
      if (square.storage(storage)) {
        square.logger.debug('attaching the %s storage engine', storage);
      }
    });

    // See if we could parse the given square file.
    if (!square.parse(bundle)) {
      square.logger.debug('failed to parse %s', bundle);
    }

    // Generage the builds, do this in an async loop so we can emit an callback
    // once everything has been build according to the specifications
    async.forEach(
        cli.platform
      , function build(platform, done) {
          square.build(platform, cli.extensions, done);
        }
      , function finished(err, builds) {
          callback(err, memo);
        }
    );

    memo[bundle] = square;
  }, function done(err, reduced) {
    cli.squares = reduced;
    cli.emit('parsed', reduced);

    // If we are not watching the files for changes we should destroy all the
    // square instances so our processes exits.
    if (cli.watch) return;

    _.each(reduced, function killswitch(square, bundle) {
      square.logger.debug('destroying instance that processed %s', bundle);
      square.destroy();
    });
  });

  if (!cli.args.length) {
    [
        'Missing files argument, make sure you call square with the correct arguments'
      , ''
      , '  square [options] ' + '[files]'.green
      , ''
      , 'Thanks for flying Square ■'
    ].forEach(function errors(line) {
      cli.errors.push(line);
    });
  }

  /**
   * Output all the found errors to STDERR.
   */
  if (cli.errors) cli.errors.forEach(function error(line) {
    console.error(line);
  });

  return cli;
};

/**
 * Some helper function that will make it easier to process the command line
 * arguments.
 */

/**
 * Split the supplied argument to create a list (array).
 *
 * @param {String} val the command line flag value
 * @returns {Array}
 * @api private
 */
function list(val) {
  return val.split(',');
}
<|endoftext|>


<commit_before>var program = require('commander'),
    Q = require('q'),
    winston = require('winston'),
    inquirer = require('inquirer'),
    _ = require('underscore'),
    Table = require('cli-table'),
    pg2json = require('..'),
    connection = require('../lib/connection'),
    tables = require('../lib/tables'),
    columns = require('../lib/columns'),
    me = module.exports;

me.start = function(argv) {
    me.setup();
    program.parse(argv);
    me.run();
};

me.setup = function() {
    program
        .description('reads the schema of a db and creates a json-schema')
        .option('-c, --config [value]', 'db-config file')
        .option('-o, --output [value]', 'output filename')
        .option('-l, --delimiter [value]', 'template delimiter')
        .option('-s, --silent', 'no console output')
        .option('-f, --force', 'create folders if not existing')
        .option('-d, --dry-run', 'don\'t create files')
        .option('-D, --debug', 'print error object')
        .option('-T, --trace', 'print stacktrace')
        .version('0.0.1');
    winston.cli();
};

me.run = function() {
    if (program.silent) {
        winston.clear();
    }

    if (program.config) {
        connection.connect(program.config)
            .then(tables.getTables)
            .then(listTables)
            .fail(onFail);

    }
};

function listTables(tables) {
    var tablesChoices = _.map(tables, function(table) {
        return table.table_name;
    });
    inquirer.prompt([{
        type: 'checkbox',
        name: 'tables',
        message: 'Select a table',
        choices: tablesChoices
    }], function(choices) {
        var promises = [];
        _.each(choices.tables, function(table) {
            promises.push(columns.get(table)
                .then(function(columns) {
                    winston.data('Table: ' + table);
                    listColumns(columns);
                })
                .catch (onFail));
        });
        Q.allSettled(promises)
            .then(finished)
            .catch(onFail);
    });
}

function listColumns(columns) {
    var table = new Table({
        head: ['Name', 'Type']
    });
    _.each(columns, function(column, key) {
        table.push(
            [column.column_name, column.data_type]
        );
    });
    console.log(table.toString());
}

function finished(path) {
    if (path) {
        winston.info('File writen to: ', path);
    }
    winston.info('Successfull!');
    if (program.dryRun) {
        winston.warn('THIS WAS A DRY RUN');
        winston.warn('nothing has been writen');
    }
    process.kill();
}

function onFail(error) {
    winston.error('Message: ' + error.message);
    if (program.debug) {
        winston.data(error);
    }
    if (program.trace) {
        console.trace();
    }
    process.kill();
}
<commit_msg>show help<commit_after>var program = require('commander'),
    Q = require('q'),
    winston = require('winston'),
    inquirer = require('inquirer'),
    _ = require('underscore'),
    Table = require('cli-table'),
    pg2json = require('..'),
    connection = require('../lib/connection'),
    tables = require('../lib/tables'),
    columns = require('../lib/columns'),
    me = module.exports;

me.start = function(argv) {
    me.setup();
    program.parse(argv);
    me.run();
};

me.setup = function() {
    program
        .description('reads the schema of a db and creates a json-schema')
        .option('-c, --config [value]', 'db-config file')
        .option('-o, --output [value]', 'output filename')
        .option('-l, --delimiter [value]', 'template delimiter')
        .option('-s, --silent', 'no console output')
        .option('-f, --force', 'create folders if not existing')
        .option('-d, --dry-run', 'don\'t create files')
        .option('-D, --debug', 'print error object')
        .option('-T, --trace', 'print stacktrace')
        .version('0.0.1');
    winston.cli();
};

me.run = function() {
    console.log(program);
    if (program.silent) {
        winston.clear();
    }

    if (program.config) {
        connection.connect(program.config)
            .then(tables.getTables)
            .then(listTables)
            .fail(onFail);
    } else {
        program.help();
    }
};

function listTables(tables) {
    var tablesChoices = _.map(tables, function(table) {
        return table.table_name;
    });
    inquirer.prompt([{
        type: 'checkbox',
        name: 'tables',
        message: 'Select a table',
        choices: tablesChoices
    }], function(choices) {
        var promises = [];
        _.each(choices.tables, function(table) {
            promises.push(columns.get(table)
                .then(function(columns) {
                    winston.data('Table: ' + table);
                    listColumns(columns);
                })
                .catch (onFail));
        });
        Q.allSettled(promises)
            .then(finished)
            .catch(onFail);
    });
}

function listColumns(columns) {
    var table = new Table({
        head: ['Name', 'Type']
    });
    _.each(columns, function(column, key) {
        table.push(
            [column.column_name, column.data_type]
        );
    });
    console.log(table.toString());
}

function finished(path) {
    if (path) {
        winston.info('File writen to: ', path);
    }
    winston.info('Successfull!');
    if (program.dryRun) {
        winston.warn('THIS WAS A DRY RUN');
        winston.warn('nothing has been writen');
    }
    process.kill();
}

function onFail(error) {
    winston.error('Message: ' + error.message);
    if (program.debug) {
        winston.data(error);
    }
    if (program.trace) {
        console.trace();
    }
    process.kill();
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
"use strict";

var path = require("path");
var coberturaBadger = require("./");

var program = require("commander");
var pkgJson = require("../package");

// Setting the defaults if the user uses istanbul
var input = path.resolve("./coverage/cobertura-coverage.xml");
var output = path.resolve("./coverage");
var defaultThresholds = require("./defaultThresholds");

program.description("Generates a badge for a given Cobertura XML report")
  .version(pkgJson.version)
  .option("-f, --defaults", "Use the default values for all the input.")
  .option("-e, --excellentThreashold <n>", "The threshold for green badges, where coverage >= -e", parseInt)
  .option("-g, --goodThreashold <n>", "The threshold for yellow badges, where -g <= coverage < -e  ", parseInt)
  .option("-r, --reportFile <report>", "The istanbul cobertura XML file path.", input)
  .option("-d, --destinationDir <destination>", "The directory where 'coverage.svg' will be generated at.", output)
  .option("-v, --verbose", "Prints the metadata for the command")
  .parse(process.argv);

program.on("--help", function() {
  console.log("  Examples:");
  console.log("");
  console.log("    $ istanbul-cobertura-coverage -e 90 -g 65 -r coverage/cobertura.xml -d coverage/");
  console.log("      * Green: coverage >= 90");
  console.log("      * Yellow: 65 <= coverage < 90");
  console.log("      * Red: coverage < 65");
  console.log("      * Created at the coverage directory from the given report.");
  console.log("");
  console.log("    $ istanbul-cobertura-coverage -e 80 -d /tmp/build");
  console.log("      * Green: coverage >= 80");
  console.log("      * Yellow: 65 <= coverage < 80");
  console.log("      * Red: coverage < 65");
  console.log("");
});

// Stop the execution if no options were provided.
if (!program.defaults && !process.argv.slice(2).length) {
  program.outputHelp();
  process.exit(0);
}

// The options to the badger API coming from the program.
var opts = {
  destinationDir: path.resolve(program.destinationDir),
  istanbulReportFile: program.reportFile,
  thresholds: {
    // overall percent >= excellent, green badge
    excellent: program.excellentThreashold || defaultThresholds.excellent,
    // excellent < overall percent >= good, yellow badge
    good: program.goodThreashold || defaultThresholds.good
    // overall percent < good, red badge
  }
};

// Generate the badge.
coberturaBadger(opts, function(err, results) {
  if (err) {
    console.log(err);
    process.exit(-1);
  }

  if (program.verbose) {
    console.log(results);
  }

  // Output the message successful message.
  console.log("Badge created at " + results.badgeFile.filePath);
});
<commit_msg>Issue #15: Updating the cli with the badgeFileName<commit_after>#!/usr/bin/env node
"use strict";

var path = require("path");
var coberturaBadger = require("./");

var program = require("commander");
var pkgJson = require("../package");

// Setting the defaults if the user uses istanbul
var input = path.resolve("./coverage/cobertura-coverage.xml");
var output = path.resolve("./coverage");
var defaultThresholds = require("./defaultThresholds");

program.description("Generates a badge for a given Cobertura XML report")
  .version(pkgJson.version)
  .option("-f, --defaults", "Use the default values for all the input.")
  .option("-e, --excellentThreashold <n>", "The threshold for green badges, where coverage >= -e", parseInt)
  .option("-g, --goodThreashold <n>", "The threshold for yellow badges, where -g <= coverage < -e  ", parseInt)
  .option("-b, --badgeFileName <badge>", "The badge file name that will be saved.")
  .option("-r, --reportFile <report>", "The istanbul cobertura XML file path.", input)
  .option("-d, --destinationDir <destination>", "The directory where 'coverage.svg' will be generated at.", output)
  .option("-v, --verbose", "Prints the metadata for the command")
  .parse(process.argv);

program.on("--help", function() {
  console.log("  Examples:");
  console.log("");
  console.log("    $ istanbul-cobertura-coverage -e 90 -g 65 -r coverage/cobertura.xml -d coverage/");
  console.log("      * Green: coverage >= 90");
  console.log("      * Yellow: 65 <= coverage < 90");
  console.log("      * Red: coverage < 65");
  console.log("      * Created at the coverage directory from the given report.");
  console.log("");
  console.log("    $ istanbul-cobertura-coverage -e 80 -d /tmp/build");
  console.log("      * Green: coverage >= 80");
  console.log("      * Yellow: 65 <= coverage < 80");
  console.log("      * Red: coverage < 65");
  console.log("");
});

// Stop the execution if no options were provided.
if (!program.defaults && !process.argv.slice(2).length) {
  program.outputHelp();
  process.exit(0);
}

// The options to the badger API coming from the program.
var opts = {
  badgeFileName: program.badgeFileName,
  destinationDir: path.resolve(program.destinationDir),
  istanbulReportFile: program.reportFile,
  thresholds: {
    // overall percent >= excellent, green badge
    excellent: program.excellentThreashold || defaultThresholds.excellent,
    // excellent < overall percent >= good, yellow badge
    good: program.goodThreashold || defaultThresholds.good
    // overall percent < good, red badge
  }
};

// Generate the badge.
coberturaBadger(opts, function(err, results) {
  if (err) {
    console.log(err);
    process.exit(-1);
  }

  if (program.verbose) {
    console.log(results);
  }

  // Output the message successful message.
  console.log("Badge created at " + results.badgeFile.filePath);
});
<|endoftext|>


<commit_before>/*jshint esnext: true */
var _ = require('underscore'),
  bag = require('bagofholding'),
  Couchpenter = require('./couchpenter');

function _init() {
  var couchpenter = new Couchpenter();
    couchpenter.init(bag.cli.exit);
}

function _task(fn) {
  return function (args) {
    var couchpenter = new Couchpenter(
      args.url,
      { setupFile: args.setupFile, dir: args.dir }
    );
    couchpenter[fn](bag.cli.exitCb(null, function (results) {
      results.forEach(function (result) {
        if (result.error) {
          console.error('%s - %s', result.id, result.message);
        } else {
          console.log('%s - %s', result.id, result.message);
        }
      });
    }));
  };
}

/**
 * Execute Couchpenter CLI.
 */
function exec() {

  // NOTE: pardon this cli target to Couchpenter methods mapping,
  // needed to preserve backward compatibility w/ v0.1.x
  const FUNCTIONS = {
    setup: 'setUp',
    'setup-db': 'setUpDatabases',
    'setup-doc': 'setUpDocuments',
    'setup-doc-overwrite': 'setUpDocumentsOverwrite',
    teardown: 'tearDown',
    'teardown-db': 'tearDownDatabases',
    'teardown-doc': 'tearDownDocuments',
    reset: 'reset',
    'reset-db': 'resetDatabases',
    'reset-doc': 'resetDocuments',
    clean: 'clean',
    'clean-db': 'cleanDatabases'
  };

  var actions = {
    commands: {
      init: { action: _init }
    }
  };

  _.keys(FUNCTIONS).forEach(function (task) {
    actions.commands[task] = { action: _task(FUNCTIONS[task]) };
  });

  bag.cli.command(__dirname, actions);
}

exports.exec = exec;
<commit_msg>Save one var declaration.<commit_after>/*jshint esnext: true */
var _ = require('underscore'),
  bag = require('bagofholding'),
  Couchpenter = require('./couchpenter');

function _init() {
  new Couchpenter().init(bag.cli.exit);
}

function _task(fn) {
  return function (args) {
    var couchpenter = new Couchpenter(
      args.url,
      { setupFile: args.setupFile, dir: args.dir }
    );
    couchpenter[fn](bag.cli.exitCb(null, function (results) {
      results.forEach(function (result) {
        if (result.error) {
          console.error('%s - %s', result.id, result.message);
        } else {
          console.log('%s - %s', result.id, result.message);
        }
      });
    }));
  };
}

/**
 * Execute Couchpenter CLI.
 */
function exec() {

  // NOTE: pardon this cli target to Couchpenter methods mapping,
  // needed to preserve backward compatibility w/ v0.1.x
  const FUNCTIONS = {
    setup: 'setUp',
    'setup-db': 'setUpDatabases',
    'setup-doc': 'setUpDocuments',
    'setup-doc-overwrite': 'setUpDocumentsOverwrite',
    teardown: 'tearDown',
    'teardown-db': 'tearDownDatabases',
    'teardown-doc': 'tearDownDocuments',
    reset: 'reset',
    'reset-db': 'resetDatabases',
    'reset-doc': 'resetDocuments',
    clean: 'clean',
    'clean-db': 'cleanDatabases'
  };

  var actions = {
    commands: {
      init: { action: _init }
    }
  };

  _.keys(FUNCTIONS).forEach(function (task) {
    actions.commands[task] = { action: _task(FUNCTIONS[task]) };
  });

  bag.cli.command(__dirname, actions);
}

exports.exec = exec;
<|endoftext|>


<commit_before>var RtmClient = require('@slack/client').RtmClient
var WebClient = require('@slack/client').WebClient
var Mopidy = require('mopidy')
var SpotifyWebApi = require('spotify-web-api-node')
var winston = require('winston')
var attachments = require('./attachments')
var DopeBot = require('./dopebot').DopeBot
var yargs = require('yargs')

'use strict'

module.exports = function () {
  var argv = yargs
    .usage('Usage: dopebot [options]')
    .option('token', {
      alias: 't',
      demand: true,
      type: 'string',
      describe: 'Set token for the Slack API'
    })
    .option('channel', {
      alias: 'c',
      demand: true,
      type: 'string',
      describe: 'Set the Slack channel name to listen for input'
    })
    .option('mopidy', {
      alias: 'm',
      type: 'string',
      describe: 'Set the WS-URL of Mopidy',
      default: 'ws://localhost:6680/mopidy/ws'
    })
    .option('mopidy', {
      alias: 'm',
      type: 'string',
      describe: 'Set the WS-URL of Mopidy',
      default: 'ws://localhost:6680/mopidy/ws'
    })
    .option('dialog', {
      alias: 'd',
      type: 'boolean',
      describe: 'Only respond to <@dopebot>',
      default: false
    })
    .option('brain', {
      alias: 'b',
      type: 'boolean',
      describe: 'Remember user commands',
      default: false
    })
    .option('unfurl', {
      alias: 'u',
      type: 'boolean',
      describe: 'Unfold Spotify URIs in Slack',
      default: false
    })
    .option('emoji', {
      alias: 'e',
      type: 'string',
      describe: 'Dopebot emoji icon in Slack',
      default: ':loud_sound:'
    })
    .option('limit', {
      alias: 'l',
      type: 'number',
      describe: 'Set limit for Spotify API result lists',
      default: 20
    })
    .option('verbose', {
      alias: 'v',
      type: 'count',
      describe: 'Increase verbosity'
    })
    .help('help')
    .alias('help', 'h')
    .locale('en')
    .argv

  if (argv.help) {
    // show help and exit
    yargs.showHelp()
  }

  var logger = new (winston.Logger)()

  logger.add(winston.transports.Console, {
    level: Object.keys(winston.config.npm.levels).find(function (level) {
      return winston.levels[level] === Math.min(argv.verbose + 2, Object.keys(winston.levels).length - 1)
    }),
    prettyPrint: true,
    colorize: true,
    silent: false,
    timestamp: true
  })

  var slack = {
    rtm: new RtmClient(argv.token, {
      logger: logger.log.bind(logger)
    }),
    web: new WebClient(argv.token, {
      logger: logger.log.bind(logger)
    })
  }

  var mopidy = new Mopidy({
    webSocketUrl: argv.mopidy,
    console: logger,
    autoConnect: false,
    callingConvention: 'by-position-only'
  })

  var spotifyApi = new SpotifyWebApi()

  var db = new DopeBot(logger, slack, mopidy, spotifyApi, {
    channel: argv.channel,
    dialog: argv.dialog === true,
    history: argv.brain === true,
    limit: parseInt(argv.limit),
    attachments: attachments({
      color: '#ff9800',
      formatTrack: function (track) {
        return {
          track: `<${track.uri}|${track.name}>`,
          artists: track.artists.map(artist => `<${artist.uri}|${artist.name}>`).join(', '),
          album: `<${track.album.uri}|${track.album.name}>`
        }
      }
    }),
    params: {
      username: 'dopebot',
      icon_emoji: argv.emoji,
      unfurl_links: argv.unfurl === true,
      unfurl_media: argv.unfurl === true
    }
  })

  db.run()
}
<commit_msg>Added spotify credentials handling<commit_after>var RtmClient = require('@slack/client').RtmClient
var WebClient = require('@slack/client').WebClient
var Mopidy = require('mopidy')
var SpotifyWebApi = require('spotify-web-api-node')
var winston = require('winston')
var attachments = require('./attachments')
var DopeBot = require('./dopebot').DopeBot
var yargs = require('yargs')

'use strict'

module.exports = function () {
  var argv = yargs
    .usage('Usage: dopebot [options]')
    .option('token', {
      alias: 't',
      demand: true,
      type: 'string',
      describe: 'Set token for the Slack API'
    })
    .option('channel', {
      alias: 'c',
      demand: true,
      type: 'string',
      describe: 'Set the Slack channel name to listen for input'
    })
    .option('mopidy', {
      alias: 'm',
      type: 'string',
      describe: 'Set the WS-URL of Mopidy',
      default: 'ws://localhost:6680/mopidy/ws'
    })
    .option('mopidy', {
      alias: 'm',
      type: 'string',
      describe: 'Set the WS-URL of Mopidy',
      default: 'ws://localhost:6680/mopidy/ws'
    })
    .option('dialog', {
      alias: 'd',
      type: 'boolean',
      describe: 'Only respond to <@dopebot>',
      default: false
    })
    .option('brain', {
      alias: 'b',
      type: 'boolean',
      describe: 'Remember user commands',
      default: false
    })
    .option('unfurl', {
      alias: 'u',
      type: 'boolean',
      describe: 'Unfold Spotify URIs in Slack',
      default: false
    })
    .option('emoji', {
      alias: 'e',
      type: 'string',
      describe: 'Dopebot emoji icon in Slack',
      default: ':loud_sound:'
    })
    .option('limit', {
      alias: 'l',
      type: 'number',
      describe: 'Set limit for Spotify API result lists',
      default: 20
    })
    .option('id', {
      alias: 'i',
      type: 'string',
      describe: 'Set the Spotify client Id'
    })
    .option('secret', {
      alias: 's',
      type: 'string',
      describe: 'Set the Spotify client secret'
    })
    .option('limit', {
      alias: 'l',
      type: 'number',
      describe: 'Set limit for Spotify API result lists',
      default: 20
    })
    .option('verbose', {
      alias: 'v',
      type: 'count',
      describe: 'Increase verbosity'
    })
    .help('help')
    .alias('help', 'h')
    .locale('en')
    .argv

  if (argv.help) {
    // show help and exit
    yargs.showHelp()
  }

  var logger = new (winston.Logger)()

  logger.add(winston.transports.Console, {
    level: Object.keys(winston.config.npm.levels).find(function (level) {
      return winston.levels[level] === Math.min(argv.verbose + 2, Object.keys(winston.levels).length - 1)
    }),
    prettyPrint: true,
    colorize: true,
    silent: false,
    timestamp: true
  })

  var slack = {
    rtm: new RtmClient(argv.token, {
      logger: logger.log.bind(logger)
    }),
    web: new WebClient(argv.token, {
      logger: logger.log.bind(logger)
    })
  }

  var mopidy = new Mopidy({
    webSocketUrl: argv.mopidy,
    console: logger,
    autoConnect: false,
    callingConvention: 'by-position-only'
  })

  var spotifyApi = new SpotifyWebApi({
    clientId : argv.id,
    clientSecret : argv.secret
  })

  var db = new DopeBot(logger, slack, mopidy, spotifyApi, {
    channel: argv.channel,
    dialog: argv.dialog === true,
    history: argv.brain === true,
    limit: parseInt(argv.limit),
    attachments: attachments({
      color: '#ff9800',
      formatTrack: function (track) {
        return {
          track: `<${track.uri}|${track.name}>`,
          artists: track.artists.map(artist => `<${artist.uri}|${artist.name}>`).join(', '),
          album: `<${track.album.uri}|${track.album.name}>`
        }
      }
    }),
    params: {
      username: 'dopebot',
      icon_emoji: argv.emoji,
      unfurl_links: argv.unfurl === true,
      unfurl_media: argv.unfurl === true
    }
  })

  db.run()
}
<|endoftext|>