<commit_before>var config = require('config');
var mongoose = require('mongoose');
var TreeNodes = require('./treeNodes.js');
var Resources = require('./resources.js');
var appRoot = require('app-root-path');
var handleUpload = require(appRoot + '/libs/core/handleUpload.js');
var helper = require(appRoot + '/libs/core/generalLibs.js');
var debug = require('debug')('cm:db');

var Plugin = require(appRoot + '/modules/apps-gallery/backgroundPlugins.js');

function catalog() {
}

/**
 *
 * @param filetype array of string
 * @param file file object of multiparty
 * @param contentNode treeNode
 * @param createdBy objectId of a user
 * @param courseId objectId of a course
 */
catalog.prototype.saveResourceFile = function (filetype, file, contentNode, createdBy, courseId) {
    var extension = file.name.split('.');
    extension = extension[extension.length - 1].toLowerCase();

    if (filetype.indexOf(extension) < 0) {
        // extension not right
        error("File extension not right, expecting " + filetype);
    }
    else {
        var fn = '/resources/' + contentNode.id + '.' + extension;
        var dest = appRoot + '/public' + fn;
        handleUpload(file, dest, true);

        var Res = new Resources({
            type: extension,
            createdBy: createdBy,
            link: fn,
            courseId: courseId,
            treeNodeId: contentNode._id
        });

        Res.save(function () {
            TreeNodes.update({_id: contentNode._id}, {
                    $addToSet: {
                        resources: Res._id
                    }
                },
                function () {
                });
        });
    }
};

catalog.prototype.addTreeNode = function (error, params, files, success) {
    var self = this;

    // check for at least 1 resource either it s a pdf or a video
    if (params.type == 'contentNode' && !params._id) {
        if (!files.file) {
            error(helper.createError('need at least 1 resource', 400));
            return;
        }
    }

    if (files.file && files.file.constructor != Array) {
        // make it an array if it s just 1 object. (we allow multiple upload on some types of node)
        var be = [files.file];
        files.file = be;
    }

    if (!helper.checkRequiredParams(params, ['userId', 'createdBy'], function (errs) {
            error(errs)
        })) {
        return;
    }

    //options for new node
    var node = {
        type: params.type,
        name: params.name,
        createdBy: params.createdBy,
        courseId: params.courseId
    };

    if (params.parent)
        node.parent = params.parent;

    function insertNodeToParent(node, tn, success){
        if (node.parent) {
            TreeNodes.findOne({_id: node.parent}, function (err, doc) {
                if (doc) {
                    doc.childrens.push(tn._id);
                    doc.save();
                    debug('success saving this node as children');

                    // because we have a parent, lets alter its position, relative to its parent
                    tn.positionFromRoot = {
                        x: doc.positionFromRoot.x + 40,
                        y: doc.positionFromRoot.y + 80
                    };

                    tn.save();
                    debug('success altering starting position to its parent');

                    success(tn);
                }
            });
        } else {
            success(tn);
        }
    }

    function attachResourcesToNode(tn, files, self, node) {
        if (files) {
            for (var i in files.file) {
                var f = files.file[i];
                self.saveResourceFile(
                    ['pdf', 'mp4', 'webm'], f,
                    tn,
                    node.createdBy,
                    node.courseId
                );
            }
        }

        debug('success attaching files');
    }

    function cbAfterSave(tn, files, self, node, params, success){
        // process files
        attachResourcesToNode(tn, files, self, node);

        // put this object as the parent's child,
        insertNodeToParent(node, tn, success);

        if (params.type == 'contentNode') {
            Plugin.doAction('onAfterContentNodeCreated', tn);
        } else {
            Plugin.doAction('onAfterSubTopicCreated', tn);
        }

        debug('success creating node');
    }

    // this is edit mode
    if(params._id){
        node._id = params._id;
        TreeNodes.findOne({_id: node._id, createdBy: params.createdBy}, function (err, tn){
            if(err){
                error(err);
            } else {
                if(tn){
                    tn.name = node.name;
                    tn.save(function(err){
                        if (err) {
                            debug('failed adding Tree Node');
                            error(err);
                        } else {
                            attachResourcesToNode(tn, files, self, node);

                            success(tn);

                            if (params.type == 'contentNode') {
                                Plugin.doAction('onAfterContentNodeEdited', tn);
                            } else {
                                Plugin.doAction('onAfterSubTopicEdited', tn);
                            }
                        }
                    });
                } else {
                    // 404 cant find node
                    error(helper.createError404('Content Node'));
                }
            }
        });
    }
    else {
        ///
        // saving new node
        ///
        node.positionFromRoot = {x: 40, y: 60};

        var tn = new TreeNodes(node);
        tn.save(function(err){
            if (err) {
                debug('failed adding Tree Node');
                error(err);
            } else {
                cbAfterSave(tn, files, self, node, params, success);
            }
        });
    }
};

catalog.prototype.getTreeNode = function (error, params, success) {
    TreeNodes.findOne(params).populate('resources').exec(function (err, doc) {
        if (err) {
            error(err);
        }
        else {
            if (doc) {
                if (doc.isDeleted) {
                    doc.name = "[DELETED]";
                }

                success(doc);
            } else {
                error(helper.createError404("Tree Node"));
            }
        }
    });
};

/**
 * get all tree nodes based on params,
 * and return it in a recursived tree manners
 * @param error
 * @param params
 * @param success
 */
catalog.prototype.getTreeNodes = function (error, params, success) {
    TreeNodes.find(params).populate('resources').exec(function (err, docs) {
        if (!err) {
            var cats = helper.convertToDictionary(docs);

            // keys for the ref ids of parent and childrens
            var parent = 'parent';
            var children = 'childrens';

            var tree = [];

            function again(cat) {
                if (cat[children]) {
                    var childrens = [];
                    for (var e in cat[children]) {
                        var catId = cat[children][e];
                        var childCat = cats[catId];
                        childrens.push(childCat);
                        again(childCat);
                    }

                    cat[children] = childrens;
                }
            }

            for (var i in cats) {
                // get the root
                var doc = cats[i];

                if (doc.isDeleted) {
                    doc.name = "[DELETED]";
                }

                if (!doc[parent]) {
                    again(doc);
                    tree.push(doc);
                }
            }

            success(tree);
        } else {
            error(err);
        }
    });
};

catalog.prototype.updateNodePosition = function (error, paramsWhere, paramsUpdate, success) {
    if (!helper.checkRequiredParams(paramsUpdate, ['x', 'y'], error)) {
        return;
    }

    TreeNodes.findOne(paramsWhere).exec(function (err, tn) {
        if (err) error(err);
        else {
            if (!tn) {
                return error(helper.createError404('Node'));
            }

            tn.update({
                $set: {
                    positionFromRoot: {
                        x: paramsUpdate.x,
                        y: paramsUpdate.y
                    }
                }
            }, function (err) {
                if (err) {
                    debug('failed update node position');
                    error(err);
                }
                else
                // success saved the cat
                    success(tn);
            });
        }
    });
};

catalog.prototype.updateNode = function (error, paramsWhere, paramsUpdate, success) {
    TreeNodes.findById(paramsWhere).exec(function (err, tn) {
        if (err) error(err);
        else {
            if (!tn)
                error(helper.createError404("Node"));
            else {
                if (paramsUpdate['name']) {
                    tn.name = paramsUpdate['name'];
                }

                tn.save(function (err) {
                    if (err) {
                        debug('failed update node content');
                        error(err);
                    }
                    else {
                        // success saved the cat
                        success(tn);
                    }
                });
            }
        }
    });
};

catalog.prototype.deleteNode = function (error, params, success) {
    TreeNodes.findById(params).exec(function (err, tn) {
        if (err) error(err);
        else {
            if (!tn)
                error(helper.createError404("Node"));

            else {
                tn.isDeleted = true;
                tn.dateDeleted = new Date();
                tn.save(
                    function (err) {
                        if (err) {
                            debug('failed update node position');
                            error(err);
                        }
                        else {
                            success(true);
                        }
                    }
                );
            }
        }

    });
};

module.exports = catalog;<commit_msg>fix cant create subtopic<commit_after>var config = require('config');
var mongoose = require('mongoose');
var TreeNodes = require('./treeNodes.js');
var Resources = require('./resources.js');
var appRoot = require('app-root-path');
var handleUpload = require(appRoot + '/libs/core/handleUpload.js');
var helper = require(appRoot + '/libs/core/generalLibs.js');
var debug = require('debug')('cm:db');

var Plugin = require(appRoot + '/modules/apps-gallery/backgroundPlugins.js');

function catalog() {
}

/**
 *
 * @param filetype array of string
 * @param file file object of multiparty
 * @param contentNode treeNode
 * @param createdBy objectId of a user
 * @param courseId objectId of a course
 */
catalog.prototype.saveResourceFile = function (filetype, file, contentNode, createdBy, courseId) {
    var extension = file.name.split('.');
    extension = extension[extension.length - 1].toLowerCase();

    if (filetype.indexOf(extension) < 0) {
        // extension not right
        error("File extension not right, expecting " + filetype);
    }
    else {
        var fn = '/resources/' + contentNode.id + '.' + extension;
        var dest = appRoot + '/public' + fn;
        handleUpload(file, dest, true);

        var Res = new Resources({
            type: extension,
            createdBy: createdBy,
            link: fn,
            courseId: courseId,
            treeNodeId: contentNode._id
        });

        Res.save(function () {
            TreeNodes.update({_id: contentNode._id}, {
                    $addToSet: {
                        resources: Res._id
                    }
                },
                function () {
                });
        });
    }
};

