<commit_before>const http = require('http');
const querystring = require('querystring');
const windows1251 = require('windows-1251');
const EventEmitter = require('events');
const Parser = require('./lib/parser');

class RutrackerApi {
  constructor() {
    this.parser = new Parser();
  }
}

module.exports = RutrackerApi;
<commit_msg>Bind methods<commit_after>const Parser = require("./lib/parser");
const PageProvider = require("./lib/parser");

class RutrackerApi {
  constructor() {
    this.parser = new Parser();
    this.pageProvider = new PageProvider();
  }

  login({ username, password }) {
    return this.pageProvider.login(username, password);
  }

  search(query) {
    return this.pageProvider
      .search(query)
      .then(html => this.parser.parseSearch(html));
  }

  download(id) {
    return this.pageProvider.torrentFile(id);
  }

  getMagnetLink(id) {
    return this.pageProvider
      .thread(id)
      .then(html => this.parser.parseMagnetLink(html));
  }
}

module.exports = RutrackerApi;
<|endoftext|>


<commit_before>"use strict";

var generateAbstractLib = require('./lib/generate');
var versionUtils = require('./lib/version-utils');
var ethUtils = require('./lib/eth-utils');

function LiveLibs(web3, config) {
  config = buildConfig(config);

  var testing = config.testing;
  var logger = getLogger(config.verbose);

  this.env = function(callback) {
    findContract(function(err, contract) {
      if (err) return callback(err);
      if (contract) {
        callback(null, contract.env);
      } else {
        callback(null, 'testrpc');
      }
    });
  }

  this.get = function(libName, version) {
    return new Promise(function(resolve, reject) {
      if (version) {
        resolve(versionUtils.parse(version));
      } else {
        findContract(function(error, contract) {
          if (error) return reject(error);
          versionUtils.latest(libName, contract, function(err, v) {
            if (err) return reject(err);
            if (!v) return reject('No versions of '+libName+' found');
            resolve(v);
          });
        });
      }
    }).then(function(v) {
      return new Promise(function(resolve, reject) {
        findContract(function(error, contract) {
          if (error) return reject(error);
          contract.get(libName, v.num, function(err, rawLibData) {
            if (err) return reject(err);
            if (ethUtils.blankAddress(rawLibData[0])) {
              reject(libName+' '+v.string+' is locked');
            } else {
              resolve({
                version: v.string,
                address: rawLibData[0],
                abi: rawLibData[1],
                docURL: rawLibData[2],
                sourceURL: rawLibData[3],
                thresholdWei: rawLibData[4].toString(),
                totalValue: rawLibData[5].toString(),
                abstractSource: function() { return generateAbstractLib(libName, rawLibData[1]); }
              });
            }
          });
        });
      });
    });
  };

  this.log = function(libName) {
    return new Promise(function(resolve, reject) {
      filterEventsBy(libName, function(error, results) {
        if (error) return reject(error);
        return resolve(results);
      });
    }).then(function(rawEvents) {
      var events = [];
      rawEvents.forEach(function(raw) {
        delete raw.args.libName; // since we're already filtering by name

        if (raw.args.versionNum) {
          raw.args.version = versionUtils.calc(raw.args.versionNum).string;
          delete raw.args.versionNum;
        }

        var block = web3.eth.getBlock(raw.blockNumber);

        events.push({time: block.timestamp, type: raw.event, args: raw.args});
      });
      return Promise.resolve(events);
    });
  };

  this.register = function(libName, version, address, abiString, docUrl, sourceUrl, thresholdWei) {
    return new Promise(function(resolve, reject) {
      if (!libName || libName.length > 32)
        return reject('Library names must be between 1-32 characters.');

      var parsedVersion;
      if (version) {
        parsedVersion = versionUtils.parse(version);
      } else {
        return reject('No version specified for '+libName);
      }

      findContract(function(error, contract) {
        if (error) return reject(error);
        contract.register(
          libName,
          parsedVersion.num,
          address,
          abiString,
          (docUrl || ''),
          (sourceUrl || ''),
          (thresholdWei || 0),
          {value: 0, gas: 2000000}, // TODO: need to estimate this
          function(err, txHash) {
            if (err) {
              reject(err);
            } else {
              resolve(txHash);
            }
          }
        );
      });
    }).then(function(txHash) {
      var message = 'Registered '+libName+' '+version+'!';
      if (thresholdWei > 0)
        message += ' Locked until '+thresholdWei+' wei contributed.';
      return txHandler(txHash, message);
    });
  };

  this.contributeTo = function(libName, version, wei) {
    return new Promise(function(resolve, reject) {
      if (!wei)
        return reject('No wei amount specified');

      findContract(function(err, liveLibsContract) {
        if (err) return reject(err);
        liveLibsContract.libFund(function(error, libFundAddress) {
          if (error) return reject(error);
          liveAddress(libFundAddress, function(err, isLive) {
            if (err) return reject(err);
            if (!isLive) return reject('LibFund instance not found!');

            var abi = JSON.parse(config.libFundABIString);
            var libFundContract = web3.eth.contract(abi);
            var instance = libFundContract.at(libFundAddress);
            var v = versionUtils.parse(version);

            instance.addTo(
              libName,
              v.num,
              {value: wei, gas: 2000000}, // TODO: need to estimate this
              function(err, txHash) {
                if (err) {
                  reject(err);
                } else {
                  resolve(txHash);
                }
              }
            );
          });
        });
      });
    }).then(function(txHash) {
      return txHandler(txHash, 'Contributed '+wei+' wei to '+libName+' '+version+'!');
    });
  };

  this.allNames = function(callback) {
    findContract(function(err, contract) {
      if (err) return callback(err);
      contract.allNames(function(error, rawNames) {
        if (error) return callback(error);
        var names = [];
        rawNames.forEach(function(rawName) {
          var plainName = ethUtils.toAscii(web3, rawName);
          names.push(plainName);
        });
        callback(null, names);
      });
    });
  };

  this.allVersionsFor = function(libName) {
    var versionStrings = [];
    findContract(function(err, contract) {
      if (err) return callback(err);
      contract.getVersions(libName, function(error, rawVersions) {
        if (error) return callback(error);
        rawVersions.forEach(function(rawVersion) {
          var version = versionUtils.calc(rawVersion);
          versionStrings.push(version.string);
        });
        callback(null, versionStrings);
      });
    });
  };

  function findContract(callback) {
    var contract = web3.eth.contract(liveLibsABI());

    if (testing)
      return findTestRPCInstance(contract, callback);

    detectLiveLibsInstance(contract, function(err, instance) {
      if (err) return callback(err);
      if (instance) {
        callback(null, instance);
      } else {
        callback(Error('No Live Libs instance found'));
      }
    });
  }
  this.findContract = findContract; // exposing it for the CLI

  this.setTesting = function() {
    testing = true;
  };

  this.isTesting = function() {
    return testing;
  };

  function liveLibsABI() {
    // NOTE: before updating this file, download the latest registry from networks
    return JSON.parse(config.liveLibsABIString);
  }

  function detectLiveLibsInstance(contract, callback) {
    var config = parseNetworkConfig();
    var promises = [];
    Object.keys(config).forEach(function(networkName) {
      var address = config[networkName];
      promises.push(new Promise(function(resolve, reject) {
        liveAddress(address, function(err, isLive) {
          if (err) return reject(err);
          var instance;
          if (isLive) {
            instance = contract.at(address);
            instance.env = networkName;
          }
          resolve(instance);
        });
      }));
    });
    return Promise.all(promises).then(function(possibilities) {
      var instance = possibilities.find(function(instance) {
        return instance;
      });
      callback(null, instance);
    });
  }

  // TODO: Can this be extracted to the test suite?
  function findTestRPCInstance(contract, callback) {
    var address = config.testRpcAddress;

    if (!address)
      return callback(Error('Contract address not found for testrpc!'));

    liveAddress(address, function(err, isLive) {
      if (err) return callback(err);
      if (isLive) {
        var instance = contract.at(address);
        instance.env = 'testrpc';
        callback(null, instance);
      } else {
        callback(Error('Contract not found for testrpc!'));
      }
    });
  }

  function parseNetworkConfig() {
    return JSON.parse(config.networksJSONString);
  }

  function liveAddress(address, callback) {
    web3.eth.getCode(address, function(err, contractCode) {
                                  //geth                  //testrpc
      var isLive = contractCode != '0x' && contractCode != '0x0';
      callback(err, isLive);
    });
  }

  function txHandler(txHash, successMessage) {
    return new Promise(function(resolve, reject) {
      var interval = setInterval(function() {
        web3.eth.getTransactionReceipt(txHash, function(err, receipt) {
          if (err != null) {
            clearInterval(interval);
            reject(err);
          }
          if (receipt != null) {
            logger.log(successMessage);
            clearInterval(interval);
            resolve();
          }
        });
      }, 500);
    });
  }

  function getLogger(verbose) {
    if (verbose) {
      return console;
    } else {
      var noop = function() {};
      return { log: noop, error: noop };
    }
  }

  function filterEventsBy(libName, callback) {

    var searchString = web3.toHex(libName);

    // TODO: Isn't there a better way to ensure the string is zero-padded?
    // If it's not zero-padded, the topic doesn't work correctly
    while (searchString.length < 66) {
      searchString += "0";
    }

    findContract(function(err, contract) {
      if (err) return callback(err);

      var filter = web3.eth.filter({
        address: contract.address,
        fromBlock: 0,
        topics: [null, searchString]
      });

      filter.get(function(error, results) {
        if (error) return callback(error);
        var abi = liveLibsABI();
        var decodedResults = results.map(function(log) { return decode(log, abi) });
        callback(null, decodedResults);
      });
    });
  }

  function decode(log, abi) {
    var SolidityEvent = require('web3/lib/web3/event');

    var decoders = abi.filter(function (json) {
        return json.type === 'event';
    }).map(function(json) {
        return new SolidityEvent(null, json, null);
    });

    var decoder = decoders.find(function(decoder) {
      return decoder.signature() == log.topics[0].replace("0x","");
    });

    return decoder.decode(log);
  }

  function buildConfig(config) {
    if (!config) config = {};
    if (!LiveLibs.config) return config; // set in ./browser
    for (var attrname in LiveLibs.config) {
      if (config[attrname] == undefined)
        config[attrname] = LiveLibs.config[attrname];
    }
    return config;
  }
}

module.exports = LiveLibs;
<commit_msg>async'ing eth.getBlock<commit_after>"use strict";

var generateAbstractLib = require('./lib/generate');
var versionUtils = require('./lib/version-utils');
var ethUtils = require('./lib/eth-utils');

