<commit_before>function Doc() {
  require('colors');
  this.bot = null;
  this.arguments = [];
  this.botConfigured = null;
  this.api = {};

  this.extractArguments();
  this.loadBot();
  this.loadDoc();
  this.showDoc();
}

Doc.prototype.extractArguments = function(){
  if(process.argv.indexOf('-h') !== -1 || process.argv.indexOf('--help') !== -1) {
    this.showHelp();
  }

  this.bot = process.argv[2] || null;

  var countArguments = process.argv.length;
  for(var i = 3; i < countArguments; i++) {
    this.arguments.push(process.argv[i].toLowerCase());
  }
};

Doc.prototype.showHelp = function() {
  console.log("\n" + 'API Endpoints Description');

  console.log("\n" + 'Usage:');
  console.log("    " + 'node doc <application>                                 list all endpoints');
  console.log("    " + 'node doc <application> <http_method>                   list all endpoints using given method');
  console.log("    " + 'node doc <application> <endpoint_url>                  endpoint detail');
  console.log("    " + 'node doc <application> <http_method> <endpoint_url>    endpoint detail using given method');
  console.log("    " + 'node doc <application> parameters                      list all parameters');

  console.log("\n" + 'Options:');
  console.log("    " + 'application    use specific application network');
  console.log("    " + 'http_method    get, post, patch, delete');
  console.log("    " + 'endpoint_url   /v1/me/');

  process.exit(1);
};

Doc.prototype.loadBot = function() {
  if(this.bot === null) {
    this.stopProcess('Bot required');
  }
  this.botConfigured = require('./rmasterbot').getBot(this.bot);
};

Doc.prototype.loadDoc = function() {
  this.api = require(this.botConfigured.docsFolder + 'api.js');
};

Doc.prototype.showDoc = function() {
  var i;

  if(this.arguments.length < 1) {
    for (i = 0; i < api.endpoints.length; i++) {
      this.displayEndpoint(api.endpoints[i]);
    }
    return;
  }

  if(this.arguments[0] === 'get') {
    if(this.arguments.length < 2) {
      for (i = 0; i < api.endpoints.length; i++) {
        if(api.endpoints[i].method === 'get') {
          this.displayEndpoint(api.endpoints[i]);
        }
      }
    }
    else {
      for (i = 0; i < api.endpoints.length; i++) {
        if(api.endpoints[i].url === this.arguments[1]) {
          this.displayDetailsEndpoint(api.endpoints[i]);
          return;
        }
      }
    }
  }
  else if(this.arguments[0] === 'post') {
    if(this.arguments.length < 2) {
      for (i = 0; i < api.endpoints.length; i++) {
        if(api.endpoints[i].method === 'post') {
          this.displayEndpoint(api.endpoints[i]);
        }
      }
    }
    else {
      for (i = 0; i < api.endpoints.length; i++) {
        if(api.endpoints[i].url === this.arguments[1]) {
          this.displayDetailsEndpoint(api.endpoints[i]);
          return;
        }
      }
    }
  }
  else if(this.arguments[0] === 'parameters') {
    for (i = 0; i < api.parameters.length; i++) {
      this.displayParameters(api.parameters[i]);
    }
  }
  else {
    for (i = 0; i < api.endpoints.length; i++) {
      if(api.endpoints[i].url === this.arguments[0]) {
        this.displayDetailsEndpoint(api.endpoints[i]);
        return;
      }
    }

    console.log('endpoint not found');
  }
};

Doc.prototype.displayEndpoint = function(endpoint) {
  console.log(endpoint.method.toUpperCase().green + ' ' + endpoint.url.magenta + ' ' + endpoint.description);
};

Doc.prototype.displayDetailsEndpoint = function(endpoint) {
  console.log(endpoint.method.toUpperCase().green + ' ' + endpoint.url.magenta + "\nScope: ".cyan + endpoint.scope + "\nDescription: ".cyan + endpoint.description);

  this.displayParametersRequired(endpoint.parameters.required);
  this.displayParametersOptionnal(endpoint.parameters.optionnal);
};

Doc.prototype.displayParametersRequired = function(parameters) {
  if(parameters.length === 0) {
    return;
  }

  console.log("\n"+'Parameters required:');
  for (var i = 0; i < parameters.length; i++) {
    if(typeof parameters[i] === 'string') {
      for (var j = 0; j < api.parameters.length; j++) {
        if(parameters[i] === api.parameters[j].name) {
          this.displayParameters(api.parameters[j]);
        }
      }
    }
    else {
      this.displayParameters(parameters[i]);
    }
  }
};

Doc.prototype.displayParametersOptionnal = function(parameters) {
  if(parameters.length === 0) {
    return;
  }

  console.log("\n"+'Parameters optionnal:');
  for (var i = 0; i < parameters.length; i++) {
    if(typeof parameters[i] === 'string') {
      for (var j = 0; j < api.parameters.length; j++) {
        if(parameters[i] === api.parameters[j].name) {
          this.displayParameters(api.parameters[j]);
        }
      }
    }
    else {
      this.displayParameters(parameters[i]);
    }
  }
};

Doc.prototype.displayParameters = function(params) {
  console.log(params.name.yellow + ' (' + params.type + ') -> ' + params.description);
};

Doc.prototype.stopProcess = function(exception) {
  require('npmlog').error('DOC', exception);
  process.exit(-1);
};

new Doc();<commit_msg>fix doc.js typo in object parameters<commit_after>function Doc() {
  require('colors');
  this.bot = null;
  this.arguments = [];
  this.botConfigured = null;
  this.api = {};

  this.extractArguments();
  this.loadBot();
  this.loadDoc();
  this.showDoc();
}

Doc.prototype.extractArguments = function(){
  if(process.argv.indexOf('-h') !== -1 || process.argv.indexOf('--help') !== -1) {
    this.showHelp();
  }

  this.bot = process.argv[2] || null;

  var countArguments = process.argv.length;
  for(var i = 3; i < countArguments; i++) {
    this.arguments.push(process.argv[i].toLowerCase());
  }
};

Doc.prototype.showHelp = function() {
  console.log("\n" + 'API Endpoints Description');

  console.log("\n" + 'Usage:');
  console.log("    " + 'node doc <application>                                 list all endpoints');
  console.log("    " + 'node doc <application> <http_method>                   list all endpoints using given method');
  console.log("    " + 'node doc <application> <endpoint_url>                  endpoint detail');
  console.log("    " + 'node doc <application> <http_method> <endpoint_url>    endpoint detail using given method');
  console.log("    " + 'node doc <application> parameters                      list all parameters');

  console.log("\n" + 'Options:');
  console.log("    " + 'application    use specific application network');
  console.log("    " + 'http_method    get, post, patch, delete');
  console.log("    " + 'endpoint_url   /v1/me/');

  process.exit(1);
};

Doc.prototype.loadBot = function() {
  if(this.bot === null) {
    this.stopProcess('Bot required');
  }
  this.botConfigured = require('./rmasterbot').getBot(this.bot);
};

Doc.prototype.loadDoc = function() {
  this.api = require(this.botConfigured.docsFolder + 'api.js');
};

Doc.prototype.showDoc = function() {
  var i;

  if(this.arguments.length < 1) {
    for (i = 0; i < api.endpoints.length; i++) {
      this.displayEndpoint(api.endpoints[i]);
    }
    return;
  }

  if(this.arguments[0] === 'get') {
    if(this.arguments.length < 2) {
      for (i = 0; i < api.endpoints.length; i++) {
        if(api.endpoints[i].method === 'get') {
          this.displayEndpoint(api.endpoints[i]);
        }
      }
    }
    else {
      for (i = 0; i < api.endpoints.length; i++) {
        if(api.endpoints[i].url === this.arguments[1]) {
          this.displayDetailsEndpoint(api.endpoints[i]);
          return;
        }
      }
    }
  }
  else if(this.arguments[0] === 'post') {
    if(this.arguments.length < 2) {
      for (i = 0; i < api.endpoints.length; i++) {
        if(api.endpoints[i].method === 'post') {
          this.displayEndpoint(api.endpoints[i]);
        }
      }
    }
    else {
      for (i = 0; i < api.endpoints.length; i++) {
        if(api.endpoints[i].url === this.arguments[1]) {
          this.displayDetailsEndpoint(api.endpoints[i]);
          return;
        }
      }
    }
  }
  else if(this.arguments[0] === 'parameters') {
    for (i = 0; i < api.parameters.length; i++) {
      this.displayParameters(api.parameters[i]);
    }
  }
  else {
    for (i = 0; i < api.endpoints.length; i++) {
      if(api.endpoints[i].url === this.arguments[0]) {
        this.displayDetailsEndpoint(api.endpoints[i]);
        return;
      }
    }

    console.log('endpoint not found');
  }
};

Doc.prototype.displayEndpoint = function(endpoint) {
  console.log(endpoint.method.toUpperCase().green + ' ' + endpoint.url.magenta + ' ' + endpoint.description);
};

Doc.prototype.displayDetailsEndpoint = function(endpoint) {
  console.log(endpoint.method.toUpperCase().green + ' ' + endpoint.url.magenta + "\nScope: ".cyan + endpoint.scope + "\nDescription: ".cyan + endpoint.description);

  this.displayParametersRequired(endpoint.parameters.required);
  this.displayParametersOptional(endpoint.parameters.optional);
};

Doc.prototype.displayParametersRequired = function(parameters) {
  if(parameters.length === 0) {
    return;
  }

  console.log("\n"+'Parameters required:');
  for (var i = 0; i < parameters.length; i++) {
    if(typeof parameters[i] === 'string') {
      for (var j = 0; j < api.parameters.length; j++) {
        if(parameters[i] === api.parameters[j].name) {
          this.displayParameters(api.parameters[j]);
        }
      }
    }
    else {
      this.displayParameters(parameters[i]);
    }
  }
};

