(function() {
  var $, Chorus, EQUAL, LESS, MORE, OrderedSet, PubSub, Status, Timeline, View, eq, extend, gt, inArray, iso_datestring, makeArray, sort, trim, uniquify, _ref, _ref2;
  var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __indexOf = Array.prototype.indexOf || function(item) {
    for (var i = 0, l = this.length; i < l; i++) {
      if (this[i] === item) return i;
    }
    return -1;
  };
  Chorus = (_ref = this.Chorus) != null ? _ref : this.Chorus = {};
  _ref2 = $ = jQuery, inArray = _ref2.inArray, makeArray = _ref2.makeArray, extend = _ref2.extend;
  OrderedSet = (function() {
    function OrderedSet(arr, ordered, uniq) {
      this.items = arr || [];
      if (!uniq) {
        uniquify(this);
      } else if (!ordered) {
        sort(this);
      }
      this.length = this.items.length;
    }
    OrderedSet.prototype.contains = function(a) {
      var item, _i, _len, _ref3;
      _ref3 = this.items;
      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
        item = _ref3[_i];
        if (eq(a, item)) {
          return true;
        }
        if (gt(item, a)) {
          return false;
        }
      }
      return false;
    };
    OrderedSet.prototype.toArray = function() {
      return this.items.slice();
    };
    OrderedSet.prototype.slice = function(a, b) {
      return this.items.slice(a, b);
    };
    OrderedSet.prototype.item = function(i) {
      return this.items[i];
    };
    OrderedSet.prototype.concat = function(ls) {
      var item, out, _i, _len;
      out = [];
      if (ls instanceof OrderedSet) {
        ls = ls.items;
      }
      for (_i = 0, _len = ls.length; _i < _len; _i++) {
        item = ls[_i];
        if (!this.contains(item)) {
          out.push(item);
        }
      }
      if (out.length === 0) {
        return this;
      } else {
        return new OrderedSet(this.items.concat(out), true);
      }
    };
    return OrderedSet;
  })();
  LESS = -1;
  MORE = 1;
  EQUAL = 0;
  sort = function(set) {
    return set.items.sort(function(a, b) {
      if (gt(a, b)) {
        return MORE;
      } else if (gt(b, a)) {
        return LESS;
      } else {
        return EQUAL;
      }
    });
  };
  uniquify = function(set) {
    var current, i, items, len;
    i = 0;
    len = set.items.length;
    items = [];
    sort(set);
    while (i < len) {
      items.push(current = set.items[i]);
      while (i < len && eq(current, set.items[i])) {
        i++;
      }
    }
    return set.items = items;
  };
  eq = function(a, b) {
    if (a.__eq__) {
      return a.__eq__(b);
    } else {
      return a === b;
    }
  };
  gt = function(a, b) {
    if (a.__gt__) {
      return a.__gt__(b);
    } else {
      return a > b;
    }
  };
  PubSub = (function() {
    function PubSub() {}
    PubSub.prototype.__subscribers__ = [];
    PubSub.prototype.subscribe = function(publisher) {
      return publisher.addSubscriber(this);
    };
    PubSub.prototype.unsubscribe = function(publisher) {
      publisher.removeSubscriber(this);
      return this;
    };
    PubSub.prototype.publish = function(data) {
      var sub, _i, _len, _ref3;
      _ref3 = this.__subscribers__;
      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
        sub = _ref3[_i];
        sub.update(data, this);
      }
      return this;
    };
    PubSub.prototype.update = function() {
      return this;
    };
    PubSub.prototype.addSubscriber = function(subscriber) {
      if (inArray(this.__subscribers__, subscriber) === -1) {
        this.__subscribers__ = this.__subscribers__.concat([subscriber]);
      }
      return this;
    };
    PubSub.prototype.removeSubscriber = function(subscriber) {
      var index;
      index = inArray(this.__subscribers__, subscriber);
      if (index !== -1) {
        return this.__subscribers__.splice(index, 1);
      }
    };
    PubSub.bind = function(object, fn) {
      var listener;
      listener = new PubSub();
      listener.update = function(data, src) {
        fn.call(listener, data, src);
        return this.publish(data);
      };
      listener.subscribe(object);
      return listener;
    };
    return PubSub;
  })();
  Status = (function() {
    function Status(id, username, avatar, date, text, raw) {
      this.id = id;
      this.username = username;
      this.avatar = avatar;
      this.text = text;
      this.raw = raw;
      this.date = new Date(date);
    }
    Status.prototype.toKey = function() {
      return "<Status:" + this.username + " ID:" + this.id + ">";
    };
    Status.prototype.toElement = function(options) {
      var body, el, element, elements, extra, extras, fn;
      if (options == null) {
        options = {};
      }
      body = this.renderBody();
      element = $('<div class="status" />');
      element.append(this.renderAvatar(), this.renderScreenName(), body, this.renderTimestamp());
      if (options.extras != null) {
        extras = (function() {
          var _i, _len, _ref3, _results;
          _ref3 = options.extras;
          _results = [];
          for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
            fn = _ref3[_i];
            _results.push(fn(element, body, this));
          }
          return _results;
        }).call(this);
        elements = (function() {
          var _i, _len, _results;
          _results = [];
          for (_i = 0, _len = extras.length; _i < _len; _i++) {
            extra = extras[_i];
            if (extra) {
              _results.push(extra);
            }
          }
          return _results;
        })();
        if (elements.length > 0) {
          el = $('<div class="extras" />');
          element.append(el);
          el.append.apply(el, elements);
        }
      }
      return element;
    };
    Status.prototype.getAvatar = function() {
      return this.avatar || ("http://robohash.org/" + this.username + ".png?size=48x48");
    };
    Status.prototype.getUrl = function() {
      return null;
    };
    Status.prototype.getStreamUrl = function() {
      return null;
    };
    Status.prototype.renderAvatar = function() {
      return "<a href=\"" + (this.getStreamUrl()) + "\" class=\"avatar\">\n    <img src=\"" + (this.getAvatar()) + "\" class=\"avatar\" />\n</a>";
    };
    Status.prototype.renderTimestamp = function() {
      var el;
      el = $("<a class=\"date\"\n   href=\"" + (this.getUrl()) + "\"\n   title=\"" + (iso_datestring(this.date)) + "\">\n    " + (this.date.toLocaleTimeString()) + " " + (this.date.toLocaleDateString()) + "\n</a>");
      if ($.fn.timeago != null) {
        return el.timeago();
      } else {
        return el;
      }
    };
    Status.prototype.renderScreenName = function() {
      return "<a class=\"username\"\n   href=\"" + (this.getStreamUrl()) + "\">\n    " + this.username + "\n</a>";
    };
    Status.prototype.renderBody = function() {
      return "<div class=\"statusBody\">" + (this.text.replace('\n', '<br />')) + "</div>";
    };
    Status.prototype.raw = null;
    Status.prototype.__eq__ = function(status) {
      return this.toKey() === status.toKey();
    };
    Status.prototype.__gt__ = function(status) {
      return this.date.getTime() < status.date.getTime();
    };
    return Status;
  })();
  iso_datestring = function(d) {
    var day, hours, minutes, month, pad, seconds, year;
    pad = function(n) {
      if (n < 10) {
        return '0' + n;
      } else {
        return n;
      }
    };
    year = pad(d.getUTCFullYear());
    month = pad(d.getUTCMonth() + 1);
    day = pad(d.getUTCDate());
    hours = pad(d.getUTCHours());
    minutes = pad(d.getUTCMinutes());
    seconds = pad(d.getUTCSeconds());
    return "" + year + "-" + month + "-" + day + "T" + hours + ":" + minutes + ":" + seconds + "Z";
  };
  Timeline = (function() {
    __extends(Timeline, PubSub);
    function Timeline(options) {
      this.options = extend({}, this.options, options);
      if (this.options.updateOnStart) {
        this.fetch();
      }
      if (this.options.updatePeriod) {
        this.startUpdates();
      }
    }
    Timeline.prototype.options = {
      count: 25,
      updateOnStart: true,
      updatePeriod: 90000,
      filter: function(status) {
        return true;
      }
    };
    Timeline.prototype.statuses = new OrderedSet();
    Timeline.prototype.subscribers = [];
    Timeline.prototype.timer = null;
    Timeline.prototype.fetch = function() {
      throw Error("Not Implemented");
    };
    Timeline.prototype.startUpdates = function(period) {
            if (period != null) {
        period;
      } else {
        period = this.options.updatePeriod;
      };
      return this.timer = setInterval((__bind(function() {
        return this.fetch();
      }, this)), period);
    };
    Timeline.prototype.stopUpdates = function() {
      clearInterval(this.timer);
      return this.timer = null;
    };
    Timeline.prototype.update = function(data, source) {
      var s, statuses;
      statuses = (function() {
        var _i, _len, _ref3, _results;
        _ref3 = this.statusesFromData(data);
        _results = [];
        for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
          s = _ref3[_i];
          if (!this.statuses.contains(s)) {
            _results.push(s);
          }
        }
        return _results;
      }).call(this);
      if ($.type(this.options.filter) === 'function') {
        statuses = (function() {
          var _i, _len, _results;
          _results = [];
          for (_i = 0, _len = statuses.length; _i < _len; _i++) {
            s = statuses[_i];
            if (this.options.filter.call(this, s)) {
              _results.push(s);
            }
          }
          return _results;
        }).call(this);
      }
      if (statuses.length > 0) {
        this.statuses = this.statuses.concat(statuses);
        return this.publish(statuses);
      }
    };
    Timeline.shorthands = [];
    Timeline.from = function(t) {
      var match, short, _i, _len, _ref3;
      if (t instanceof Timeline) {
        return t;
      }
      t = trim(t);
      _ref3 = Timeline.shorthands;
      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
        short = _ref3[_i];
        match = short.pattern.exec(t);
        if (match) {
          return short.fun.apply(short, match);
        }
      }
      return null;
    };
    return Timeline;
  })();
  trim = function(str) {
    return str.replace(/^\s*/, '').replace(/\s*$/, '');
  };
  View = (function() {
    __extends(View, PubSub);
    function View(options) {
      var feed, _i, _len, _ref3;
      this.options = extend({}, this.options, options);
      _ref3 = this.options.feeds;
      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
        feed = _ref3[_i];
        if (feed != null) {
          this.subscribe(feed);
        }
      }
      this.loading = true;
      if (this.options.container != null) {
        this.toElement().appendTo(this.options.container);
      }
    }
    View.prototype.options = {
      count: 10,
      feeds: [],
      container: false,
      renderOptions: {},
      filter: function() {
        return true;
      }
    };
    View.prototype.renderStatus = function(status) {
      var cache, options, _name, _ref3, _ref4;
      cache = (_ref3 = this.htmlCache) != null ? _ref3 : this.htmlCache = {};
      options = this.options.renderOptions;
      return (_ref4 = cache[_name = status.toKey()]) != null ? _ref4 : cache[_name] = status.toElement(options);
    };
    View.prototype.statuses = new OrderedSet();
    View.prototype.htmlCache = null;
    View.prototype.subscribe = function(pub) {
      return View.__super__.subscribe.call(this, Timeline.from(pub));
    };
    View.prototype.update = function(data, source) {
      var new_statuses, s, statuses;
      new_statuses = (function() {
        var _i, _len, _ref3, _results;
        _ref3 = source.statuses.slice(0, this.options.count);
        _results = [];
        for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
          s = _ref3[_i];
          if (this.options.filter(s)) {
            _results.push(s);
          }
        }
        return _results;
      }).call(this);
      statuses = this.statuses.concat(new_statuses);
      if (statuses !== this.statuses) {
        this.loading = false;
        this.statuses = statuses;
        return this.publish(statuses);
      }
    };
    View.prototype.toElement = function() {
      var element;
      element = $('<div class="view chorus_view" />');
      if (this.loading) {
        element.addClass('loading');
      }
      PubSub.bind(this, __bind(function() {
        return this.updateElement(element);
      }, this));
      this.updateElement(element);
      return element.data('View', this);
    };
    View.prototype.updateElement = function(element) {
      var children, status, statuses, _ref3;
      if (!this.loading) {
        element.removeClass('loading');
      }
      statuses = this.statuses.slice(0, this.options.count);
      children = (function() {
        var _i, _len, _results;
        _results = [];
        for (_i = 0, _len = statuses.length; _i < _len; _i++) {
          status = statuses[_i];
          _results.push(this.renderStatus(status));
        }
        return _results;
      }).call(this);
      return (_ref3 = element.empty()).append.apply(_ref3, children);
    };
    View.prototype.renderStatus = function(status) {
      var key, options, _ref3;
      options = this.options.renderOptions;
      key = status.toKey();
            if ((_ref3 = this.htmlCache) != null) {
        _ref3;
      } else {
        this.htmlCache = {};
      };
      if (__indexOf.call(this.htmlCache, key) < 0) {
        this.htmlCache[key] = status.toElement(this.options.renderOptions);
      }
      return this.htmlCache[key];
    };
    return View;
  })();
  extend(this.Chorus, {
    OrderedSet: OrderedSet,
    PubSub: PubSub,
    Timeline: Timeline,
    View: View,
    Status: Status
  });
  $.fn.chorus = function(arg) {
    var view;
    view = (function() {
      switch ($.type(arg)) {
        case "string":
          return new View({
            feeds: makeArray(arguments)
          });
        case "object":
          return new View(arg);
        default:
          return null;
      }
    }).apply(this, arguments);
    return $(this).append(view.toElement()).data('View', view);
  };
}).call(this);