function LiveLibs(web3, config) {
  config = buildConfig(config);

  var testing = config.testing;
  var logger = getLogger(config.verbose);

  this.env = function(callback) {
    findContract(function(err, contract) {
      if (err) return callback(err);
      if (contract) {
        callback(null, contract.env);
      } else {
        callback(null, 'testrpc');
      }
    });
  }

  this.get = function(libName, version) {
    return new Promise(function(resolve, reject) {
      if (version) {
        resolve(versionUtils.parse(version));
      } else {
        findContract(function(error, contract) {
          if (error) return reject(error);
          versionUtils.latest(libName, contract, function(err, v) {
            if (err) return reject(err);
            if (!v) return reject('No versions of '+libName+' found');
            resolve(v);
          });
        });
      }
    }).then(function(v) {
      return new Promise(function(resolve, reject) {
        findContract(function(error, contract) {
          if (error) return reject(error);
          contract.get(libName, v.num, function(err, rawLibData) {
            if (err) return reject(err);
            if (ethUtils.blankAddress(rawLibData[0])) {
              reject(libName+' '+v.string+' is locked');
            } else {
              resolve({
                version: v.string,
                address: rawLibData[0],
                abi: rawLibData[1],
                docURL: rawLibData[2],
                sourceURL: rawLibData[3],
                thresholdWei: rawLibData[4].toString(),
                totalValue: rawLibData[5].toString(),
                abstractSource: function() { return generateAbstractLib(libName, rawLibData[1]); }
              });
            }
          });
        });
      });
    });
  };

  this.log = function(libName) {
    return new Promise(function(resolve, reject) {
      filterEventsBy(libName, function(error, results) {
        if (error) return reject(error);
        return resolve(results);
      });
    }).then(function(rawEvents) {
      var events = [];
      var promises = [];
      rawEvents.forEach(function(raw) {
        delete raw.args.libName; // since we're already filtering by name

        if (raw.args.versionNum) {
          raw.args.version = versionUtils.calc(raw.args.versionNum).string;
          delete raw.args.versionNum;
        }

        var event = {type: raw.event, args: raw.args};
        events.push(event);

        var promise = new Promise(function(resolve, reject) {
          web3.eth.getBlock(raw.blockNumber, function(err, block) {
            if (err) return reject(err);
            event.time = block.timestamp;
            resolve();
          });
        });
        promises.push(promise);
      });
      return Promise.all(promises).then(function() { return events; });
    });
  };

  this.register = function(libName, version, address, abiString, docUrl, sourceUrl, thresholdWei) {
    return new Promise(function(resolve, reject) {
      if (!libName || libName.length > 32)
        return reject('Library names must be between 1-32 characters.');

      var parsedVersion;
      if (version) {
        parsedVersion = versionUtils.parse(version);
      } else {
        return reject('No version specified for '+libName);
      }

      findContract(function(error, contract) {
        if (error) return reject(error);
        contract.register(
          libName,
          parsedVersion.num,
          address,
          abiString,
          (docUrl || ''),
          (sourceUrl || ''),
          (thresholdWei || 0),
          {value: 0, gas: 2000000}, // TODO: need to estimate this
          function(err, txHash) {
            if (err) {
              reject(err);
            } else {
              resolve(txHash);
            }
          }
        );
      });
    }).then(function(txHash) {
      var message = 'Registered '+libName+' '+version+'!';
      if (thresholdWei > 0)
        message += ' Locked until '+thresholdWei+' wei contributed.';
      return txHandler(txHash, message);
    });
  };

  this.contributeTo = function(libName, version, wei) {
    return new Promise(function(resolve, reject) {
      if (!wei)
        return reject('No wei amount specified');

      findContract(function(err, liveLibsContract) {
        if (err) return reject(err);
        liveLibsContract.libFund(function(error, libFundAddress) {
          if (error) return reject(error);
          liveAddress(libFundAddress, function(err, isLive) {
            if (err) return reject(err);
            if (!isLive) return reject('LibFund instance not found!');

            var abi = JSON.parse(config.libFundABIString);
            var libFundContract = web3.eth.contract(abi);
            var instance = libFundContract.at(libFundAddress);
            var v = versionUtils.parse(version);

            instance.addTo(
              libName,
              v.num,
              {value: wei, gas: 2000000}, // TODO: need to estimate this
              function(err, txHash) {
                if (err) {
                  reject(err);
                } else {
                  resolve(txHash);
                }
              }
            );
          });
        });
      });
    }).then(function(txHash) {
      return txHandler(txHash, 'Contributed '+wei+' wei to '+libName+' '+version+'!');
    });
  };

  this.allNames = function(callback) {
    findContract(function(err, contract) {
      if (err) return callback(err);
      contract.allNames(function(error, rawNames) {
        if (error) return callback(error);
        var names = [];
        rawNames.forEach(function(rawName) {
          var plainName = ethUtils.toAscii(web3, rawName);
          names.push(plainName);
        });
        callback(null, names);
      });
    });
  };

  this.allVersionsFor = function(libName) {
    var versionStrings = [];
    findContract(function(err, contract) {
      if (err) return callback(err);
      contract.getVersions(libName, function(error, rawVersions) {
        if (error) return callback(error);
        rawVersions.forEach(function(rawVersion) {
          var version = versionUtils.calc(rawVersion);
          versionStrings.push(version.string);
        });
        callback(null, versionStrings);
      });
    });
  };

  function findContract(callback) {
    var contract = web3.eth.contract(liveLibsABI());

    if (testing)
      return findTestRPCInstance(contract, callback);

    detectLiveLibsInstance(contract, function(err, instance) {
      if (err) return callback(err);
      if (instance) {
        callback(null, instance);
      } else {
        callback(Error('No Live Libs instance found'));
      }
    });
  }
  this.findContract = findContract; // exposing it for the CLI

  this.setTesting = function() {
    testing = true;
  };

  this.isTesting = function() {
    return testing;
  };

  function liveLibsABI() {
    // NOTE: before updating this file, download the latest registry from networks
    return JSON.parse(config.liveLibsABIString);
  }

  function detectLiveLibsInstance(contract, callback) {
    var config = parseNetworkConfig();
    var promises = [];
    Object.keys(config).forEach(function(networkName) {
      var address = config[networkName];
      promises.push(new Promise(function(resolve, reject) {
        liveAddress(address, function(err, isLive) {
          if (err) return reject(err);
          var instance;
          if (isLive) {
            instance = contract.at(address);
            instance.env = networkName;
          }
          resolve(instance);
        });
      }));
    });
    return Promise.all(promises).then(function(possibilities) {
      var instance = possibilities.find(function(instance) {
        return instance;
      });
      callback(null, instance);
    });
  }

  // TODO: Can this be extracted to the test suite?
  function findTestRPCInstance(contract, callback) {
    var address = config.testRpcAddress;

    if (!address)
      return callback(Error('Contract address not found for testrpc!'));

    liveAddress(address, function(err, isLive) {
      if (err) return callback(err);
      if (isLive) {
        var instance = contract.at(address);
        instance.env = 'testrpc';
        callback(null, instance);
      } else {
        callback(Error('Contract not found for testrpc!'));
      }
    });
  }

  function parseNetworkConfig() {
    return JSON.parse(config.networksJSONString);
  }

  function liveAddress(address, callback) {
    web3.eth.getCode(address, function(err, contractCode) {
                                  //geth                  //testrpc
      var isLive = contractCode != '0x' && contractCode != '0x0';
      callback(err, isLive);
    });
  }

  function txHandler(txHash, successMessage) {
    return new Promise(function(resolve, reject) {
      var interval = setInterval(function() {
        web3.eth.getTransactionReceipt(txHash, function(err, receipt) {
          if (err != null) {
            clearInterval(interval);
            reject(err);
          }
          if (receipt != null) {
            logger.log(successMessage);
            clearInterval(interval);
            resolve();
          }
        });
      }, 500);
    });
  }

  function getLogger(verbose) {
    if (verbose) {
      return console;
    } else {
      var noop = function() {};
      return { log: noop, error: noop };
    }
  }

  function filterEventsBy(libName, callback) {

    var searchString = web3.toHex(libName);

    // TODO: Isn't there a better way to ensure the string is zero-padded?
    // If it's not zero-padded, the topic doesn't work correctly
    while (searchString.length < 66) {
      searchString += "0";
    }

    findContract(function(err, contract) {
      if (err) return callback(err);

      var filter = web3.eth.filter({
        address: contract.address,
        fromBlock: 0,
        topics: [null, searchString]
      });

      filter.get(function(error, results) {
        if (error) return callback(error);
        var abi = liveLibsABI();
        var decodedResults = results.map(function(log) { return decode(log, abi) });
        callback(null, decodedResults);
      });
    });
  }

  function decode(log, abi) {
    var SolidityEvent = require('web3/lib/web3/event');

    var decoders = abi.filter(function (json) {
        return json.type === 'event';
    }).map(function(json) {
        return new SolidityEvent(null, json, null);
    });

    var decoder = decoders.find(function(decoder) {
      return decoder.signature() == log.topics[0].replace("0x","");
    });

    return decoder.decode(log);
  }

  function buildConfig(config) {
    if (!config) config = {};
    if (!LiveLibs.config) return config; // set in ./browser
    for (var attrname in LiveLibs.config) {
      if (config[attrname] == undefined)
        config[attrname] = LiveLibs.config[attrname];
    }
    return config;
  }
}

module.exports = LiveLibs;
<|endoftext|>