catalog.prototype.addTreeNode = function (error, params, files, success) {
    var self = this;

    // check for at least 1 resource either it s a pdf or a video
    if (params.type == 'contentNode' && !params._id) {
        if (!files.file) {
            error(helper.createError('need at least 1 resource', 400));
            return;
        }
    }

    if (files && files.file && files.file.constructor != Array) {
        // make it an array if it s just 1 object. (we allow multiple upload on some types of node)
        var be = [files.file];
        files.file = be;
    }

    if (!helper.checkRequiredParams(params, ['userId', 'createdBy'], function (errs) {
            error(errs)
        })) {
        return;
    }

    //options for new node
    var node = {
        type: params.type,
        name: params.name,
        createdBy: params.createdBy,
        courseId: params.courseId
    };

    if (params.parent)
        node.parent = params.parent;

    function insertNodeToParent(node, tn, success){
        if (node.parent) {
            TreeNodes.findOne({_id: node.parent}, function (err, doc) {
                if (doc) {
                    doc.childrens.push(tn._id);
                    doc.save();
                    debug('success saving this node as children');

                    // because we have a parent, lets alter its position, relative to its parent
                    tn.positionFromRoot = {
                        x: doc.positionFromRoot.x + 40,
                        y: doc.positionFromRoot.y + 80
                    };

                    tn.save();
                    debug('success altering starting position to its parent');

                    success(tn);
                }
            });
        } else {
            success(tn);
        }
    }

    function attachResourcesToNode(tn, files, self, node) {
        if (files) {
            for (var i in files.file) {
                var f = files.file[i];
                self.saveResourceFile(
                    ['pdf', 'mp4', 'webm'], f,
                    tn,
                    node.createdBy,
                    node.courseId
                );
            }
        }

        debug('success attaching files');
    }

    function cbAfterSave(tn, files, self, node, params, success){
        // process files
        attachResourcesToNode(tn, files, self, node);

        // put this object as the parent's child,
        insertNodeToParent(node, tn, success);

        if (params.type == 'contentNode') {
            Plugin.doAction('onAfterContentNodeCreated', tn);
        } else {
            Plugin.doAction('onAfterSubTopicCreated', tn);
        }

        debug('success creating node');
    }

    // this is edit mode
    if(params._id){
        node._id = params._id;
        TreeNodes.findOne({_id: node._id, createdBy: params.createdBy}, function (err, tn){
            if(err){
                error(err);
            } else {
                if(tn){
                    tn.name = node.name;
                    tn.save(function(err){
                        if (err) {
                            debug('failed adding Tree Node');
                            error(err);
                        } else {
                            attachResourcesToNode(tn, files, self, node);

                            success(tn);

                            if (params.type == 'contentNode') {
                                Plugin.doAction('onAfterContentNodeEdited', tn);
                            } else {
                                Plugin.doAction('onAfterSubTopicEdited', tn);
                            }
                        }
                    });
                } else {
                    // 404 cant find node
                    error(helper.createError404('Content Node'));
                }
            }
        });
    }
    else {
        ///
        // saving new node
        ///
        node.positionFromRoot = {x: 40, y: 60};

        var tn = new TreeNodes(node);
        tn.save(function(err){
            if (err) {
                debug('failed adding Tree Node');
                error(err);
            } else {
                cbAfterSave(tn, files, self, node, params, success);
            }
        });
    }
};

catalog.prototype.getTreeNode = function (error, params, success) {
    TreeNodes.findOne(params).populate('resources').exec(function (err, doc) {
        if (err) {
            error(err);
        }
        else {
            if (doc) {
                if (doc.isDeleted) {
                    doc.name = "[DELETED]";
                }

                success(doc);
            } else {
                error(helper.createError404("Tree Node"));
            }
        }
    });
};

/**
 * get all tree nodes based on params,
 * and return it in a recursived tree manners
 * @param error
 * @param params
 * @param success
 */
catalog.prototype.getTreeNodes = function (error, params, success) {
    TreeNodes.find(params).populate('resources').exec(function (err, docs) {
        if (!err) {
            var cats = helper.convertToDictionary(docs);

            // keys for the ref ids of parent and childrens
            var parent = 'parent';
            var children = 'childrens';

            var tree = [];

            function again(cat) {
                if (cat[children]) {
                    var childrens = [];
                    for (var e in cat[children]) {
                        var catId = cat[children][e];
                        var childCat = cats[catId];
                        childrens.push(childCat);
                        again(childCat);
                    }

                    cat[children] = childrens;
                }
            }

            for (var i in cats) {
                // get the root
                var doc = cats[i];

                if (doc.isDeleted) {
                    doc.name = "[DELETED]";
                }

                if (!doc[parent]) {
                    again(doc);
                    tree.push(doc);
                }
            }

            success(tree);
        } else {
            error(err);
        }
    });
};

catalog.prototype.updateNodePosition = function (error, paramsWhere, paramsUpdate, success) {
    if (!helper.checkRequiredParams(paramsUpdate, ['x', 'y'], error)) {
        return;
    }

    TreeNodes.findOne(paramsWhere).exec(function (err, tn) {
        if (err) error(err);
        else {
            if (!tn) {
                return error(helper.createError404('Node'));
            }

            tn.update({
                $set: {
                    positionFromRoot: {
                        x: paramsUpdate.x,
                        y: paramsUpdate.y
                    }
                }
            }, function (err) {
                if (err) {
                    debug('failed update node position');
                    error(err);
                }
                else
                // success saved the cat
                    success(tn);
            });
        }
    });
};

catalog.prototype.updateNode = function (error, paramsWhere, paramsUpdate, success) {
    TreeNodes.findById(paramsWhere).exec(function (err, tn) {
        if (err) error(err);
        else {
            if (!tn)
                error(helper.createError404("Node"));
            else {
                if (paramsUpdate['name']) {
                    tn.name = paramsUpdate['name'];
                }

                tn.save(function (err) {
                    if (err) {
                        debug('failed update node content');
                        error(err);
                    }
                    else {
                        // success saved the cat
                        success(tn);
                    }
                });
            }
        }
    });
};

catalog.prototype.deleteNode = function (error, params, success) {
    TreeNodes.findById(params).exec(function (err, tn) {
        if (err) error(err);
        else {
            if (!tn)
                error(helper.createError404("Node"));

            else {
                tn.isDeleted = true;
                tn.dateDeleted = new Date();
                tn.save(
                    function (err) {
                        if (err) {
                            debug('failed update node position');
                            error(err);
                        }
                        else {
                            success(true);
                        }
                    }
                );
            }
        }

    });
};

module.exports = catalog;<|endoftext|>


<commit_before>var events = require('events');
var util = require('util');

module.exports = Command;

/**
 * Base command class for Presto.
 *
 * All commands should inherit from this command. It provides the following:
 *
 * - Integration into the Pronto events system
 * - Basic flow control
 * - Error capturing
 */
function Command() {}
util.inherits(Command, events.EventEmitter);

/**
 * Initialize the command.
 *
 * When overriding, make sure you call the parent init(name) to
 * execute this.
 */
Command.prototype.init = function(name) {
  this.name = name;
}

/**
 * Override this to provide your command with a task.
 *
 * This is the entry point for a command. It is executed exactly
 * once. When it is at the point where it should return control
 * to the command processor, it should call this.done().
 *
 * Anything stored in the context will be accessible to subsequent
 * commands in the chain.
 *
 *
 */
Command.prototype.execute = function(cxt, params) {
  this.done();
}

/**
 * Wraps calls to execute().
 *
 * The wrapper monitors execution of the command, emitting
 * any necessary events. This offloads responsibility from
 * commands. (For example, a command does not need to
 * manually emit 'continue' and 'complete'.)
 *
 * This function does the following:
 *
 * - Fires execCommand event before executing the command
 * - Executes the command's execute() method
 * - Catches any errors and emits them as 'error'
 * - Emits 'continue' if necessary
 * - Emits 'complete' when the command is done
 */
Command.prototype.executionWrapper = function(cxt, params) {
  this.hasContinued = false;
  this.cxt = cxt;
  this.emit('execCommand', cxt, params);
  try {
    this.execute(cxt, params);
  } catch (err) {
    // Event: error is given the Error object.
    this.emit('error', err);
  }

  // Event: complete fired when command is 100% done. Note that this may be well
  // after the command has 'continued'.
  //this.done(cxt);
}

/**
 * Provided just in case you need to this.keepCalmAnd().carryOn();
 */
Command.prototype.keepCalmAnd = function () {
  return this;
}

/**
 * Instruct the runner that it can continue on to the next command.
 *
 * However, the current command can continue performing operations,
 * though the order in which they are executed is indeterminent.
 *
 * This is useful for simulating background processing.
 */
Command.prototype.carryOn = function() {
  this.hasContinued = true;
  this.emit('continue');
}

/**
 * Notify Presto that this command is done.
 *
 * This will allow Presto to continue executing the chain of
 * commands. Not that you can call done, and then continue processing, but
 * the execution order after calling done() is not insured. For example,
 * a logging command can call done() before inserting a message into the log.
 * That message may not be inserted into the log until the rest of the commands
 * have completed (MAY be, not WILL be -- the order is determined by the node runtime).
 */
Command.prototype.done = function(value) {

  if (value != undefined) {
    this.store(value);
  }

  if (!this.hasContinued) {
    this.hasContinued = true;
    this.emit('continue');
  }

  // Event: continue
  this.emit('complete', this.cxt);
}

/**
 * Store a value in the context.
 *
 * Store a value in the context, with the command name being the key.
 *
 * If a prefix is provided, then the command name will be prefixed. Example:
 * if `prefix` is 'foo' and `this.name` is 'myCommand', then the key will
 * be `foo-myCommand`.
 */
Command.prototype.store = function(value, prefix) {
  var key = prefix == undefined ? this.name : prefix + '-' + this.name;
  this.cxt.add(key, value);
}<commit_msg>Added 'required' function to Command prototype.<commit_after>var events = require('events');
var util = require('util');

module.exports = Command;

/**
 * Base command class for Presto.
 *
 * All commands should inherit from this command. It provides the following:
 *
 * - Integration into the Pronto events system
 * - Basic flow control
 * - Error capturing
 */
function Command() {}
util.inherits(Command, events.EventEmitter);

/**
 * Initialize the command.
 *
 * When overriding, make sure you call the parent init(name) to
 * execute this.
 */
Command.prototype.init = function(name) {
  this.name = name;
}

/**
 * Override this to provide your command with a task.
 *
 * This is the entry point for a command. It is executed exactly
 * once. When it is at the point where it should return control
 * to the command processor, it should call this.done().
 *
 * Anything stored in the context will be accessible to subsequent
 * commands in the chain.
 *
 *
 */
Command.prototype.execute = function(cxt, params) {
  this.done();
}

/**
 * Wraps calls to execute().
 *
 * The wrapper monitors execution of the command, emitting
 * any necessary events. This offloads responsibility from
 * commands. (For example, a command does not need to
 * manually emit 'continue' and 'complete'.)
 *
 * This function does the following:
 *
 * - Fires execCommand event before executing the command
 * - Executes the command's execute() method
 * - Catches any errors and emits them as 'error'
 * - Emits 'continue' if necessary
 * - Emits 'complete' when the command is done
 */
Command.prototype.executionWrapper = function(cxt, params) {
  this.hasContinued = false;
  this.cxt = cxt;
  this.emit('execCommand', cxt, params);
  try {
    this.execute(cxt, params);
  } catch (err) {
    // Event: error is given the Error object.
    this.emit('error', err);
  }

  // Event: complete fired when command is 100% done. Note that this may be well
  // after the command has 'continued'.
  //this.done(cxt);
}

/**
 * Provided just in case you need to this.keepCalmAnd().carryOn();
 */
Command.prototype.keepCalmAnd = function () {
  return this;
}

/**
 * Instruct the runner that it can continue on to the next command.
 *
 * However, the current command can continue performing operations,
 * though the order in which they are executed is indeterminent.
 *
 * This is useful for simulating background processing.
 */
Command.prototype.carryOn = function() {
  this.hasContinued = true;
  this.emit('continue');
}

/**
 * Notify Presto that this command is done.
 *
 * This will allow Presto to continue executing the chain of
 * commands. Not that you can call done, and then continue processing, but
 * the execution order after calling done() is not insured. For example,
 * a logging command can call done() before inserting a message into the log.
 * That message may not be inserted into the log until the rest of the commands
 * have completed (MAY be, not WILL be -- the order is determined by the node runtime).
 */
