def startCollab(self, view): """ Send the provided C{sublime.View} contents to the connected peer. """ self.view = view self.view.set_read_only(True) viewName = self.view.file_name() if not viewName == None: viewName = os.path.basename(viewName) else: viewName = 'NONAME' totalToSend = self.view.size() begin = 0 end = MAX_CHUNK_SIZE # now we make sure we are connected... better way to do this? while not self.state == interface.STATE_CONNECTED: time.sleep(1.0) if (self.state == interface.STATE_DISCONNECTING) or (self.state == interface.STATE_DISCONNECTED): logger.error('While waiting to share view over a connection the peer was disconnected!') self.disconnect() return logger.info('Sharing view %s with %s' % (self.view.file_name(), self.sharingWithUser)) self.toAck = [] self.sendMessage(interface.SHARE_VIEW, payload=('%s|%s' % (viewName, totalToSend))) while begin < totalToSend: chunkToSend = self.view.substr(sublime.Region(begin, end)) self.toAck.append(len(chunkToSend)) self.sendMessage(interface.VIEW_CHUNK, payload=chunkToSend) begin = begin + MAX_CHUNK_SIZE end = end + MAX_CHUNK_SIZE status_bar.progress_message("sending view to %s" % self.sharingWithUser, begin, totalToSend) self.sendMessage(interface.END_OF_VIEW, payload=view.settings().get('syntax')) self.view.set_read_only(False) # start the view monitoring thread self.viewMonitorThread.start()
def startCollab(self, view): """ Send the provided C{sublime.View} contents to the connected peer. """ self.view = view self.view.set_read_only(True) viewName = self.view.file_name() if not viewName == None: viewName = os.path.basename(viewName) else: viewName = 'NONAME' totalToSend = self.view.size() begin = 0 end = MAX_CHUNK_SIZE # now we make sure we are connected... better way to do this? while not self.state == base.STATE_CONNECTED: time.sleep(1.0) if (self.state == base.STATE_DISCONNECTING) or (self.state == base.STATE_DISCONNECTED): self.logger.error('While waiting to share view over a connection the peer was disconnected!') self.disconnect() return self.logger.info('Sharing view %s with %s' % (self.view.file_name(), self.sharingWithUser)) self.toAck = [] self.sendMessage(base.SHARE_VIEW, payload=('%s|%s' % (viewName, totalToSend))) while begin < totalToSend: chunkToSend = self.view.substr(sublime.Region(begin, end)) self.toAck.append(len(chunkToSend)) self.sendMessage(base.VIEW_CHUNK, payload=chunkToSend) begin = begin + MAX_CHUNK_SIZE end = end + MAX_CHUNK_SIZE status_bar.progress_message("sending view to %s" % self.sharingWithUser, begin, totalToSend) self.sendMessage(base.END_OF_VIEW, payload=view.settings().get('syntax')) self.view.set_read_only(False) # start the view monitoring thread self.viewMonitorThread.start()
def resyncCollab(self): """ Resync the shared editor contents between the host and the partner. """ status_bar.status_message('RESYNCING VIEW CONTENT WITH PEER') self.view.set_read_only(True) totalToSend = self.view.size() begin = 0 end = MAX_CHUNK_SIZE # now we make sure we are connected... better way to do this? while not self.state == interface.STATE_CONNECTED: time.sleep(1.0) if (self.state == interface.STATE_DISCONNECTING) or ( self.state == interface.STATE_DISCONNECTED): logger.error( 'While waiting to resync view over a connection the peer was disconnected!' ) self.disconnect() return view_name = self.view.file_name() if not view_name: view_name = self.view.name() logger.info('Resyncing view %s with %s' % (view_name, self.sharingWithUser)) self.toAck = [] self.sendMessage(interface.RESHARE_VIEW, payload=str(totalToSend)) while begin < totalToSend: chunkToSend = self.view.substr(sublime.Region(begin, end)) self.toAck.append(len(chunkToSend)) self.sendMessage(interface.VIEW_CHUNK, payload=chunkToSend) begin = begin + MAX_CHUNK_SIZE end = end + MAX_CHUNK_SIZE status_bar.progress_message( "sending view to %s" % self.sharingWithUser, begin, totalToSend) self.sendMessage(interface.END_OF_VIEW, payload=self.view.settings().get('syntax')) self.view.set_read_only(False) # send view position as it stands now so the partner view is positioned appropriately post-resync viewRegionLines = self.view.split_by_newlines( self.view.visible_region()) lineIdx = len(viewRegionLines) / 2 - 1 if lineIdx < 0: lineIdx = 0 viewCenterRegion = viewRegionLines[lineIdx] self.sendViewPositionUpdate(viewCenterRegion) # start the view monitoring thread if not already running if not self.viewMonitorThread.is_alive(): self.viewMonitorThread.start()
def resyncCollab(self): """ Resync the shared editor contents between the host and the partner. """ status_bar.status_message('RESYNCING VIEW CONTENT WITH PEER') self.view.set_read_only(True) totalToSend = self.view.size() begin = 0 end = MAX_CHUNK_SIZE # now we make sure we are connected... better way to do this? while not self.state == interface.STATE_CONNECTED: time.sleep(1.0) if (self.state == interface.STATE_DISCONNECTING) or (self.state == interface.STATE_DISCONNECTED): logger.error('While waiting to resync view over a connection the peer was disconnected!') self.disconnect() return view_name = self.view.file_name() if not view_name: view_name = self.view.name() logger.info('Resyncing view %s with %s' % (view_name, self.sharingWithUser)) self.toAck = [] self.sendMessage(interface.RESHARE_VIEW, payload=str(totalToSend)) while begin < totalToSend: chunkToSend = self.view.substr(sublime.Region(begin, end)) self.toAck.append(len(chunkToSend)) self.sendMessage(interface.VIEW_CHUNK, payload=chunkToSend) begin = begin + MAX_CHUNK_SIZE end = end + MAX_CHUNK_SIZE status_bar.progress_message("sending view to %s" % self.sharingWithUser, begin, totalToSend) self.sendMessage(interface.END_OF_VIEW, payload=self.view.settings().get('syntax')) self.view.set_read_only(False) # send view position as it stands now so the partner view is positioned appropriately post-resync viewRegionLines = self.view.split_by_newlines(self.view.visible_region()) lineIdx = len(viewRegionLines) / 2 - 1 if lineIdx < 0: lineIdx = 0 viewCenterRegion = viewRegionLines[lineIdx] self.sendViewPositionUpdate(viewCenterRegion) # start the view monitoring thread if not already running if not self.viewMonitorThread.is_alive(): self.viewMonitorThread.start()
def handleViewChanges(self): """ Runs on the main UI event loop. Goes through the list of events queued up to modify the shared view and applies them to the associated view. """ self.toDoToViewQueueLock.acquire() while len(self.toDoToViewQueue) > 0: toDo = self.toDoToViewQueue.pop(0) if len(toDo) == 2: logger.debug('Handling view change %s with size %d payload' % (interface.numeric_to_symbolic[toDo[0]], len(toDo[1]))) if (toDo[0] == interface.SHARE_VIEW) or (toDo[0] == interface.RESHARE_VIEW): self.totalNewViewSize = 0 if toDo[0] == interface.SHARE_VIEW: self.view = sublime.active_window().new_file() payloadBits = toDo[1].split('|') if payloadBits[0] == 'NONAME': self.view.set_name('SHARING-WITH-%s' % self.sharingWithUser) else: self.view.set_name(payloadBits[0]) self.totalNewViewSize = int(payloadBits[1]) else: # resync event, purge the old view in preparation for the fresh content logger.debug('resyncing view') self.lastResyncdPosition = 0 self.totalNewViewSize = int(toDo[1]) self.view.set_read_only(True) self.view.set_scratch(True) status_bar.progress_message("receiving view from %s" % self.sharingWithUser, self.view.size(), self.totalNewViewSize) elif toDo[0] == interface.VIEW_CHUNK: self.view.set_read_only(False) self.viewPopulateEdit = self.view.begin_edit() # if we are a resync chunk... if hasattr(self, 'lastResyncdPosition'): self.view.replace(self.viewPopulateEdit, \ sublime.Region(self.lastResyncdPosition, self.lastResyncdPosition + len(toDo[1])), \ toDo[1]) self.lastResyncdPosition += len(toDo[1]) else: self.view.insert(self.viewPopulateEdit, self.view.size(), toDo[1]) self.view.end_edit(self.viewPopulateEdit) self.viewPopulateEdit = None self.view.set_read_only(True) status_bar.progress_message("receiving view from %s" % self.sharingWithUser, self.view.size(), self.totalNewViewSize) elif toDo[0] == interface.END_OF_VIEW: self.view.set_syntax_file(toDo[1]) if hasattr(self, 'lastResyncdPosition'): del self.lastResyncdPosition status_bar.progress_message("receiving view from %s" % self.sharingWithUser, self.view.size(), self.totalNewViewSize) # view is populated and configured, lets share! self.onStartCollab() elif toDo[0] == interface.SELECTION: status_bar.heartbeat_message('sharing with %s' % self.str()) regions = [] for regionMatch in REGION_PATTERN.finditer(toDo[1]): regions.append(sublime.Region(int(regionMatch.group(1)), int(regionMatch.group(2)))) self.recvSelectionUpdate(regions) elif toDo[0] == interface.POSITION: status_bar.heartbeat_message('sharing with %s' % self.str()) regionMatch = REGION_PATTERN.search(toDo[1]) if regionMatch: self.recvViewPositionUpdate(sublime.Region(int(regionMatch.group(1)), int(regionMatch.group(2)))) elif len(toDo) == 3: status_bar.heartbeat_message('sharing with %s' % self.str()) # edit event assert toDo[0] == interface.EDIT # make the shared selection the ACTUAL selection self.view.sel().clear() for region in self.view.get_regions(self.sharingWithUser): self.view.sel().add(region) self.view.erase_regions(self.sharingWithUser) self.recvEdit(toDo[1], toDo[2]) self.toDoToViewQueueLock.release()
def handleViewChanges(self): """ Runs on the main UI event loop. Goes through the list of events queued up to modify the shared view and applies them to the associated view. """ self.toDoToViewQueueLock.acquire() while len(self.toDoToViewQueue) > 0: toDo = self.toDoToViewQueue.pop(0) if len(toDo) == 2: logger.debug( 'Handling view change %s with size %d payload' % (interface.numeric_to_symbolic[toDo[0]], len(toDo[1]))) if (toDo[0] == interface.SHARE_VIEW) or ( toDo[0] == interface.RESHARE_VIEW): self.totalNewViewSize = 0 if toDo[0] == interface.SHARE_VIEW: self.view = sublime.active_window().new_file() payloadBits = toDo[1].split('|') if payloadBits[0] == 'NONAME': self.view.set_name('SHARING-WITH-%s' % self.sharingWithUser) else: self.view.set_name(payloadBits[0]) self.totalNewViewSize = int(payloadBits[1]) else: # resync event, purge the old view in preparation for the fresh content logger.debug('resyncing view') self.lastResyncdPosition = 0 self.totalNewViewSize = int(toDo[1]) self.view.set_read_only(True) self.view.set_scratch(True) status_bar.progress_message( "receiving view from %s" % self.sharingWithUser, self.view.size(), self.totalNewViewSize) elif toDo[0] == interface.VIEW_CHUNK: self.view.set_read_only(False) self.viewPopulateEdit = self.view.begin_edit() # if we are a resync chunk... if hasattr(self, 'lastResyncdPosition'): self.view.replace(self.viewPopulateEdit, \ sublime.Region(self.lastResyncdPosition, self.lastResyncdPosition + len(toDo[1])), \ toDo[1]) self.lastResyncdPosition += len(toDo[1]) else: self.view.insert(self.viewPopulateEdit, self.view.size(), toDo[1]) self.view.end_edit(self.viewPopulateEdit) self.viewPopulateEdit = None self.view.set_read_only(True) status_bar.progress_message( "receiving view from %s" % self.sharingWithUser, self.view.size(), self.totalNewViewSize) elif toDo[0] == interface.END_OF_VIEW: self.view.set_syntax_file(toDo[1]) if hasattr(self, 'lastResyncdPosition'): del self.lastResyncdPosition status_bar.progress_message( "receiving view from %s" % self.sharingWithUser, self.view.size(), self.totalNewViewSize) # view is populated and configured, lets share! self.onStartCollab() elif toDo[0] == interface.SELECTION: status_bar.heartbeat_message('sharing with %s' % self.str()) regions = [] for regionMatch in REGION_PATTERN.finditer(toDo[1]): regions.append( sublime.Region(int(regionMatch.group(1)), int(regionMatch.group(2)))) self.recvSelectionUpdate(regions) elif toDo[0] == interface.POSITION: status_bar.heartbeat_message('sharing with %s' % self.str()) regionMatch = REGION_PATTERN.search(toDo[1]) if regionMatch: self.recvViewPositionUpdate( sublime.Region(int(regionMatch.group(1)), int(regionMatch.group(2)))) elif len(toDo) == 3: status_bar.heartbeat_message('sharing with %s' % self.str()) # edit event assert toDo[0] == interface.EDIT # make the shared selection the ACTUAL selection self.view.sel().clear() for region in self.view.get_regions(self.sharingWithUser): self.view.sel().add(region) self.view.erase_regions(self.sharingWithUser) self.recvEdit(toDo[1], toDo[2]) self.toDoToViewQueueLock.release()