<commit_before>(function (exports) {
    'use strict';

    // Get an object's type
    function type (val) {
        var str = Object.prototype.toString.call(val);
        switch (str) {
            case '[object Array]':
                return 'array';
            case '[object Null]':
                return 'null';
            default:
                return typeof val;
        }
    }
    exports.type = type;

    // Check whether an object is of a certain type
    function is (val, type) {
        return (exports.type(val) === type);
    }
    exports.is = is;

    // Cast an object to a given type
    function to (val, type) {

        // Get type and return if already correct
        var from = exports.type(val);
        if (type === from) {
            return val;
        }

        // Check for caster
        // if (typeof to.cast[type] === 'undefined' || typeof to.cast[type]._default !== 'function') {
        //     throw new Error('Cannot cast to type: \'' + type + '\'');
        // }

        // Get a caster and cast!
        var caster = to.cast[type][from] || to.cast[type]._default;
        return caster(val);

    }
    exports.to = to;

    // Default casters
    to.cast = {
        array: {
            null: function () { return []; },
            string: function (val) { return val.split(''); },
            undefined: function () { return []; },
            _default: function (val) { return [val]; }
        },
        boolean: {
            array: function (val) { return val.length > 0; },
            _default: function (val) { return (val ? true : false); }
        },
        function: {
            _default: function (val) { return function () { return val; }; }
        },
        null: {
            _default: function () { return null; }
        },
        number: {
            array: function (val) { return to(to(val, 'string'), 'number'); },
            string: function (val) {
                var num = parseInt(val, 10);
                return (isNaN(num) ? 0 : num);
            },
            undefined: function () { return 0; },
            _default: function (val) { return Number(val); }
        },
        object: {
            _default: function (val) { return new Object(val); }
        },
        string: {
            array: function (val) { return val.join(''); },
            null: function () { return ''; },
            undefined: function () { return ''; },
            _default: function (val) { return val + ''; }
        },
        undefined: {
            _default: function () { return void 0; }
        }
    };

    // Check/cast shortcuts
    function shortcut (type, alias) {
        is[alias] = function (val) {
            return exports.is(val, type);
        };
        to[alias] = function (val) {
            return exports.to(val, type);
        };
    }
    shortcut('array', 'arr');
    shortcut('boolean', 'bool');
    shortcut('function', 'fn');
    shortcut('null', 'nul');
    shortcut('number', 'num');
    shortcut('object', 'obj');
    shortcut('string', 'str');
    shortcut('undefined', 'und');

} (typeof exports === 'undefined' ? (this.upcast = this.upcast || {}) : exports));<commit_msg>Remove temporary code<commit_after>(function (exports) {
    'use strict';

    // Get an object's type
    function type (val) {
        var str = Object.prototype.toString.call(val);
        switch (str) {
            case '[object Array]':
                return 'array';
            case '[object Null]':
                return 'null';
            default:
                return typeof val;
        }
    }
    exports.type = type;

    // Check whether an object is of a certain type
    function is (val, type) {
        return (exports.type(val) === type);
    }
    exports.is = is;

    // Cast an object to a given type
    function to (val, type) {

        // Get type and return if already correct
        var from = exports.type(val);
        if (type === from) {
            return val;
        }

        // Todo: guarding

        // Get a caster and cast!
        var caster = to.cast[type][from] || to.cast[type]._default;
        return caster(val);

    }
    exports.to = to;

    // Default casters
    to.cast = {
        array: {
            null: function () { return []; },
            string: function (val) { return val.split(''); },
            undefined: function () { return []; },
            _default: function (val) { return [val]; }
        },
        boolean: {
            array: function (val) { return val.length > 0; },
            _default: function (val) { return (val ? true : false); }
        },
        function: {
            _default: function (val) { return function () { return val; }; }
        },
        null: {
            _default: function () { return null; }
        },
        number: {
            array: function (val) { return to(to(val, 'string'), 'number'); },
            string: function (val) {
                var num = parseInt(val, 10);
                return (isNaN(num) ? 0 : num);
            },
            undefined: function () { return 0; },
            _default: function (val) { return Number(val); }
        },
        object: {
            _default: function (val) { return new Object(val); }
        },
        string: {
            array: function (val) { return val.join(''); },
            null: function () { return ''; },
            undefined: function () { return ''; },
            _default: function (val) { return val + ''; }
        },
        undefined: {
            _default: function () { return void 0; }
        }
    };

    // Check/cast shortcuts
    function shortcut (type, alias) {
        is[alias] = function (val) {
            return exports.is(val, type);
        };
        to[alias] = function (val) {
            return exports.to(val, type);
        };
    }
    shortcut('array', 'arr');
    shortcut('boolean', 'bool');
    shortcut('function', 'fn');
    shortcut('null', 'nul');
    shortcut('number', 'num');
    shortcut('object', 'obj');
    shortcut('string', 'str');
    shortcut('undefined', 'und');

} (typeof exports === 'undefined' ? (this.upcast = this.upcast || {}) : exports));<|endoftext|>


<commit_before>var config = require('rc')('upmon', {tray: {limit: 250}})
var menubar = require('menubar')
var upmon = require('upmon')
var ndjson = require('ndjson')
var ipcMain = require('electron').ipcMain
var debounce = require('debounce')
var Icons = require('./icons')

var data = {}

upmon().pipe(ndjson.parse()).on('data', d => {
  data[d.url] = data[d.url] || []
  data[d.url].unshift(d)
  data[d.url] = data[d.url].slice(0, config.tray.limit)
  send()
  updateIcon()
})

var mb = menubar({icon: Icons.default, height: 50})

mb.on('ready', () => {
  mb.tray.setPressedImage(Icons.pressed)

  updateIcon()

  mb.on('after-create-window', () => {
    // mb.window.webContents.openDevTools()
    mb.window.webContents.on('did-finish-load', send)
  })

  mb.on('show', send)
})

function send () {
  if (!mb.window) return
  if (!mb.window.isVisible()) return
  mb.window.webContents.send('render', data)
}

function updateIcon () {
  if (!mb.tray) return

  var isError = Object.keys(data).some(url => {
    return data[url][0].status < 200 || data[url][0].status >= 300
  })

  mb.tray.setImage(isError ? Icons.error : Icons.default)
}

ipcMain.on('height', (event, height) => setWindowSize(400, height))

var setWindowSize = debounce((w, h) => {
  if (h < 50) h = 50
  mb.window.setSize(w, h, true)
}, 500)
<commit_msg>Handle upmon errors<commit_after>var config = require('rc')('upmon', {tray: {limit: 250}})
var menubar = require('menubar')
var upmon = require('upmon')
var ndjson = require('ndjson')
var ipcMain = require('electron').ipcMain
var debounce = require('debounce')
var Icons = require('./icons')

var data = {}

function startUpmon () {
  var pinger = upmon().on('error', restartUpmon)

  pinger
    .pipe(ndjson.parse())
    .on('data', d => {
      data[d.url] = data[d.url] || []
      data[d.url].unshift(d)
      data[d.url] = data[d.url].slice(0, config.tray.limit)
      send()
      updateIcon()
    })
    .on('error', restartUpmon)
}

function restartUpmon (err) {
  if (err) return console.error(err)
  setTimeout(startUpmon, 1000)
}

startUpmon()

var mb = menubar({icon: Icons.default, height: 50})

mb.on('ready', () => {
  mb.tray.setPressedImage(Icons.pressed)

  updateIcon()

  mb.on('after-create-window', () => {
    // mb.window.webContents.openDevTools()
    mb.window.webContents.on('did-finish-load', send)
  })

  mb.on('show', send)
})

function send () {
  if (!mb.window) return
  if (!mb.window.isVisible()) return
  mb.window.webContents.send('render', data)
}

function updateIcon () {
  if (!mb.tray) return

  var isError = Object.keys(data).some(url => {
    return data[url][0].status < 200 || data[url][0].status >= 300
  })

  mb.tray.setImage(isError ? Icons.error : Icons.default)
}

ipcMain.on('height', (event, height) => setWindowSize(400, height))

var setWindowSize = debounce((w, h) => {
  if (h < 50) h = 50
  mb.window.setSize(w, h, true)
}, 500)
<|endoftext|>


<commit_before>var es = require('event-stream');
var extend = require('extend');
var async = require('async');

exports.createPermutationStream = function createPermutationStream(data, opts) {
  opts = extend(opts || {}, { min: 0, max: data.length, repitition: false });
  var output = es.through();

  process.nextTick(function() {
    permutate(data, 0, write, end);
  });

  return output;

  function write(data) {
    output.write(data);
  }

  function end() {
    output.write(null);
  }
}

function permutate(list, i, emit, done) {
  emit(list.slice(0,i));
  if(i == list.length-1) {
    emit(list);
    done();
  } else {
    var j = i;
    async.whilst(
      function() {
        return j < list.length
      },
      function(cb) {
        var l = list.slice();
        l[i] = list[j], l[j] = list[i];
        j++;
        permutate(l, i+1, emit, cb);
      },
      function() {
        done();
      });
  }
}<commit_msg>jshint fixes<commit_after>var es = require('event-stream');
var extend = require('extend');
var async = require('async');

exports.createPermutationStream = function createPermutationStream(data, opts) {
  opts = extend(opts || {}, { min: 0, max: data.length, repitition: false });
  var output = es.through();

  process.nextTick(function() {
    permutate(data, 0, write, end);
  });

  return output;

  function write(data) {
    output.write(data);
  }

  function end() {
    output.write(null);
  }
};

function permutate(list, i, emit, done) {
  emit(list.slice(0,i));
  if(i == list.length-1) {
    emit(list);
    done();
  } else {
    var j = i;
    async.whilst(
      function() {
        return j < list.length;
      },
      function(cb) {
        var l = list.slice();
        l[i] = list[j];
        l[j] = list[i];
        j++;
        permutate(l, i+1, emit, cb);
      },
      function() {
        done();
      });
  }
}<|endoftext|>


<commit_before>"use strict";

var bootstrap = require("./bootstrap");
var EventEmitter = require("events");
var transform = require("./transform");
var _ = require("lodash");
var crypto = require("crypto");
var async = require("async");

var defaultBehaviour = {
  reuse: "default",
  ack: false,
  confirm: false,
  heartbeat: 10,
  productName: getProductName(),
  resubscribeOnError: true,
  queueArguments: {}
};

function init(behaviour) {
  var api = new EventEmitter();
  behaviour = _.assign(defaultBehaviour, behaviour);

  api.subscribeTmp = function (routingKeyOrKeys, handler, cb) {
    api.subscribe(routingKeyOrKeys, undefined, handler, cb);
  };

  api.subscribe = function (routingKeyOrKeys, queue, handler, cb) {
    bootstrap(behaviour, api, function (connErr, conn) {
      var resubTimer;
      if (connErr) return handleSubscribeError(connErr);
      conn.on("error", handleSubscribeError);

      var routingKeys = Array.isArray(routingKeyOrKeys) ? routingKeyOrKeys : [routingKeyOrKeys];
      conn.createChannel(function (channelErr, subChannel) {
        subChannel.prefetch(behaviour.prefetch);
        var queueOpts = {
          durable: !!queue,
          autoDelete: !queue,
          exclusive: !queue,
          arguments: behaviour.queueArguments};
        var queueName = queue ? queue : getProductName() + "-" + getRandomStr();
        subChannel.assertExchange(behaviour.exchange, "topic");
        subChannel.assertQueue(queueName, queueOpts);
        routingKeys.forEach(function (key) {
          subChannel.bindQueue(queueName, behaviour.exchange, key, {});
        });
        var amqpHandler = function (message) {
          if (!message) return handleSubscribeError("Subscription cancelled");
          var ackFun = function () {
            subChannel.ack(message);
          };
          handler(transform.decode(message), message, {ack: ackFun});
        };
        var consumeOpts = {noAck: !behaviour.ack};
        subChannel.consume(queueName, amqpHandler, consumeOpts, cb);
        api.emit("subscribed", {key: routingKeyOrKeys, queue: queueName});
      });

      function handleSubscribeError(err) {
        if (err) {
          api.emit("error", err);
          if (behaviour.resubscribeOnError && !resubTimer) {
            resubTimer = setTimeout(function () {
              api.subscribe(routingKeyOrKeys, queue, handler);
            }, 5000);
          }
        }
      }
    });
  };

  api.publish = function (routingKey, message, cb) {
    cb = cb || function () {};
    bootstrap(behaviour, api, function (connErr, conn, channel) {
      if (connErr) {
        api.emit("error", connErr);
        return cb(connErr);
      }
      var encodedMsg = transform.encode(message);
      channel.publish(behaviour.exchange, routingKey, encodedMsg.buffer, encodedMsg.props, cb);
    });
  };

  api.delayedPublish = function (routingKey, message, delay, cb) {
    cb = cb || function () {};
    bootstrap(behaviour, api, function (connErr, conn, channel) {
      var name = behaviour.exchange + "-exp-amqp-delayed-" + delay;
      channel.assertExchange(name, "fanout", {
        durable: true,
        autoDelete: true
      });
      channel.assertQueue(name, {
        durable: true,
        autoDelete: true,
        arguments: {
          "x-dead-letter-exchange": behaviour.exchange,
          "x-message-ttl": delay,
          "x-expires": delay + 60000
        }
      });
      var encodedMsg = transform.encode(message);
      async.series([
        function (done) {
          channel.bindQueue(name, name, "#", {}, done);
        },
        function (done) {
          channel.publish(name, routingKey, encodedMsg.buffer, encodedMsg.props, done);
        }
      ], cb);
    });
  };

  api.deleteQueue = function (queue) {
    bootstrap(behaviour, api, function (connErr, conn, channel) {
      channel.deleteQueue(queue);
    });
  };

  api.shutdown = function (cb) {
    cb = cb || function () {};
    bootstrap(behaviour, api, function (connErr, conn) {
      if (connErr) return cb();
      conn.close(cb);
    });
  };

  return api;
}