(function() {
  var $, Chorus, ReplyTimeline, Status, Subscriber, Timeline, Tweet, TwitterAboutTimeline, TwitterConversationTimeline, TwitterListConversationTimeline, TwitterListTimeline, TwitterSearchTimeline, TwitterTimeline, TwitterUserTimeline, datefix, extend, get_segments, linkify, linkify_with_entities, ungroup_entities, __callbacks__, __tweet_cache__, _ref;
  var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
    function ctor() { this.constructor = child; }
    ctor.prototype = parent.prototype;
    child.prototype = new ctor;
    child.__super__ = parent.prototype;
    return child;
  }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  _ref = Chorus = this.Chorus, Timeline = _ref.Timeline, Status = _ref.Status, Subscriber = _ref.Subscriber;
  extend = ($ = jQuery).extend;
  Tweet = (function() {
    __extends(Tweet, Status);
    function Tweet(id, username, avatar, date, text, raw, reply) {
      var _ref2;
      this.reply = reply;
      Tweet.__super__.constructor.call(this, id, username, avatar, datefix(date), text, raw);
            if ((_ref2 = __tweet_cache__[id]) != null) {
        _ref2;
      } else {
        __tweet_cache__[id] = this;
      };
    }
    Tweet.prototype.getUrl = function() {
      return "http://twitter.com/" + this.username + "/statuses/" + this.id;
    };
    Tweet.prototype.getStreamUrl = function() {
      return "http://twitter.com/" + this.username;
    };
    Tweet.prototype.renderBody = function() {
      return "<p class=\"statusBody\">\n    " + this.text + "\n</p>";
    };
    Tweet.prototype.renderReply = function() {
      return "<a class=\"reply\"\n   href=\"http://twitter.com/" + this.reply.username + "/statuses/" + this.reply.statusID + "\">\n   in reply to @" + this.reply.username + "\n</a>";
    };
    Tweet.prototype.toElement = function(options) {
      var element;
      element = Tweet.__super__.toElement.call(this, options);
      if (this.reply != null) {
        element.append(this.renderReply());
      }
      return element;
    };
    Tweet.from = function(data) {
      var avatar, created_at, entities, id_str, reply, text, user_name, _ref2;
      if (data instanceof Status) {
        return data;
      }
      data = (_ref2 = data.retweeted_status) != null ? _ref2 : data;
      reply = data.in_reply_to_status_id != null ? {
        username: data.in_reply_to_screen_name,
        userID: data.in_reply_to_user_id_str,
        statusID: data.in_reply_to_status_id_str
      } : void 0;
      id_str = data.id_str, created_at = data.created_at, text = data.text, entities = data.entities;
      if (!(data.user != null)) {
        user_name = data.from_user;
        avatar = data.profile_image_url;
      } else {
        user_name = data.user.screen_name;
        avatar = data.user.profile_image_url;
      }
      return new Tweet(id_str, user_name, avatar, created_at, linkify(text, entities), data, reply);
    };
    Tweet.fromID = function(id, callback) {
      var cached, callbacks, fresh, key, placeholder, _ref2, _ref3;
      if (callback == null) {
        placeholder = $('<div class="placeholder" />');
        callback = function(status) {
          return status.toElement().replaceAll(placeholder);
        };
      }
      key = "" + id;
      cached = (_ref2 = __tweet_cache__[key]) != null ? _ref2 : null;
      callbacks = ((_ref3 = __callbacks__[key]) != null ? _ref3 : __callbacks__[key] = []);
      fresh = cached === null && callbacks.length === 0;
      if (cached != null) {
        callback(cached);
      } else {
        callbacks.push(callback);
      }
      if (fresh) {
        $.ajax({
          url: "http://api.twitter.com/1/statuses/show/" + id + ".json",
          dataType: "jsonp",
          success: function(json) {
            var callback, status, _i, _len, _ref4;
            status = Tweet.from(json);
            __tweet_cache__[key] = status;
            _ref4 = __callbacks__[key];
            for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
              callback = _ref4[_i];
              try {
                callback(status);
              } catch (_e) {}
            }
            return null;
          }
        });
      }
      return placeholder || null;
    };
    return Tweet;
  })();
  __tweet_cache__ = {};
  __callbacks__ = {};
  TwitterTimeline = (function() {
    __extends(TwitterTimeline, Timeline);
    function TwitterTimeline() {
      TwitterTimeline.__super__.constructor.apply(this, arguments);
    }
    TwitterTimeline.prototype.fetch = function(n) {
      var data;
      data = extend({}, this.sendData);
      if (this.statuses.length > 0) {
        data.since_id = this.statuses.item(0).id;
      }
      return jQuery.ajax({
        url: this.queryUrl,
        data: data,
        dataType: "jsonp",
        success: __bind(function(data) {
          return this.update(data);
        }, this)
      });
    };
    TwitterTimeline.prototype.queryUrl = "http://api.twitter.com/1/statuses/public_timeline.json";
    TwitterTimeline.prototype.statusesFromData = function(data) {
      var item, _i, _len, _results;
      _results = [];
      for (_i = 0, _len = data.length; _i < _len; _i++) {
        item = data[_i];
        _results.push(Tweet.from(item));
      }
      return _results;
    };
    TwitterTimeline.prototype.sendData = {
      include_rts: true,
      include_entities: true
    };
    return TwitterTimeline;
  })();
  TwitterUserTimeline = (function() {
    __extends(TwitterUserTimeline, TwitterTimeline);
    function TwitterUserTimeline(username, options) {
      this.options = extend({}, this.options, options);
      this.username = username.toLowerCase();
      this.sendData = extend({}, this.sendData, {
        screen_name: this.username,
        count: this.options.count,
        include_rts: this.options.includeRetweets
      });
      TwitterUserTimeline.__super__.constructor.call(this, options);
    }
    TwitterUserTimeline.prototype.options = extend({}, Timeline.prototype.options, {
      includeRetweets: true
    });
    TwitterUserTimeline.prototype.queryUrl = "http://api.twitter.com/1/statuses/user_timeline.json";
    return TwitterUserTimeline;
  })();
  TwitterSearchTimeline = (function() {
    __extends(TwitterSearchTimeline, TwitterTimeline);
    function TwitterSearchTimeline(searchTerm, options) {
      this.searchTerm = searchTerm;
      this.options = extend({}, this.options, options);
      this.sendData = {
        q: searchTerm,
        rpp: this.options.count,
        result_type: "recent",
        include_entities: true
      };
      TwitterSearchTimeline.__super__.constructor.call(this, options);
    }
    TwitterSearchTimeline.prototype.queryUrl = "http://search.twitter.com/search.json";
    TwitterSearchTimeline.prototype.update = function(data) {
      if (data.results != null) {
        return TwitterSearchTimeline.__super__.update.call(this, data.results);
      }
    };
    return TwitterSearchTimeline;
  })();
  TwitterListTimeline = (function() {
    __extends(TwitterListTimeline, TwitterTimeline);
    function TwitterListTimeline(user, listname, options) {
      this.options = extend({}, this.options, options);
      this.queryUrl = "http://api.twitter.com/1/" + user + "/lists/" + listname + "/statuses.json";
      this.sendData = extend({}, this.sendData, {
        per_page: this.options.count
      });
      TwitterListTimeline.__super__.constructor.call(this, options);
    }
    return TwitterListTimeline;
  })();
  TwitterAboutTimeline = (function() {
    __extends(TwitterAboutTimeline, TwitterTimeline);
    function TwitterAboutTimeline(screenname, options) {
      this.user = new TwitterUserTimeline(screenname, options);
      this.search = new TwitterSearchTimeline("to:" + screenname);
      this.subscribe(this.user);
      this.subscribe(this.search);
    }
    return TwitterAboutTimeline;
  })();
  TwitterConversationTimeline = (function() {
    __extends(TwitterConversationTimeline, TwitterTimeline);
    function TwitterConversationTimeline(username, options) {
      this.user = new TwitterUserTimeline(username, options);
      this.replies = new ReplyTimeline(this.user);
      this.subscribe(this.replies);
      this.subscribe(this.user);
    }
    return TwitterConversationTimeline;
  })();
  TwitterListConversationTimeline = (function() {
    __extends(TwitterListConversationTimeline, TwitterTimeline);
    function TwitterListConversationTimeline(username, listname, options) {
      this.list = new TwitterListTimeline(username, listname, options);
      this.replies = new ReplyTimeline(this.list);
      this.subscribe(this.list);
      this.subscribe(this.replies);
    }
    return TwitterListConversationTimeline;
  })();
  ReplyTimeline = (function() {
    __extends(ReplyTimeline, Timeline);
    function ReplyTimeline(timeline) {
      this.timeline = timeline;
      this.subscribe(this.timeline);
    }
    ReplyTimeline.prototype.update = function(statuses) {
      var status, _i, _len;
      for (_i = 0, _len = statuses.length; _i < _len; _i++) {
        status = statuses[_i];
        if (status.reply != null) {
          Tweet.fromID(status.reply.statusID, __bind(function(tweet) {
            this.statuses = this.statuses.concat([tweet]);
            this.latest = this.statuses.item(0);
            return this.publish(this.statuses.toArray());
          }, this));
        }
      }
      return null;
    };
    return ReplyTimeline;
  })();
  datefix = function(str) {
    return str.replace(/^(.+) (\d+:\d+:\d+) ((?:\+|-)\d+) (\d+)$/, "$1 $4 $2 GMT$3");
  };
  linkify = function(str, entities) {
    if (entities != null) {
      return linkify_with_entities(str, entities);
    }
    return str.replace('\n', '<br />').replace(/(\s|^)(mailto\:|(news|(ht|f)tp(s?))\:\/\/\S+)/g, '$1<a href="$2">$2</a>').replace(/(\s|^)@(\w+)/g, '$1<a class="mention" href="http://twitter.com/$2">@$2</a>').replace(/(\s|^)#(\w+)/g, '$1<a class="hashTag" href="http://twitter.com/search?q=%23$2">#$2</a>');
  };
  linkify_with_entities = function(str, entities) {
    var link, segment, segments;
    segments = (function() {
      var _i, _len, _ref2, _results;
      _ref2 = get_segments(str, entities);
      _results = [];
      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
        segment = _ref2[_i];
        _results.push((function() {
          switch (segment.type) {
            case 'string':
              return segment.val.replace('\n', '<br />');
            case 'hashtags':
              return "<a class=\"hashTag\" href=\"http://twitter.com/search?q=%23" + segment.val.text + "\">#" + segment.val.text + "</a>";
              break;
            case 'urls':
              link = segment.val;
              if (link.display_url) {
                return "<a href=\"http://" + link.display_url + "\">" + link.display_url + "</a>";
              } else {
                return "<a href=\"" + link.url + "\">" + link.url + "</a>";
              }
              break;
            case 'user_mentions':
              return "<a class=\"mention\"\nhref=\"http://twitter.com/" + segment.val.screen_name + "\"\ntitle=\"" + segment.val.name + "\">@" + segment.val.screen_name + "</a>";
          }
        })());
      }
      return _results;
    })();
    return segments.join('');
  };
  get_segments = function(str, entities) {
    var entity, from, segments, _i, _len;
    entities = ungroup_entities(entities);
    segments = [];
    from = 0;
    for (_i = 0, _len = entities.length; _i < _len; _i++) {
      entity = entities[_i];
      segments.push({
        type: 'string',
        val: str.slice(from, entity.span[0])
      });
      segments.push(entity);
      from = entity.span[1];
    }
    segments.push({
      type: 'string',
      val: str.slice(from)
    });
    return segments;
  };
  ungroup_entities = function(entities) {
    var e, key, value, _entities, _i, _len;
    _entities = [];
    for (key in entities) {
      value = entities[key];
      for (_i = 0, _len = value.length; _i < _len; _i++) {
        e = value[_i];
        _entities.push({
          type: key,
          span: e.indices,
          val: e
        });
      }
    }
    _entities.sort(function(a, b) {
      return a.span[0] - b.span[0];
    });
    return _entities;
  };
  Timeline.shorthands.push({
    pattern: /^@([a-z-_]+)\/([a-z-_]+)/i,
    fun: function(_, name, list_name) {
      return new TwitterListTimeline(name, list_name);
    }
  }, {
    pattern: /^@@([a-z-_]+)\/([a-z-_]+)/i,
    fun: function(_, name, list_name) {
      return new TwitterListConversationTimeline(name, list_name);
    }
  }, {
    pattern: /^@@([a-z0-9-_]+)$/i,
    fun: function(_, name) {
      return new TwitterConversationTimeline(name);
    }
  }, {
    pattern: /^@\+([a-z-_]+)/i,
    fun: function(_, name) {
      return new TwitterAboutTimeline(name);
    }
  }, {
    pattern: /^@([a-z-_]+)/i,
    fun: function(_, name) {
      return new TwitterUserTimeline(name);
    }
  }, {
    pattern: /^(.*)$/,
    fun: function(_, terms) {
      return new TwitterSearchTimeline(terms);
    }
  });
  extend(this.Chorus, {
    Tweet: Tweet,
    TwitterTimeline: TwitterTimeline,
    TwitterUserTimeline: TwitterUserTimeline,
    TwitterListTimeline: TwitterListTimeline,
    TwitterSearchTimeline: TwitterSearchTimeline,
    TwitterAboutTimeline: TwitterAboutTimeline,
    TwitterConversationTimeline: TwitterConversationTimeline
  });
}).call(this);

