def _processCallTip_response(self, future): """ Process response of shell to show signature. """ # Process future if future.cancelled(): #print('Introspect cancelled') # No kernel return elif future.exception(): print('Introspect-exception: ', future.exception()) return else: response = future.result() cto = future.cto # First see if this is still the right editor (can also be a shell) editor1 = iep.editors.getCurrentEditor() editor2 = iep.shells.getCurrentShell() if cto.textCtrl not in [editor1, editor2]: # The editor or shell starting the autocomp is no longer active aco.textCtrl.autocompleteCancel() return # Invalid response if response is None: cto.textCtrl.autocompleteCancel() return # If still required, show tip, otherwise only store result if cto is self._currentCTO: cto.finish(response) else: cto.setBuffer(response)
def setInfo(self, info=None): """ Set the shell info struct, and use it to update the widgets. Not via init, because this function also sets the tab name. """ # If info not given, use default as specified by the KernelInfo struct if info is None: info = KernelInfo() # Name n = self.parent().parent().count() if n > 1: info.name = "Shell config %i" % n # Store info self._info = info # Set widget values according to info try: for key in info: widget = self._shellInfoWidgets.get(key, None) if widget is not None: widget.setTheText(info[key]) except Exception as why: print("Error setting info in shell config:", why) print(info)
def _processAutoComp_response(self, future): """ Process the response of the shell for the auto completion. """ # Process future if future.cancelled(): #print('Introspect cancelled') # No living kernel return elif future.exception(): print('Introspect-exception: ', future.exception()) return else: response = future.result() aco = future.aco # First see if this is still the right editor (can also be a shell) editor1 = iep.editors.getCurrentEditor() editor2 = iep.shells.getCurrentShell() if aco.textCtrl not in [editor1, editor2]: # The editor or shell starting the autocomp is no longer active aco.textCtrl.autocompleteCancel() return # Add result to the list foundNames = [] if response is not None: foundNames = response aco.addNames(foundNames) # Process list if aco.name and not foundNames: # No names found for the requested name. This means # it does not exist, let's try to import it importNames, importLines = iep.parser.getFictiveImports(editor1) baseName = aco.nameInImportNames(importNames) if baseName: line = importLines[baseName].strip() if line not in self._importAttempts: # Do import self.processLine(line + ' # auto-import') self._importAttempts.append(line) # Wait a barely noticable time to increase the chances # That the import is complete when we repost the request. time.sleep(0.2) # To be sure, decrease the experiration date on the buffer aco.setBuffer(timeout=1) # Repost request future = self._request.signature(aco.name) future.add_done_callback(self._processAutoComp_response) future.aco = aco else: # If still required, show list, otherwise only store result if self._currentACO is aco: aco.finish() else: aco.setBuffer()
def saveFile(self, editor=None, filename=None): """ Save the file. returns: True if succesfull, False if fails """ # get editor if editor is None: editor = self.getCurrentEditor() elif isinstance(editor, int): index = editor editor = None if index>=0: item = self._tabs.items()[index] editor = item.editor if editor is None: return False # get filename if filename is None: filename = editor._filename if not filename: return self.saveFileAs(editor) # let the editor do the low level stuff... try: editor.save(filename) except Exception as err: # Notify in logger print("Error saving file:",err) # Make sure the user knows m = QtGui.QMessageBox(self) m.setWindowTitle("Error saving file") m.setText(str(err)) m.setIcon(m.Warning) m.exec_() # Return now return False # get actual normalized filename filename = editor._filename # notify # TODO: message concerining line endings print("saved file: {} ({})".format(filename, editor.lineEndingsHumanReadable)) self._tabs.updateItems() # todo: this is where we once detected whether the file being saved was a style file. # Notify done return True
def loadFile(self, filename, updateTabs=True): """ Load the specified file. On success returns the item of the file, also if it was already open.""" # Note that by giving the name of a tempfile, we can select that # temp file. # normalize path if filename[0] != '<': filename = normalizePath(filename) if not filename: return None # if the file is already open... for item in self._tabs.items(): if item.id == filename: # id gets _filename or _name for temp files break else: item = None if item: self._tabs.setCurrentItem(item) print("File already open: '{}'".format(filename)) return item # create editor try: editor = createEditor(self, filename) except Exception as err: # Notify in logger print("Error loading file: ", err) # Make sure the user knows m = QtGui.QMessageBox(self) m.setWindowTitle("Error loading file") m.setText(str(err)) m.setIcon(m.Warning) m.exec_() return None # create list item item = FileItem(editor) self._tabs.addItem(item, updateTabs) if updateTabs: self._tabs.setCurrentItem(item) # store the path self._lastpath = os.path.dirname(item.filename) return item
def getInfo(self): info = self._info # Set struct values according to widgets try: for key, widget in self._shellInfoWidgets.items(): info[key] = widget.getTheText() except Exception as why: print("Error getting info in shell config:", why) print(info) # Return the original (but modified) ssdf struct object return info
def getInfo(self): info = self._info # Set struct values according to widgets try: for key in info: widget = self._shellInfoWidgets.get(key, None) if widget is not None: info[key] = widget.getTheText() except Exception as why: print("Error getting info in shell config:", why) print(info) # Return the original (but modified) ssdf struct object return info
def normalizePath(path): """ Normalize the path given. All slashes will be made the same (and doubles removed) The real case as stored on the file system is recovered. Returns None on error. """ # normalize path = os.path.abspath(path) # make sure it is defined from the drive up path = os.path.normpath(path) # If does not exist, return as is. # This also happens if the path's case is incorrect and the # file system is case sensitive. That's ok, because the stuff we # do below is intended to get the path right on case insensitive # file systems. if not os.path.isfile(path): return path # split drive name from the rest drive, rest = os.path.splitdrive(path) fullpath = drive.upper() + os.sep # make lowercase and split in parts parts = rest.lower().split(os.sep) parts = [part for part in parts if part] for part in parts: options = [x for x in os.listdir(fullpath) if x.lower()==part] if len(options) > 1: print("Error normalizing path: Ambiguous path names!") return path elif not options: print("Invalid path (part %s) in %s" % (part, fullpath)) return path fullpath = os.path.join(fullpath, options[0]) # remove last sep return fullpath
def _setCurrentOpenFilesAsSsdfList(self, state): """ Set the state of the editor in terms of opened files. The input should be a list object as returned by ._getCurrentOpenFilesAsSsdfList(). """ # Init dict fileItems = {} # Process items for item in state: fname = item[0] if item[1] == 'hist': # select item (to make the history right) if fname in fileItems: self._tabs.setCurrentItem( fileItems[fname] ) elif fname: # a file item, create editor-item and store itm = self.loadFile(fname) fileItems[fname] = itm # set position if itm: try: ed = itm.editor cursor = ed.textCursor() cursor.setPosition(int(item[1])) ed.setTextCursor(cursor) # set scrolling ed.verticalScrollBar().setValue(int(item[2])) #ed.centerCursor() #TODO: this does not work properly yet # set main and/or pinned? if 'main' in item: self._tabs._mainFile = itm.id if 'pinned' in item: itm._pinned = True except Exception as err: print('Could not set position for %s' % fname, err)
def loadDir(self, path): """ Create a project with the dir's name and add all files contained in the directory to it. extensions is a komma separated list of extenstions of files to accept... """ # if the path does not exist, stop path = os.path.abspath(path) if not os.path.isdir(path): print("ERROR loading dir: the specified directory does not exist!") return # get extensions extensions = iep.config.advanced.fileExtensionsToLoadFromDir extensions = extensions.replace(',',' ').replace(';',' ') extensions = ["."+a.lstrip(".").strip() for a in extensions.split(" ")] # init item item = None # open all qualified files... self._tabs.setUpdatesEnabled(False) try: filelist = os.listdir(path) for filename in filelist: filename = os.path.join(path, filename) ext = os.path.splitext(filename)[1] if str(ext) in extensions: item = self.loadFile(filename, False) finally: self._tabs.setUpdatesEnabled(True) self._tabs.updateItems() # return lastopened item return item
def poll(self, channel=None): """ poll() To keep the shell up-to-date. Call this periodically. """ if self._write_buffer: # There is still data in the buffer sub, M = self._write_buffer else: # Check what subchannel has the latest message pending sub = yoton.select_sub_channel(self._strm_out, self._strm_err, self._strm_echo, self._strm_raw, self._strm_broker, self._strm_prompt) # Read messages from it if sub: M = sub.recv_selected() #M = [sub.recv()] # Slow version (for testing) # Optimization: handle backspaces on stack of messages if sub is self._strm_out: M = self._handleBackspacesOnList(M) # New prompt? if sub is self._strm_prompt: self.stateChanged.emit(self) # Write all pending messages that are later than any other message if sub: # Select messages to process N = 256 M, buffer = M[:N], M[N:] # Buffer the rest if buffer: self._write_buffer = sub, buffer else: self._write_buffer = None # Get how to deal with prompt prompt = 0 if sub is self._strm_echo: prompt = 1 elif sub is self._strm_prompt: prompt = 2 # Get color color = None if sub is self._strm_broker: color = '#000' elif sub is self._strm_raw: color = '#888888' # Halfway elif sub is self._strm_err: color = '#F00' # Write self.write(''.join(M), prompt, color) # Do any actions? action = self._strm_action.recv(False) if action: if action.startswith('open '): fname = action.split(' ', 1)[1] iep.editors.loadFile(fname) else: print('Unkown action: %s' % action) # Update status state = self._stat_interpreter.recv() if state != self._state: self._state = state self.stateChanged.emit(self) # Update debug status state = self._stat_debug.recv() if state != self._debugState: self._debugState = state self.debugStateChanged.emit(self)
def poll(self, channel=None): """ poll() To keep the shell up-to-date. Call this periodically. """ if self._write_buffer: # There is still data in the buffer sub, M = self._write_buffer else: # Check what subchannel has the latest message pending sub = yoton.select_sub_channel(self._strm_out, self._strm_err, self._strm_echo, self._strm_raw, self._strm_broker, self._strm_prompt ) # Read messages from it if sub: M = sub.recv_selected() #M = [sub.recv()] # Slow version (for testing) # Optimization: handle backspaces on stack of messages if sub is self._strm_out: M = self._handleBackspacesOnList(M) # New prompt? if sub is self._strm_prompt: self.stateChanged.emit(self) # Write all pending messages that are later than any other message if sub: # Select messages to process N = 256 M, buffer = M[:N], M[N:] # Buffer the rest if buffer: self._write_buffer = sub, buffer else: self._write_buffer = None # Get how to deal with prompt prompt = 0 if sub is self._strm_echo: prompt = 1 elif sub is self._strm_prompt: prompt = 2 # Get color color = None if sub is self._strm_broker: color = '#000' elif sub is self._strm_raw: color = '#888888' # Halfway elif sub is self._strm_err: color = '#F00' # Write self.write(''.join(M), prompt, color) # Do any actions? action = self._strm_action.recv(False) if action: if action.startswith('open '): fname = action.split(' ',1)[1] iep.editors.loadFile(fname) else: print('Unkown action: %s' % action) # Update status state = self._stat_interpreter.recv() if state != self._state: self._state = state self.stateChanged.emit(self) # Update debug status state = self._stat_debug.recv() if state != self._debugState: self._debugState = state self.debugStateChanged.emit(self)