def completeBlockStart(self, iLine, inspectLineBefore): '''Add preceding lines that are required to execute the selected code, e.g. the beginning of an indented code block.''' iFirstCodeLine = iLine satisfied = False while iLine >= 0: line = editor.getLine(iLine).rstrip() isCodeLine = len(line) > 0 and not line.lstrip().startswith('#') isDecorator = line.startswith('@') if satisfied and not isDecorator: break isIndent = isCodeLine and (line.startswith(' ') or line.startswith('\t')) requireLineBefore = isIndent or line.startswith('else:') or line.startswith('elif') \ or line.startswith('except:') or line.startswith('finally:') inspectLineBefore = line.startswith( 'def ') or inspectLineBefore or requireLineBefore satisfied = isCodeLine and not (requireLineBefore or inspectLineBefore) satisfied = satisfied or not (requireLineBefore or isCodeLine or inspectLineBefore) if isDecorator: satisfied = False if satisfied: break if isCodeLine: iFirstCodeLine = iLine if not (requireLineBefore or isIndent): inspectLineBefore = False satisfied = True iLine -= 1 return max(0, iFirstCodeLine)
def paint_it(indicator, pos, length): current_line = editor.lineFromPosition(pos) line_start_position = editor.positionFromLine(current_line) text = editor.getLine(current_line) found_comment_char = text.find('#') relative_line_position = pos - line_start_position if ((-1 < found_comment_char < relative_line_position) or (text.count('"', 0, relative_line_position) % 2 == 1) or (text.count("'", 0, relative_line_position) % 2 == 1)): return else: editor.setIndicatorCurrent(indicator) editor.indicatorFillRange(pos, length)
def paint_it(indicator, pos, length): current_line = editor.lineFromPosition(pos) line_start_position = editor.positionFromLine(current_line) text = editor.getLine(current_line) found_comment_char = text.find('#') relative_line_position = pos-line_start_position if((-1 < found_comment_char < relative_line_position) or (text.count('"', 0, relative_line_position) % 2 == 1) or (text.count("'", 0, relative_line_position) % 2 == 1)): return else: editor.setIndicatorCurrent(indicator) editor.indicatorFillRange(pos,length)
def completeBlockEnd(self, iLine, iLineMin, iLineMax, isEmpty=True, inspectLineBefore=False): '''Add following lines that are required to execute the selected code, without leaving code that cannot be executed seperately in the next step.''' iLastCodeLine = iLine iFirstCodeLine = None inspectLineAfter = False isFirstCodeLine = True while iLine <= iLineMax: line = editor.getLine(iLine).rstrip() isCodeLine = len(line) > 0 and not line.lstrip().startswith('#') isIndent = isCodeLine and (line.startswith(' ') or line.startswith('\t')) thisLineIsRequiredAndMaybeMore = line.startswith( 'elif') or line.startswith('except:') thisLineIsRequired = line.startswith('else:') or line.startswith('finally:') \ or thisLineIsRequiredAndMaybeMore mightRequireLineAfter = (thisLineIsRequiredAndMaybeMore or isFirstCodeLine and \ (line.startswith('if ') or line.startswith('for ') or line.startswith('while ') )) and not inspectLineAfter if thisLineIsRequired or isIndent or mightRequireLineAfter: inspectLineAfter = True if thisLineIsRequired: isCodeLine = True if isEmpty and isIndent: inspectLineBefore = True if isCodeLine: isEmpty = False if not thisLineIsRequired and not mightRequireLineAfter: inspectLineAfter = False if iFirstCodeLine is None: iFirstCodeLine = iLine if thisLineIsRequired or iLine <= iLineMin: iLastCodeLine = iLine if isCodeLine and line.endswith('\\'): inspectLineAfter = True satisfied = not isIndent and isCodeLine and not inspectLineAfter if iLine >= iLineMin and satisfied: yield iFirstCodeLine, iLastCodeLine, isEmpty, inspectLineBefore if isCodeLine: iLastCodeLine = iLine isFirstCodeLine = False iLine += 1 yield iFirstCodeLine, iLastCodeLine, isEmpty, inspectLineBefore
def completeBlockEnd(self, iLine, iLineMin, iLineMax, isEmpty=True, expectMoreLinesBefore=False): '''Add following lines that are required to execute the selected code, without leaving code that cannot be executed seperately in the next step.''' iLastCodeLine = iLine iFirstCodeLine = None inspectMoreLines = False nextLineIsRequired = False while iLine <= iLineMax: thisLineIsRequired = nextLineIsRequired line = editor.getLine(iLine).rstrip() isCodeLine = len(line) > 0 and not line.lstrip().startswith('#') isIndent = isCodeLine and (line.startswith(' ') or line.startswith('\t')) nextLineIsRequired = line.startswith('else:') or line.startswith('elif') \ or line.startswith('except:') or line.startswith('finally:') if nextLineIsRequired or isIndent: inspectMoreLines = True if isEmpty and isIndent: expectMoreLinesBefore = True if isCodeLine: isEmpty = False if isCodeLine and not nextLineIsRequired: inspectMoreLines = False if isCodeLine: if iFirstCodeLine is None: iFirstCodeLine = iLine if thisLineIsRequired or iLine <= iLineMin: iLastCodeLine = iLine satisfied = not isIndent and isCodeLine and not inspectMoreLines and not nextLineIsRequired if iLine >= iLineMin and satisfied: yield iFirstCodeLine, iLastCodeLine, isEmpty, expectMoreLinesBefore if isCodeLine: iLastCodeLine = iLine iLine += 1 yield iFirstCodeLine, iLastCodeLine, isEmpty, expectMoreLinesBefore
def column_lexer(self, start_pos, end_pos): ''' Main lexing logic. Gets called by styleneeded callback ''' def style_it(start, length, STYLE): ''' Inform scintilla to do the styling''' if length >= 0: editor.startStyling(start, 31) editor.setStyling(length, STYLE) # first everything will be styled with default style style_it(start_pos, end_pos-start_pos, self.DEFAULT) # loop over line indexes from start_pos and end_pos for line in range(editor.lineFromPosition(start_pos), editor.lineFromPosition(end_pos)): # get start position for each line line_start_pos = editor.positionFromLine(line) # split current line into columns columns = editor.getLine(line).split(self.COLUMN_SEPARATOR) if columns > 0: # iterate over all columns for i, column in enumerate(columns): # get the width of the current column col_length = len(column) if i % 2 == 0: # even column style_it(line_start_pos,col_length,self.EVEN_COLUMN_STYLE) else: # odd column style_it(line_start_pos,col_length, self.ODD_COLUMN_STYLE) # recalculate start position for next column line_start_pos += col_length+1 # this needs to stay and to be the last line, to signal scintilla we are done. editor.startStyling(end_pos,31)
def showCalltip(self, pos=None): iStart = editor.getSelectionStart() iEnd = editor.getSelectionEnd() if pos is None: pos = editor.getCurrentPos() CT_unselected = True CT_expression = True else: CT_unselected = self.popupForUnselectedVariable CT_expression = self.popupForSelectedExpression if iEnd != iStart and iStart <= pos <= iEnd: if CT_expression and iEnd - iStart > 1: expression = editor.getTextRange(iStart, iEnd) if expression == 'False': self.activeCalltip = False editor.callTipShow(iStart, 'set to True') elif expression == 'True': self.activeCalltip = True editor.callTipShow(iStart, 'set to False') elif not '\n' in expression: ret = self.interp.getCallTip(None, expression) if ret and (CT_unselected or ret[-1] != 'value error'): element, nHighlight, calltip = ret self.activeCalltip = 'doc' editor.callTipShow(iStart, ''.join(calltip)) editor.callTipSetHlt(0, int(nHighlight)) else: iLineStart = editor.positionFromLine( editor.lineFromPosition(iStart)) var = editor.getTextRange(iStart, iEnd) line = editor.getTextRange(iLineStart, iEnd) if var == '.': autoCompleteList = self.interp.autoCompleteObject( self.getUncompleteLine(iStart + 1)) if autoCompleteList: editor.autoCSetSeparator(ord('\t')) editor.autoCSetIgnoreCase(False) editor.autoCSetCaseInsensitiveBehaviour(False) editor.autoCSetOrder(0) editor.autoCSetDropRestOfWord(True) editor.autoCShow(0, autoCompleteList) else: ret = self.interp.getCallTip(line, var) if ret: element, nHighlight, calltip = ret if element == var == 'False': self.activeCalltip = False editor.callTipShow(iStart, 'set to True') elif element == var == 'True': self.activeCalltip = True editor.callTipShow(iStart, 'set to False') elif ret[-1] != 'value error': self.activeCalltip = 'doc' editor.callTipShow(iStart, ''.join(calltip)) editor.callTipSetHlt(0, int(nHighlight)) elif CT_unselected and iStart == iEnd and pos >= 0: iLine = editor.lineFromPosition(pos) line = editor.getLine(iLine) iLineStart = editor.positionFromLine(iLine) posInLine = pos - iLineStart iWordEnd = 0 for iWordStart in range(posInLine, -1, -1): s = line[iWordStart] if not ('a' <= s <= 'z' or 'A' <= s <= 'Z' or '0' <= s <= '9' or s == '_'): iWordStart += 1 break if iWordStart <= posInLine: for iWordEnd in range(posInLine + 1, len(line)): s = line[iWordEnd] if not ('a' <= s <= 'z' or 'A' <= s <= 'Z' or '0' <= s <= '9' or s == '_'): iWordEnd -= 1 break var = line[iWordStart:iWordEnd + 1] if var: var = line[iWordStart:iWordEnd + 1] ret = self.interp.getCallTip(line[0:iWordEnd + 1], var) pos = iLineStart + iWordStart if ret: element, nHighlight, calltip = ret if calltip != 'value error': self.activeCalltip = 'doc' editor.callTipShow(pos, ''.join(calltip)) editor.callTipSetHlt(0, int(nHighlight))
def runThread(self, moveCursor=True, nonSelectedLine=None, onlyInsideCodeLines=False): '''Executes the smallest possible code element for the current selection. Or execute one marked cell.''' bufferID = notepad.getCurrentBufferID() self.bufferActive = bufferID lang = notepad.getLangType() filename = notepad.getCurrentFilename() if lang == Npp.LANGTYPE.TXT and '.' not in os.path.basename(filename): notepad.setLangType(Npp.LANGTYPE.PYTHON) elif lang != Npp.LANGTYPE.PYTHON: self.bufferActive = 0 return if nonSelectedLine is None: iSelStart = editor.getSelectionStart() iSelEnd = editor.getSelectionEnd() iPos = editor.getCurrentPos() iLineCursor = iLineStart = editor.lineFromPosition(iSelStart) iLineEnd = max(iLineStart, editor.lineFromPosition(iSelEnd - 1)) else: iLineCursor = iLineStart = iLineEnd = nonSelectedLine iSelStart = iSelEnd = 0 selection = iSelStart != iSelEnd startLine = editor.getLine(iLineStart).rstrip() cellMode = not selection and (startLine.startswith('#%%') or startLine.startswith('# %%')) err = None if not cellMode: getLineEnd = self.completeBlockEnd(iLineStart, iLineMin=iLineEnd, iLineMax=editor.getLineCount() - 1) iFirstCodeLine, iLineEnd, isEmpty, inspectLineBefore = next( getLineEnd) if not inspectLineBefore and iFirstCodeLine: iLineStart = iFirstCodeLine if isEmpty: self.hideMarkers(bufferID) self.bufferActive = 0 return iLineStart = self.completeBlockStart(iLineStart, inspectLineBefore) requireMore = True iStart = editor.positionFromLine(iLineStart) iDocEnd = editor.getLength() if cellMode: iMatch = [] editor.research('^# ?%%(.*)$', lambda m: iMatch.append(m.span(0)[0] - 1), 0, iStart + 4, iDocEnd - 1, 1) iEnd = iMatch[0] if len(iMatch) else iDocEnd iLineEnd = editor.lineFromPosition(iEnd) block = editor.getTextRange(iStart, iEnd).rstrip() r = self.interp.tryCode(iLineStart, filename, block) if r is None: self.hideMarkers(bufferID) self.bufferActive = 0 return err, requireMore, isValue = r if requireMore: err = True else: # add more lines until the parser is happy or finds # a syntax error while requireMore: iEnd = editor.getLineEndPosition(iLineEnd) block = editor.getTextRange(iStart, iEnd).rstrip() if block: res = self.interp.tryCode(iLineStart, filename, block) if res is None: self.bufferActive = 0 return else: err, requireMore, isValue = res else: err, requireMore, isValue = None, True, False if requireMore: nextLine = next(getLineEnd, None) if nextLine is None: self.bufferActive = 0 iEnd = editor.getLength() block = editor.getTextRange(iStart, iEnd).rstrip() err, buff = self.interp.execute( block, iLineStart, filename) self.outBuffer(buff) self.setMarkers(iLineStart, iLineEnd, block, iMarker=self.m_error, bufferID=bufferID) return iCodeLineStart, iLineEnd, isEmpty, inspectLineBefore = nextLine if onlyInsideCodeLines and not selection and not iLineStart <= iLineCursor <= iLineEnd: self.hideMarkers() self.bufferActive = 0 return if self.activeCalltip: editor.callTipCancel() self.activeCalltip = None self.setMarkers(iLineStart, iLineEnd, block, iMarker=(self.m_active if not err else self.m_error), bufferID=bufferID) if err is not None: if moveCursor: editor.setSelectionStart(iStart) editor.scrollRange(iEnd, iStart) if err is not True: self.outBuffer(err) else: # Check if correct path is set if self.lastActiveBufferID != bufferID and '.' in os.path.basename( filename): filePath = os.path.normpath(os.path.split(filename)[0]) self.interp.execute('os.chdir(' + repr(filePath) + ')') self.lastActiveBufferID = bufferID # Start a thread to execute the code if moveCursor: iNewPos = max(iPos, editor.positionFromLine(iLineEnd + 1)) editor.setSelectionStart(iNewPos) editor.setCurrentPos(iNewPos) if iNewPos >= iDocEnd and iLineEnd == editor.getLineCount( ) - 1: editor.newLine() editor.scrollCaret() if self.matplotlib_eventHandler and not self.matplotlib_enabled: if 'matplotlib' in block: self.interp.execute(init_matplotlib_eventHandler) self.matplotlib_enabled = True if isValue: res = self.interp.evaluate() if res is not None: err, result = res if not err: if self.bufferActive: self.changeMarkers(iMarker=self.m_finish, bufferID=bufferID) if result: self.stdout(result + '\n') else: self.changeMarkers(iMarker=self.m_error, bufferID=bufferID) self.outBuffer(result) else: res = self.interp.execute() if res is not None: err, result = res if not err and self.bufferActive: self.changeMarkers(iMarker=self.m_finish, bufferID=bufferID) else: self.changeMarkers(iMarker=self.m_error, bufferID=bufferID) self.outBuffer(result) if err: self.changeMarkers(iMarker=self.m_error, bufferID=bufferID) self.bufferActive = 0
def callback_scintillawrapper_int_int_stringresult_getLine(self, args): lineTwo = editor.getLine(1) lineThree = editor.getLine(2) self.assertEqual(lineTwo, 'Two\r\n') self.assertEqual(lineThree, 'Three') self.callbackCalled = True
def test_scintillawrapper_int_int_stringresult_getLine(self): editor.write('One\r\nTwo\r\nThree') lineTwo = editor.getLine(1) lineThree = editor.getLine(2) self.assertEqual(lineTwo, 'Two\r\n') self.assertEqual(lineThree, 'Three')
def onMouseDwell(self, args): '''Show a call tip window about the current content of a selected variable''' if self.bufferBusy or self.interp.kernelBusy.isSet(): return if editor.callTipActive(): return p = editor.positionFromPoint(args['x'], args['y']) iStart = editor.getSelectionStart() iEnd = editor.getSelectionEnd() if iEnd != iStart and iStart <= p <= iEnd: if self.popupForSelectedExpression and iEnd - iStart > 1: expression = editor.getTextRange(iStart, iEnd) if expression == 'False': self.activeCalltip = False editor.callTipShow(iStart, 'set to True') elif expression == 'True': self.activeCalltip = True editor.callTipShow(iStart, 'set to False') elif not '\n' in expression: ret = self.interp.getCallTip(None, expression) if ret: element, nHighlight, calltip = ret self.activeCalltip = 'doc' editor.callTipShow(iStart, ''.join(calltip)) editor.callTipSetHlt(0, int(nHighlight)) else: iLineStart = editor.positionFromLine( editor.lineFromPosition(iStart)) var = editor.getTextRange(iStart, iEnd) line = editor.getTextRange(iLineStart, iEnd) if var == '.': autoCompleteList = self.interp.autoCompleteObject( self.getUncompleteLine(iStart + 1)) if autoCompleteList: editor.autoCSetSeparator(ord('\t')) editor.autoCSetIgnoreCase(False) editor.autoCSetCaseInsensitiveBehaviour(False) editor.autoCSetOrder(0) editor.autoCSetDropRestOfWord(True) editor.autoCShow(0, autoCompleteList) else: ret = self.interp.getCallTip(line, var) if ret: element, nHighlight, calltip = ret if element == var == 'False': self.activeCalltip = False editor.callTipShow(iStart, 'set to True') elif element == var == 'True': self.activeCalltip = True editor.callTipShow(iStart, 'set to False') else: self.activeCalltip = 'doc' editor.callTipShow(iStart, ''.join(calltip)) editor.callTipSetHlt(0, int(nHighlight)) elif self.popupForUnselectedVariable and iStart == iEnd and p >= 0: iLine = editor.lineFromPosition(p) line = editor.getLine(iLine) iLineStart = editor.positionFromLine(iLine) posInLine = p - iLineStart iWordEnd = 0 for iWordStart in range(posInLine, -1, -1): s = line[iWordStart] if not ('a' <= s <= 'z' or 'A' <= s <= 'Z' or '0' <= s <= '9' or s == '_'): iWordStart += 1 break if iWordStart <= posInLine: for iWordEnd in range(posInLine + 1, len(line)): s = line[iWordEnd] if not ('a' <= s <= 'z' or 'A' <= s <= 'Z' or '0' <= s <= '9' or s == '_'): iWordEnd -= 1 break var = line[iWordStart:iWordEnd + 1] if var: var = line[iWordStart:iWordEnd + 1] ret = self.interp.getCallTip(line[0:iWordEnd + 1], var) pos = iLineStart + iWordStart if ret: element, nHighlight, calltip = ret self.activeCalltip = 'doc' editor.callTipShow(pos, ''.join(calltip)) editor.callTipSetHlt(0, int(nHighlight))