Command.prototype.done = function(value) {

  if (value != undefined) {
    this.store(value);
  }

  if (!this.hasContinued) {
    this.hasContinued = true;
    this.emit('continue');
  }

  // Event: continue
  this.emit('complete', this.cxt);
}

/**
 * Store a value in the context.
 *
 * Store a value in the context, with the command name being the key.
 *
 * If a prefix is provided, then the command name will be prefixed. Example:
 * if `prefix` is 'foo' and `this.name` is 'myCommand', then the key will
 * be `foo-myCommand`.
 */
Command.prototype.store = function(value, prefix) {
  var key = prefix == undefined ? this.name : prefix + '-' + this.name;
  this.cxt.add(key, value);
}

Command.prototype.required = function(params, names) {
  for (var i = 0; i < names.length; ++i) {
    if (params[names[i]] == undefined || params[names[i]] == null) {
      console.log('Emitting an error');
      this.emit('error', new Error(params[names[i]] + ' is a required parameter for ' + this.name));
    }
  }
}<|endoftext|>


<commit_before>'use strict';

var assert = require('assert')
  , Grid = require('../../../server/grid');

describe('Grid', function() {
  var gridDimensions = 32;
  describe('constructor', function() {
    it('should instantiate a new grid', function() {
      var grid = new Grid(gridDimensions);
      assert(grid instanceof Grid);
    });

    it('should create a 2d array representing the grid', function() {
      var grid = new Grid(gridDimensions);
      assert(grid.gridMatrix instanceof Array);
      assert(grid.gridMatrix.length === gridDimensions);
      assert(grid.gridMatrix[0].length === gridDimensions);
    });
  });

  describe('updateGridMatrix', function() {
    var grid = new Grid(gridDimensions);
    it('should update gridMatrix with new values', function() {
      var data = {
        row: 0,
        col: 0,
        color: '#fff'
      };
      var gridCol = grid.gridMatrix[data.row][data.col];
      assert(gridCol.color === '');

      grid.updateGridMatrix(data);
      assert(gridCol.color === data.color);

      grid.updateGridMatrix(data);
      assert(gridCol.color === '');
    });
  });

});<commit_msg>Removed updateGridMatrix unit test since method doesn't exist anymore (#66)<commit_after>'use strict';

var assert = require('assert')
  , Grid = require('../../../server/grid');

describe('Grid', function() {
  var gridDimensions = 32;
  describe('constructor', function() {
    it('should instantiate a new grid', function() {
      var grid = new Grid(gridDimensions);
      assert(grid instanceof Grid);
    });

    it('should create a 2d array representing the grid', function() {
      var grid = new Grid(gridDimensions);
      assert(grid.gridMatrix instanceof Array);
      assert(grid.gridMatrix.length === gridDimensions);
      assert(grid.gridMatrix[0].length === gridDimensions);
    });
  });
});
<|endoftext|>


<commit_before>var _ = require('underscore');
var chalk = require('chalk');
var sprintf = require('sprintf-js').sprintf;

var core = require('../core');

var cmd = {
  command: 'stat',
  desc:    'show question statistics',
  builder: {
    company: {
      alias:    'c',
      type:     'boolean',
      describe: 'Count by company'
    },
    tag: {
      alias:    't',
      type:     'boolean',
      describe: 'Count by tag'
    },
    num: {
      alias:    'n',
      type:     'number',
      default:  10,
      describe: 'Only show the first n results (0 means all)'
    }
  }
};

function hasLabel(q, label) {
  return q.labels && q.labels.indexOf(label) >= 0;
}

cmd.handler = function(argv) {
  core.getQuestions({}, function(e, questions) {
    if (e) return console.log('ERROR:', e);

    var stat = {};
    var statDone = {};
    var keyword = '';

    if (argv.company) {
      keyword = 'Company';
      questions.forEach(function(q) {
        var k = q.company || 'N/A';
        stat[k] = (stat[k] || 0) + 1;

        if (hasLabel(q, 'done')) {
          statDone[k] = (statDone[k] || 0) + 1;
        }
      });
    } else if (argv.tag) {
      keyword = 'Tags';
      questions.forEach(function(q) {
        q.tags.forEach(function(tag) {
          stat[tag] = (stat[tag] || 0) + 1;

          if (hasLabel(q, 'done')) {
            statDone[tag] = (statDone[tag] || 0) + 1;
          }
        });
      });
    }

    var results = _.sortBy(_.pairs(stat), function(p) {
      return -p[1];
    });

    if (argv.num > 0) {
      results = _.first(results, argv.num);
    }

    console.log();
    var all = questions.length;
    var done = _.reduce(questions, function(s, q) {
      return s + (hasLabel(q, 'done') ? 1 : 0);
    }, 0);

    console.log(sprintf('[**] %5s/%-5s (%.2f%%)  %s',
          done, all, done * 100 / all,
          chalk.yellow(keyword)));

    if (results.length > 0) {
      var len = _.max(results, function(p) {
        return p[0].length;
      })[0].length + 27;
      console.log(new Buffer(len).fill('-').toString());
    }

    results.forEach(function(p, i) {
      var subDone = statDone[p[0]] || 0;

      console.log(
          sprintf('[%-2d]', i + 1),
          sprintf('%5s/%-5s', subDone, p[1]),
          sprintf('(%.2f%%) ', subDone * 100 / p[1]),
          chalk.yellow(p[0]));
    });
  });
};

module.exports = cmd;
<commit_msg>Add 'stat -l'.<commit_after>var _ = require('underscore');
var chalk = require('chalk');
var sprintf = require('sprintf-js').sprintf;

var core = require('../core');

var cmd = {
  command: 'stat',
  desc:    'show question statistics',
  builder: {
    company: {
      alias:    'c',
      type:     'boolean',
      default:  false,
      describe: 'Count by company'
    },
    tag: {
      alias:    't',
      type:     'boolean',
      default:  false,
      describe: 'Count by tag'
    },
    label: {
      alias:    'l',
      type:     'boolean',
      default:  false,
      describe: 'Count by label'
    },
    num: {
      alias:    'n',
      type:     'number',
      default:  10,
      describe: 'Only show the first n results (0 means all)'
    }
  }
};

function countDone(q) {
  return (q.labels && q.labels.indexOf('done') >= 0) ? 1 : 0;
}

function add(map, k, v) {
  k = k || 'N/A';
  map[k] = (map[k] || 0) + v;
}

cmd.handler = function(argv) {
  core.getQuestions({}, function(e, questions) {
    if (e) return console.log('ERROR:', e);

    var stat = {};
    var statDone = {};
    var keyword = '';

    if (argv.company) {
      keyword = 'Company';
      questions.forEach(function(q) {
        add(stat, q.company, 1);
        add(statDone, q.company, countDone(q));
      });
    } else if (argv.tag) {
      keyword = 'Tags';
      questions.forEach(function(q) {
        q.tags.forEach(function(tag) {
          add(stat, tag, 1);
          add(statDone, tag, countDone(q));
        });
      });
    } else if (argv.label) {
      keyword = 'Labels';
      questions.forEach(function(q) {
        (q.labels || []).forEach(function(label) {
          add(stat, label, 1);
          add(statDone, label, countDone(q));
        });
      });
    }

    var results = _.sortBy(_.pairs(stat), function(p) {
      return -p[1];
    });

    if (argv.num > 0) {
      results = _.first(results, argv.num);
    }

    console.log();
    var all = questions.length;
    var done = _.reduce(questions, function(sum, q) {
      return sum + countDone(q);
    }, 0);

    console.log(sprintf('     %5s/%-5s %6.2f%%  %s',
          done, all, done * 100 / all,
          chalk.yellow(keyword)));

    if (results.length > 0) {
      var len = _.max(results, function(p) {
        return p[0].length;
      })[0].length + 27;
      console.log('-'.repeat(len));
    }

    results.forEach(function(p, i) {
      console.log(
          sprintf('%3d.', i + 1),
          sprintf('%5s/%-5s', statDone[p[0]], p[1]),
          sprintf('%6.2f%% ', statDone[p[0]] * 100 / p[1]),
          chalk.yellow(p[0]));
    });
  });
};

module.exports = cmd;
<|endoftext|>


<commit_before>var
  bify = require('browserify'),
  rs = require('browserify/node_modules/readable-stream'),
  util = require('util'),
  pathmodify = require('../'),
  path = require('path'),
  assert = require('assert'),
  vm = require('vm'),
  b;

// Transform stream to test programatic transforms.
function Xform () {
  rs.Transform.apply(this, arguments);
}

util.inherits(Xform, rs.Transform);

Xform.prototype._transform = function (chunk, enc, cb) {
  this.push(chunk.toString().replace("lowercase", "UPPERCASE"));
  cb();
};

describe('Plugin', function () {
  var
    bify_opts,
    paths = {};

  bify_opts =  {
    entries: ['./src/entry'],
    basedir: __dirname,
  };

  paths.prefix = 'app/';
  paths.src = path.join(__dirname, 'src');
  paths.a_rel = 'a/a.js';

  function aliaser (input) {
    var
      output = {};

    if (input.id.indexOf(paths.prefix) === 0) {
      output.id = path.join(paths.src, input.id.substr(paths.prefix.length));

      if (input.opts && input.opts.filename) {
        output.id = './' + path.relative(
          path.dirname(input.opts.filename),
          output.id
        );
      }

      output.expose = "whatever";
    }
    return output;
  }
  // aliaser

  function run_test (opts, done) {
    bify(bify_opts)
      .plugin(pathmodify, opts)
      .transform(function (file) { return new Xform; })
      .bundle(function (err, src) {
        if (err) throw err;

        var c = {};
        vm.runInNewContext(src.toString(), c);

        assert.equal(c.require('whatever'), 'UPPERCASE app/a/a.js');

        done();
      });
  }
  // run_test

  it(
    "Should resolve 'app/a/a' as 'src/a/a.js' via function, expose as 'whatever', and apply programmatic transform.",
    function (done) {
      run_test({
        mods: [aliaser]
      }, done);
    }
  );
});
<commit_msg>Add test.<commit_after>var
  bify = require('browserify'),
  rs = require('browserify/node_modules/readable-stream'),
  util = require('util'),
  pathmodify = require('../'),
  path = require('path'),
  assert = require('assert'),
  vm = require('vm'),
  b;

// Transform stream to test programatic transforms.
function Xform () {
  rs.Transform.apply(this, arguments);
}

util.inherits(Xform, rs.Transform);

Xform.prototype._transform = function (chunk, enc, cb) {
  this.push(chunk.toString().replace("lowercase", "UPPERCASE"));
  cb();
};