function getProductName() {
  try {
    var pkg = require(process.cwd() + "/package.json");
    var nodeEnv = (process.env.NODE_ENV || "development");
    return pkg.name + "-" + nodeEnv;
  } catch (e) {
    return "exp-amqp-connection";
  }
}

function getRandomStr() {
  return crypto.randomBytes(20).toString("hex").slice(1, 8);
}

module.exports = init;
<commit_msg>Add expiry to tmp queues.<commit_after>"use strict";

var bootstrap = require("./bootstrap");
var EventEmitter = require("events");
var transform = require("./transform");
var _ = require("lodash");
var crypto = require("crypto");
var async = require("async");

var TMP_Q_TTL = 60000;

var defaultBehaviour = {
  reuse: "default",
  ack: false,
  confirm: false,
  heartbeat: 10,
  productName: getProductName(),
  resubscribeOnError: true,
  queueArguments: {}
};

function init(behaviour) {
  var api = new EventEmitter();
  behaviour = _.assign(defaultBehaviour, behaviour);

  api.subscribeTmp = function (routingKeyOrKeys, handler, cb) {
    api.subscribe(routingKeyOrKeys, undefined, handler, cb);
  };

  api.subscribe = function (routingKeyOrKeys, queue, handler, cb) {
    bootstrap(behaviour, api, function (connErr, conn) {
      var resubTimer;
      if (connErr) return handleSubscribeError(connErr);
      conn.on("error", handleSubscribeError);

      var routingKeys = Array.isArray(routingKeyOrKeys) ? routingKeyOrKeys : [routingKeyOrKeys];
      conn.createChannel(function (channelErr, subChannel) {
        subChannel.prefetch(behaviour.prefetch);
        var queueOpts = {
          durable: !!queue,
          autoDelete: !queue,
          exclusive: !queue,
          arguments: Object.assign(!queue ? {"x-expires": TMP_Q_TTL} : {}, behaviour.queueArguments)
        };
        var queueName = queue ? queue : getProductName() + "-" + getRandomStr();
        subChannel.assertExchange(behaviour.exchange, "topic");
        subChannel.assertQueue(queueName, queueOpts);
        routingKeys.forEach(function (key) {
          subChannel.bindQueue(queueName, behaviour.exchange, key, {});
        });
        var amqpHandler = function (message) {
          if (!message) return handleSubscribeError("Subscription cancelled");
          var ackFun = function () {
            subChannel.ack(message);
          };
          handler(transform.decode(message), message, {ack: ackFun});
        };
        var consumeOpts = {noAck: !behaviour.ack};
        subChannel.consume(queueName, amqpHandler, consumeOpts, cb);
        api.emit("subscribed", {key: routingKeyOrKeys, queue: queueName});
      });

      function handleSubscribeError(err) {
        if (err) {
          api.emit("error", err);
          if (behaviour.resubscribeOnError && !resubTimer) {
            resubTimer = setTimeout(function () {
              api.subscribe(routingKeyOrKeys, queue, handler);
            }, 5000);
          }
        }
      }
    });
  };

  api.publish = function (routingKey, message, cb) {
    cb = cb || function () {};
    bootstrap(behaviour, api, function (connErr, conn, channel) {
      if (connErr) {
        api.emit("error", connErr);
        return cb(connErr);
      }
      var encodedMsg = transform.encode(message);
      channel.publish(behaviour.exchange, routingKey, encodedMsg.buffer, encodedMsg.props, cb);
    });
  };

  api.delayedPublish = function (routingKey, message, delay, cb) {
    cb = cb || function () {};
    bootstrap(behaviour, api, function (connErr, conn, channel) {
      var name = behaviour.exchange + "-exp-amqp-delayed-" + delay;
      channel.assertExchange(name, "fanout", {
        durable: true,
        autoDelete: true
      });
      channel.assertQueue(name, {
        durable: true,
        autoDelete: true,
        arguments: {
          "x-dead-letter-exchange": behaviour.exchange,
          "x-message-ttl": delay,
          "x-expires": delay + 60000
        }
      });
      var encodedMsg = transform.encode(message);
      async.series([
        function (done) {
          channel.bindQueue(name, name, "#", {}, done);
        },
        function (done) {
          channel.publish(name, routingKey, encodedMsg.buffer, encodedMsg.props, done);
        }
      ], cb);
    });
  };

  api.deleteQueue = function (queue) {
    bootstrap(behaviour, api, function (connErr, conn, channel) {
      channel.deleteQueue(queue);
    });
  };

  api.shutdown = function (cb) {
    cb = cb || function () {};
    bootstrap(behaviour, api, function (connErr, conn) {
      if (connErr) return cb();
      conn.close(cb);
    });
  };

  return api;
}

function getProductName() {
  try {
    var pkg = require(process.cwd() + "/package.json");
    var nodeEnv = (process.env.NODE_ENV || "development");
    return pkg.name + "-" + nodeEnv;
  } catch (e) {
    return "exp-amqp-connection";
  }
}

function getRandomStr() {
  return crypto.randomBytes(20).toString("hex").slice(1, 8);
}

module.exports = init;
<|endoftext|>


<commit_before>import {Link} from 'route'
import Hammer from 'react-hammerjs'
import Icon from 'widget/icon'
import PropTypes from 'prop-types'
import React from 'react'
import Tooltip from 'widget/tooltip'
import lookStyles from '../style/look.module.css'
import styles from './button.module.css'

const hammerOptions = ({onClick, onClickHold}) => {
    const tapOnly = {
        recognizers: {
            tap: {
                time: 10000
            },
            press: {
                enable: false
            }
        }
    }
    const tapAndPress = {
        recognizers: {
            tap: {
                time: 750
            },
            press: {
                time: 750
            }
        }
    }
    const pressOnly = {
        recognizers: {
            tap: {
                enable: false
            },
            press: {
                time: 750
            }
        }
    }
    const nothing = {
        recognizers: {
            tap: {
                enable: false
            },
            press: {
                enable: false
            }
        }
    }
    return onClick
        ? (onClickHold ? tapAndPress : tapOnly)
        : (onClickHold ? pressOnly : nothing)
}

const renderContents = ({icon, label, children}) =>
    children ? children : (

            {icon ? <Icon name={icon}/> : null}
            {label ? {label} : null}

    )

const classNames = ({className, look, size, onClickHold}) =>
    className ? className : [
        styles.button,
        styles[size],
        lookStyles.look,
        lookStyles[look],
        onClickHold ? styles.hold : null
    ].join(' ')

const renderButton = ({type, className, look, size, tabIndex, onMouseDown, onClickHold, shown, disabled}, contents) =>
    <button
        type={type}
        className={classNames({className, look, size, onClickHold})}
        style={{visibility: shown ? 'visible' : 'hidden'}}
        tabIndex={tabIndex}
        disabled={disabled || !shown}
        onMouseDown={e => onMouseDown && onMouseDown(e)}>
        {contents}
    </button>

const renderHammer = ({onClick, onClickHold, shown, disabled}, contents) =>
    shown && !disabled ? (
        <Hammer
            onTap={e => onClick && onClick(e.srcEvent, e)}
            onPressUp={e => onClickHold && onClickHold(e.srcEvent, e)}
            options={hammerOptions({onClick, onClickHold})}>
            {contents}
        </Hammer>
    ) : contents

const renderPropagationStopper = ({stopPropagation}, contents) =>
    stopPropagation ? (
         e.stopPropagation()}>
            {contents}

    ) : contents

const renderTooltip = ({tooltip, tooltipPlacement, tooltipDisabled, shown, disabled}, contents) =>
    tooltip && !tooltipDisabled && shown && !disabled ? (
        <Tooltip msg={tooltip} placement={tooltipPlacement}>
            {contents}
        </Tooltip>
    ) : contents

const renderLink = ({link, shown, disabled}, contents) =>
    link && shown && !disabled ? (
        <Link to={link} onMouseDown={e => e.preventDefault()}>
            {contents}
        </Link>
    ) : contents

export const Button = ({
    type = 'button',
    className,
    look = 'default',
    size = 'normal',
    tabIndex,
    icon,
    label,
    onMouseDown,
    onClick,
    onClickHold,
    link,
    shown = true,
    disabled,
    stopPropagation,
    children,
    tooltip,
    tooltipPlacement,
    tooltipDisabled
}) =>
    renderLink({link, shown, disabled},
        renderTooltip({tooltip, tooltipPlacement, tooltipDisabled, shown, disabled},
            renderPropagationStopper({stopPropagation},
                renderHammer({onClick, onClickHold, shown, disabled},
                    renderButton({type, className, look, size, tabIndex, onMouseDown, onClickHold, shown, disabled},
                        renderContents({icon, label, children})
                    )
                )
            )
        )
    )

Button.propTypes = {
    children: PropTypes.array,
    className: PropTypes.string,
    disabled: PropTypes.any,
    icon: PropTypes.string,
    label: PropTypes.string,
    link: PropTypes.string,
    look: PropTypes.oneOf(['default', 'highlight', 'transparent', 'apply', 'cancel']),
    shown: PropTypes.any,
    size: PropTypes.oneOf(['normal', 'large', 'x-large']),
    stopPropagation: PropTypes.any,
    tabIndex: PropTypes.number,
    tooltip: PropTypes.string,
    tooltipDisabled: PropTypes.any,
    tooltipPlacement: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
    type: PropTypes.string,
    onClick: PropTypes.func,
    onClickHold: PropTypes.func,
    onMouseDown: PropTypes.func
}

