<commit_before>diamondash.components.structures = function() {
  var utils = diamondash.utils;

  function Extendable() {}
  Extendable.extend = Backbone.Model.extend;

  var Eventable = Extendable.extend(Backbone.Events);

  var ColorMaker = Extendable.extend({
    constructor: function(options) {
      options = _({}).defaults(options, this.defaults);
      this.colors = options.scale.domain(d3.range(0, options.n));
      this.i = 0;
    },

    defaults: {
      scale: d3.scale.category10(),
      n: 10
    },

    next: function() {
      return this.colors(this.i++);
    }
  });

  Registry = Eventable.extend({
    constructor: function(items) {
      this.items = {};
      
      _(items || {}).each(function(data, name) {
        this.add(name, data);
      }, this);
    },

    processAdd: function(name, data) {
      return data;
    },

    processGet: function(name, data) {
      return data;
    },

    add: function(name, data) {
      if (name in this.items) {
        throw new Error("'" + name + "' is already registered.");
      }

      data = this.processAdd(name, data);
      this.trigger('add', name, data);
      this.items[name] = data;
    },

    get: function(name) {
      return this.processGet(name, this.items[name]);
    },

    remove: function(name) {
      var data = this.items[name];
      this.trigger('remove', name, data);
      delete this.items[name];
      return data;
    }
  });

  var ViewSet = Extendable.extend.call(Backbone.ChildViewContainer, {
    keyOf: function(view) {
      return _(view).result('id');
    },

    ensureKey: function(obj) {
      return obj instanceof Backbone.View
        ? this.keyOf(obj)
        : obj;
    },

    get: function(key) {
      return this.findByCustom(key);
    },

    add: function(widget, key) {
      if (typeof key == 'undefined') { key = this.keyOf(widget); }
      return ViewSet.__super__.add.call(this, widget, key);
    },

    remove: function(obj) {
      var widget = this.get(this.ensureKey(obj));
      if (widget) { ViewSet.__super__.remove.call(this, widget); }
      return this;
    },

    each: function(fn, that) {
      that = that || this;

      for (var k in this._indexByCustom) {
        fn.call(that, this.get(k), k);
      }
    }
  });

  ViewSet.extend = Extendable.extend;

  var SubviewSet = ViewSet.extend({
    constructor: function(options) {
      SubviewSet.__super__.constructor.call(this);
      this.parent = options.parent;
    },

    selector: function(key) {
      return key;
    },

    render: function() {
      this.each(function(view, key) {
        view.setElement(this.parent.$(this.selector(key)), true);
      }, this);

      this.apply('render', arguments);
    }
  });

  return {
    Extendable: Extendable,
    Eventable: Eventable,
    Registry: Registry,
    ColorMaker: ColorMaker,
    ViewSet: ViewSet,
    SubviewSet: SubviewSet
  };
}.call(this);
<commit_msg>Allow a SubviewSet's parent instance to be aliased<commit_after>diamondash.components.structures = function() {
  var utils = diamondash.utils;

  function Extendable() {}
  Extendable.extend = Backbone.Model.extend;

  var Eventable = Extendable.extend(Backbone.Events);

  var ColorMaker = Extendable.extend({
    constructor: function(options) {
      options = _({}).defaults(options, this.defaults);
      this.colors = options.scale.domain(d3.range(0, options.n));
      this.i = 0;
    },

    defaults: {
      scale: d3.scale.category10(),
      n: 10
    },

    next: function() {
      return this.colors(this.i++);
    }
  });

  Registry = Eventable.extend({
    constructor: function(items) {
      this.items = {};
      
      _(items || {}).each(function(data, name) {
        this.add(name, data);
      }, this);
    },

    processAdd: function(name, data) {
      return data;
    },

    processGet: function(name, data) {
      return data;
    },

    add: function(name, data) {
      if (name in this.items) {
        throw new Error("'" + name + "' is already registered.");
      }

      data = this.processAdd(name, data);
      this.trigger('add', name, data);
      this.items[name] = data;
    },

    get: function(name) {
      return this.processGet(name, this.items[name]);
    },

    remove: function(name) {
      var data = this.items[name];
      this.trigger('remove', name, data);
      delete this.items[name];
      return data;
    }
  });

  var ViewSet = Extendable.extend.call(Backbone.ChildViewContainer, {
    keyOf: function(view) {
      return _(view).result('id');
    },

    ensureKey: function(obj) {
      return obj instanceof Backbone.View
        ? this.keyOf(obj)
        : obj;
    },

    get: function(key) {
      return this.findByCustom(key);
    },

    add: function(widget, key) {
      if (typeof key == 'undefined') { key = this.keyOf(widget); }
      return ViewSet.__super__.add.call(this, widget, key);
    },

    remove: function(obj) {
      var widget = this.get(this.ensureKey(obj));
      if (widget) { ViewSet.__super__.remove.call(this, widget); }
      return this;
    },

    each: function(fn, that) {
      that = that || this;

      for (var k in this._indexByCustom) {
        fn.call(that, this.get(k), k);
      }
    }
  });

  ViewSet.extend = Extendable.extend;

  var SubviewSet = ViewSet.extend({
    parentAlias: 'parent',

    constructor: function(options) {
      SubviewSet.__super__.constructor.call(this);

      this.parent = options[this.parentAlias];
      this[this.parentAlias] = this.parent;
    },

    selector: function(key) {
      return key;
    },

    render: function() {
      this.each(function(view, key) {
        view.setElement(this.parent.$(this.selector(key)), true);
      }, this);

      this.apply('render', arguments);
    }
  });

  return {
    Extendable: Extendable,
    Eventable: Eventable,
    Registry: Registry,
    ColorMaker: ColorMaker,
    ViewSet: ViewSet,
    SubviewSet: SubviewSet
  };
}.call(this);

{'fraction_non_alphanumeric': 0.1481543343911809, 'fraction_numerical': 0.002672456990145315, 'mean_word_length': 2.471304347826087, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3097670', 'n_tokens_mistral': 1956, 'n_tokens_neox': 1884, 'n_words': 387}