describe('Plugin', function () {
  var
    bify_opts,
    paths = {};

  bify_opts =  {
    entries: ['./src/entry'],
    basedir: __dirname,
  };

  paths.prefix = 'app/';
  paths.src = path.join(__dirname, 'src');
  paths.a_rel = 'a/a.js';

  function aliaser (input) {
    var
      output = {};

    if (input.id.indexOf(paths.prefix) === 0) {
      output.id = path.join(paths.src, input.id.substr(paths.prefix.length));

      if (input.opts && input.opts.filename) {
        output.id = './' + path.relative(
          path.dirname(input.opts.filename),
          output.id
        );
      }

      output.expose = "whatever";
    }
    return output;
  }
  // aliaser

  function run_test (opts, done) {
    bify(bify_opts)
      .plugin(pathmodify, opts)
      .transform(function (file) { return new Xform; })
      .bundle(function (err, src) {
        if (err) throw err;

        var c = {};
        vm.runInNewContext(src.toString(), c);

        assert.equal(c.require('whatever'), 'UPPERCASE app/a/a.js');

        done();
      });
  }
  // run_test

  it(
    "Should resolve 'app/a/a' as 'src/a/a.js' via function, expose as 'whatever', and apply programmatic transform.",
    function (done) {
      run_test({
        mods: [aliaser]
      }, done);
    }
  );

  it(
    "Should resolve 'app/a/a' as 'src/a/a.js' via `id` type modification, expose as 'whatever' via string, and apply programmatic transform.",
    function (done) {
      run_test({
        mods: [pathmodify.mod.id(
          'app/a/a',
          path.join(paths.src, paths.a_rel),
          'whatever'
        )]
      }, done);
    }
  );
});
<|endoftext|>


<commit_before><commit_msg>Removed some duplicate files<commit_after><|endoftext|>


<commit_before>'use strict';

var each = require('p-each-series');
var algoliasearch = require('algoliasearch');
var crypto = require('crypto');

var CONSOLE_DEFAULTS = {
  dryRun: false,
  flush: false,
  chunkSize: 50
};

var INDEXED_PROPERTIES = [
  'title',
  'date',
  'updated',
  'slug',
  'excerpt',
  'permalink',
  'layout'
];

function computeSha1(text) {
  return crypto.createHash('sha1').update(text, 'utf8').digest('hex');
}

function pick(object, properties) {
  return properties.reduce(function(filteredObj, prop) {
    filteredObj[prop] = object[prop];
    return filteredObj;
  }, {});
}

function chunk(array, chunkSize) {
  var batches = [];

  while (array.length > 0) {
    batches.push(array.splice(0, chunkSize));
  }

  return batches;
}

module.exports = function(args, callback) {
  var hexo = this;
  var config = Object.assign({}, hexo.config.algolia);
  var indexName = config.indexName;
  var applicationID = config.applicationID;
  var apiKey = String(process.env.HEXO_ALGOLIA_INDEXING_KEY || '');
  var client;
  var index;

  Promise.resolve(apiKey)
    .then(function(){
      if (!apiKey) {
        hexo.log.error('[Algolia] Please set an `HEXO_ALGOLIA_INDEXING_KEY` environment variable to enable content indexing.');
        hexo.log.error('>> Read %s for more informations.', 'https://npmjs.com/hexo-algolia#api-key');
        process.exit(1);
      }

      if (!indexName) {
        hexo.log.error('[Algolia] Please provide an Algolia index name in your hexo _config.yml file.');
        hexo.log.error('>> Read %s for more informations.', 'https://npmjs.com/hexo-algolia#public-facing-search-options');
        process.exit(1);
      }

      client = algoliasearch(applicationID, apiKey);
      index = client.initIndex(indexName);
    })
    .then(function(){
      hexo.log.info('[Algolia] Testing HEXO_ALGOLIA_INDEXING_KEY permissions.');

      return client.getApiKey(apiKey)
        .catch(function(err){
          hexo.log.error('[Algolia] %s', err.message);
          hexo.log.error('>> You might have used an Admin Key or an invalid Key.');
          hexo.log.error('>> Read %s for more informations.', 'https://npmjs.com/hexo-algolia#security-concerns');
          process.exit(1);
        });
    })
    .then(function() {
      return hexo.load();
    })
    .then(function() {
      var posts = hexo.database.model('Post').find({ published: true });

      return posts.toArray();
    })
    .then(function(publishedPosts) {
      var pages = hexo.database.model('Page').find({
        layout: {
          '$in': ['page']
        }
      });

      return publishedPosts.concat(pages.toArray());
    })
    .then(function(publishedPagesAndPosts) {
      return publishedPagesAndPosts.map(function(data) {
        var storedPost = pick(data, INDEXED_PROPERTIES);

        storedPost.objectID = computeSha1(data.path);
        storedPost.date_as_int = Date.parse(data.date) / 1000;
        storedPost.updated_as_int = Date.parse(data.updated) / 1000;

        if (data.categories) {
          storedPost.categories = data.categories.map(function(item) {
            return pick(item, ['name', 'path']);
          });
        }

        if (data.tags) {
          storedPost.tags = data.tags.map(function(item) {
            return pick(item, ['name', 'path']);
          });
        }

        storedPost.author = data.author || config.author;

        return storedPost;
      });
    })
    .then(function(publishedPagesAndPosts) {
      hexo.log.info(
        '[Algolia] Identified %d pages and posts to index.',
        publishedPagesAndPosts.length
      );

      return publishedPagesAndPosts.map(function toAlgoliaBatchActions(post) {
        return {
          action: 'updateObject',
          indexName: indexName,
          body: post
        };
      });
    })
    .then(function(actions) {
      var options = Object.assign({}, CONSOLE_DEFAULTS, args || {});

      if (options.dryRun) {
        hexo.log.info('[Algolia] Skipping due to --dry-run option');
        return;
      }

      return Promise.resolve(options.flush)
        .then(function(flush) {
          if (flush) {
            hexo.log.info('[Algolia] Clearing index...');
            return index.clearIndex();
          }
        })
        .then(function() {
          var chunks = chunk(actions, options.chunkSize);

          return each(chunks, function(chunk, i) {
            hexo.log.info(
              '[Algolia] Indexing chunk %d of %d (%d items each)',
              i + 1,
              chunks.length,
              options.chunkSize
            );

            return client
              .batch(chunk)
              .catch(function(err){
                hexo.log.error('[Algolia] %s', err.message);
              });
          });
        })

        .then(function() {
          hexo.log.info('[Algolia] Indexing done.');
        });
    })
    .catch(callback);
};
<commit_msg>Index tags/categories only if they are arrays<commit_after>'use strict';

var each = require('p-each-series');
var algoliasearch = require('algoliasearch');
var crypto = require('crypto');

var CONSOLE_DEFAULTS = {
  dryRun: false,
  flush: false,
  chunkSize: 50
};

var INDEXED_PROPERTIES = [
  'title',
  'date',
  'updated',
  'slug',
  'excerpt',
  'permalink',
  'layout'
];

function computeSha1(text) {
  return crypto.createHash('sha1').update(text, 'utf8').digest('hex');
}

function pick(object, properties) {
  return properties.reduce(function(filteredObj, prop) {
    filteredObj[prop] = object[prop];
    return filteredObj;
  }, {});
}

function chunk(array, chunkSize) {
  var batches = [];

  while (array.length > 0) {
    batches.push(array.splice(0, chunkSize));
  }

  return batches;
}

module.exports = function(args, callback) {
  var hexo = this;
  var config = Object.assign({}, hexo.config.algolia);
  var indexName = config.indexName;
  var applicationID = config.applicationID;
  var apiKey = String(process.env.HEXO_ALGOLIA_INDEXING_KEY || '');
  var client;
  var index;

  Promise.resolve(apiKey)
    .then(function(){
      if (!apiKey) {
        hexo.log.error('[Algolia] Please set an `HEXO_ALGOLIA_INDEXING_KEY` environment variable to enable content indexing.');
        hexo.log.error('>> Read %s for more informations.', 'https://npmjs.com/hexo-algolia#api-key');
        process.exit(1);
      }

      if (!indexName) {
        hexo.log.error('[Algolia] Please provide an Algolia index name in your hexo _config.yml file.');
        hexo.log.error('>> Read %s for more informations.', 'https://npmjs.com/hexo-algolia#public-facing-search-options');
        process.exit(1);
      }

      client = algoliasearch(applicationID, apiKey);
      index = client.initIndex(indexName);
    })
    .then(function(){
      hexo.log.info('[Algolia] Testing HEXO_ALGOLIA_INDEXING_KEY permissions.');

      return client.getApiKey(apiKey)
        .catch(function(err){
          hexo.log.error('[Algolia] %s', err.message);
          hexo.log.error('>> You might have used an Admin Key or an invalid Key.');
          hexo.log.error('>> Read %s for more informations.', 'https://npmjs.com/hexo-algolia#security-concerns');
          process.exit(1);
        });
    })
    .then(function() {
      return hexo.load();
    })
    .then(function() {
      var posts = hexo.database.model('Post').find({ published: true });

      return posts.toArray();
    })
    .then(function(publishedPosts) {
      var pages = hexo.database.model('Page').find({
        layout: {
          '$in': ['page']
        }
      });

      return publishedPosts.concat(pages.toArray());
    })
    .then(function(publishedPagesAndPosts) {
      return publishedPagesAndPosts.map(function(data) {
        var storedPost = pick(data, INDEXED_PROPERTIES);

        storedPost.objectID = computeSha1(data.path);
        storedPost.date_as_int = Date.parse(data.date) / 1000;
        storedPost.updated_as_int = Date.parse(data.updated) / 1000;

        if (Array.isArray(data.categories)) {
          storedPost.categories = data.categories.map(function(item) {
            return pick(item, ['name', 'path']);
          });
        }

        if (Array.isArray(data.tags)) {
          storedPost.tags = data.tags.map(function(item) {
            return pick(item, ['name', 'path']);
          });
        }

        storedPost.author = data.author || config.author;

        return storedPost;
      });
    })
    .then(function(publishedPagesAndPosts) {
      hexo.log.info(
        '[Algolia] Identified %d pages and posts to index.',
        publishedPagesAndPosts.length
      );

      return publishedPagesAndPosts.map(function toAlgoliaBatchActions(post) {
        return {
          action: 'updateObject',
          indexName: indexName,
          body: post
        };
      });
    })
    .then(function(actions) {
      var options = Object.assign({}, CONSOLE_DEFAULTS, args || {});

      if (options.dryRun) {
        hexo.log.info('[Algolia] Skipping due to --dry-run option');
        return;
      }

      return Promise.resolve(options.flush)
        .then(function(flush) {
          if (flush) {
            hexo.log.info('[Algolia] Clearing index...');
            return index.clearIndex();
          }
        })
        .then(function() {
          var chunks = chunk(actions, options.chunkSize);

          return each(chunks, function(chunk, i) {
            hexo.log.info(
              '[Algolia] Indexing chunk %d of %d (%d items each)',
              i + 1,
              chunks.length,
              options.chunkSize
            );

            return client
              .batch(chunk)
              .catch(function(err){
                hexo.log.error('[Algolia] %s', err.message);
              });
          });
        })

        .then(function() {
          hexo.log.info('[Algolia] Indexing done.');
        });
    })
    .catch(callback);
};
<|endoftext|>