export const ButtonGroup = ({children}) =>

        {children}

ButtonGroup.propTypes = {
    children: PropTypes.array.isRequired
}
<commit_msg>Allowed single child.<commit_after>import {Link} from 'route'
import Hammer from 'react-hammerjs'
import Icon from 'widget/icon'
import PropTypes from 'prop-types'
import React from 'react'
import Tooltip from 'widget/tooltip'
import lookStyles from '../style/look.module.css'
import styles from './button.module.css'

const hammerOptions = ({onClick, onClickHold}) => {
    const tapOnly = {
        recognizers: {
            tap: {
                time: 10000
            },
            press: {
                enable: false
            }
        }
    }
    const tapAndPress = {
        recognizers: {
            tap: {
                time: 750
            },
            press: {
                time: 750
            }
        }
    }
    const pressOnly = {
        recognizers: {
            tap: {
                enable: false
            },
            press: {
                time: 750
            }
        }
    }
    const nothing = {
        recognizers: {
            tap: {
                enable: false
            },
            press: {
                enable: false
            }
        }
    }
    return onClick
        ? (onClickHold ? tapAndPress : tapOnly)
        : (onClickHold ? pressOnly : nothing)
}

const renderContents = ({icon, label, children}) =>
    children ? children : (

            {icon ? <Icon name={icon}/> : null}
            {label ? {label} : null}

    )

const classNames = ({className, look, size, onClickHold}) =>
    className ? className : [
        styles.button,
        styles[size],
        lookStyles.look,
        lookStyles[look],
        onClickHold ? styles.hold : null
    ].join(' ')

const renderButton = ({type, className, look, size, tabIndex, onMouseDown, onClickHold, shown, disabled}, contents) =>
    <button
        type={type}
        className={classNames({className, look, size, onClickHold})}
        style={{visibility: shown ? 'visible' : 'hidden'}}
        tabIndex={tabIndex}
        disabled={disabled || !shown}
        onMouseDown={e => onMouseDown && onMouseDown(e)}>
        {contents}
    </button>

const renderHammer = ({onClick, onClickHold, shown, disabled}, contents) =>
    shown && !disabled ? (
        <Hammer
            onTap={e => onClick && onClick(e.srcEvent, e)}
            onPressUp={e => onClickHold && onClickHold(e.srcEvent, e)}
            options={hammerOptions({onClick, onClickHold})}>
            {contents}
        </Hammer>
    ) : contents

const renderPropagationStopper = ({stopPropagation}, contents) =>
    stopPropagation ? (
         e.stopPropagation()}>
            {contents}

    ) : contents

const renderTooltip = ({tooltip, tooltipPlacement, tooltipDisabled, shown, disabled}, contents) =>
    tooltip && !tooltipDisabled && shown && !disabled ? (
        <Tooltip msg={tooltip} placement={tooltipPlacement}>
            {contents}
        </Tooltip>
    ) : contents

const renderLink = ({link, shown, disabled}, contents) =>
    link && shown && !disabled ? (
        <Link to={link} onMouseDown={e => e.preventDefault()}>
            {contents}
        </Link>
    ) : contents

export const Button = ({
    type = 'button',
    className,
    look = 'default',
    size = 'normal',
    tabIndex,
    icon,
    label,
    onMouseDown,
    onClick,
    onClickHold,
    link,
    shown = true,
    disabled,
    stopPropagation,
    children,
    tooltip,
    tooltipPlacement,
    tooltipDisabled
}) =>
    renderLink({link, shown, disabled},
        renderTooltip({tooltip, tooltipPlacement, tooltipDisabled, shown, disabled},
            renderPropagationStopper({stopPropagation},
                renderHammer({onClick, onClickHold, shown, disabled},
                    renderButton({type, className, look, size, tabIndex, onMouseDown, onClickHold, shown, disabled},
                        renderContents({icon, label, children})
                    )
                )
            )
        )
    )

Button.propTypes = {
    children: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
    className: PropTypes.string,
    disabled: PropTypes.any,
    icon: PropTypes.string,
    label: PropTypes.string,
    link: PropTypes.string,
    look: PropTypes.oneOf(['default', 'highlight', 'transparent', 'apply', 'cancel']),
    shown: PropTypes.any,
    size: PropTypes.oneOf(['normal', 'large', 'x-large']),
    stopPropagation: PropTypes.any,
    tabIndex: PropTypes.number,
    tooltip: PropTypes.string,
    tooltipDisabled: PropTypes.any,
    tooltipPlacement: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
    type: PropTypes.string,
    onClick: PropTypes.func,
    onClickHold: PropTypes.func,
    onMouseDown: PropTypes.func
}

export const ButtonGroup = ({children}) =>

        {children}

ButtonGroup.propTypes = {
    children: PropTypes.array.isRequired
}
<|endoftext|>


<commit_before>'use strict';

module.exports = function (template, args) {
  if (!args) {
    return interpolate.bind(null, template);
  }

  return interpolate(template, args);
};

function interpolate(template, args) {
  return template.replace(/{([^}]*)}/g, function (match, key) {
    return key in args ? args[key] : match;
  });
}<commit_msg>Set the args variable value as an empty object if the argument in missing<commit_after>'use strict';

module.exports = function (template, args) {
  if (!args) {
    return interpolate.bind(null, template);
  }

  return interpolate(template, args);
};

function interpolate(template, args) {
  if (typeof args === 'undefined') {
    args = {};
  }
  return template.replace(/{([^}]*)}/g, function (match, key) {
    return key in args ? args[key] : match;
  });
}
<|endoftext|>


<commit_before>'use strict';
var through = require('through2');
var fs = require('graceful-fs');
var path = require('path');
var File = require('vinyl');
var convert = require('convert-source-map');
var stripBom = require('strip-bom');

var PLUGIN_NAME = 'gulp-sourcemap';
var urlRegex = /^https?:\/\//;

/**
 * Initialize source mapping chain
 */
module.exports.init = function init(options) {
  function sourceMapInit(file, encoding, callback) {
    /*jshint validthis:true */

    if (file.isNull()) {
      this.push(file);
      return callback();
    }

    if (file.isStream()) {
      return callback(new Error(PLUGIN_NAME + '-init: Streaming not supported'));
    }

    var fileContent = file.contents.toString();
    var sourceMap;

    if (options && options.loadMaps) {
      var sourcePath = ''; //root path for the sources in the map

      // Try to read inline source map
      sourceMap = convert.fromSource(fileContent);
      if (sourceMap) {
        sourceMap = sourceMap.toObject();
        // sources in map are relative to the source file
        sourcePath = path.dirname(file.path);
        fileContent = convert.removeComments(fileContent);
      } else {
        // look for source map comment referencing a source map file
        var mapComment = convert.mapFileCommentRegex.exec(fileContent);

        var mapFile;
        if (mapComment) {
          mapFile = path.resolve(path.dirname(file.path), mapComment[1] || mapComment[2]);
          fileContent = convert.removeMapFileComments(fileContent);
        // if no comment try map file with same name as source file
        } else {
          mapFile = file.path + '.map';
        }

        // sources in external map are relative to map file
        sourcePath = path.dirname(mapFile);

        try {
          sourceMap = JSON.parse(stripBom(fs.readFileSync(mapFile, 'utf8')));
        } catch(e) {}
      }

      // fix source paths and sourceContent for imported source map
      if (sourceMap) {
        sourceMap.sourcesContent = sourceMap.sourcesContent || [];
        sourceMap.sources.forEach(function(source, i) {
          if (source.match(urlRegex)) {
            sourceMap.sourcesContent[i] = sourceMap.sourcesContent[i] || null;
            return;
          }
          var absPath = path.resolve(sourcePath, source);
          sourceMap.sources[i] = unixStylePath(path.relative(file.base, absPath));

          if (!sourceMap.sourcesContent[i]) {
            var sourceContent = null;
            if (sourceMap.sourceRoot) {
              if (sourceMap.sourceRoot.match(urlRegex)) {
                sourceMap.sourcesContent[i] = null;
                return;
              }
              absPath = path.resolve(sourcePath, sourceMap.sourceRoot, source);
            }

            // if current file: use content
            if (absPath === file.path) {
              sourceContent = fileContent;

            // else load content from file
            } else {
              try {
                if (options.debug)
                  console.log(PLUGIN_NAME + '-init: No source content for "' + source + '". Loading from file.');
                sourceContent = stripBom(fs.readFileSync(absPath, 'utf8'));
              } catch (e) {
                if (options.debug)
                  console.warn(PLUGIN_NAME + '-init: source file not found: ' + absPath);
              }
            }
            sourceMap.sourcesContent[i] = sourceContent;
          }
        });

        // remove source map comment from source
        file.contents = new Buffer(fileContent, 'utf8');
      }
    }

    if (!sourceMap) {
      // Make an empty source map
      sourceMap = {
        version : 3,
        names: [],
        mappings: '',
        sources: [unixStylePath(file.relative)],
        sourcesContent: [fileContent]
      };
    }

    sourceMap.file = unixStylePath(file.relative);
    file.sourceMap = sourceMap;

    this.push(file);
    callback();
  }

  return through.obj(sourceMapInit);
};

/**
 * Write the source map
 *
 * @param options options to change the way the source map is written
 *
 */