Doc.prototype.displayParametersOptional = function(parameters) {
  if(parameters.length === 0) {
    return;
  }

  console.log("\n"+'Parameters optional:');
  for (var i = 0; i < parameters.length; i++) {
    if(typeof parameters[i] === 'string') {
      for (var j = 0; j < api.parameters.length; j++) {
        if(parameters[i] === api.parameters[j].name) {
          this.displayParameters(api.parameters[j]);
        }
      }
    }
    else {
      this.displayParameters(parameters[i]);
    }
  }
};

Doc.prototype.displayParameters = function(params) {
  console.log(params.name.yellow + ' (' + params.type + ') -> ' + params.description);
};

Doc.prototype.stopProcess = function(exception) {
  require('npmlog').error('DOC', exception);
  process.exit(-1);
};

new Doc();<|endoftext|>


<commit_before>// DSS Object
var dss = ( function () {

  // Store reference
  var _dss = function (){};

  // Default detect function
  _dss.detect = function () {
    return true;
  };

  /*
   * Modify detector method
   *
   * @param (Function) The callback to be used to detect variables
   */
  _dss.detector = function ( callback ) {

    _dss.detect = callback;

  };

  // Store parsers
  _dss.parsers = {};

  /*
   * Add a parser for a specific variable
   *
   * @param (String) The name of the variable
   * @param (Function) The callback to be executed at parse time
   */
  _dss.parser = function ( name, callback ) {
    _dss.parsers[ name ] = callback;
  };

  /*
   * Add an alias for a parser
   *
   * @param (String) The name of the new variable
   * @param (String) The name of the existing parser to use
   */
  _dss.alias = function(newName, oldName){
    _dss.parsers[newName] = _dss.parsers[oldName];
  };

  /*
   * Trim whitespace from string
   *
   * @param (String) The string to be trimmed
   * @return (String) The trimmed string
   */
  _dss.trim = function ( str, arr ) {
    var defaults = [ /^\s\s*/, /\s\s*$/ ];
    arr = ( _dss.isArray( arr ) ) ? arr.concat( defaults ) : defaults;
    arr.forEach( function( regEx ) {
      str = str.replace( regEx, '' );
    });
    return str;
  };

  /*
   * Check if object is an array
   *
   * @param (Object) The object to check
   * @return (Boolean) The result of the test
   */
  _dss.isArray = function ( obj ) {
    return toString.call( obj ) == '[object Array]';
  };

  /*
   * Check the size of an object
   *
   * @param (Object) The object to check
   * @return (Boolean) The result of the test
   */
  _dss.size = function(obj){
    var size = 0;
    for(var key in obj){
      if(Object.prototype.hasOwnProperty.call(obj, key))
        size++;
    }
    return size;
  };

  /*
   * Iterate over an object
   *
   * @param (Object) The object to iterate over
   * @param (Function) Callback function to use when iterating
   * @param (Object) Optional context to pass to iterator
   */
  _dss.each = function(obj, iterator, context){
    if(obj == null) return;
    if(obj.length === +obj.length){
      for(var i = 0, l = obj.length; i < l; i++){
        if(iterator.call(context, obj[i], i, obj) === {}) return;
      }
    } else {
      for(var key in obj){
        if(_.has(obj, key)){
          if(iterator.call(context, obj[key], key, obj) === {}) return;
        }
      }
    }
  };

  /*
   * Extend an object
   *
   * @param (Object) The object to extend
   */
  _dss.extend = function(obj){
    _dss.each(Array.prototype.slice.call(arguments, 1), function(source){
      if(source){
        for(var prop in source){
          obj[prop] = source[prop];
        }
      }
    });
    return obj;
  };

  /*
   * Squeeze unnecessary extra characters/string
   *
   * @param (String) The string to be squeeze
   * @param (String) The string to be matched
   * @return (String) The modified string
   */
  _dss.squeeze = function(str, def){
    return str.replace(/\s{2,}/g, def);
  };

  /*
   * Normalizes the comment block to ignore any consistent preceding
   * whitespace. Consistent means the same amount of whitespace on every line
   * of the comment block. Also strips any whitespace at the start and end of
   * the whole block.
   *
   * @param (String) Text block
   * @return (String) A cleaned up text block
   */
  _dss.normalize = function(text_block){

    // Strip out any preceding [whitespace]* that occur on every line. Not
    // the smartest, but I wonder if I care.
    text_block = text_block.replace(/^(\s*\*+)/, '');

    // Strip consistent indenting by measuring first line's whitespace
    var indent_size = false;
    var unindented = (function(lines){
      return lines.map(function(line){
        var preceding_whitespace = line.match(/^\s*/)[0].length;
        if(!indent_size)
          indent_size = preceding_whitespace;
        if(line == ''){
          return '';
        } else if(indent_size <= preceding_whitespace && indent_size > 0){
          return line.slice(indent_size, (line.length - 1));
        } else {
          return line;
        }
      }).join("\n");
    })(text_block.split("\n"));

    return _dss.trim(text_block);

  };

  /*
   * Takes a file and extracts comments from it.
   *
   * @param (Object) options
   * @param (Function) callback
   */
  _dss.parse = function(lines, options, callback){

    // Options
    options = (options) ? options : {};
    options.preserve_whitespace = !!(options.preserve_whitespace);

    // Setup
    var _this = this,
        current_block = '',
        inside_single_line_block = false,
        inside_multi_line_block = false,
        last_line = '',
        start = "{start}",
        end = "{/end}",
        _parsed = false,
        _blocks = [],
        parsed = '',
        blocks = [],
        temp = {},
        lineNum = 0;

    /*
     * Parses line
     *
     * @param (Num) the line number
     * @param (Num) number of lines
     * @param (String) line to parse/check
     * @return (Boolean) result of parsing
     */
    var parser = function(temp, line, block, file){
      var indexer = function(str, find){
            return (str.indexOf(find) > 0) ? str.indexOf(find) : false;
          },
          parts = line.replace(/.*@/, ''),
          i = indexer(parts, ' ') || indexer(parts, '\n') || indexer(parts, '\r') || parts.length,
          name = _dss.trim(parts.substr(0, i)),
          description = _dss.trim(parts.substr(i)),
          variable = _dss.parsers[name],
          index = block.indexOf(line);
      line = {};
      line[name] = (variable) ? variable.apply(null, [index, description, block, file, name]) : '';

      if(temp[name]){
        if(!_dss.isArray(temp[name]))
          temp[name] = [ temp[name] ];
        temp[name].push(line[name]);
      } else {
        temp = _dss.extend(temp, line);
      }
      return temp;
    };

    /*
     * Comment block
     */
    var block = function(){
      this._raw = (comment_text) ? comment_text : '';
      this._filename = filename;
    };

    /*
     * Check for single-line comment
     *
     * @param (String) line to parse/check
     * @return (Boolean) result of check
     */
    var single_line_comment = function(line){
      return !!line.match(/^\s*\/\//);
    };

    /*
     * Checks for start of a multi-line comment
     *
     * @param (String) line to parse/check
     * @return (Boolean) result of check
     */
    var start_multi_line_comment = function(line){
      return !!line.match(/^\s*\/\*/);
    };

    /*
     * Check for end of a multi-line comment
     *
     * @parse (String) line to parse/check
     * @return (Boolean) result of check
     */
    var end_multi_line_comment = function(line){
      if(single_line_comment(line))
        return false;
      return !!line.match(/.*\*\//);
    };

    /*
     * Removes comment identifiers for single-line comments.
     *
     * @param (String) line to parse/check
     * @return (Boolean) result of check
     */
    var parse_single_line = function(line){
      return line.replace(/\s*\/\//, '');
    };

    /*
     * Remove comment identifiers for multi-line comments.
     *
     * @param (String) line to parse/check
     * @return (Boolean) result of check
     */
    var parse_multi_line = function(line){
      var cleaned = line.replace(/\s*\/\*/, '');
      return cleaned.replace(/\*\//, '');
    };

    lines = lines + '';
    lines.split(/\n/).forEach(function(line){

      lineNum = lineNum + 1;
      line = line + '';

      // Parse Single line comment
      if(single_line_comment(line)){
        parsed = parse_single_line(line);
        if(inside_single_line_block){
          current_block += '\n' + parsed;
        } else {
          current_block = parsed;
          inside_single_line_block = true;
        }
      }

      // Parse multi-line comments
      if(start_multi_line_comment(line) || inside_multi_line_block){
        parsed = parse_multi_line(line);
        if(inside_multi_line_block){
          current_block += '\n' + parsed;
        } else {
          current_block += parsed;
          inside_multi_line_block = true;
        }
      }

      // End a multi-line block
      if(end_multi_line_comment(line)){
        inside_multi_line_block = false;
      }

      // Store current block if done
      if(!single_line_comment(line) && !inside_multi_line_block){
        if(current_block){
          _blocks.push(_dss.normalize(current_block));
        }
        inside_single_line_block = false;
        current_block = '';
        last_line = '';
      }

    });

    // Done first pass
    _parsed = true;

    // Create new blocks with custom parsing
    _blocks.forEach(function(block){

      // Remove extra whitespace
      block = block.split('\n').filter(function(line){
        return (_dss.trim(_dss.normalize(line)));
      }).join('\n');

      // Split block into lines
      block.split('\n').forEach(function(line){
        if(_dss.detect(line))
          temp = parser(temp, _dss.normalize(line), block, lines);
      });

      // Push to blocks if object isn't empty
      if(_dss.size(temp))
        blocks.push(temp);
      temp = {};

    });

    // Execute callback with filename and blocks
    callback({ blocks: blocks });

  };

  // Return function
  return _dss;

})();

// Describe detection pattern
dss.detector(function(line){
  if(typeof line !== 'string')
    return false;
  var reference = line.split("\n\n").pop();
  return !!reference.match(/.*@/);
});

// Describe parsing a name
dss.parser('name', function(i, line, block, file){
  return line;
});

// Describe parsing a description
dss.parser('description', function(i, line, block, file){
  return line;
});

// Describe parsing a state
dss.parser('state', function(i, line, block, file){
  var state = line.split(' - ');
  return {
    name: (state[0]) ? dss.trim(state[0]) : '',
    escaped: (state[0]) ? dss.trim(state[0].replace('.', ' ').replace(':', ' pseudo-class-')) : '',
    description: (state[1]) ? dss.trim(state[1]) : ''
  };
});

// Describe parsing markup
dss.parser('markup', function(i, line, block, file, parserName){

  // find the next instance of a parser (if there is one based on the @ symbol)
  // in order to isolate the current multi-line parser
  var nextParserIndex = block.indexOf('* @', i+1),
      markupLength = nextParserIndex > -1 ? nextParserIndex - i : block.length,
      markup = block.split('').splice(i, markupLength).join(''),
      parserMarker = '@' + parserName;

  markup = (function(markup){
    var ret = [],
        lines = markup.split('\n');

    lines.forEach(function(line){
      var pattern = '*',
          index = line.indexOf(pattern);

      if (index > 0 && index < 10)
        line = line.split('').splice((index + pattern.length), line.length).join('');

      // multiline
      if (lines.length <= 2)
        line = dss.trim(line);

      if (line && line.indexOf( parserMarker ) == -1)
        ret.push(line);

    });
    return ret.join('\n');
  })(markup);

  return {
    example: markup,
    escaped: markup.replace(/</g, '<').replace(/>/g, '>')
  };
});

// Module exports
if(typeof exports !== 'undefined'){
  if(typeof module !== 'undefined' && module.exports){
    exports = module.exports = dss;
  }
  exports.dss = dss;
} else {
  root['dss'] = dss;
}

// AMD definition
if (typeof define === 'function' && define.amd){
  define(function(require){
    return dss;
  });
}
<commit_msg>Cleaned up syntax<commit_after>// DSS Object
var dss = ( function () {

  // Store reference
  var _dss = function () {};

  // Default detect function
  _dss.detect = function () {
    return true;
  };

  /*
   * Modify detector method
   *
   * @param (Function) The callback to be used to detect variables
   */
  _dss.detector = function ( callback ) {
    _dss.detect = callback;
  };

  // Store parsers
  _dss.parsers = {};

  /*
   * Add a parser for a specific variable
   *
   * @param (String) The name of the variable
   * @param (Function) The callback to be executed at parse time
   */
  _dss.parser = function ( name, callback ) {
    _dss.parsers[ name ] = callback;
  };

  /*
   * Add an alias for a parser
   *
   * @param (String) The name of the new variable
   * @param (String) The name of the existing parser to use
   */
  _dss.alias = function ( newName, oldName ) {
    _dss.parsers[ newName ] = _dss.parsers[ oldName ];
  };

  /*
   * Trim whitespace from string
   *
   * @param (String) The string to be trimmed
   * @return (String) The trimmed string
   */
  _dss.trim = function ( str, arr ) {
    var defaults = [ /^\s\s*/, /\s\s*$/ ];
    arr = ( _dss.isArray( arr ) ) ? arr.concat( defaults ) : defaults;
    arr.forEach( function( regEx ) {
      str = str.replace( regEx, '' );
    } );
    return str;
  };

  /*
   * Check if object is an array
   *
   * @param (Object) The object to check
   * @return (Boolean) The result of the test
   */
  _dss.isArray = function ( obj ) {
    return toString.call( obj ) == '[object Array]';
  };

  /*
   * Check the size of an object
   *
   * @param (Object) The object to check
   * @return (Boolean) The result of the test
   */
  _dss.size = function ( obj ) {
    var size = 0;
    for ( var key in obj ) {
      if ( Object.prototype.hasOwnProperty.call( obj, key ) )
        size++;
    }
    return size;
  };

  /*
   * Iterate over an object
   *
   * @param (Object) The object to iterate over
   * @param (Function) Callback function to use when iterating
   * @param (Object) Optional context to pass to iterator
   */
  _dss.each = function ( obj, iterator, context ) {
    if ( obj == null ) {
      return;
    }
    if ( obj.length === +obj.length ) {
      for ( var i = 0, l = obj.length; i < l; i++ ) {
        if ( iterator.call( context, obj[ i ], i, obj ) === {} ) {
          return;
        }
      }
    } else {
      for ( var key in obj ) {
        if ( _.has( obj, key ) ) {
          if ( iterator.call( context, obj[ key ], key, obj ) === {} ) {
            return;
          }
        }
      }
    }
  };

  /*
   * Extend an object
   *
   * @param (Object) The object to extend
   */
  _dss.extend = function ( obj ) {
    _dss.each( Array.prototype.slice.call( arguments, 1 ), function ( source ) {
      if ( source ) {
        for ( var prop in source ) {
          obj[ prop ] = source[ prop ];
        }
      }
    });
    return obj;
  };

  /*
   * Squeeze unnecessary extra characters/string
   *
   * @param (String) The string to be squeeze
   * @param (String) The string to be matched
   * @return (String) The modified string
   */
  _dss.squeeze = function ( str, def ) {
    return str.replace( /\s{2,}/g, def );
  };

  /*
   * Normalizes the comment block to ignore any consistent preceding
   * whitespace. Consistent means the same amount of whitespace on every line
   * of the comment block. Also strips any whitespace at the start and end of
   * the whole block.
   *
   * @param (String) Text block
   * @return (String) A cleaned up text block
   */
  _dss.normalize = function ( text_block ) {

    // Strip out any preceding [whitespace]* that occur on every line. Not
    // the smartest, but I wonder if I care.
    text_block = text_block.replace( /^(\s*\*+)/, '' );

    // Strip consistent indenting by measuring first line's whitespace
    var indent_size = false;
    var unindented = ( function ( lines ) {
      return lines.map( function ( line ) {
        var preceding_whitespace = line.match( /^\s*/ )[ 0 ].length;
        if ( !indent_size ) {
          indent_size = preceding_whitespace;
        }
        if ( line == '' ) {
          return '';
        } else if ( indent_size <= preceding_whitespace && indent_size > 0 ) {
          return line.slice( indent_size, ( line.length - 1 ) );
        } else {
          return line;
        }
      } ).join( "\n" );
    } )( text_block.split( "\n" ) );

    return _dss.trim( text_block );

  };

  /*
   * Takes a file and extracts comments from it.
   *
   * @param (Object) options
   * @param (Function) callback
   */
  _dss.parse = function ( lines, options, callback ) {

    // Options
    options = ( options ) ? options : {};
    options.preserve_whitespace = !!( options.preserve_whitespace );

    // Setup
    var _this = this;
    var current_block = '';
    var inside_single_line_block = false;
    var inside_multi_line_block = false;
    var last_line = '';
    var start = "{start}";
    var end = "{/end}";
    var _parsed = false;
    var _blocks = [];
    var parsed = '';
    var blocks = [];
    var temp = {};
    var lineNum = 0;

    /*
     * Parses line
     *
     * @param (Num) the line number
     * @param (Num) number of lines
     * @param (String) line to parse/check
     * @return (Boolean) result of parsing
     */
    var parser = function ( temp, line, block, file ) {
      var indexer = function ( str, find ) {
        return ( str.indexOf( find ) > 0 ) ? str.indexOf( find ) : false;
      };
      var parts = line.replace( /.*@/, '' );
      var i = indexer( parts, ' ' ) || indexer( parts, '\n' ) || indexer( parts, '\r' ) || parts.length;
      var name = _dss.trim( parts.substr( 0, i ) );
      var description = _dss.trim( parts.substr( i ) );
      var variable = _dss.parsers[ name ];
      var index = block.indexOf( line );
      line = {};
      line[ name ] = ( variable ) ? variable.apply( null, [ index, description, block, file, name ] ) : '';
      if ( temp[ name ] ) {
        if ( !_dss.isArray( temp[ name ] ) ) {
          temp[name] = [ temp[ name ] ];
        }
        temp[ name ].push( line[ name ] );
      } else {
        temp = _dss.extend( temp, line );
      }
      return temp;
    };

    /*
     * Comment block
     */
    var block = function () {
      this._raw = ( comment_text ) ? comment_text : '';
      this._filename = filename;
    };

    /*
     * Check for single-line comment
     *
     * @param (String) line to parse/check
     * @return (Boolean) result of check
     */
    var single_line_comment = function ( line ) {
      return !!line.match( /^\s*\/\// );
    };

    /*
     * Checks for start of a multi-line comment
     *
     * @param (String) line to parse/check
     * @return (Boolean) result of check
     */
    var start_multi_line_comment = function ( line ) {
      return !!line.match( /^\s*\/\*/ );
    };

    /*
     * Check for end of a multi-line comment
     *
     * @parse (String) line to parse/check
     * @return (Boolean) result of check
     */
    var end_multi_line_comment = function ( line ) {
      if( single_line_comment( line ) ) {
        return false;
      }
      return !!line.match( /.*\*\// );
    };

    /*
     * Removes comment identifiers for single-line comments.
     *
     * @param (String) line to parse/check
     * @return (Boolean) result of check
     */
    var parse_single_line = function ( line ) {
      return line.replace( /\s*\/\//, '' );
    };

    /*
     * Remove comment identifiers for multi-line comments.
     *
     * @param (String) line to parse/check
     * @return (Boolean) result of check
     */
    var parse_multi_line = function ( line ) {
      var cleaned = line.replace( /\s*\/\*/, '' );
      return cleaned.replace( /\*\//, '' );
    };

    lines = lines + '';
    lines.split( /\n/ ).forEach( function ( line ) {

      lineNum = lineNum + 1;
      line = line + '';

      // Parse Single line comment
      if ( single_line_comment( line ) ) {
        parsed = parse_single_line( line );
        if ( inside_single_line_block ) {
          current_block += '\n' + parsed;
        } else {
          current_block = parsed;
          inside_single_line_block = true;
        }
      }

      // Parse multi-line comments
      if ( start_multi_line_comment( line ) || inside_multi_line_block ) {
        parsed = parse_multi_line( line );
        if ( inside_multi_line_block ) {
          current_block += '\n' + parsed;
        } else {
          current_block += parsed;
          inside_multi_line_block = true;
        }
      }

      // End a multi-line block
      if ( end_multi_line_comment( line ) ) {
        inside_multi_line_block = false;
      }

      // Store current block if done
      if ( !single_line_comment( line ) && !inside_multi_line_block ) {
        if ( current_block ) {
          _blocks.push( _dss.normalize( current_block ) );
        }
        inside_single_line_block = false;
        current_block = '';
        last_line = '';
      }

    });

    // Done first pass
    _parsed = true;

    // Create new blocks with custom parsing
    _blocks.forEach( function ( block ) {

      // Remove extra whitespace
      block = block.split( '\n' ).filter( function ( line ) {
        return ( _dss.trim( _dss.normalize( line ) ) );
      } ).join( '\n' );

      // Split block into lines
      block.split( '\n' ).forEach( function ( line ) {
        if ( _dss.detect( line ) ) {
          temp = parser( temp, _dss.normalize( line ), block, lines );
        }
      });

      // Push to blocks if object isn't empty
      if( _dss.size( temp ) ) {
        blocks.push( temp );
      }
      temp = {};

    });

    // Execute callback with filename and blocks
    callback( { blocks: blocks } );

  };

  // Return function
  return _dss;

})();

// Describe detection pattern
dss.detector( function( line ) {
  if( typeof line !== 'string' ) {
    return false;
  }
  var reference = line.split( "\n\n" ).pop();
  return !!reference.match( /.*@/ );
});

// Describe parsing a name
dss.parser( 'name', function ( i, line, block, file ) {
  return line;
});

// Describe parsing a description
dss.parser( 'description', function ( i, line, block, file ) {
  return line;
});

// Describe parsing a state
dss.parser( 'state', function ( i, line, block, file ) {
  var state = line.split( ' - ' );
  return {
    name: ( state[ 0 ] ) ? dss.trim( state[ 0 ] ) : '',
    escaped: ( state[ 0 ] ) ? dss.trim( state[ 0 ].replace( '.', ' ' ).replace( ':', ' pseudo-class-' ) ) : '',
    description: ( state[ 1 ] ) ? dss.trim( state[ 1 ] ) : ''
  };
});

// Describe parsing markup
dss.parser( 'markup', function ( i, line, block, file, parserName ) {

  // find the next instance of a parser (if there is one based on the @ symbol)
  // in order to isolate the current multi-line parser
  var nextParserIndex = block.indexOf( '* @', i + 1 );
  var markupLength = ( nextParserIndex > -1 ) ? nextParserIndex - i : block.length;
  var markup = block.split( '' ).splice( i, markupLength ).join( '' );
  var parserMarker = '@' + parserName;

  markup = ( function( markup ) {
    var ret = [];
    var lines = markup.split( '\n' );

    lines.forEach( function( line ) {
      var pattern = '*';
      var index = line.indexOf( pattern );

      if ( index > 0 && index < 10 ) {
        line = line.split( '' ).splice( ( index + pattern.length ), line.length ).join( '' );
      }

      // multiline
      if ( lines.length <= 2 ) {
        line = dss.trim( line );
      }

      if ( line && line.indexOf( parserMarker ) == -1 ) {
        ret.push( line );
      }

    });

    return ret.join( '\n' );

  })( markup );

  return {
    example: markup,
    escaped: markup.replace( /</g, '<' ).replace( />/g, '>' )
  };

});

// Module exports
if( typeof exports !== 'undefined' ) {
  if ( typeof module !== 'undefined' && module.exports ) {
    exports = module.exports = dss;
  }
  exports.dss = dss;
} else {
  root[ 'dss' ] = dss;
}

// AMD definition
if ( typeof define === 'function' && define.amd ) {
  define( function ( require ) {
    return dss;
  });
}
<|endoftext|>


<commit_before>let base = require('./ts')

module.exports = {
  ...base,
  plugins: [...base.plugins],
  rules: {
    ...base.rules,
    'unicorn/prefer-module': 'error',
    'import/extensions': [
      'error',
      'always',
      {
        ignorePackages: true
      }
    ]
  },
  overrides: [
    ...base.overrides,
    {
      files: '*.cjs',
      rules: {
        'unicorn/prefer-module': 'off'
      }
    }
  ]
}
<commit_msg>Add note to enable unicorn/prefer-node-protocol on ESLint 8 release<commit_after>let base = require('./ts')

module.exports = {
  ...base,
  plugins: [...base.plugins],
  rules: {
    ...base.rules,
    // 'unicorn/prefer-node-protocol': 'error',
    'unicorn/prefer-module': 'error',
    'import/extensions': [
      'error',
      'always',
      {
        ignorePackages: true
      }
    ]
  },
  overrides: [
    ...base.overrides,
    {
      files: '*.cjs',
      rules: {
        'unicorn/prefer-module': 'off'
      }
    }
  ]
}
<|endoftext|>


<commit_before>(function () {
	var myConnector = tableau.makeConnector();
	myConnector.init = function (initCallback) {
		initCallback();
		tableau.authType = tableau.authTypeEnum.custom;
		if (tableau.username) {
			var connectionData = JSON.parse(tableau.username);
			$('#txtReportPath').val(connectionData.reportPath);
			$('#selectEndpoint').val(connectionData.endpoint);
			$('#selectMaxRows').val(connectionData.maxRows);
			if (connectionData.apikey) {
				$('#txtApiKey').val(connectionData.apikey);
			} else {
				$('#chkRemember').prop('checked',false);
			}
		}
		if (tableau.phase == tableau.phaseEnum.authPhase) {
			if (tableau.username && tableau.password)
				tableau.submit();
		}
	}

	myConnector.getSchema = function (schemaCallback) {
		var connectionData = JSON.parse(tableau.username);
		$.ajax({
			url: connectionData.endpoint +
				'?path=' + connectionData.reportPath,
			type: "GET",
			beforeSend: function(xhr) { xhr.setRequestHeader('Authorization', 'apikey ' + tableau.password) },
			success: function(data) {
				var $xml = $( data );
				var elements = $('xsd\\:element, element', $xml);
				var cols = [];
				elements.each(function(){
					var $entry = $(this);
					cols.push( {
						id: $entry.attr('name'),
						alias: $entry.attr('saw-sql:columnHeading') || $entry.attr('name'),
						dataType: mapDt($entry.attr('type'))
					});
					// TODO: fact vs dimension?
				})

				var tableInfo = {
					id: "exl_" + connectionData.reportName.toLowerCase().replace(/\W+/g, "_"),
					alias: connectionData.reportName,
					columns: cols
				};

				schemaCallback([tableInfo]);
			}
		});
	};

	myConnector.getData = function(table, doneCallback) {
		getData(null, function(data) {
			console.log('Data retrieved. Total rows', data.length);
			table.appendRows(data);
			doneCallback();
		});
	};

	tableau.registerConnector(myConnector);

	$(document).ready(function () {
		$("#submitButton").click(function () {
			var reportPath = $('#txtReportPath').val();
			if (reportPath.indexOf('/') >= 0) reportPath = encodeURIComponent(reportPath);
			var connectionData = {
				endpoint: $('#selectEndpoint').val(),
				reportPath: reportPath,
				reportName: decodeURIComponent(reportPath).substring(decodeURIComponent(reportPath).lastIndexOf('/')+1),
				maxRows: $('#selectMaxRows').val()
			};
			if ($('#chkRemember').prop('checked') ) {
				connectionData.apikey = $('#txtApiKey').val();
			}
			tableau.username = JSON.stringify(connectionData);
			tableau.password = $('#txtApiKey').val();
			tableau.connectionName = "ExLibris";
			tableau.submit();
		});
	});

})();

function mapDt(val) {
	var types = {
		"xsd:int": tableau.dataTypeEnum.int,
		"xsd:string": tableau.dataTypeEnum.string,
		"xsd:double": tableau.dataTypeEnum.float,
		"xsd:bool": tableau.dataTypeEnum.bool,
		"xsd:date": tableau.dataTypeEnum.date
	};

	var type = types[val];
	if (!type) type = tableau.dataTypeEnum.string;
	return type;
}

var tableData;

function getData(resumptionToken, callback) {
	var connectionData = JSON.parse(tableau.username);
	var url = connectionData.endpoint;
	if (resumptionToken) {
		url = url + '?token=' + resumptionToken;
	} else {
		url = url + '?path=' + connectionData.reportPath;
		tableData = [];
	}
	console.log('Calling url', url);
	$.ajax({
		url: url,
		type: "POST",
		cache: false,
		beforeSend: function(xhr) { xhr.setRequestHeader('Authorization', 'apikey ' + tableau.password) },
		success: function(data) {
			var $xml = $( data );
			var token = resumptionToken || $('ResumptionToken', $xml).text();
			var rows = $('Row', $xml);
			rows.each(function(){
				var $entry = $(this);
				var obj = {};
				$entry.children().each(function() {
					obj[this.nodeName] = $(this).text();
				});
				tableData.push(obj);
			});
			console.log('Added rows to data table. Total', tableData.length);
			tableau.reportProgress("Getting row: " + tableData.length);
			if ($('IsFinished', $xml).text() == 'false' && tableData.length < connectionData.maxRows) {
				getData(token, callback);
			} else {
				callback(tableData);
			}
		}
	});
}
<commit_msg>removed additional initCallback info<commit_after>(function () {
	var myConnector = tableau.makeConnector();

	myConnector.getSchema = function (schemaCallback) {
		var connectionData = JSON.parse(tableau.username);
		$.ajax({
			url: connectionData.endpoint +
				'?path=' + connectionData.reportPath,
			type: "GET",
			beforeSend: function(xhr) { xhr.setRequestHeader('Authorization', 'apikey ' + tableau.password) },
			success: function(data) {
				var $xml = $( data );
				var elements = $('xsd\\:element, element', $xml);
				var cols = [];
				elements.each(function(){
					var $entry = $(this);
					cols.push( {
						id: $entry.attr('name'),
						alias: $entry.attr('saw-sql:columnHeading') || $entry.attr('name'),
						dataType: mapDt($entry.attr('type'))
					});
					// TODO: fact vs dimension?
				})

				var tableInfo = {
					id: "exl_" + connectionData.reportName.toLowerCase().replace(/\W+/g, "_"),
					alias: connectionData.reportName,
					columns: cols
				};

				schemaCallback([tableInfo]);
			}
		});
	};

	myConnector.getData = function(table, doneCallback) {
		getData(null, function(data) {
			console.log('Data retrieved. Total rows', data.length);
			table.appendRows(data);
			doneCallback();
		});
	};

	tableau.registerConnector(myConnector);

	$(document).ready(function () {
		$("#submitButton").click(function () {
			var reportPath = $('#txtReportPath').val();
			if (reportPath.indexOf('/') >= 0) reportPath = encodeURIComponent(reportPath);
			var connectionData = {
				endpoint: $('#selectEndpoint').val(),
				reportPath: reportPath,
				reportName: decodeURIComponent(reportPath).substring(decodeURIComponent(reportPath).lastIndexOf('/')+1),
				maxRows: $('#selectMaxRows').val()
			};
			if ($('#chkRemember').prop('checked') ) {
				connectionData.apikey = $('#txtApiKey').val();
			}
			tableau.username = JSON.stringify(connectionData);
			tableau.password = $('#txtApiKey').val();
			tableau.connectionName = "ExLibris";
			tableau.submit();
		});
	});

})();

function mapDt(val) {
	var types = {
		"xsd:int": tableau.dataTypeEnum.int,
		"xsd:string": tableau.dataTypeEnum.string,
		"xsd:double": tableau.dataTypeEnum.float,
		"xsd:bool": tableau.dataTypeEnum.bool,
		"xsd:date": tableau.dataTypeEnum.date
	};

	var type = types[val];
	if (!type) type = tableau.dataTypeEnum.string;
	return type;
}

var tableData;

function getData(resumptionToken, callback) {
	var connectionData = JSON.parse(tableau.username);
	var url = connectionData.endpoint;
	if (resumptionToken) {
		url = url + '?token=' + resumptionToken;
	} else {
		url = url + '?path=' + connectionData.reportPath;
		tableData = [];
	}
	console.log('Calling url', url);
	$.ajax({
		url: url,
		type: "POST",
		cache: false,
		beforeSend: function(xhr) { xhr.setRequestHeader('Authorization', 'apikey ' + tableau.password) },
		success: function(data) {
			var $xml = $( data );
			var token = resumptionToken || $('ResumptionToken', $xml).text();
			var rows = $('Row', $xml);
			rows.each(function(){
				var $entry = $(this);
				var obj = {};
				$entry.children().each(function() {
					obj[this.nodeName] = $(this).text();
				});
				tableData.push(obj);
			});
			console.log('Added rows to data table. Total', tableData.length);
			tableau.reportProgress("Getting row: " + tableData.length);
			if ($('IsFinished', $xml).text() == 'false' && tableData.length < connectionData.maxRows) {
				getData(token, callback);
			} else {
				callback(tableData);
			}
		}
	});
}
<|endoftext|>


<commit_before>/***********************
    Framework
***********************/

function Camera() {
    this.x = 0;
    this.y = 0;
}
Camera.prototype.start = function() {
    canvas.save();
    canvas.translate(0-this.x, 0-this.y);
};
Camera.prototype.end = function() {
    canvas.restore();
};

var SpriteManager = {
    camera: new Camera(),
    images:{},
    sprites:new Array(),
    add:function(name) {
        var path = name;

        // handle the case where we want a static URL
        if (name.indexOf("http") < 0)
            path = "content/" + name + ".png";

        // now initialize the image
        var img;
        if (name in this.images) {
            img = this.images[name];
        }
        else {
            img = new Image();
            img.src = path;

            this.images[name] = img;
        }

        // now create the sprite
        var sprite = new Sprite(name, img, game.width/2-img.width/2, game.height/2-img.height/2);
        this.sprites.push(sprite);

        return sprite;
    }  ,
    update:function() {
        for(var i=0;i<this.sprites.length;i++) {
            var sprite = this.sprites[i];
            sprite.update();
        }
    },
    draw:function() {
        this.camera.start();
        for(var i=0;i<this.sprites.length;i++) {
            var sprite = this.sprites[i];
            sprite.draw();
        }
        this.camera.end();
    }
};

function Sprite(name, img, x, y) {
    this.name = name;
    this.img = img;
    this.width = img.width;
    this.height = img.height;
    this.x = x;
    this.y = y;
    this.xVelocity = 0;
    this.yVelocity = 0;
    this.xAcceleration = 0;
    this.yAcceleration = 0;
    this.zRotation = 0;
    this.zRotationAcceleration = 0;
    this.zRotationVelocity = 0;
}
Sprite.prototype.draw = function() {
    canvas.save();
    canvas.translate(this.x + this.width/2, this.y + this.height/2);
    canvas.rotate(this.zRotation);
    canvas.drawImage(this.img, this.width/-2,this.height/-2);

    canvas.restore();
};
Sprite.prototype.update = function() {
    this.x += this.xVelocity;
    this.y += this.yVelocity;
    this.xVelocity += this.xAcceleration;
    this.yVelocity += this.yAcceleration;

    this.zRotation += this.zRotationVelocity;
    this.zRotationVelocity += this.zRotationAcceleration;
};

/***********************
    Game initialization
***********************/
var game = {
    width:480,
    height:320,
    fps:30
};

var canvasElement = $("<canvas width='" + game.width +
                      "' height='" + game.height + "'></canvas>");
var canvas = canvasElement.get(0).getContext("2d");
canvasElement.appendTo('body');

function coreUpdate() {
    SpriteManager.update();
    update();
}

function coreDraw() {
    canvas.fillStyle ="#6495ED";
    canvas.fillRect(0, 0, game.width, game.height);

    SpriteManager.draw();
    draw();
}

setInterval(function() {
  coreUpdate();
  coreDraw();
}, 1000/game.fps);
<commit_msg>removed dependency on jQuery<commit_after>/***********************
    Framework
***********************/

function Camera() {
    this.x = 0;
    this.y = 0;
}
Camera.prototype.start = function() {
    canvas.save();
    canvas.translate(0-this.x, 0-this.y);
};
Camera.prototype.end = function() {
    canvas.restore();
};

var SpriteManager = {
    camera: new Camera(),
    images:{},
    sprites:new Array(),
    add:function(name) {
        var path = name;

        // handle the case where we want a static URL
        if (name.indexOf("http") < 0)
            path = "content/" + name + ".png";

        // now initialize the image
        var img;
        if (name in this.images) {
            img = this.images[name];
        }
        else {
            img = new Image();
            img.src = path;

            this.images[name] = img;
        }

        // now create the sprite
        var sprite = new Sprite(name, img, game.width/2-img.width/2, game.height/2-img.height/2);
        this.sprites.push(sprite);

        return sprite;
    }  ,
    update:function() {
        for(var i=0;i<this.sprites.length;i++) {
            var sprite = this.sprites[i];
            sprite.update();
        }
    },
    draw:function() {
        this.camera.start();
        for(var i=0;i<this.sprites.length;i++) {
            var sprite = this.sprites[i];
            sprite.draw();
        }
        this.camera.end();
    }
};

function Sprite(name, img, x, y) {
    this.name = name;
    this.img = img;
    this.width = img.width;
    this.height = img.height;
    this.x = x;
    this.y = y;
    this.xVelocity = 0;
    this.yVelocity = 0;
    this.xAcceleration = 0;
    this.yAcceleration = 0;
    this.zRotation = 0;
    this.zRotationAcceleration = 0;
    this.zRotationVelocity = 0;
}
Sprite.prototype.draw = function() {
    canvas.save();
    canvas.translate(this.x + this.width/2, this.y + this.height/2);
    canvas.rotate(this.zRotation);
    canvas.drawImage(this.img, this.width/-2,this.height/-2);

    canvas.restore();
};
Sprite.prototype.update = function() {
    this.x += this.xVelocity;
    this.y += this.yVelocity;
    this.xVelocity += this.xAcceleration;
    this.yVelocity += this.yAcceleration;

    this.zRotation += this.zRotationVelocity;
    this.zRotationVelocity += this.zRotationAcceleration;
};

/***********************
    Game initialization
***********************/

function coreUpdate() {
    SpriteManager.update();

    if (update && typeof(update) == "function")update();
}

function coreDraw() {
    canvas.fillStyle ="#6495ED";
    canvas.fillRect(0, 0, game.width, game.height);

    SpriteManager.draw();

    if (draw && typeof(draw) == "function")draw();
}

function r(f){/in/(document.readyState)?setTimeout(r,9,f):f()}
r(function(){
    // initialize the canvas
    var game = {
        width:480,
        height:320,
        fps:30
    };

    var canvasElement = $("<canvas width='" + game.width +
                          "' height='" + game.height + "'></canvas>");
    var canvas = canvasElement.get(0).getContext("2d");
    canvasElement.appendTo('body');

    // run the user's initialization code
    if (init && typeof(init) == "function") init();

    // set up the game loop
    setInterval(function() {
      coreUpdate();
      coreDraw();
    }, 1000/game.fps);
});

<|endoftext|>


<commit_before>//maintainRepo ensures our repo is being maintained and is updated
exports.maintainRepo = function (dir,url,callback) {
	var exec = require('child_process').exec;
	//Ensure git is installed
	var child = exec('command -v git',function(error,stdout,stderr) {
		if(error) {
			console.error('GIT IS NOT INSTALLED');
			process.exit(1);
		}
	});

	//File system maintenence
	var fs = require('fs');
	try {
		fs.mkdirSync(dir);
	} catch(error) {
		if(!error.code=='EEXIST') {
			console.error('Could not access ~/.cfi: '+error.message);
		}
	}

	//TODO: Handle errors for git. May not have permission for the specified directory
	var child = exec('git init '+dir, function(error, stdout,stderr) {
		var child = exec('git -c "'+dir+'" remote add origin '+url,function(error,stdout,stderr) {
			var child = exec('git -c "'+dir+'" reset --hard && git -c "'+dir+'" pull origin master',function(error,stdout,stderr) {
				if(!execResult(error,stdout,stderr)) {
					console.log('exec error: '+error);
				}
				callback();
			});
		});
	});
}

function execResult(error, stdout,stderr) {
	if(error!=null) {
		return false;
	}
	return true;
}
<commit_msg>Fixing case on -C<commit_after>//maintainRepo ensures our repo is being maintained and is updated
exports.maintainRepo = function (dir,url,callback) {
	var exec = require('child_process').exec;
	//Ensure git is installed
	var child = exec('command -v git',function(error,stdout,stderr) {
		if(error) {
			console.error('GIT IS NOT INSTALLED');
			process.exit(1);
		}
	});

	//File system maintenence
	var fs = require('fs');
	try {
		fs.mkdirSync(dir);
	} catch(error) {
		if(!error.code=='EEXIST') {
			console.error('Could not access ~/.cfi: '+error.message);
		}
	}

	//TODO: Handle errors for git. May not have permission for the specified directory
	var child = exec('git init '+dir, function(error, stdout,stderr) {
		var child = exec('git -C "'+dir+'" remote add origin '+url,function(error,stdout,stderr) {
			var child = exec('git -C "'+dir+'" reset --hard && git -C "'+dir+'" pull origin master',function(error,stdout,stderr) {
				if(!execResult(error,stdout,stderr)) {
					console.log('exec error: '+error);
				}
				callback();
			});
		});
	});
}

function execResult(error, stdout,stderr) {
	if(error!=null) {
		return false;
	}
	return true;
}
<|endoftext|>


<commit_before>define(function(require, module, exports) {
    main.consumes = [
        "c9", "Plugin", "run", "settings", "menus",
        "tabbehavior", "ace", "commands", "layout", "tabManager", "preferences",
        "ui", "fs", "layout", "output", "debugger", "tree"
    ];
    main.provides = ["run.gui"];
    return main;

    function main(options, imports, register) {
        var Plugin      = imports.Plugin;
        var settings    = imports.settings;
        var menus       = imports.menus;
        var commands    = imports.commands;
        var run         = imports.run;
        var c9          = imports.c9;
        var ui          = imports.ui;
        var fs          = imports.fs;
        var layout      = imports.layout;
        var tree        = imports.tree;
        var tabs        = imports.tabManager;
        var output      = imports.output;
        var tabbehavior = imports.tabbehavior;
        var debug       = imports.debugger;
        var prefs       = imports.preferences;
        var ace         = imports.ace;

        var cssString = require("text!./style.css");
        var basename  = require("path").basename;

        /***** Initialization *****/

        var plugin  = new Plugin("Ajax.org", main.consumes);
        var emit    = plugin.getEmitter();

        var btnRun, lastRun, process;

        var loaded = false;
        function load(){
            if (loaded) return false;
            loaded = true;

            // Commands
            commands.addCommand({
                name    : "run",
                group   : "Run & Debug",
                "hint"  : "run or debug an application",
                bindKey : { mac: "Option-F5", win: "Alt-F5" },
                exec    : function(){ runNow() }
            }, plugin);

            commands.addCommand({
                name    : "stop",
                group   : "Run & Debug",
                "hint"  : "stop a running node program on the server",
                bindKey : { mac: "Shift-F5", win: "Shift-F5" },
                exec    : function(){ stop(function(){}) }
            }, plugin);

            commands.addCommand({
                name    : "runthisfile",
                group   : "Run & Debug",
                "hint"  : "run or debug this file (stops the app if running)",
                exec    : function(){ runThisFile() }
            }, plugin);

            commands.addCommand({
                name    : "runthistab",
                group   : "Run & Debug",
                "hint"  : "run or debug current file (stops the app if running)",
                exec    : function(){ runThisTab() },
                isAvailable : function(){
                    return tabs.focussedTab && tabs.focussedTab.path;
                }
            }, plugin);

            commands.addCommand({
                name    : "runlast",
                group   : "Run & Debug",
                "hint"  : "run or debug the last run file",
                bindKey: { mac: "F5", win: "F5" },
                exec    : function(){ runLastFile() },
                isAvailable : function(){
                    return lastRun ? true : false;
                }
            }, plugin);

            // Tree context menu
            // Needs to be hidden in readonly mode
            var itemCtxTreeRunFile = new apf.item({
                id      : "itemCtxTreeRunFile",
                match   : "[file]",
                visible : "{!c9.readonly}",
                command : "runthisfile",
                caption : "Run"
            });
            tree.getElement("mnuCtxTree", function(mnuCtxTree) {
                menus.addItemToMenu(mnuCtxTree, new apf.divider({
                    visible: "{!c9.readonly}"
                }), 800, plugin);
                menus.addItemToMenu(mnuCtxTree, itemCtxTreeRunFile, 810, plugin);
            });

            // Check after state.change
            c9.on("stateChange", function(e){
                // @todo consider moving this to the run plugin
                if (itemCtxTreeRunFile)
                    itemCtxTreeRunFile.setAttribute("disabled", !(e.state & c9.PROCESS));
            }, plugin);

            // Menus
            var c = 1000;
            menus.setRootMenu("Run", 600, plugin);
            var itmRun = menus.addItemByPath("Run/Run", new ui.item({
                isAvailable : function(){
                    var tab = tabs.focussedTab;
                    var path = tab && tab.path;

                    if (process && process.running) {
                        itmRun.setAttribute("caption", "Stop");
                        itmRun.setAttribute("command", "stop");
                        return true;
                    }
                    else {
                        var runner = path && getRunner(path);
                        if (runner) {
                            itmRun.setAttribute("command", "run");
                            itmRun.setAttribute("caption", "Run "
                                + basename(path) + " with "
                                + runner.caption);
                            return true;
                        }
                        else {
                            itmRun.setAttribute("command", "run");
                            itmRun.setAttribute("caption", "Run");
                            return false;
                        }
                    }
                }
            }), c += 100, plugin);
            var itmRunLast = menus.addItemByPath("Run/Run Last", new ui.item({
                command     : "runlast",
                isAvailable : function(){
                    if (process && process.running || !lastRun) {
                        itmRunLast.setAttribute("caption", "Run Last");
                        return false;
                    }
                    else {
                        var runner = lastRun[0] == "auto"
                            ? getRunner(lastRun[1])
                            : lastRun[0];

                        itmRunLast.setAttribute("caption", "Run Last ("
                            + basename(lastRun[1]) + ", "
                            + (runner.caption || "auto") + ")");
                        return true;
                    }
                }
            }), c += 100, plugin);
            menus.addItemByPath("Run/Show Output Window", new ui.item({
                command: "showoutput"
            }), c += 100, plugin);
            menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);

            menus.addItemByPath("Run/Run in Debug Mode", new ui.item({
                type    : "check",
                checked : "[{settings.model}::user/runconfig/@debug]"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Enable Source Maps", new ui.item({
                type    : "check",
                checked : "[{settings.model}::project/debug/@sourcemaps]"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Show Debugger at Break", new ui.item({
                type    : "check",
                checked : "[{settings.model}::user/debug/@autoshow]"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Show Output at Run", new ui.item({
                type    : "check",
                checked : "[{settings.model}::user/runconfig/@showconsole]"
            }), c += 100, plugin);

            menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);

            var mnuRunAs = new ui.menu({
                "onprop.visible": function(e){
                    if (e.value) {
                        run.listRunners(function(err, names){
                            var nodes = mnuRunAs.childNodes;
                            for (var i = nodes.length - 3; i >= 0; i--) {
                                mnuRunAs.removeChild(nodes[i]);
                            }

                            var c = 300;
                            names.forEach(function(name){
                                menus.addItemToMenu(mnuRunAs, new ui.item({
                                    caption  : name.uCaseFirst(),
                                    value    : name
                                }), c++, plugin);
                            });
                        });
                    }
                },
                "onitemclick": function(e){
                    if (e.value == "new-run-system") {
                        tabs.open({
                            path   : settings.get("project/run/@path")
                              + "/New Runner",
                            active : true,
                            value  : '{\n'
                              + '    "caption" : "",\n'
                              + '    "cmd" : ["ls"],\n'
                              + '    "hint" : "",\n'
                              + '    "selector": "source.ext"\n'
                              + '}',
                            document : {
                                meta : {
                                    newfile: true
                                },
                                ace : {
                                    customType : "json"
                                }
                            }
                        }, function(){});
                        return;
                    }

                    run.getRunner(e.value, function(err, runner){
                        if (err)
                            return layout.showError(err);

                        runNow(runner);
                    });

                    settings.set("project/build/@builder", e.value);
                }
            });

            menus.addItemByPath("Run/Run With/", mnuRunAs,
                c += 100, plugin);
            menus.addItemByPath("Run/Run History/", new ui.item({
                isAvailable : function(){ return false; }
            }), c += 100, plugin);
            menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);

            menus.addItemByPath("Run/Run Configurations", new ui.item({
                isAvailable : function(){ return false; }
            }), c += 100, plugin);

            c = 0;
            menus.addItemByPath("Run/Run With/~", new ui.divider(), c += 1000, plugin);
            menus.addItemByPath("Run/Run With/New Runner", new ui.item({
                value : "new-run-system"
            }), c += 100, plugin);

            // Other Menus

            var itmRunFile1 = new apf.item({ command : "runthistab" });
            var itmRunFile2 = new apf.item({ command : "runthistab" });

            menus.addItemByPath("View/Tabs/Run This File", itmRunFile1, 400, plugin);
            menus.addItemByPath("View/Tabs/~", new apf.divider(), 300, plugin)

            tabbehavior.getElement("mnuContextTabs", function(mnuContextTabs){
                menus.addItemByPath("~", new apf.divider(), 800, mnuContextTabs, plugin);
                menus.addItemByPath("Run This File", itmRunFile2, 850, mnuContextTabs, plugin);
            });

            // Draw
            draw();

            // Hooks
            function updateRunFile(){
                itmRunFile1.setAttribute("disable", !tabs.focussedTab ||
                    !tabs.focussedTab.path || !process || !process.running);
                itmRunFile2.setAttribute("disable", !tabs.focussedTab ||
                    !tabs.focussedTab.path || !process || !process.running);
            }

            // run.on("starting", updateRunFile, plugin);
            // run.on("started", updateRunFile, plugin);
            run.on("stopped", updateRunFile, plugin);

            c9.on("stateChange", function(e){
                btnRun.setAttribute("disabled", !(e.state & c9.PROCESS));
            }, plugin);

            // Preferences
            prefs.add({
                "Run" : {
                    position : 600,
                    "Run & Debug" : {
                        position : 100,
                        "Save All Unsaved Tabs Before Running" : {
                           type : "checkbox",
                           path : "user/runconfig/@saveallbeforerun",
                           position : 100
                        }
                    }
                }
            }, plugin);

            // settings
            settings.on("read", function(e){
                settings.setDefaults("user/runconfig", [
                    ["saveallbeforerun", "false"],
                    ["debug", "true"],
                    ["showconsole", "true"],
                    ["showruncfglist", "false"]
                ]);
            }, plugin);

            tabs.on("focus", function(e){
                updateRunFile();

                if (process && process.running)
                    return;

                if (e.tab.path) {
                    btnRun.enable();
                    btnRun.setAttribute("tooltip", "Run "
                        + basename(e.tab.path));
                }
                else {
                    btnRun.disable();
                    btnRun.setAttribute("tooltip", "")
                }
            }, plugin);

            tabs.on("tabDestroy", function(e){
                updateRunFile();

                if (e.last) {
                    btnRun.disable();
                    btnRun.setAttribute("tooltip", "");
                }
            }, plugin);

            ace.getElement("menu", function(menu){
                menus.addItemToMenu(menu, new ui.item({
                    caption  : "Run This File",
                    command  : "runthistab",
                }), 800, plugin);
                menus.addItemToMenu(menu, new ui.divider(), 900, plugin);
            });
        };

        var drawn = false;
        function draw(){
            if (drawn) return;
            drawn = true;

            // Import CSS
            ui.insertCss(cssString, plugin);

            // Menus
            btnRun = ui.insertByIndex(layout.findParent(plugin),
              new ui.button({
                id       : "btnRun",
                skin     : "c9-toolbarbutton-glossy",
                command  : "run",
                caption  : "Run",
                disabled : true,
                icon     : "run.png",
                visible  : "true"
            }), 100, plugin);

            emit("draw");
        }

        /***** Methods *****/

        function getRunner(path){
            var ext = fs.getExtension(path);
            for (var name in run.runners) {
                if (run.runners[name].selector == "source." + ext)
                    return run.runners[name];
            }
            return false;
        }

        function runNow(runner, path){
            if (!path) {
                path = tabs.focussedTab && tabs.focussedTab.path;
                if (!path) return;
            }

            if (process && process.running)
                stop(done);
            else
                done();

            function done(){
                if (!runner)
                    runner = "auto";

                if (settings.getBool("user/runconfig/@showconsole")) {
                    commands.exec("showoutput");
                }

                var bDebug = settings.getBool("user/runconfig/@debug");

                process = run.run(runner, {
                    path  : path,
                    debug : bDebug
                }, function(err, pid){
                    if (err) {
                        transformButton();
                        process = null;
                        return layout.showError(err);
                    }

                    if (bDebug) {
                        debug.debug(process, function(err){
                            if (err)
                                return; // Either the debugger is not found or paused
                        });
                    }
                });

                process.on("stopping", function(){
                    btnRun.disable();
                }, plugin);

                process.on("stopped", function(){
                    btnRun.enable();

                    var path = transformButton();

                    if (path)
                        btnRun.enable();
                    else
                        btnRun.disable();
                }, plugin);

                transformButton("stop");
            }

            lastRun = [runner, path];
        }

        function transformButton(to){
            if (to == "stop") {
                btnRun.setAttribute("command", "stop");
                btnRun.setAttribute("icon", "stop.png");
                btnRun.setAttribute("caption", "Stop");
                btnRun.setAttribute("tooltip", "");
                btnRun.setAttribute("class", "running");
                btnRun.enable();
            }
            else {
                var path = tabs.focussedTab && tabs.focussedTab.path;

                btnRun.setAttribute("icon",
                    btnRun.checked ? "bug.png" : "run.png");
                btnRun.setAttribute("caption", "Run");
                btnRun.setAttribute("tooltip", (path
                    ? "Run " + basename(path)
                    : ""));
                btnRun.setAttribute("class", "stopped");
                btnRun.setAttribute("command", "run");

                return path;
            }
        }

        function stop(callback) {
            if (process)
                process.stop(function(err){
                    if (err) {
                        layout.showError(err.message || err);
                        transformButton();
                    }

                    debug.stop();

                    callback(err);
                });
        }

        function runLastFile(){
            if (lastRun)
                runNow.apply(this, lastRun);
        }

        function runThisFile() {
            var file = tree.selected;
            var node = this.addConfig(true, file);

            this.runConfig(node);
        }

        function runThisTab() {
            var file = ide.getActiveTabModel();
            var node = this.addConfig(true, file);

            this.runConfig(node);
        }

        function onHelpClick() {
            var tab = "running_and_debugging_code";
            if (ide.infraEnv)
                require("ext/docum" + "entation/documentation").show(tab);
            else
                window.open("https://docs.c9.io/" + tab + ".html");
        }

        /***** Lifecycle *****/

        plugin.on("load", function(){
            load();
        });
        plugin.on("enable", function(){

        });
        plugin.on("disable", function(){

        });
        plugin.on("unload", function(){
            loaded = false;
            drawn  = false;
        });

        /***** Register and define API *****/

        /**
         * UI for the {@link run} plugin. This plugin is responsible for the Run
         * menu in the main menu bar, as well as the settings and the
         * preferences UI for the run plugin.
         * @singleton
         */
        /**
         * @command run Runs the currently focussed tab.
         */
        /**
         * @command stop Stops the running process.
         */
        /**
         * @command runlast Stops the last run file
         */
        plugin.freezePublicAPI({

        });

        register(null, {
            "run.gui": plugin
        });
    }
});
<commit_msg>Fixes +239. Run via context menu now works<commit_after>define(function(require, module, exports) {
    main.consumes = [
        "c9", "Plugin", "run", "settings", "menus",
        "tabbehavior", "ace", "commands", "layout", "tabManager", "preferences",
        "ui", "fs", "layout", "output", "debugger", "tree"
    ];
    main.provides = ["run.gui"];
    return main;

    function main(options, imports, register) {
        var Plugin      = imports.Plugin;
        var settings    = imports.settings;
        var menus       = imports.menus;
        var commands    = imports.commands;
        var run         = imports.run;
        var c9          = imports.c9;
        var ui          = imports.ui;
        var fs          = imports.fs;
        var layout      = imports.layout;
        var tree        = imports.tree;
        var tabs        = imports.tabManager;
        var output      = imports.output;
        var tabbehavior = imports.tabbehavior;
        var debug       = imports.debugger;
        var prefs       = imports.preferences;
        var ace         = imports.ace;

        var cssString = require("text!./style.css");
        var basename  = require("path").basename;

        /***** Initialization *****/

        var plugin  = new Plugin("Ajax.org", main.consumes);
        var emit    = plugin.getEmitter();

        var btnRun, lastRun, process;

        var loaded = false;
        function load(){
            if (loaded) return false;
            loaded = true;

            // Commands
            commands.addCommand({
                name    : "run",
                group   : "Run & Debug",
                "hint"  : "run or debug an application",
                bindKey : { mac: "Option-F5", win: "Alt-F5" },
                exec    : function(){ runNow() }
            }, plugin);

            commands.addCommand({
                name    : "stop",
                group   : "Run & Debug",
                "hint"  : "stop a running node program on the server",
                bindKey : { mac: "Shift-F5", win: "Shift-F5" },
                exec    : function(){ stop(function(){}) }
            }, plugin);

            commands.addCommand({
                name    : "runlast",
                group   : "Run & Debug",
                "hint"  : "run or debug the last run file",
                bindKey: { mac: "F5", win: "F5" },
                exec    : function(){ runLastFile() },
                isAvailable : function(){
                    return lastRun ? true : false;
                }
            }, plugin);

            // Tree context menu
            // Needs to be hidden in readonly mode
            var itemCtxTreeRunFile = new apf.item({
                id      : "itemCtxTreeRunFile",
                match   : "[file]",
                visible : "{!c9.readonly}",
                caption : "Run",
                isAvailable : function(){
                    return tree.selectedNode && !tree.selectedNode.isFolder;
                },
                onclick : function(){
                    runNow("auto", tree.selected);
                }
            });
            tree.getElement("mnuCtxTree", function(mnuCtxTree) {
                menus.addItemToMenu(mnuCtxTree, new apf.divider({
                    visible: "{!c9.readonly}"
                }), 800, plugin);
                menus.addItemToMenu(mnuCtxTree, itemCtxTreeRunFile, 810, plugin);
            });

            // Check after state.change
            c9.on("stateChange", function(e){
                // @todo consider moving this to the run plugin
                if (itemCtxTreeRunFile)
                    itemCtxTreeRunFile.setAttribute("disabled", !(e.state & c9.PROCESS));
            }, plugin);

            // Menus
            var c = 1000;
            menus.setRootMenu("Run", 600, plugin);
            var itmRun = menus.addItemByPath("Run/Run", new ui.item({
                isAvailable : function(){
                    var tab = tabs.focussedTab;
                    var path = tab && tab.path;

                    if (process && process.running) {
                        itmRun.setAttribute("caption", "Stop");
                        itmRun.setAttribute("command", "stop");
                        return true;
                    }
                    else {
                        var runner = path && getRunner(path);
                        if (runner) {
                            itmRun.setAttribute("command", "run");
                            itmRun.setAttribute("caption", "Run "
                                + basename(path) + " with "
                                + runner.caption);
                            return true;
                        }
                        else {
                            itmRun.setAttribute("command", "run");
                            itmRun.setAttribute("caption", "Run");
                            return false;
                        }
                    }
                }
            }), c += 100, plugin);
            var itmRunLast = menus.addItemByPath("Run/Run Last", new ui.item({
                command     : "runlast",
                isAvailable : function(){
                    if (process && process.running || !lastRun) {
                        itmRunLast.setAttribute("caption", "Run Last");
                        return false;
                    }
                    else {
                        var runner = lastRun[0] == "auto"
                            ? getRunner(lastRun[1])
                            : lastRun[0];

                        itmRunLast.setAttribute("caption", "Run Last ("
                            + basename(lastRun[1]) + ", "
                            + (runner.caption || "auto") + ")");
                        return true;
                    }
                }
            }), c += 100, plugin);
            menus.addItemByPath("Run/Show Output Window", new ui.item({
                command: "showoutput"
            }), c += 100, plugin);
            menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);

            menus.addItemByPath("Run/Run in Debug Mode", new ui.item({
                type    : "check",
                checked : "[{settings.model}::user/runconfig/@debug]"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Enable Source Maps", new ui.item({
                type    : "check",
                checked : "[{settings.model}::project/debug/@sourcemaps]"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Show Debugger at Break", new ui.item({
                type    : "check",
                checked : "[{settings.model}::user/debug/@autoshow]"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Show Output at Run", new ui.item({
                type    : "check",
                checked : "[{settings.model}::user/runconfig/@showconsole]"
            }), c += 100, plugin);

            menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);

            var mnuRunAs = new ui.menu({
                "onprop.visible": function(e){
                    if (e.value) {
                        run.listRunners(function(err, names){
                            var nodes = mnuRunAs.childNodes;
                            for (var i = nodes.length - 3; i >= 0; i--) {
                                mnuRunAs.removeChild(nodes[i]);
                            }

                            var c = 300;
                            names.forEach(function(name){
                                menus.addItemToMenu(mnuRunAs, new ui.item({
                                    caption  : name.uCaseFirst(),
                                    value    : name
                                }), c++, plugin);
                            });
                        });
                    }
                },
                "onitemclick": function(e){
                    if (e.value == "new-run-system") {
                        tabs.open({
                            path   : settings.get("project/run/@path")
                              + "/New Runner",
                            active : true,
                            value  : '{\n'
                              + '    "caption" : "",\n'
                              + '    "cmd" : ["ls"],\n'
                              + '    "hint" : "",\n'
                              + '    "selector": "source.ext"\n'
                              + '}',
                            document : {
                                meta : {
                                    newfile: true
                                },
                                ace : {
                                    customType : "json"
                                }
                            }
                        }, function(){});
                        return;
                    }

                    run.getRunner(e.value, function(err, runner){
                        if (err)
                            return layout.showError(err);

                        runNow(runner);
                    });

                    settings.set("project/build/@builder", e.value);
                }
            });

            menus.addItemByPath("Run/Run With/", mnuRunAs,
                c += 100, plugin);
            menus.addItemByPath("Run/Run History/", new ui.item({
                isAvailable : function(){ return false; }
            }), c += 100, plugin);
            menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);

            menus.addItemByPath("Run/Run Configurations", new ui.item({
                isAvailable : function(){ return false; }
            }), c += 100, plugin);

            c = 0;
            menus.addItemByPath("Run/Run With/~", new ui.divider(), c += 1000, plugin);
            menus.addItemByPath("Run/Run With/New Runner", new ui.item({
                value : "new-run-system"
            }), c += 100, plugin);

            // Other Menus

            var itmRunFile1 = new apf.item({ command : "runthistab" });
            var itmRunFile2 = new apf.item({ command : "runthistab" });

            menus.addItemByPath("View/Tabs/Run This File", itmRunFile1, 400, plugin);
            menus.addItemByPath("View/Tabs/~", new apf.divider(), 300, plugin)

            tabbehavior.getElement("mnuContextTabs", function(mnuContextTabs){
                menus.addItemByPath("~", new apf.divider(), 800, mnuContextTabs, plugin);
                menus.addItemByPath("Run This File", itmRunFile2, 850, mnuContextTabs, plugin);
            });

            // Draw
            draw();

            // Hooks
            function updateRunFile(){
                itmRunFile1.setAttribute("disable", !tabs.focussedTab ||
                    !tabs.focussedTab.path || !process || !process.running);
                itmRunFile2.setAttribute("disable", !tabs.focussedTab ||
                    !tabs.focussedTab.path || !process || !process.running);
            }

            // run.on("starting", updateRunFile, plugin);
            // run.on("started", updateRunFile, plugin);
            run.on("stopped", updateRunFile, plugin);

            c9.on("stateChange", function(e){
                btnRun.setAttribute("disabled", !(e.state & c9.PROCESS));
            }, plugin);

            // Preferences
            prefs.add({
                "Run" : {
                    position : 600,
                    "Run & Debug" : {
                        position : 100,
                        "Save All Unsaved Tabs Before Running" : {
                           type : "checkbox",
                           path : "user/runconfig/@saveallbeforerun",
                           position : 100
                        }
                    }
                }
            }, plugin);

            // settings
            settings.on("read", function(e){
                settings.setDefaults("user/runconfig", [
                    ["saveallbeforerun", "false"],
                    ["debug", "true"],
                    ["showconsole", "true"],
                    ["showruncfglist", "false"]
                ]);
            }, plugin);

            tabs.on("focus", function(e){
                updateRunFile();

                if (process && process.running)
                    return;

                if (e.tab.path) {
                    btnRun.enable();
                    btnRun.setAttribute("tooltip", "Run "
                        + basename(e.tab.path));
                }
                else {
                    btnRun.disable();
                    btnRun.setAttribute("tooltip", "")
                }
            }, plugin);

            tabs.on("tabDestroy", function(e){
                updateRunFile();

                if (e.last) {
                    btnRun.disable();
                    btnRun.setAttribute("tooltip", "");
                }
            }, plugin);

            ace.getElement("menu", function(menu){
                menus.addItemToMenu(menu, new ui.item({
                    caption  : "Run This File",
                    command  : "runthistab",
                }), 800, plugin);
                menus.addItemToMenu(menu, new ui.divider(), 900, plugin);
            });
        };

        var drawn = false;
        function draw(){
            if (drawn) return;
            drawn = true;

            // Import CSS
            ui.insertCss(cssString, plugin);

            // Menus
            btnRun = ui.insertByIndex(layout.findParent(plugin),
              new ui.button({
                id       : "btnRun",
                skin     : "c9-toolbarbutton-glossy",
                command  : "run",
                caption  : "Run",
                disabled : true,
                icon     : "run.png",
                visible  : "true"
            }), 100, plugin);

            emit("draw");
        }

        /***** Methods *****/

        function getRunner(path){
            var ext = fs.getExtension(path);
            for (var name in run.runners) {
                if (run.runners[name].selector == "source." + ext)
                    return run.runners[name];
            }
            return false;
        }

        function runNow(runner, path){
            if (!path) {
                path = tabs.focussedTab && tabs.focussedTab.path;
                if (!path) return;
            }

            if (process && process.running)
                stop(done);
            else
                done();

            function done(){
                if (!runner)
                    runner = "auto";

                if (settings.getBool("user/runconfig/@showconsole")) {
                    commands.exec("showoutput");
                }

                var bDebug = settings.getBool("user/runconfig/@debug");

                process = run.run(runner, {
                    path  : path,
                    debug : bDebug
                }, function(err, pid){
                    if (err) {
                        transformButton();
                        process = null;
                        return layout.showError(err);
                    }

                    if (bDebug) {
                        debug.debug(process, function(err){
                            if (err)
                                return; // Either the debugger is not found or paused
                        });
                    }
                });

                process.on("stopping", function(){
                    btnRun.disable();
                }, plugin);

                process.on("stopped", function(){
                    btnRun.enable();

                    var path = transformButton();

                    if (path)
                        btnRun.enable();
                    else
                        btnRun.disable();
                }, plugin);

                transformButton("stop");
            }

            lastRun = [runner, path];
        }

        function transformButton(to){
            if (to == "stop") {
                btnRun.setAttribute("command", "stop");
                btnRun.setAttribute("icon", "stop.png");
                btnRun.setAttribute("caption", "Stop");
                btnRun.setAttribute("tooltip", "");
                btnRun.setAttribute("class", "running");
                btnRun.enable();
            }
            else {
                var path = tabs.focussedTab && tabs.focussedTab.path;

                btnRun.setAttribute("icon",
                    btnRun.checked ? "bug.png" : "run.png");
                btnRun.setAttribute("caption", "Run");
                btnRun.setAttribute("tooltip", (path
                    ? "Run " + basename(path)
                    : ""));
                btnRun.setAttribute("class", "stopped");
                btnRun.setAttribute("command", "run");

                return path;
            }
        }

        function stop(callback) {
            if (process)
                process.stop(function(err){
                    if (err) {
                        layout.showError(err.message || err);
                        transformButton();
                    }

                    debug.stop();

                    callback(err);
                });
        }

        function runLastFile(){
            if (lastRun)
                runNow.apply(this, lastRun);
        }

        function onHelpClick() {
            var tab = "running_and_debugging_code";
            if (ide.infraEnv)
                require("ext/docum" + "entation/documentation").show(tab);
            else
                window.open("https://docs.c9.io/" + tab + ".html");
        }

        /***** Lifecycle *****/

        plugin.on("load", function(){
            load();
        });
        plugin.on("enable", function(){

        });
        plugin.on("disable", function(){

        });
        plugin.on("unload", function(){
            loaded = false;
            drawn  = false;
        });

        /***** Register and define API *****/

        /**
         * UI for the {@link run} plugin. This plugin is responsible for the Run
         * menu in the main menu bar, as well as the settings and the
         * preferences UI for the run plugin.
         * @singleton
         */
        /**
         * @command run Runs the currently focussed tab.
         */
        /**
         * @command stop Stops the running process.
         */
        /**
         * @command runlast Stops the last run file
         */
        plugin.freezePublicAPI({

        });

        register(null, {
            "run.gui": plugin
        });
    }
});
<|endoftext|>