<commit_before>import { exec } from 'child-process-promise';

describe('rdcli', () => {
    before(() => {
        delete process.env.NODE_ENV;
    });

    it('should exec rdcli command', async () => {
        const { stdout, stderr } = await exec('node ./build/rdcli.js');

        assert.isNotNull(stdout);
        assert.equal(stderr, '');
    });

    after(() => {
        process.env.NODE_ENV = 'test';
    });
});
<commit_msg>Skip test<commit_after>import { exec } from 'child-process-promise';

describe('rdcli', () => {
    before(() => {
        delete process.env.NODE_ENV;
    });

    it.skip('should exec rdcli command', async () => {
        const { stdout, stderr } = await exec('node ./build/rdcli.js');

        assert.isNotNull(stdout);
        assert.equal(stderr, '');
    });

    after(() => {
        process.env.NODE_ENV = 'test';
    });
});
<|endoftext|>


<commit_before>// Copyright (c) 2018, Marc Tiehuis
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

const BaseCompiler = require('../base-compiler'),
    _ = require('underscore'),
    path = require('path'),
    Semver = require('semver');

class ZigCompiler extends BaseCompiler {
    constructor(info, env) {
        super(info, env);
        this.compiler.supportsIntel = true;
        this.compiler.supportsIrView = true;
        this.compiler.irArg = ['--emit', 'llvm-ir'];
    }

    getSharedLibraryPathsAsArguments() {
        return [];
    }

    preProcess(source) {
        if (this.compiler.semver === '0.2.0') {
            source += '\n';
            source += 'extern fn zig_panic() noreturn;\n';
            source += 'pub fn panic(msg: []const u8, error_return_trace: ' +
                '?&@import("builtin").StackTrace) noreturn {\n';
            source += '    zig_panic();\n';
            source += '}\n';
        } else {
            source += '\n';
            source += 'extern fn zig_panic() noreturn;\n';
            source += 'pub fn panic(msg: []const u8, error_return_trace: ' +
                '?*@import("builtin").StackTrace) noreturn {\n';
            source += '    zig_panic();\n';
            source += '}\n';
        }

        return source;
    }

    optionsForFilter(filters, outputFilename, userOptions) {
        let options = [filters.execute ? 'build-exe' : 'build-obj'];
        if (this.compiler.semver === 'trunk' || Semver.gt(this.compiler.semver, '0.3.0')) {
            const outputDir = path.dirname(outputFilename);
            const desiredName = path.basename(outputFilename);
            // strip '.s' if we aren't executing
            const name = filters.execute ? desiredName : desiredName.slice(0, -2);
            options.push('--cache-dir', outputDir,
                '--output-dir', outputDir,
                '--name', name);
        } else {
            // Older versions use a different command line interface (#1304)
            options.push('--cache-dir', path.dirname(outputFilename),
                '--output', this.filename(outputFilename),
                '--output-h', '/dev/null');
        }

        if (!filters.binary) {
            let userRequestedEmit = _.any(userOptions, opt => opt.indexOf("--emit") > -1);
            if (!userRequestedEmit) {
                options = options.concat('--emit', 'asm');
            }
            if (filters.intel) options = options.concat('-mllvm', '--x86-asm-syntax=intel');
        }
        return options;
    }

    getIrOutputFilename(inputFilename) {
        return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase)
            .replace('.s', '.ll');
    }

    filterUserOptions(userOptions) {
        const blacklist = /^(((--(cache-dir|name|output|verbose))|(-mllvm)).*)$/;
        return _.filter(userOptions, option => !blacklist.test(option));
    }

    isCfgCompiler(/*compilerVersion*/) {
        return true;
    }
}

module.exports = ZigCompiler;
<commit_msg>Stop zig from crashing if semver is not set<commit_after>// Copyright (c) 2018, Marc Tiehuis
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

const BaseCompiler = require('../base-compiler'),
    _ = require('underscore'),
    path = require('path'),
    Semver = require('semver');

class ZigCompiler extends BaseCompiler {
    constructor(info, env) {
        super(info, env);
        this.compiler.supportsIntel = true;
        this.compiler.supportsIrView = true;
        this.compiler.irArg = ['--emit', 'llvm-ir'];
    }

    getSharedLibraryPathsAsArguments() {
        return [];
    }

    preProcess(source) {
        if (this.compiler.semver === '0.2.0') {
            source += '\n';
            source += 'extern fn zig_panic() noreturn;\n';
            source += 'pub fn panic(msg: []const u8, error_return_trace: ' +
                '?&@import("builtin").StackTrace) noreturn {\n';
            source += '    zig_panic();\n';
            source += '}\n';
        } else {
            source += '\n';
            source += 'extern fn zig_panic() noreturn;\n';
            source += 'pub fn panic(msg: []const u8, error_return_trace: ' +
                '?*@import("builtin").StackTrace) noreturn {\n';
            source += '    zig_panic();\n';
            source += '}\n';
        }

        return source;
    }

    optionsForFilter(filters, outputFilename, userOptions) {
        let options = [filters.execute ? 'build-exe' : 'build-obj'];
        if (this.compiler.semver === 'trunk' || (this.compiler.semver && Semver.gt(this.compiler.semver, '0.3.0'))) {
            const outputDir = path.dirname(outputFilename);
            const desiredName = path.basename(outputFilename);
            // strip '.s' if we aren't executing
            const name = filters.execute ? desiredName : desiredName.slice(0, -2);
            options.push('--cache-dir', outputDir,
                '--output-dir', outputDir,
                '--name', name);
        } else {
            // Older versions use a different command line interface (#1304)
            options.push('--cache-dir', path.dirname(outputFilename),
                '--output', this.filename(outputFilename),
                '--output-h', '/dev/null');
        }

        if (!filters.binary) {
            let userRequestedEmit = _.any(userOptions, opt => opt.indexOf("--emit") > -1);
            if (!userRequestedEmit) {
                options = options.concat('--emit', 'asm');
            }
            if (filters.intel) options = options.concat('-mllvm', '--x86-asm-syntax=intel');
        }
        return options;
    }

    getIrOutputFilename(inputFilename) {
        return this.getOutputFilename(path.dirname(inputFilename), this.outputFilebase)
            .replace('.s', '.ll');
    }

    filterUserOptions(userOptions) {
        const blacklist = /^(((--(cache-dir|name|output|verbose))|(-mllvm)).*)$/;
        return _.filter(userOptions, option => !blacklist.test(option));
    }

    isCfgCompiler(/*compilerVersion*/) {
        return true;
    }
}

module.exports = ZigCompiler;
<|endoftext|>


<commit_before>require( 'source-map-support' ).install();
require( 'console-group' ).install();

var path = require( 'path' );
var sander = require( 'sander' );
var assert = require( 'assert' );
var exec = require( 'child_process' ).exec;
var babel = require( 'babel-core' );
var sequence = require( './utils/promiseSequence' );
var rollup = require( '../dist/rollup' );

var FUNCTION = path.resolve( __dirname, 'function' );
var FORM = path.resolve( __dirname, 'form' );
var SOURCEMAPS = path.resolve( __dirname, 'sourcemaps' );
var CLI = path.resolve( __dirname, 'cli' );

var PROFILES = [
	{ format: 'amd' },
	{ format: 'cjs' },
	{ format: 'es6' },
	{ format: 'iife' },
	{ format: 'umd' }
];

function extend ( target ) {
	[].slice.call( arguments, 1 ).forEach( function ( source ) {
		source && Object.keys( source ).forEach( function ( key ) {
			target[ key ] = source[ key ];
		});
	});

	return target;
}