module.exports.write = function write(destPath, options) {
  if (options === undefined && Object.prototype.toString.call(destPath) === '[object Object]') {
    options = destPath;
    destPath = undefined;
  }
  options = options || {};

  // set defaults for options if unset
  if (options.includeContent === undefined)
    options.includeContent = true;
  if (options.addComment === undefined)
    options.addComment = true;

  function sourceMapWrite(file, encoding, callback) {
    /*jshint validthis:true */

    if (file.isNull() || !file.sourceMap) {
      this.push(file);
      return callback();
    }

    if (file.isStream()) {
      return callback(new Error(PLUGIN_NAME + '-write: Streaming not supported'));
    }

    var sourceMap = file.sourceMap;
    // fix paths if Windows style paths
    sourceMap.file = unixStylePath(file.relative);
    sourceMap.sources = sourceMap.sources.map(function(filePath) {
      return unixStylePath(filePath);
    });

    if (typeof options.sourceRoot === 'function') {
      sourceMap.sourceRoot = options.sourceRoot(file);
    } else {
      sourceMap.sourceRoot = options.sourceRoot;
    }

    if (options.includeContent) {
      sourceMap.sourcesContent = sourceMap.sourcesContent || [];

      // load missing source content
      for (var i = 0; i < file.sourceMap.sources.length; i++) {
        if (!sourceMap.sourcesContent[i]) {
          var sourcePath = path.resolve(sourceMap.sourceRoot || file.base, sourceMap.sources[i]);
          try {
            if (options.debug)
              console.log(PLUGIN_NAME + '-write: No source content for "' + sourceMap.sources[i] + '". Loading from file.');
            sourceMap.sourcesContent[i] = stripBom(fs.readFileSync(sourcePath, 'utf8'));
          } catch (e) {
            if (options.debug)
              console.warn(PLUGIN_NAME + '-write: source file not found: ' + sourcePath);
          }
        }
      }
      if (sourceMap.sourceRoot === null) {
        sourceMap.sourceRoot = undefined;
      } else {
        sourceMap.sourceRoot = sourceMap.sourceRoot || '/source/';
      }
    } else {
      delete sourceMap.sourcesContent;
    }

    var extension = file.relative.split('.').pop();
    var commentFormatter;

    switch (extension) {
      case 'css':
        commentFormatter = function(url) { return "\n/*# sourceMappingURL=" + url + " */"; };
        break;
      case 'js':
        commentFormatter = function(url) { return "\n//# sourceMappingURL=" + url; };
        break;
      default:
        commentFormatter = function(url) { return ""; };
    }

    var comment, sourceMappingURLPrefix;
    if (!destPath) {
      // encode source map into comment
      var base64Map = new Buffer(JSON.stringify(sourceMap)).toString('base64');
      comment = commentFormatter('data:application/json;base64,' + base64Map);
    } else {
      var source_map_path = path.join(file.base, destPath, file.relative) + '.map';
      // add new source map file to stream
      var sourceMapFile = new File({
        cwd: file.cwd,
        base: file.base,
        path: source_map_path,
        contents: new Buffer(JSON.stringify(sourceMap))
      });
      this.push(sourceMapFile);

      var source_map_path_relative = path.relative(path.dirname(file.path), source_map_path);

      var prefix = '';
      if (options.sourceMappingURLPrefix) {
        if (typeof options.sourceMappingURLPrefix === 'function') {
          prefix = options.sourceMappingURLPrefix(file);
        } else {
          prefix = options.sourceMappingURLPrefix;
        }
        source_map_path_relative = prefix+path.join('/', source_map_path_relative);
      }
      comment = commentFormatter(unixStylePath(source_map_path_relative));

    }

    // append source map comment
    if (options.addComment)
      file.contents = Buffer.concat([file.contents, new Buffer(comment)]);

    this.push(file);
    callback();
  }

  return through.obj(sourceMapWrite);
};

function unixStylePath(filePath) {
  return filePath.split(path.sep).join('/');
}
<commit_msg>Added sourcemap's file `stat` property to improve compatibility with other modules.<commit_after>'use strict';
var through = require('through2');
var fs = require('graceful-fs');
var path = require('path');
var File = require('vinyl');
var convert = require('convert-source-map');
var stripBom = require('strip-bom');

var PLUGIN_NAME = 'gulp-sourcemap';
var urlRegex = /^https?:\/\//;

/**
 * Initialize source mapping chain
 */
module.exports.init = function init(options) {
  function sourceMapInit(file, encoding, callback) {
    /*jshint validthis:true */

    if (file.isNull()) {
      this.push(file);
      return callback();
    }

    if (file.isStream()) {
      return callback(new Error(PLUGIN_NAME + '-init: Streaming not supported'));
    }

    var fileContent = file.contents.toString();
    var sourceMap;

    if (options && options.loadMaps) {
      var sourcePath = ''; //root path for the sources in the map

      // Try to read inline source map
      sourceMap = convert.fromSource(fileContent);
      if (sourceMap) {
        sourceMap = sourceMap.toObject();
        // sources in map are relative to the source file
        sourcePath = path.dirname(file.path);
        fileContent = convert.removeComments(fileContent);
      } else {
        // look for source map comment referencing a source map file
        var mapComment = convert.mapFileCommentRegex.exec(fileContent);

        var mapFile;
        if (mapComment) {
          mapFile = path.resolve(path.dirname(file.path), mapComment[1] || mapComment[2]);
          fileContent = convert.removeMapFileComments(fileContent);
        // if no comment try map file with same name as source file
        } else {
          mapFile = file.path + '.map';
        }

        // sources in external map are relative to map file
        sourcePath = path.dirname(mapFile);

        try {
          sourceMap = JSON.parse(stripBom(fs.readFileSync(mapFile, 'utf8')));
        } catch(e) {}
      }

      // fix source paths and sourceContent for imported source map
      if (sourceMap) {
        sourceMap.sourcesContent = sourceMap.sourcesContent || [];
        sourceMap.sources.forEach(function(source, i) {
          if (source.match(urlRegex)) {
            sourceMap.sourcesContent[i] = sourceMap.sourcesContent[i] || null;
            return;
          }
          var absPath = path.resolve(sourcePath, source);
          sourceMap.sources[i] = unixStylePath(path.relative(file.base, absPath));

          if (!sourceMap.sourcesContent[i]) {
            var sourceContent = null;
            if (sourceMap.sourceRoot) {
              if (sourceMap.sourceRoot.match(urlRegex)) {
                sourceMap.sourcesContent[i] = null;
                return;
              }
              absPath = path.resolve(sourcePath, sourceMap.sourceRoot, source);
            }

            // if current file: use content
            if (absPath === file.path) {
              sourceContent = fileContent;

            // else load content from file
            } else {
              try {
                if (options.debug)
                  console.log(PLUGIN_NAME + '-init: No source content for "' + source + '". Loading from file.');
                sourceContent = stripBom(fs.readFileSync(absPath, 'utf8'));
              } catch (e) {
                if (options.debug)
                  console.warn(PLUGIN_NAME + '-init: source file not found: ' + absPath);
              }
            }
            sourceMap.sourcesContent[i] = sourceContent;
          }
        });

        // remove source map comment from source
        file.contents = new Buffer(fileContent, 'utf8');
      }
    }

    if (!sourceMap) {
      // Make an empty source map
      sourceMap = {
        version : 3,
        names: [],
        mappings: '',
        sources: [unixStylePath(file.relative)],
        sourcesContent: [fileContent]
      };
    }

    sourceMap.file = unixStylePath(file.relative);
    file.sourceMap = sourceMap;

    this.push(file);
    callback();
  }

  return through.obj(sourceMapInit);
};

/**
 * Write the source map
 *
 * @param options options to change the way the source map is written
 *
 */
module.exports.write = function write(destPath, options) {
  if (options === undefined && Object.prototype.toString.call(destPath) === '[object Object]') {
    options = destPath;
    destPath = undefined;
  }
  options = options || {};

  // set defaults for options if unset
  if (options.includeContent === undefined)
    options.includeContent = true;
  if (options.addComment === undefined)
    options.addComment = true;

  function sourceMapWrite(file, encoding, callback) {
    /*jshint validthis:true */

    if (file.isNull() || !file.sourceMap) {
      this.push(file);
      return callback();
    }

    if (file.isStream()) {
      return callback(new Error(PLUGIN_NAME + '-write: Streaming not supported'));
    }

    var sourceMap = file.sourceMap;
    // fix paths if Windows style paths
    sourceMap.file = unixStylePath(file.relative);
    sourceMap.sources = sourceMap.sources.map(function(filePath) {
      return unixStylePath(filePath);
    });

    if (typeof options.sourceRoot === 'function') {
      sourceMap.sourceRoot = options.sourceRoot(file);
    } else {
      sourceMap.sourceRoot = options.sourceRoot;
    }

    if (options.includeContent) {
      sourceMap.sourcesContent = sourceMap.sourcesContent || [];

      // load missing source content
      for (var i = 0; i < file.sourceMap.sources.length; i++) {
        if (!sourceMap.sourcesContent[i]) {
          var sourcePath = path.resolve(sourceMap.sourceRoot || file.base, sourceMap.sources[i]);
          try {
            if (options.debug)
              console.log(PLUGIN_NAME + '-write: No source content for "' + sourceMap.sources[i] + '". Loading from file.');
            sourceMap.sourcesContent[i] = stripBom(fs.readFileSync(sourcePath, 'utf8'));
          } catch (e) {
            if (options.debug)
              console.warn(PLUGIN_NAME + '-write: source file not found: ' + sourcePath);
          }
        }
      }
      if (sourceMap.sourceRoot === null) {
        sourceMap.sourceRoot = undefined;
      } else {
        sourceMap.sourceRoot = sourceMap.sourceRoot || '/source/';
      }
    } else {
      delete sourceMap.sourcesContent;
    }

    var extension = file.relative.split('.').pop();
    var commentFormatter;

    switch (extension) {
      case 'css':
        commentFormatter = function(url) { return "\n/*# sourceMappingURL=" + url + " */"; };
        break;
      case 'js':
        commentFormatter = function(url) { return "\n//# sourceMappingURL=" + url; };
        break;
      default:
        commentFormatter = function(url) { return ""; };
    }

    var comment, sourceMappingURLPrefix;
    if (!destPath) {
      // encode source map into comment
      var base64Map = new Buffer(JSON.stringify(sourceMap)).toString('base64');
      comment = commentFormatter('data:application/json;base64,' + base64Map);
    } else {
      var source_map_path = path.join(file.base, destPath, file.relative) + '.map';
      // add new source map file to stream
      var sourceMapFile = new File({
        cwd: file.cwd,
        base: file.base,
        path: source_map_path,
        contents: new Buffer(JSON.stringify(sourceMap)),
        stat: {
          isFile: function () { return true; },
          isDirectory: function () { return false; },
          isBlockDevice: function () { return false; },
          isCharacterDevice: function () { return false; },
          isSymbolicLink: function () { return false; },
          isFIFO: function () { return false; },
          isSocket: function () { return false; }
        }
      });
      this.push(sourceMapFile);

      var source_map_path_relative = path.relative(path.dirname(file.path), source_map_path);

      var prefix = '';
      if (options.sourceMappingURLPrefix) {
        if (typeof options.sourceMappingURLPrefix === 'function') {
          prefix = options.sourceMappingURLPrefix(file);
        } else {
          prefix = options.sourceMappingURLPrefix;
        }
        source_map_path_relative = prefix+path.join('/', source_map_path_relative);
      }
      comment = commentFormatter(unixStylePath(source_map_path_relative));

    }

    // append source map comment
    if (options.addComment)
      file.contents = Buffer.concat([file.contents, new Buffer(comment)]);

    this.push(file);
    callback();
  }

  return through.obj(sourceMapWrite);
};

function unixStylePath(filePath) {
  return filePath.split(path.sep).join('/');
}
<|endoftext|>


<commit_before>'use babel';

import path from 'path';
import { CompositeDisposable, Emitter } from 'event-kit';
import TermView from './lib/term-view';
import ListView from './lib/list-view';
import store from './lib/store';

