def poll_for_move():
     msg.debug('poll_for_move')
     win.focus_view(view)
     win.set_view_index(view, win.num_groups() - 1, 0)
     if not get_view_in_group(view.buffer_id(), focus_group):
         return utils.set_timeout(poll_for_move, 20)
     msg.debug('found view, now moving ', view.name(), win.num_groups() - 1)
     swap_regions(view)
     view.show(regions[0])
     win.focus_view(view)
     utils.set_timeout(win.focus_group, 0, 0)
     try:
         del self.temp_ignore_highlight[buf_id]
     except Exception:
         pass
 def poll_for_move():
     msg.debug('poll_for_move')
     win.focus_view(view)
     win.set_view_index(view, win.num_groups() - 1, 0)
     if not get_view_in_group(view.buffer_id(), focus_group):
         return utils.set_timeout(poll_for_move, 20)
     msg.debug('found view, now moving ', view.name(),
               win.num_groups() - 1)
     swap_regions(view)
     view.show(regions[0])
     win.focus_view(view)
     utils.set_timeout(win.focus_group, 0, 0)
     try:
         del self.temp_ignore_highlight[buf_id]
     except Exception:
         pass
    def _on_highlight(self, data, clone=True):
        region_key = 'floobits-highlight-%s' % (data['user_id'])
        buf_id = int(data['id'])
        username = data['username']
        ranges = data['ranges']
        summon = data.get('summon', False)
        user_id = str(data['user_id'])
        following = data.get('following', False)
        msg.debug(
            str([
                buf_id, region_key, user_id, username, ranges, summon,
                following, clone
            ]))
        if not ranges:
            msg.warn('Ignoring empty highlight from ', username)
            return
        buf = self.bufs.get(buf_id)
        if not buf:
            return

        # TODO: move this state machine into one variable
        b = self.on_load.get(buf_id)
        if b and b.get('highlight'):
            msg.debug('ignoring command until on_load is complete')
            return
        if buf_id in self.on_clone:
            msg.debug('ignoring command until on_clone is complete')
            return
        if buf_id in self.temp_ignore_highlight:
            msg.debug(
                'ignoring command until temp_ignore_highlight is complete')
            return

        if summon or not following:
            self.last_highlight = data
            self.last_highlight_by_user[username] = data

        do_stuff = summon
        if G.FOLLOW_MODE and not summon:
            if self.temp_disable_follow or following:
                do_stuff = False
            elif G.FOLLOW_USERS:
                do_stuff = username in G.FOLLOW_USERS
            else:
                do_stuff = True

        view = self.get_view(buf_id)
        if not view or view.is_loading():
            if do_stuff:
                msg.debug('creating view')
                create_view(buf)
                self.on_load[buf_id]['highlight'] = lambda: self._on_highlight(
                    data, False)
            return
        view = view.view
        regions = []
        for r in ranges:
            # Ranges with a length of zero are invisible in Sublime
            if r[0] == r[1]:
                r[1] += 1
            regions.append(sublime.Region(*r))

        def swap_regions(v, following=False):
            v.erase_regions(region_key)
            if following:
                draw = sublime.HIDDEN
            else:
                draw = sublime.DRAW_OUTLINED
            v.add_regions(region_key, regions, region_key, 'dot', draw)

        if not do_stuff:
            return swap_regions(view, following)

        win = G.WORKSPACE_WINDOW

        if not G.SPLIT_MODE:
            win.focus_view(view)
            swap_regions(view)
            # Explicit summon by another user. Center the line.
            if summon:
                view.show_at_center(regions[0])
            # Avoid scrolling/jumping lots in follow mode
            else:
                view.show(regions[0])
            return

        focus_group = win.num_groups() - 1
        view_in_group = get_view_in_group(view.buffer_id(), focus_group)

        if view_in_group:
            msg.debug('view in group')
            win.focus_view(view_in_group)
            swap_regions(view_in_group)
            utils.set_timeout(win.focus_group, 0, 0)
            return view_in_group.show(regions[0])

        if not clone:
            msg.debug('no clone... moving ', view.buffer_id(),
                      win.num_groups() - 1, 0)
            win.focus_view(view)
            win.set_view_index(view, win.num_groups() - 1, 0)

            def dont_crash_sublime():
                utils.set_timeout(win.focus_group, 0, 0)
                swap_regions(view)
                return view.show(regions[0])

            return utils.set_timeout(dont_crash_sublime, 0)

        msg.debug('View not in group... cloning')
        win.focus_view(view)

        def on_clone(buf, view):
            msg.debug('on clone')

            def poll_for_move():
                msg.debug('poll_for_move')
                win.focus_view(view)
                win.set_view_index(view, win.num_groups() - 1, 0)
                if not get_view_in_group(view.buffer_id(), focus_group):
                    return utils.set_timeout(poll_for_move, 20)
                msg.debug('found view, now moving ', view.name(),
                          win.num_groups() - 1)
                swap_regions(view)
                view.show(regions[0])
                win.focus_view(view)
                utils.set_timeout(win.focus_group, 0, 0)
                try:
                    del self.temp_ignore_highlight[buf_id]
                except Exception:
                    pass

            utils.set_timeout(win.focus_group, 0, 0)
            poll_for_move()

        self.on_clone[buf_id] = on_clone
        self.temp_ignore_highlight[buf_id] = True
        win.run_command('clone_file')
        return win.focus_group(0)
    def _on_highlight(self, data, clone=True):
        region_key = 'floobits-highlight-%s' % (data['user_id'])
        buf_id = int(data['id'])
        username = data['username']
        ranges = data['ranges']
        summon = data.get('ping', False)
        user_id = str(data['user_id'])
        msg.debug(str([buf_id, region_key, user_id, username, ranges, summon, data.get('following'), clone]))
        if not ranges:
            msg.warn('Ignoring empty highlight from ', username)
            return
        buf = self.bufs.get(buf_id)
        if not buf:
            return

        # TODO: move this state machine into one variable
        b = self.on_load.get(buf_id)
        if b and b.get('highlight'):
            msg.debug('ignoring command until on_load is complete')
            return
        if buf_id in self.on_clone:
            msg.debug('ignoring command until on_clone is complete')
            return
        if buf_id in self.temp_ignore_highlight:
            msg.debug('ignoring command until temp_ignore_highlight is complete')
            return

        if summon or not data.get('following'):
            self.last_highlight = data
            self.last_highlight_by_user[username] = data

        do_stuff = summon
        if G.FOLLOW_MODE and not summon:
            if self.temp_disable_follow or data.get('following'):
                do_stuff = False
            elif G.FOLLOW_USERS:
                do_stuff = username in G.FOLLOW_USERS
            else:
                do_stuff = True

        view = self.get_view(buf_id)
        if not view or view.is_loading():
            if do_stuff:
                msg.debug('creating view')
                create_view(buf)
                self.on_load[buf_id]['highlight'] = lambda: self._on_highlight(data, False)
            return
        view = view.view
        regions = []
        for r in ranges:
            # TODO: add one to the ranges that have a length of zero
            regions.append(sublime.Region(*r))

        def swap_regions(v):
            v.erase_regions(region_key)
            v.add_regions(region_key, regions, region_key, 'dot', sublime.DRAW_OUTLINED)

        if not do_stuff:
            return swap_regions(view)

        win = G.WORKSPACE_WINDOW

        if not G.SPLIT_MODE:
            win.focus_view(view)
            swap_regions(view)
            # Explicit summon by another user. Center the line.
            if summon:
                view.show_at_center(regions[0])
            # Avoid scrolling/jumping lots in follow mode
            else:
                view.show(regions[0])
            return

        focus_group = win.num_groups() - 1
        view_in_group = get_view_in_group(view.buffer_id(), focus_group)

        if view_in_group:
            msg.debug('view in group')
            win.focus_view(view_in_group)
            swap_regions(view_in_group)
            utils.set_timeout(win.focus_group, 0, 0)
            return view_in_group.show(regions[0])

        if not clone:
            msg.debug('no clone... moving ', view.buffer_id(), win.num_groups() - 1, 0)
            win.focus_view(view)
            win.set_view_index(view, win.num_groups() - 1, 0)

            def dont_crash_sublime():
                utils.set_timeout(win.focus_group, 0, 0)
                swap_regions(view)
                return view.show(regions[0])
            return utils.set_timeout(dont_crash_sublime, 0)

        msg.debug('View not in group... cloning')
        win.focus_view(view)

        def on_clone(buf, view):
            msg.debug('on clone')

            def poll_for_move():
                msg.debug('poll_for_move')
                win.focus_view(view)
                win.set_view_index(view, win.num_groups() - 1, 0)
                if not get_view_in_group(view.buffer_id(), focus_group):
                    return utils.set_timeout(poll_for_move, 20)
                msg.debug('found view, now moving ', view.name(), win.num_groups() - 1)
                swap_regions(view)
                view.show(regions[0])
                win.focus_view(view)
                utils.set_timeout(win.focus_group, 0, 0)
                try:
                    del self.temp_ignore_highlight[buf_id]
                except Exception:
                    pass
            utils.set_timeout(win.focus_group, 0, 0)
            poll_for_move()

        self.on_clone[buf_id] = on_clone
        self.temp_ignore_highlight[buf_id] = True
        win.run_command('clone_file')
        return win.focus_group(0)
    def highlight(self, buf_id, region_key, username, ranges, summon, clone):
        buf_id = int(buf_id)
        msg.debug(str([buf_id, region_key, username, ranges, summon, clone]))
        buf = self.bufs.get(buf_id)
        if not buf:
            return

        # TODO: move this state machine into one variable
        if buf_id in self.on_load:
            msg.debug("ignoring command until on_load is complete")
            return
        if buf_id in self.on_clone:
            msg.debug("ignoring command until on_clone is complete")
            return
        if buf_id in self.temp_ignore_highlight:
            msg.debug("ignoring command until temp_ignore_highlight is complete")
            return

        do_stuff = summon or (G.STALKER_MODE and not self.temp_disable_stalk)

        view = self.get_view(buf_id)
        if not view or view.is_loading():
            if do_stuff:
                msg.debug("creating view")
                create_view(buf)
                self.on_load[buf_id] = lambda: self.highlight(buf_id, region_key, username, ranges, summon, False)
            return
        view = view.view
        regions = []
        for r in ranges:
            regions.append(sublime.Region(*r))

        def swap_regions(v):
            v.erase_regions(region_key)
            v.add_regions(region_key, regions, region_key, "dot", sublime.DRAW_OUTLINED)

        if not do_stuff:
            return swap_regions(view)

        win = G.WORKSPACE_WINDOW

        if not G.SPLIT_MODE:
            win.focus_view(view)
            swap_regions(view)
            # Explicit summon by another user. Center the line.
            if summon:
                view.show_at_center(regions[0])
            # Avoid scrolling/jumping lots in stalker mode
            else:
                view.show(regions[0])
            return

        focus_group = win.num_groups() - 1
        view_in_group = get_view_in_group(view.buffer_id(), focus_group)

        if view_in_group:
            msg.debug("view in group")
            win.focus_view(view_in_group)
            swap_regions(view_in_group)
            utils.set_timeout(win.focus_group, 0, 0)
            return view_in_group.show(regions[0])

        if not clone:
            msg.debug("no clone... moving ", view.buffer_id(), win.num_groups() - 1, 0)
            win.focus_view(view)
            win.set_view_index(view, win.num_groups() - 1, 0)

            def dont_crash_sublime():
                utils.set_timeout(win.focus_group, 0, 0)
                swap_regions(view)
                return view.show(regions[0])

            return utils.set_timeout(dont_crash_sublime, 0)

        msg.debug("View not in group... cloning")
        win.focus_view(view)

        def on_clone(buf, view):
            msg.debug("on clone")

            def poll_for_move():
                msg.debug("poll_for_move")
                win.focus_view(view)
                win.set_view_index(view, win.num_groups() - 1, 0)
                if not get_view_in_group(view.buffer_id(), focus_group):
                    return utils.set_timeout(poll_for_move, 20)
                msg.debug("found view, now moving ", view.name(), win.num_groups() - 1)
                swap_regions(view)
                view.show(regions[0])
                win.focus_view(view)
                utils.set_timeout(win.focus_group, 0, 0)
                try:
                    del self.temp_ignore_highlight[buf_id]
                except:
                    pass

            utils.set_timeout(win.focus_group, 0, 0)
            poll_for_move()

        self.on_clone[buf_id] = on_clone
        self.temp_ignore_highlight[buf_id] = True
        win.run_command("clone_file")
        return win.focus_group(0)