describe( 'rollup', function () {
	describe( 'sanity checks', function () {
		it( 'exists', function () {
			assert.ok( !!rollup );
		});

		it( 'has a rollup method', function () {
			assert.equal( typeof rollup.rollup, 'function' );
		});
	});

	describe( 'function', function () {
		sander.readdirSync( FUNCTION ).sort().forEach( function ( dir ) {
			if ( dir[0] === '.' ) return; // .DS_Store...

			var config;

			try {
				config = require( FUNCTION + '/' + dir + '/_config' );
			} catch ( err ) {
				config = { description: dir };
			}

			( config.skip ? it.skip : config.solo ? it.only : it )( dir, function () {
				var options = extend( {}, config.options, {
					entry: FUNCTION + '/' + dir + '/main.js'
				});

				if ( config.solo ) console.group( dir );

				return rollup.rollup( options )
					.then( function ( bundle ) {
						var unintendedError;

						if ( config.error ) {
							throw new Error( 'Expected an error while rolling up' );
						}

						// try to generate output
						try {
							var result = bundle.generate( extend( {}, config.bundleOptions, {
								format: 'cjs'
							}));

							if ( config.error ) {
								unintendedError = new Error( 'Expected an error while generating output' );
							}
						} catch ( err ) {
							if ( config.error ) {
								config.error( err );
							} else {
								unintendedError = err;
							}
						}

						if ( unintendedError ) throw unintendedError;

						var code;

						try {
							if ( config.babel ) {
								code = babel.transform( code, {
									whitelist: config.babel
								}).code;
							} else {
								code = result.code;
							}

							var module = {
								exports: {}
							};

							var context = extend({
								require: require,
								module: module,
								exports: module.exports,
								assert: assert
							}, config.context || {} );

							var contextKeys = Object.keys( context );
							var contextValues = contextKeys.map( function ( key ) {
								return context[ key ];
							});

							var fn = new Function( contextKeys, code );
							fn.apply( {}, contextValues );

							if ( config.error ) {
								unintendedError = new Error( 'Expected an error while executing output' );
							}

							if ( config.exports ) {
								config.exports( module.exports );
							}
						} catch ( err ) {
							if ( config.error ) {
								config.error( err );
							} else {
								unintendedError = err;
							}
						}

						if ( config.show || unintendedError ) {
							console.log( code + '\n\n\n' );
						}

						if ( config.solo ) console.groupEnd();

						if ( unintendedError ) throw unintendedError;
					}, function ( err ) {
						if ( config.error ) {
							config.error( err );
						} else {
							throw err;
						}
					});
			});
		});
	});

	describe( 'form', function () {
		sander.readdirSync( FORM ).sort().forEach( function ( dir ) {
			if ( dir[0] === '.' ) return; // .DS_Store...

			describe( dir, function () {
				var config = require( FORM + '/' + dir + '/_config' );

				var options = extend( {}, config.options, {
					entry: FORM + '/' + dir + '/main.js'
				});

				var bundlePromise = rollup.rollup( options );

				PROFILES.forEach( function ( profile ) {
					( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () {
						if ( config.solo ) console.group( dir );

						return bundlePromise.then( function ( bundle ) {
							var options = extend( {}, config.options, {
								dest: FORM + '/' + dir + '/_actual/' + profile.format + '.js',
								format: profile.format
							});

							return bundle.write( options ).then( function () {
								var actualCode = sander.readFileSync( FORM, dir, '_actual', profile.format + '.js' ).toString().trim();
								var expectedCode;
								var actualMap;
								var expectedMap;

								try {
									expectedCode = sander.readFileSync( FORM, dir, '_expected', profile.format + '.js' ).toString().trim();
								} catch ( err ) {
									expectedCode = 'missing file';
								}

								try {
									actualMap = JSON.parse( sander.readFileSync( FORM, dir, '_actual', profile.format + '.js.map' ).toString() );
								} catch ( err ) {}

								try {
									expectedMap = JSON.parse( sander.readFileSync( FORM, dir, '_expected', profile.format + '.js.map' ).toString() );
								} catch ( err ) {}

								assert.equal( actualCode, expectedCode );
								assert.deepEqual( actualMap, expectedMap );

								if ( config.solo ) console.groupEnd();
							});
						});
					});
				});
			});
		});
	});

	describe( 'sourcemaps', function () {
		sander.readdirSync( SOURCEMAPS ).sort().forEach( function ( dir ) {
			if ( dir[0] === '.' ) return; // .DS_Store...

			describe( dir, function () {
				var config = require( SOURCEMAPS + '/' + dir + '/_config' );

				var options = extend( {}, config.options, {
					entry: SOURCEMAPS + '/' + dir + '/main.js'
				});

				var bundlePromise = rollup.rollup( options );

				PROFILES.forEach( function ( profile ) {
					( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () {
						return bundlePromise.then( function ( bundle ) {
							var result = bundle.generate({
								format: profile.format,
								sourceMap: true,
								sourceMapFile: 'bundle.js'
							});

							config.test( result.code, result.map );
						});
					});
				});
			});
		});
	});

	describe( 'cli', function () {
		sander.readdirSync( CLI ).sort().forEach( function ( dir ) {
			if ( dir[0] === '.' ) return; // .DS_Store...

			describe( dir, function () {
				var config = require( CLI + '/' + dir + '/_config' );

				( config.skip ? it.skip : config.solo ? it.only : it )( dir, function ( done ) {
					process.chdir( path.resolve( CLI, dir ) );

					exec( config.command, {
						env: {
							PATH: path.resolve( __dirname, '../bin' ) + ':' + process.env.PATH
						}
					}, function ( err, code, stderr ) {
						if ( err ) return done( err );

						if ( stderr ) console.error( stderr );

						var unintendedError;

						if ( config.execute ) {
							try {
								if ( config.babel ) {
									code = babel.transform( code, {
										whitelist: config.babel
									}).code;
								}

								var fn = new Function( 'require', 'module', 'exports', 'assert', code );
								var module = {
									exports: {}
								};
								fn( require, module, module.exports, assert );

								if ( config.error ) {
									unintendedError = new Error( 'Expected an error while executing output' );
								}

								if ( config.exports ) {
									config.exports( module.exports );
								}
							} catch ( err ) {
								if ( config.error ) {
									config.error( err );
								} else {
									unintendedError = err;
								}
							}

							if ( config.show || unintendedError ) {
								console.log( code + '\n\n\n' );
							}

							if ( config.solo ) console.groupEnd();

							unintendedError ? done( unintendedError ) : done();
						}
					});
				});
			});
		});
	});
});
<commit_msg>fix babel step<commit_after>require( 'source-map-support' ).install();
require( 'console-group' ).install();

var path = require( 'path' );
var sander = require( 'sander' );
var assert = require( 'assert' );
var exec = require( 'child_process' ).exec;
var babel = require( 'babel-core' );
var sequence = require( './utils/promiseSequence' );
var rollup = require( '../dist/rollup' );

var FUNCTION = path.resolve( __dirname, 'function' );
var FORM = path.resolve( __dirname, 'form' );
var SOURCEMAPS = path.resolve( __dirname, 'sourcemaps' );
var CLI = path.resolve( __dirname, 'cli' );

var PROFILES = [
	{ format: 'amd' },
	{ format: 'cjs' },
	{ format: 'es6' },
	{ format: 'iife' },
	{ format: 'umd' }
];

function extend ( target ) {
	[].slice.call( arguments, 1 ).forEach( function ( source ) {
		source && Object.keys( source ).forEach( function ( key ) {
			target[ key ] = source[ key ];
		});
	});

	return target;
}

describe( 'rollup', function () {
	describe( 'sanity checks', function () {
		it( 'exists', function () {
			assert.ok( !!rollup );
		});

		it( 'has a rollup method', function () {
			assert.equal( typeof rollup.rollup, 'function' );
		});
	});

	describe( 'function', function () {
		sander.readdirSync( FUNCTION ).sort().forEach( function ( dir ) {
			if ( dir[0] === '.' ) return; // .DS_Store...

			var config;

			try {
				config = require( FUNCTION + '/' + dir + '/_config' );
			} catch ( err ) {
				config = { description: dir };
			}

			( config.skip ? it.skip : config.solo ? it.only : it )( dir, function () {
				var options = extend( {}, config.options, {
					entry: FUNCTION + '/' + dir + '/main.js'
				});

				if ( config.solo ) console.group( dir );

				return rollup.rollup( options )
					.then( function ( bundle ) {
						var unintendedError;

						if ( config.error ) {
							throw new Error( 'Expected an error while rolling up' );
						}

						// try to generate output
						try {
							var result = bundle.generate( extend( {}, config.bundleOptions, {
								format: 'cjs'
							}));

							if ( config.error ) {
								unintendedError = new Error( 'Expected an error while generating output' );
							}
						} catch ( err ) {
							if ( config.error ) {
								config.error( err );
							} else {
								unintendedError = err;
							}
						}

						if ( unintendedError ) throw unintendedError;

						var code;

						try {
							if ( config.babel ) {
								code = babel.transform( result.code, {
									whitelist: config.babel
								}).code;
							} else {
								code = result.code;
							}

							var module = {
								exports: {}
							};

							var context = extend({
								require: require,
								module: module,
								exports: module.exports,
								assert: assert
							}, config.context || {} );

							var contextKeys = Object.keys( context );
							var contextValues = contextKeys.map( function ( key ) {
								return context[ key ];
							});

							var fn = new Function( contextKeys, code );
							fn.apply( {}, contextValues );

							if ( config.error ) {
								unintendedError = new Error( 'Expected an error while executing output' );
							}

							if ( config.exports ) {
								config.exports( module.exports );
							}
						} catch ( err ) {
							if ( config.error ) {
								config.error( err );
							} else {
								unintendedError = err;
							}
						}

						if ( config.show || unintendedError ) {
							console.log( code + '\n\n\n' );
						}

						if ( config.solo ) console.groupEnd();

						if ( unintendedError ) throw unintendedError;
					}, function ( err ) {
						if ( config.error ) {
							config.error( err );
						} else {
							throw err;
						}
					});
			});
		});
	});

	describe( 'form', function () {
		sander.readdirSync( FORM ).sort().forEach( function ( dir ) {
			if ( dir[0] === '.' ) return; // .DS_Store...

			describe( dir, function () {
				var config = require( FORM + '/' + dir + '/_config' );

				var options = extend( {}, config.options, {
					entry: FORM + '/' + dir + '/main.js'
				});

				var bundlePromise = rollup.rollup( options );

				PROFILES.forEach( function ( profile ) {
					( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () {
						if ( config.solo ) console.group( dir );

						return bundlePromise.then( function ( bundle ) {
							var options = extend( {}, config.options, {
								dest: FORM + '/' + dir + '/_actual/' + profile.format + '.js',
								format: profile.format
							});

							return bundle.write( options ).then( function () {
								var actualCode = sander.readFileSync( FORM, dir, '_actual', profile.format + '.js' ).toString().trim();
								var expectedCode;
								var actualMap;
								var expectedMap;

								try {
									expectedCode = sander.readFileSync( FORM, dir, '_expected', profile.format + '.js' ).toString().trim();
								} catch ( err ) {
									expectedCode = 'missing file';
								}

								try {
									actualMap = JSON.parse( sander.readFileSync( FORM, dir, '_actual', profile.format + '.js.map' ).toString() );
								} catch ( err ) {}

								try {
									expectedMap = JSON.parse( sander.readFileSync( FORM, dir, '_expected', profile.format + '.js.map' ).toString() );
								} catch ( err ) {}

								assert.equal( actualCode, expectedCode );
								assert.deepEqual( actualMap, expectedMap );

								if ( config.solo ) console.groupEnd();
							});
						});
					});
				});
			});
		});
	});

	describe( 'sourcemaps', function () {
		sander.readdirSync( SOURCEMAPS ).sort().forEach( function ( dir ) {
			if ( dir[0] === '.' ) return; // .DS_Store...

			describe( dir, function () {
				var config = require( SOURCEMAPS + '/' + dir + '/_config' );

				var options = extend( {}, config.options, {
					entry: SOURCEMAPS + '/' + dir + '/main.js'
				});

				var bundlePromise = rollup.rollup( options );

				PROFILES.forEach( function ( profile ) {
					( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () {
						return bundlePromise.then( function ( bundle ) {
							var result = bundle.generate({
								format: profile.format,
								sourceMap: true,
								sourceMapFile: 'bundle.js'
							});

							config.test( result.code, result.map );
						});
					});
				});
			});
		});
	});

	describe( 'cli', function () {
		sander.readdirSync( CLI ).sort().forEach( function ( dir ) {
			if ( dir[0] === '.' ) return; // .DS_Store...

			describe( dir, function () {
				var config = require( CLI + '/' + dir + '/_config' );

				( config.skip ? it.skip : config.solo ? it.only : it )( dir, function ( done ) {
					process.chdir( path.resolve( CLI, dir ) );

					exec( config.command, {
						env: {
							PATH: path.resolve( __dirname, '../bin' ) + ':' + process.env.PATH
						}
					}, function ( err, code, stderr ) {
						if ( err ) return done( err );

						if ( stderr ) console.error( stderr );

						var unintendedError;

						if ( config.execute ) {
							try {
								if ( config.babel ) {
									code = babel.transform( code, {
										whitelist: config.babel
									}).code;
								}

								var fn = new Function( 'require', 'module', 'exports', 'assert', code );
								var module = {
									exports: {}
								};
								fn( require, module, module.exports, assert );

								if ( config.error ) {
									unintendedError = new Error( 'Expected an error while executing output' );
								}

								if ( config.exports ) {
									config.exports( module.exports );
								}
							} catch ( err ) {
								if ( config.error ) {
									config.error( err );
								} else {
									unintendedError = err;
								}
							}

							if ( config.show || unintendedError ) {
								console.log( code + '\n\n\n' );
							}

							if ( config.solo ) console.groupEnd();

							unintendedError ? done( unintendedError ) : done();
						}
					});
				});
			});
		});
	});
});
<|endoftext|>