const capitalize = str => str[0].toUpperCase() + str.slice(1).toLowerCase();

function getColors(colors) {
  const {
    normalBlack,
    normalRed,
    normalGreen,
    normalYellow,
    normalBlue,
    normalPurple,
    normalCyan,
    normalWhite,
    brightBlack,
    brightRed,
    brightGreen,
    brightYellow,
    brightBlue,
    brightPurple,
    brightCyan,
    brightWhite,
    background,
    foreground,
  } = colors;
  return [
    normalBlack,
    normalRed,
    normalGreen,
    normalYellow,
    normalBlue,
    normalPurple,
    normalCyan,
    normalWhite,
    brightBlack,
    brightRed,
    brightGreen,
    brightYellow,
    brightBlue,
    brightPurple,
    brightCyan,
    brightWhite,
    background,
    foreground,
  ].map(color => (color.toHexString == null ? color : color.toHexString()));
}

function getFirstEditorPath() {
  const editors = atom.workspace.getTextEditors();
  if (editors.length > 0) {
    return editors[0].getPath();
  }
  return undefined;
}

function createColorsStyleSheet(colors) {
  const title = 'term3-colors';
  let ssEl = document.querySelector(`style[title="${title}"]`);
  if (ssEl != null) {
    ssEl.parentElement.removeChild(ssEl);
  }
  const stylePrefix = '.term3 .terminal';
  const styles = [];
  const addStyle = s => styles.push(stylePrefix + s);

  let i = 0;
  for (const c of Array.from(colors.slice(0, 16))) {
    addStyle(` .xterm-color-${i} { color: ${c}; }`);
    addStyle(` .xterm-bg-color-${i} { background-color: ${c}; }`);
    i += 1;
  }
  addStyle(` { background: ${colors[16]}; color: ${colors[17]}; }`);
  addStyle(
    ` .xterm-viewport { background: ${colors[16]}; color: ${colors[17]}; }`,
  );

  ssEl = document.createElement('style');
  ssEl.title = title;
  ssEl.innerHTML = styles.join('\n');
  return document.querySelector('head').appendChild(ssEl);
}

const config = {
  autoRunCommand: {
    type: 'string',
    default: '',
  },
  titleTemplate: {
    type: 'string',
    default: 'Terminal ({{ bashName }})',
  },
  fontFamily: {
    type: 'string',
    default: '',
  },
  fontSize: {
    type: 'string',
    default: '',
  },
  colors: {
    type: 'object',
    properties: {
      normalBlack: {
        type: 'color',
        default: '#2e3436',
      },
      normalRed: {
        type: 'color',
        default: '#cc0000',
      },
      normalGreen: {
        type: 'color',
        default: '#4e9a06',
      },
      normalYellow: {
        type: 'color',
        default: '#c4a000',
      },
      normalBlue: {
        type: 'color',
        default: '#3465a4',
      },
      normalPurple: {
        type: 'color',
        default: '#75507b',
      },
      normalCyan: {
        type: 'color',
        default: '#06989a',
      },
      normalWhite: {
        type: 'color',
        default: '#d3d7cf',
      },
      brightBlack: {
        type: 'color',
        default: '#555753',
      },
      brightRed: {
        type: 'color',
        default: '#ef2929',
      },
      brightGreen: {
        type: 'color',
        default: '#8ae234',
      },
      brightYellow: {
        type: 'color',
        default: '#fce94f',
      },
      brightBlue: {
        type: 'color',
        default: '#729fcf',
      },
      brightPurple: {
        type: 'color',
        default: '#ad7fa8',
      },
      brightCyan: {
        type: 'color',
        default: '#34e2e2',
      },
      brightWhite: {
        type: 'color',
        default: '#eeeeec',
      },
      background: {
        type: 'color',
        default: '#000000',
      },
      foreground: {
        type: 'color',
        default: '#f0f0f0',
      },
    },
  },
  scrollback: {
    type: 'integer',
    default: 1000,
  },
  cursorBlink: {
    type: 'boolean',
    default: true,
  },
  shellOverride: {
    type: 'string',
    default: '',
  },
  shellArguments: {
    type: 'array',
    default: (({ SHELL, HOME }) => {
      switch (path.basename(SHELL && SHELL.toLowerCase())) {
        case 'bash':
          return ['--init-file', path.join(HOME, '.bash_profile')];
        case 'zsh':
          return ['-l'];
        default:
          return [];
      }
    })(process.env),
  },
  openPanesInSameSplit: {
    type: 'boolean',
    default: false,
  },
};

export default {
  termViews: [],
  focusedTerminal: false,
  emitter: new Emitter(),
  config,
  disposables: null,

  activate(state) {
    this.state = state;
    this.disposables = new CompositeDisposable();

    if (!process.env.LANG) {
      console.warn(
        'Term3: LANG environment variable is not set. Fancy characters (å, ñ, ó, etc`) may be corrupted. The only work-around is to quit Atom and run `atom` from your shell.',
      );
    }

    ['up', 'right', 'down', 'left'].forEach(direction =>
      this.disposables.add(
        atom.commands.add(
          'atom-workspace',
          `term3:open-split-${direction}`,
          this.splitTerm.bind(this, direction),
        ),
      ),
    );

    this.disposables.add(
      atom.config.observe('term3.colors', cs =>
        createColorsStyleSheet(getColors(cs)),
      ),
    );

    this.disposables.add(
      atom.commands.add(
        'atom-workspace',
        'term3:open',
        this.newTerm.bind(this),
      ),
    );
    this.disposables.add(
      atom.commands.add(
        'atom-workspace',
        'term3:pipe-path',
        this.pipeTerm.bind(this, 'path'),
      ),
    );
    this.disposables.add(
      atom.commands.add(
        'atom-workspace',
        'term3:pipe-selection',
        this.pipeTerm.bind(this, 'selection'),
      ),
    );

    this.disposables.add(
      atom.workspace.addOpener(uri => {
        if (uri === 'atom://term3-term-view') {
          this.newTerm();
        }
      }),
    );

    this.disposables.add(
      atom.workspace.observeActivePaneItem(item => {
        if (item instanceof TermView) {
          item.focus();
        }
      }),
    );

    this.disposables.add(
      atom.packages.onDidActivatePackage(pkg => {
        if (pkg.name !== 'tree-view') {
          return;
        }
        const node = new ListView();
        const treeView = pkg.mainModule.treeView.element;
        const el = treeView.querySelector('.tree-view-scroller');
        el.insertBefore(node, el.firstChild);
      }),
    );
  },

  service_0_1_3() {
    return {
      getTerminals: this.getTerminals.bind(this),
      onTerm: this.onTerm.bind(this),
      newTerm: this.newTerm.bind(this),
    };
  },

  getTerminals() {
    return store.getState().terminals.map(t => t.term);
  },

  onTerm(callback) {
    return this.emitter.on('term', callback);
  },

  newTerm(forkPTY = true, rows = 30, cols = 80, title = 'tty') {
    const termView = this.createTermView(forkPTY, rows, cols, title);
    const pane = atom.workspace.getActivePane();
    const item = pane.addItem(termView);
    pane.activateItem(item);
    return termView;
  },

  createTermView(forkPTY = true, rows = 30, cols = 80, title = 'tty') {
    const opts = {
      runCommand: atom.config.get('term3.autoRunCommand'),
      shellOverride: atom.config.get('term3.shellOverride'),
      shellArguments: atom.config.get('term3.shellArguments'),
      titleTemplate: atom.config.get('term3.titleTemplate'),
      cursorBlink: atom.config.get('term3.cursorBlink'),
      fontFamily: atom.config.get('term3.fontFamily'),
      fontSize: atom.config.get('term3.fontSize'),
      forkPTY,
      rows,
      cols,
    };

    if (opts.shellOverride) {
      opts.shell = opts.shellOverride;
    } else {
      opts.shell = process.env.SHELL || 'bash';
    }

    opts.cwd =
      opts.cwd ||
      atom.project.getPaths()[0] ||
      getFirstEditorPath() ||
      process.env.HOME;

    const termView = new TermView(opts);
    const model = store.addTerminal({
      local: !!forkPTY,
      term: termView,
      title,
    }).terminal;
    const { id } = model;
    termView.id = id;

    termView.onExit(() => this.handleRemoveTerm(termView));

    termView.onDidChangeTitle(() => {
      let newTitle = null;
      if (forkPTY) {
        newTitle = termView.getTitle();
      } else {
        newTitle = `${title}-${termView.getTitle()}`;
      }
      store.updateTerminal({ id: termView.id, title: newTitle });
    });

    termView.onFocus(() => {
      this.focusedTerminal = termView;
      store.setActiveTerminal(termView);
    });

    termView.onBlur(() => {
      store.setActiveTerminal(null);
    });

    if (typeof this.termViews.push === 'function') {
      this.termViews.push(termView);
    }
    process.nextTick(() => this.emitter.emit('term', termView));
    return termView;
  },

  splitTerm(dir) {
    let pane;
    const openPanesInSameSplit = atom.config.get('term3.openPanesInSameSplit');
    const termView = this.createTermView();
    const direction = capitalize(dir);
    const activePane = atom.workspace.getActivePane();

    const splitter = () => {
      pane = activePane[`split${direction}`]({ items: [termView] });
      activePane.termSplits[direction] = pane;
      this.focusedTerminal = [pane, pane.items[0]];
    };

    if (!activePane.termSplits) {
      activePane.termSplits = {};
    }
    if (openPanesInSameSplit) {
      if (
        activePane.termSplits[direction] &&
        activePane.termSplits[direction].items.length > 0
      ) {
        pane = activePane.termSplits[direction];
        const item = pane.addItem(termView);
        pane.activateItem(item);
        this.focusedTerminal = [pane, item];
      } else {
        splitter();
      }
    } else {
      splitter();
    }
  },

  pipeTerm(action) {
    const editor = atom.workspace.getActiveTextEditor();
    if (!editor) {
      return;
    }
    const stream = (() => {
      switch (action) {
        case 'path':
          return editor.getBuffer().file.path;
        case 'selection':
          return editor.getSelectedText();
        default:
          return null;
      }
    })();

    const itemInput = i => {
      i.input(stream.trim());
      i.focus();
    };

    if (stream && this.focusedTerminal) {
      if (Array.isArray(this.focusedTerminal)) {
        const [pane, item] = Array.from(this.focusedTerminal);
        pane.activateItem(item);
        itemInput(item);
      } else {
        itemInput(this.focusedTerminal);
      }
    }
  },

  handleRemoveTerm(termView) {
    store.removeTerminal(termView);
    this.termViews.splice(this.termViews.indexOf(termView), 1);
  },

  deactivate() {
    this.termViews.forEach(view => view.exit());
    this.termViews = [];
    this.disposables.dispose();
  },

  deserializeTermView() {
    return this.createTermView();
  },
};
<commit_msg>Simplified tracking of active terminal pane<commit_after>'use babel';

import path from 'path';
import { CompositeDisposable, Emitter } from 'event-kit';
import TermView from './lib/term-view';
import ListView from './lib/list-view';
import store from './lib/store';

const capitalize = str => str[0].toUpperCase() + str.slice(1).toLowerCase();

function getColors(colors) {
  const {
    normalBlack,
    normalRed,
    normalGreen,
    normalYellow,
    normalBlue,
    normalPurple,
    normalCyan,
    normalWhite,
    brightBlack,
    brightRed,
    brightGreen,
    brightYellow,
    brightBlue,
    brightPurple,
    brightCyan,
    brightWhite,
    background,
    foreground,
  } = colors;
  return [
    normalBlack,
    normalRed,
    normalGreen,
    normalYellow,
    normalBlue,
    normalPurple,
    normalCyan,
    normalWhite,
    brightBlack,
    brightRed,
    brightGreen,
    brightYellow,
    brightBlue,
    brightPurple,
    brightCyan,
    brightWhite,
    background,
    foreground,
  ].map(color => (color.toHexString == null ? color : color.toHexString()));
}

function getFirstEditorPath() {
  const editors = atom.workspace.getTextEditors();
  if (editors.length > 0) {
    return editors[0].getPath();
  }
  return undefined;
}

function createColorsStyleSheet(colors) {
  const title = 'term3-colors';
  let ssEl = document.querySelector(`style[title="${title}"]`);
  if (ssEl != null) {
    ssEl.parentElement.removeChild(ssEl);
  }
  const stylePrefix = '.term3 .terminal';
  const styles = [];
  const addStyle = s => styles.push(stylePrefix + s);

  let i = 0;
  for (const c of Array.from(colors.slice(0, 16))) {
    addStyle(` .xterm-color-${i} { color: ${c}; }`);
    addStyle(` .xterm-bg-color-${i} { background-color: ${c}; }`);
    i += 1;
  }
  addStyle(` { background: ${colors[16]}; color: ${colors[17]}; }`);
  addStyle(
    ` .xterm-viewport { background: ${colors[16]}; color: ${colors[17]}; }`,
  );

  ssEl = document.createElement('style');
  ssEl.title = title;
  ssEl.innerHTML = styles.join('\n');
  return document.querySelector('head').appendChild(ssEl);
}

const config = {
  autoRunCommand: {
    type: 'string',
    default: '',
  },
  titleTemplate: {
    type: 'string',
    default: 'Terminal ({{ bashName }})',
  },
  fontFamily: {
    type: 'string',
    default: '',
  },
  fontSize: {
    type: 'string',
    default: '',
  },
  colors: {
    type: 'object',
    properties: {
      normalBlack: {
        type: 'color',
        default: '#2e3436',
      },
      normalRed: {
        type: 'color',
        default: '#cc0000',
      },
      normalGreen: {
        type: 'color',
        default: '#4e9a06',
      },
      normalYellow: {
        type: 'color',
        default: '#c4a000',
      },
      normalBlue: {
        type: 'color',
        default: '#3465a4',
      },
      normalPurple: {
        type: 'color',
        default: '#75507b',
      },
      normalCyan: {
        type: 'color',
        default: '#06989a',
      },
      normalWhite: {
        type: 'color',
        default: '#d3d7cf',
      },
      brightBlack: {
        type: 'color',
        default: '#555753',
      },
      brightRed: {
        type: 'color',
        default: '#ef2929',
      },
      brightGreen: {
        type: 'color',
        default: '#8ae234',
      },
      brightYellow: {
        type: 'color',
        default: '#fce94f',
      },
      brightBlue: {
        type: 'color',
        default: '#729fcf',
      },
      brightPurple: {
        type: 'color',
        default: '#ad7fa8',
      },
      brightCyan: {
        type: 'color',
        default: '#34e2e2',
      },
      brightWhite: {
        type: 'color',
        default: '#eeeeec',
      },
      background: {
        type: 'color',
        default: '#000000',
      },
      foreground: {
        type: 'color',
        default: '#f0f0f0',
      },
    },
  },
  scrollback: {
    type: 'integer',
    default: 1000,
  },
  cursorBlink: {
    type: 'boolean',
    default: true,
  },
  shellOverride: {
    type: 'string',
    default: '',
  },
  shellArguments: {
    type: 'array',
    default: (({ SHELL, HOME }) => {
      switch (path.basename(SHELL && SHELL.toLowerCase())) {
        case 'bash':
          return ['--init-file', path.join(HOME, '.bash_profile')];
        case 'zsh':
          return ['-l'];
        default:
          return [];
      }
    })(process.env),
  },
  openPanesInSameSplit: {
    type: 'boolean',
    default: false,
  },
};

export default {
  termViews: [],
  focusedTerminal: false,
  emitter: new Emitter(),
  config,
  disposables: null,

  activate(state) {
    this.state = state;
    this.disposables = new CompositeDisposable();

    if (!process.env.LANG) {
      console.warn(
        'Term3: LANG environment variable is not set. Fancy characters (å, ñ, ó, etc`) may be corrupted. The only work-around is to quit Atom and run `atom` from your shell.',
      );
    }

    ['up', 'right', 'down', 'left'].forEach(direction =>
      this.disposables.add(
        atom.commands.add(
          'atom-workspace',
          `term3:open-split-${direction}`,
          this.splitTerm.bind(this, direction),
        ),
      ),
    );

    this.disposables.add(
      atom.config.observe('term3.colors', cs =>
        createColorsStyleSheet(getColors(cs)),
      ),
    );

    this.disposables.add(
      atom.commands.add(
        'atom-workspace',
        'term3:open',
        this.newTerm.bind(this),
      ),
    );
    this.disposables.add(
      atom.commands.add(
        'atom-workspace',
        'term3:pipe-path',
        this.pipeTerm.bind(this, 'path'),
      ),
    );
    this.disposables.add(
      atom.commands.add(
        'atom-workspace',
        'term3:pipe-selection',
        this.pipeTerm.bind(this, 'selection'),
      ),
    );

    this.disposables.add(
      atom.workspace.addOpener(uri => {
        if (uri === 'atom://term3-term-view') {
          this.newTerm();
        }
      }),
    );

    this.disposables.add(
      atom.workspace.observeActivePaneItem(item => {
        if (item instanceof TermView) {
          item.focus();
        }
      }),
    );

    this.disposables.add(
      atom.packages.onDidActivatePackage(pkg => {
        if (pkg.name !== 'tree-view') {
          return;
        }
        const node = new ListView();
        const treeView = pkg.mainModule.treeView.element;
        const el = treeView.querySelector('.tree-view-scroller');
        el.insertBefore(node, el.firstChild);
      }),
    );
  },

  service_0_1_3() {
    return {
      getTerminals: this.getTerminals.bind(this),
      onTerm: this.onTerm.bind(this),
      newTerm: this.newTerm.bind(this),
    };
  },

  getTerminals() {
    return store.getState().terminals.map(t => t.term);
  },

  onTerm(callback) {
    return this.emitter.on('term', callback);
  },

  newTerm(forkPTY = true, rows = 30, cols = 80, title = 'tty') {
    const termView = this.createTermView(forkPTY, rows, cols, title);
    const pane = atom.workspace.getActivePane();
    const item = pane.addItem(termView);
    pane.activateItem(item);
    return termView;
  },

  createTermView(forkPTY = true, rows = 30, cols = 80, title = 'tty') {
    const opts = {
      runCommand: atom.config.get('term3.autoRunCommand'),
      shellOverride: atom.config.get('term3.shellOverride'),
      shellArguments: atom.config.get('term3.shellArguments'),
      titleTemplate: atom.config.get('term3.titleTemplate'),
      cursorBlink: atom.config.get('term3.cursorBlink'),
      fontFamily: atom.config.get('term3.fontFamily'),
      fontSize: atom.config.get('term3.fontSize'),
      forkPTY,
      rows,
      cols,
    };

    if (opts.shellOverride) {
      opts.shell = opts.shellOverride;
    } else {
      opts.shell = process.env.SHELL || 'bash';
    }

    opts.cwd =
      opts.cwd ||
      atom.project.getPaths()[0] ||
      getFirstEditorPath() ||
      process.env.HOME;

    const termView = new TermView(opts);
    const model = store.addTerminal({
      local: !!forkPTY,
      term: termView,
      title,
    }).terminal;
    const { id } = model;
    termView.id = id;

    termView.onExit(() => this.handleRemoveTerm(termView));

    termView.onDidChangeTitle(() => {
      let newTitle = null;
      if (forkPTY) {
        newTitle = termView.getTitle();
      } else {
        newTitle = `${title}-${termView.getTitle()}`;
      }
      store.updateTerminal({ id: termView.id, title: newTitle });
    });

    termView.onFocus(() => {
      this.focusedTerminal = termView;
      store.setActiveTerminal(termView);
    });

    termView.onBlur(() => {
      store.setActiveTerminal(null);
    });

    if (typeof this.termViews.push === 'function') {
      this.termViews.push(termView);
    }
    process.nextTick(() => this.emitter.emit('term', termView));
    return termView;
  },

  splitTerm(dir) {
    let pane;
    const openPanesInSameSplit = atom.config.get('term3.openPanesInSameSplit');
    const termView = this.createTermView();
    const direction = capitalize(dir);
    const activePane = atom.workspace.getActivePane();

    const splitter = () => {
      pane = activePane[`split${direction}`]({ items: [termView] });
      activePane.termSplits[direction] = pane;
    };

    if (!activePane.termSplits) {
      activePane.termSplits = {};
    }
    if (openPanesInSameSplit) {
      if (
        activePane.termSplits[direction] &&
        activePane.termSplits[direction].items.length > 0
      ) {
        pane = activePane.termSplits[direction];
        const item = pane.addItem(termView);
        pane.activateItem(item);
      } else {
        splitter();
      }
    } else {
      splitter();
    }
  },

  pipeTerm(action) {
    const editor = atom.workspace.getActiveTextEditor();
    if (!editor) {
      return;
    }
    const stream = (() => {
      switch (action) {
        case 'path':
          return editor.getBuffer().file.path;
        case 'selection':
          return editor.getSelectedText();
        default:
          return null;
      }
    })();

    if (stream && this.focusedTerminal) {
      this.focusedTerminal.input(stream.trim());
      this.focusedTerminal.focusAndActivatePane();
    }
  },

  handleRemoveTerm(termView) {
    store.removeTerminal(termView);
    this.termViews.splice(this.termViews.indexOf(termView), 1);
  },

  deactivate() {
    this.termViews.forEach(view => view.exit());
    this.termViews = [];
    this.disposables.dispose();
  },

  deserializeTermView() {
    return this.createTermView();
  },
};
<|endoftext|>