<commit_before>define(['require', 'exports', './cli-parser/js/parser.js', './stream', './events', './pipeSeq'], function(require, exports, cliParser, Stream, events, pipeSeq) {
	var PipeSequence = pipeSeq.PipeSequence;
	var CLIParser = cliParser.Parser;
	var EventEmitter = events.EventEmitter;

	var inherits = function(ctor, superCtor) {
	  ctor.super_ = superCtor;
	  ctor.prototype = Object.create(superCtor.prototype, {
		constructor: {
		  value: ctor,
		  enumerable: false,
		  writable: true,
		  configurable: true
		}
	  });
	};

	var merge = function merge(dest, source) {
		for(key in source) {
			dest[key] = source[key];
		}

		return dest;
	};

	var CommandRunner = exports.CommandRunner = (function() {
		function CommandRunner(terminal) {
			this.terminal = terminal;
			this.env = this.terminal.env;
			this.commandParser = new CommandParser(this.env);
			this.fs = this.terminal.fs;

			EventEmitter.call(this);
		}

		inherits(CommandRunner, EventEmitter);

		CommandRunner.prototype.pipeTo = function pipeTo(from, to) {
			for(pipeName in from) {
				if(to[pipeName] && from[pipeName]) {
					from[pipeName].pipe(to[pipeName]);
				}
			}
		};

		CommandRunner.prototype.run = function run(cmd, curDir, cb, /* internal */ sendMessage) {
			var cmdFiles, cmds, runContext, curPipeSeq, startSeq, allowRun, /*runCmd, pipes, tmpPipes, nextPipes, pipeList, toPipes,*/ rtnCode, self;

			self = this;
			cmds = this.commandParser.parse(cmd, function(cmdLine, env, execCmd) {
				var output = '';
				self.run(cmdLine, curDir, function(context) {
					context.data.on('data', function(d) {
						output += d;
					});
				}, false);

				return output;
			});
			cmdFiles = cmds.map(function(cmd) {
				return merge(cmd, { file: self.terminal.findCMD(cmd.args[0], curDir), args: cmd.args.slice(1), name: cmd.args[0] });
			});
			runContext = this.terminal.createRunContext(cmdFiles, ( sendMessage === false ? true : false ));

			for(i = 0; i < cmdFiles.length; i++) {
				curFile = cmdFiles[i];

				if(curFile.joiner == '|') {
					if(!curPipeSeq) {
						curPipeSeq = new PipeSequence();
						curPipeSeq.push(cmdFiles[i - 1]);
						startSeq = i - 1;
					}

					curPipeSeq.push(curFile);
				} else if(curPipeSeq) {
					cmdFiles.splice(startSeq, i - startSeq, curPipeSeq);
					curPipeSeq = undefined;
					startSeq = undefined;
				}
			}

			if(curPipeSeq) {
				cmdFiles.splice(startSeq, cmdFiles.length, curPipeSeq);
				curPipeSeq = undefined;
				startSeq = undefined;
			}

			for(i = 0; i < cmdFiles.length; i++) {
				allowRun = true;

				if(cmdFiles[i].joiner == '&&') allowRun = rtnCode == 0;
				else if(cmdFiles[i].joiner == '||') allowRun = rtnCode != 0;

				if(allowRun) {
					rtnCode = this.exec(cmdFiles[i], undefined, undefined, runContext);
				}
			}

			return rtnCode;
		};

		CommandRunner.prototype.exec = function exec(obj, args, context, runContext) {
			if(obj) {
				if(obj.file && this.fs.isExec(obj.file)) return this.execFile(obj.file, obj.args || args, context || runContext.createCMDContext(obj, { filePipes: obj.pipes || {} }));
				else if(obj instanceof PipeSequence || typeof(obj.run) == 'function') return obj.run(this, runContext, args, context);
			}
		};

		CommandRunner.prototype.execFile = function execFile(file, args, context) {
			var exitCode = 0;

			if(!this.fs.isExec(file)) return new Error("Not executable");

			try {
				if(file.command && typeof(file.command.exec) == 'function') {
					exitCode = file.command.exec(args, context);
				} else if(file.contents && file.contents.length && file.contents.length > 0) {
					console.log('shell:', this.fs.pathTo(file), this.run(file.contents));
					exitCode = 0;
				}
			} catch(e) {
				console.error('shell:', this.fs.pathTo(file), e, e.message, e.stack);
				exitCode = 1;
			}

			context.setExitCode(exitCode || 0);

			return exitCode || 0;
		};

		return CommandRunner;
	})();

	var CommandParser = exports.CommandParser = (function() {
		function CommandParser(env) {
			this.env = env;
			this.cliParser = new CLIParser();
		}

		CommandParser.prototype.parseFileStreams = function parseFileStreams(cmd) {
			var str, pipes, chars, curChar;

			pipes = {};
			chars = cmd.split('');

			/*function replaceCommands(str, pipes) {
				cmd.replace(/(\\\\|[^\\])(([\>\<])?([12])?([\>\<])\s*([\w\d\.\$]+))/g, function($A, $1, $2, $3, $4, $5, $6) {
					if($3 == $5 || $3.length != 1) {
//						console.log(arguments);
						pipes[$4 || '1'] = $6;

						return $1;
					}

					return $A;
				});

				return { str: str, pipes: pipes };
			}

			str = replaceCommands(cmd, pipes).str;*/

			var inPipeName, inStr, startPipe, fileName, inFileName, pipeName, appending, pipeDir;

			for(var i = 0; i < chars.length; i++) {
				curChar = chars[i];

				if(curChar == '"' || curChar == "'" && (chars[i - 1] != '\\' || chars[i - 2] == '\\')) {
					if(inStr == curChar) {
						inStr = undefined;
					} else {
						inStr = curChar;
					}
				} else if(!inStr) {
					if(curChar == '>' || curChar == '<' && (chars[i - 1] != '\\' || chars[i - 2] == '\\')) {
						if(!inPipeName) {
							inPipeName = curChar;
							startPipe = i;
							pipeDir = curChar;
						} else if(inPipeName == curChar) {
							if(chars[i - 1] == inPipeName) {
								appending = true;
							} else {
								console.log(chars.slice(startPipe, i).join(''));
								pipeName = chars.slice(startPipe + 1, i).join('');
								inPipeName = undefined;
								inFileName = true;
								fileName = undefined;
							}
						}
					} else if(/^[\w\d\.\/]$/.test(curChar) && inFileName) {
						fileName = fileName ? fileName + curChar : curChar;
					} else if(/^\s$/.test(curChar) && fileName && inFileName) { // End of filename
						console.log(pipeName || (/^[12]$/.test(chars[startPipe - 1]) ? chars[startPipe - 1] : '1'), 'goes to', fileName, 'and is' + ( !!appending ? '' : ' not' ), 'appending');
						pipes[pipeName || (/^[12]$/.test(chars[startPipe - 1]) ? chars[startPipe - 1] : '1')] = { fileName: fileName, appending: !!appending, dir: pipeDir };
//						chars.splice(startPipe - ( /^\d$/.test(chars[startPipe - 1]) ? 1 : 0),

						// Remove the pipe
						startRemove = startPipe - ( /^\d$/.test(chars[startPipe - 1]) ? 1 : 0);
						endRemove = i;
						chars.splice(startRemove, endRemove - startRemove);
						// End remove pipe

						fileName = undefined;
						pipeName = undefined;
						inFileName = undefined;
					} else if(inPipeName && /^\s$/.test(curChar)) {
						inPipeName = undefined;
						inFileName = true;
						i = startPipe;
					}

					if(i == chars.length - 1) {
						if(inPipeName) {
							inPipeName = undefined;
							inFileName = true;
							i = startPipe;
						} else if(inFileName && fileName) {
							console.log(pipeName || (/^[12]$/.test(chars[startPipe - 1]) ? chars[startPipe - 1] : '1'), 'goes to', fileName, 'and is' + ( !!appending ? '' : ' not' ), 'appending');
							pipes[pipeName || (/^[12]$/.test(chars[startPipe - 1]) ? chars[startPipe - 1] : '1')] = { fileName: fileName, appending: !!appending, dir: pipeDir };

							// Remove the pipe
							startRemove = startPipe - ( /^\d$/.test(chars[startPipe - 1]) ? 1 : 0);
							endRemove = i + 1;
							chars.splice(startRemove, endRemove - startRemove);
							// End remove pipe

							fileName = undefined;
							pipeName = undefined;
							inFileName = undefined;
						}
					}
				}
			}

			//console.log(pipes, fileName, { inPipeName: inPipeName, inFileName: inFileName, inStr: inStr, startPipe: startPipe, fileName: fileName, pipeName: pipeName });

			return { pipedStr: chars.join(''), pipes: pipes };
		};

		CommandParser.prototype.splitCommands = function splitCommand(cmdLine) {
			var curChar, splits, i, inStr, split, chars, curSplit;

			splits = [];
			split = [];
			chars = cmdLine.split('');

			for(i = 0; i < cmdLine.length; i++) {
				curChar = chars[i];

				if(!inStr && (curChar == '"' || curChar == "'")) {
					inStr = curChar;
				} else if(curChar == inStr) {
					inStr = undefined;
				} else if(!inStr && (chars[i - 1] != '\\' || chars[i - 2] == '\\')) {
					if(/^(?:\&|\|)$/.test(curChar) && chars[i + 1] == curChar) {
						splits.push({ type: curChar + chars[i + 1], index: i });
						i++;
					} else if(/^(?:\;|\||\n)$/.test(curChar)) {
						splits.push({ type: curChar, index: i });
					}
				} else if((i > 0 ? chars[i - 1] == '\\' : false) && (i > 1 ? chars[i - 2] != '\\' : true) && curChar == '\n') {
					chars.splice(i - 1, 1);
					i--;
				}
			}

			for(i = 0; i < splits.length; i++) {
				curSplit = splits[i];

				split.push({ str: chars.slice(i > 0 ? splits[i - 1].index + splits[i - 1].type.length : 0, curSplit.index).join('').trim(), joiner: i > 0 ? splits[i - 1].type : '^' });
			}

			split.push({ str: chars.slice(!!curSplit ? curSplit.index + curSplit.type.length : 0).join('').trim(), joiner: curSplit ? curSplit.type : '^' });

			return split;
		};

		CommandParser.prototype.parse = function parse(cmdLine, execCmd) {
			var cmds, self;

			self = this;
			cmds = this.splitCommands(cmdLine);

			return cmds.map(function(cmd) {
				return merge(merge(cmd, { str: cmd.str }), self.parseFileStreams(cmd.str));
			}).map(function(cmd) {
				return merge(cmd, { args: self.cliParser.parse(cmd.pipedStr, self.env.vars, execCmd) });
			}).filter(function(cmd) {
				return cmd.str && cmd.str.length > 0 && cmd.joiner && cmd.joiner.length > 0 && cmd.args && cmd.args.length > 0;
			});
		};

		return CommandParser;
	})();
});
<commit_msg>Fix append bug where it sends one of the >s into the file<commit_after>define(['require', 'exports', './cli-parser/js/parser.js', './stream', './events', './pipeSeq'], function(require, exports, cliParser, Stream, events, pipeSeq) {
	var PipeSequence = pipeSeq.PipeSequence;
	var CLIParser = cliParser.Parser;
	var EventEmitter = events.EventEmitter;

	var inherits = function(ctor, superCtor) {
	  ctor.super_ = superCtor;
	  ctor.prototype = Object.create(superCtor.prototype, {
		constructor: {
		  value: ctor,
		  enumerable: false,
		  writable: true,
		  configurable: true
		}
	  });
	};

	var merge = function merge(dest, source) {
		for(key in source) {
			dest[key] = source[key];
		}

		return dest;
	};

	var CommandRunner = exports.CommandRunner = (function() {
		function CommandRunner(terminal) {
			this.terminal = terminal;
			this.env = this.terminal.env;
			this.commandParser = new CommandParser(this.env);
			this.fs = this.terminal.fs;

			EventEmitter.call(this);
		}

		inherits(CommandRunner, EventEmitter);

		CommandRunner.prototype.pipeTo = function pipeTo(from, to) {
			for(pipeName in from) {
				if(to[pipeName] && from[pipeName]) {
					from[pipeName].pipe(to[pipeName]);
				}
			}
		};

		CommandRunner.prototype.run = function run(cmd, curDir, cb, /* internal */ sendMessage) {
			var cmdFiles, cmds, runContext, curPipeSeq, startSeq, allowRun, /*runCmd, pipes, tmpPipes, nextPipes, pipeList, toPipes,*/ rtnCode, self;

			self = this;
			cmds = this.commandParser.parse(cmd, function(cmdLine, env, execCmd) {
				var output = '';
				self.run(cmdLine, curDir, function(context) {
					context.data.on('data', function(d) {
						output += d;
					});
				}, false);

				return output;
			});
			cmdFiles = cmds.map(function(cmd) {
				return merge(cmd, { file: self.terminal.findCMD(cmd.args[0], curDir), args: cmd.args.slice(1), name: cmd.args[0] });
			});
			runContext = this.terminal.createRunContext(cmdFiles, ( sendMessage === false ? true : false ));

			for(i = 0; i < cmdFiles.length; i++) {
				curFile = cmdFiles[i];

				if(curFile.joiner == '|') {
					if(!curPipeSeq) {
						curPipeSeq = new PipeSequence();
						curPipeSeq.push(cmdFiles[i - 1]);
						startSeq = i - 1;
					}

					curPipeSeq.push(curFile);
				} else if(curPipeSeq) {
					cmdFiles.splice(startSeq, i - startSeq, curPipeSeq);
					curPipeSeq = undefined;
					startSeq = undefined;
				}
			}

			if(curPipeSeq) {
				cmdFiles.splice(startSeq, cmdFiles.length, curPipeSeq);
				curPipeSeq = undefined;
				startSeq = undefined;
			}

			for(i = 0; i < cmdFiles.length; i++) {
				allowRun = true;

				if(cmdFiles[i].joiner == '&&') allowRun = rtnCode == 0;
				else if(cmdFiles[i].joiner == '||') allowRun = rtnCode != 0;

				if(allowRun) {
					rtnCode = this.exec(cmdFiles[i], undefined, undefined, runContext);
				}
			}

			return rtnCode;
		};

		CommandRunner.prototype.exec = function exec(obj, args, context, runContext) {
			if(obj) {
				if(obj.file && this.fs.isExec(obj.file)) return this.execFile(obj.file, obj.args || args, context || runContext.createCMDContext(obj, { filePipes: obj.pipes || {} }));
				else if(obj instanceof PipeSequence || typeof(obj.run) == 'function') return obj.run(this, runContext, args, context);
			}
		};

		CommandRunner.prototype.execFile = function execFile(file, args, context) {
			var exitCode = 0;

			if(!this.fs.isExec(file)) return new Error("Not executable");

			try {
				if(file.command && typeof(file.command.exec) == 'function') {
					exitCode = file.command.exec(args, context);
				} else if(file.contents && file.contents.length && file.contents.length > 0) {
					console.log('shell:', this.fs.pathTo(file), this.run(file.contents));
					exitCode = 0;
				}
			} catch(e) {
				console.error('shell:', this.fs.pathTo(file), e, e.message, e.stack);
				exitCode = 1;
			}

			context.setExitCode(exitCode || 0);

			return exitCode || 0;
		};

		return CommandRunner;
	})();

	var CommandParser = exports.CommandParser = (function() {
		function CommandParser(env) {
			this.env = env;
			this.cliParser = new CLIParser();
		}

		CommandParser.prototype.parseFileStreams = function parseFileStreams(cmd) {
			var str, pipes, chars, curChar;

			pipes = {};
			chars = cmd.split('');

			/*function replaceCommands(str, pipes) {
				cmd.replace(/(\\\\|[^\\])(([\>\<])?([12])?([\>\<])\s*([\w\d\.\$]+))/g, function($A, $1, $2, $3, $4, $5, $6) {
					if($3 == $5 || $3.length != 1) {
//						console.log(arguments);
						pipes[$4 || '1'] = $6;

						return $1;
					}

					return $A;
				});

				return { str: str, pipes: pipes };
			}

			str = replaceCommands(cmd, pipes).str;*/

			var inPipeName, inStr, startPipe, fileName, inFileName, pipeName, appending, pipeDir;

			for(var i = 0; i < chars.length; i++) {
				curChar = chars[i];

				if(curChar == '"' || curChar == "'" && (chars[i - 1] != '\\' || chars[i - 2] == '\\')) {
					if(inStr == curChar) {
						inStr = undefined;
					} else {
						inStr = curChar;
					}
				} else if(!inStr) {
					if(curChar == '>' || curChar == '<' && (chars[i - 1] != '\\' || chars[i - 2] == '\\')) {
						if(!inPipeName) {
							inPipeName = curChar;
							startPipe = i;
							pipeDir = curChar;
						} else if(inPipeName == curChar) {
							if(chars[i - 1] == inPipeName) {
								appending = true;
							} else {
								console.log(chars.slice(startPipe, i).join(''));
								pipeName = chars.slice(startPipe + 1, i).join('');
								inPipeName = undefined;
								inFileName = true;
								fileName = undefined;
							}
						}
					} else if(/^[\w\d\.\/]$/.test(curChar) && inFileName) {
						fileName = fileName ? fileName + curChar : curChar;
					} else if(/^\s$/.test(curChar) && fileName && inFileName) { // End of filename
						console.log(pipeName || (/^[12]$/.test(chars[startPipe - 1]) ? chars[startPipe - 1] : '1'), 'goes to', fileName, 'and is' + ( !!appending ? '' : ' not' ), 'appending');
						pipes[pipeName || (/^[12]$/.test(chars[startPipe - 1]) ? chars[startPipe - 1] : '1')] = { fileName: fileName, appending: !!appending, dir: pipeDir };
//						chars.splice(startPipe - ( /^\d$/.test(chars[startPipe - 1]) ? 1 : 0),

						// Remove the pipe
						startRemove = startPipe - ( /^\d$/.test(chars[startPipe - 1]) ? 1 : 0);
						endRemove = i;
						chars.splice(startRemove, endRemove - startRemove);
						// End remove pipe

						fileName = undefined;
						pipeName = undefined;
						inFileName = undefined;
					} else if(inPipeName && /^\s$/.test(curChar)) {
						inPipeName = undefined;
						inFileName = true;
						i = ( appending ? 1 : 0 ) + startPipe;
					}

					if(i == chars.length - 1) {
						if(inPipeName) {
							inPipeName = undefined;
							inFileName = true;
							i = startPipe;
						} else if(inFileName && fileName) {
							console.log(pipeName || (/^[12]$/.test(chars[startPipe - 1]) ? chars[startPipe - 1] : '1'), 'goes to', fileName, 'and is' + ( !!appending ? '' : ' not' ), 'appending');
							pipes[pipeName || (/^[12]$/.test(chars[startPipe - 1]) ? chars[startPipe - 1] : '1')] = { fileName: fileName, appending: !!appending, dir: pipeDir };

							// Remove the pipe
							startRemove = startPipe - ( /^\d$/.test(chars[startPipe - 1]) ? 1 : 0);
							endRemove = i + 1;
							chars.splice(startRemove, endRemove - startRemove);
							// End remove pipe

							fileName = undefined;
							pipeName = undefined;
							inFileName = undefined;
						}
					}
				}
			}

			//console.log(pipes, fileName, { inPipeName: inPipeName, inFileName: inFileName, inStr: inStr, startPipe: startPipe, fileName: fileName, pipeName: pipeName });

			return { pipedStr: chars.join(''), pipes: pipes };
		};

		CommandParser.prototype.splitCommands = function splitCommand(cmdLine) {
			var curChar, splits, i, inStr, split, chars, curSplit;

			splits = [];
			split = [];
			chars = cmdLine.split('');

			for(i = 0; i < cmdLine.length; i++) {
				curChar = chars[i];

				if(!inStr && (curChar == '"' || curChar == "'")) {
					inStr = curChar;
				} else if(curChar == inStr) {
					inStr = undefined;
				} else if(!inStr && (chars[i - 1] != '\\' || chars[i - 2] == '\\')) {
					if(/^(?:\&|\|)$/.test(curChar) && chars[i + 1] == curChar) {
						splits.push({ type: curChar + chars[i + 1], index: i });
						i++;
					} else if(/^(?:\;|\||\n)$/.test(curChar)) {
						splits.push({ type: curChar, index: i });
					}
				} else if((i > 0 ? chars[i - 1] == '\\' : false) && (i > 1 ? chars[i - 2] != '\\' : true) && curChar == '\n') {
					chars.splice(i - 1, 1);
					i--;
				}
			}

			for(i = 0; i < splits.length; i++) {
				curSplit = splits[i];

				split.push({ str: chars.slice(i > 0 ? splits[i - 1].index + splits[i - 1].type.length : 0, curSplit.index).join('').trim(), joiner: i > 0 ? splits[i - 1].type : '^' });
			}

			split.push({ str: chars.slice(!!curSplit ? curSplit.index + curSplit.type.length : 0).join('').trim(), joiner: curSplit ? curSplit.type : '^' });

			return split;
		};

		CommandParser.prototype.parse = function parse(cmdLine, execCmd) {
			var cmds, self;

			self = this;
			cmds = this.splitCommands(cmdLine);

			return cmds.map(function(cmd) {
				return merge(merge(cmd, { str: cmd.str }), self.parseFileStreams(cmd.str));
			}).map(function(cmd) {
				return merge(cmd, { args: self.cliParser.parse(cmd.pipedStr, self.env.vars, execCmd) });
			}).filter(function(cmd) {
				return cmd.str && cmd.str.length > 0 && cmd.joiner && cmd.joiner.length > 0 && cmd.args && cmd.args.length > 0;
			});
		};

		return CommandParser;
	})();
});
<|endoftext|>