private synchronized void store() { File history = getHistoryFile(); if (history != null) { try { BufferedWriter bw = new BufferedWriter(new FileWriter(history)); try { for (String line : lines) { bw.write(line); bw.write("\n"); } } catch (IOException e) { Log.log("Failed writing console history.py", e); } finally { try { bw.close(); } catch (IOException e) { Log.log("Failed closing console history.py", e); } } } catch (IOException e) { Log.log("Failed creating console history.py", e); } } }
private synchronized void load() { File history = getHistoryFile(); if (history != null) { try { BufferedReader br = new BufferedReader(new FileReader(history)); try { String line = br.readLine(); while (line != null) { lines.add(line); line = br.readLine(); } } catch (IOException e) { Log.log("Failed reading existing console history.py", e); } finally { try { br.close(); } catch (IOException e) { Log.log("Failed closing existing console history.py", e); } } } catch (FileNotFoundException e) { Log.logInfo("No existing console history at: " + history, e); } } }
/** This method should be called after all the lines received were processed. */ private void onAfterAllLinesHandled( final String finalText, final boolean finalAddedParen, final int finalStart, final int finalOffset, final boolean finalAddedCloseParen, final String finalIndentString, final int finalNewDeltaCaretPosition) { boolean shiftsCaret = true; String newText = finalText.substring(finalStart, finalText.length()); if (finalAddedParen) { String cmdLine = getCommandLine(); Document parenDoc = new Document(cmdLine + newText); int currentOffset = cmdLine.length() + 1; DocCmd docCmd = new DocCmd(currentOffset, 0, "("); docCmd.shiftsCaret = true; try { strategy.customizeParenthesis(parenDoc, docCmd); } catch (BadLocationException e) { Log.log(e); } newText = docCmd.text + newText.substring(1); if (!docCmd.shiftsCaret) { shiftsCaret = false; setCaretOffset(finalOffset + (docCmd.caretOffset - currentOffset)); } } else if (finalAddedCloseParen) { String cmdLine = getCommandLine(); String existingDoc = cmdLine + finalText.substring(1); int cmdLineOffset = cmdLine.length(); if (existingDoc.length() > cmdLineOffset) { Document parenDoc = new Document(existingDoc); DocCmd docCmd = new DocCmd(cmdLineOffset, 0, ")"); docCmd.shiftsCaret = true; boolean canSkipOpenParenthesis; try { canSkipOpenParenthesis = strategy.canSkipCloseParenthesis(parenDoc, docCmd); } catch (BadLocationException e) { canSkipOpenParenthesis = false; Log.log(e); } if (canSkipOpenParenthesis) { shiftsCaret = false; setCaretOffset(finalOffset + 1); newText = newText.substring(1); } } } // and now add the last line (without actually handling it). String cmd = finalIndentString + newText; cmd = convertTabs(cmd); applyStyleToUserAddedText(cmd, doc.getLength()); appendText(cmd); if (shiftsCaret) { setCaretOffset(doc.getLength() - finalNewDeltaCaretPosition); } history.update(getCommandLine()); }
/** * @return the command line that the user entered. * @throws BadLocationException */ public String getCommandLine() { int commandLineOffset; int commandLineLength; try { commandLineOffset = getCommandLineOffset(); commandLineLength = getCommandLineLength(); } catch (BadLocationException e1) { Log.log(e1); return ""; } if (commandLineLength < 0) { return ""; } try { return doc.get(commandLineOffset, commandLineLength); } catch (BadLocationException e) { String msg = new FastStringBuffer(60) .append("Error: bad location: offset:") .append(commandLineOffset) .append(" text:") .append(commandLineLength) .toString(); Log.log(msg); return ""; } }
/** * Appends some text at the end of the document. * * @param text the text to be added. */ protected void appendText(String text) { int initialOffset = doc.getLength(); try { doc.replace(initialOffset, 0, text); } catch (BadLocationException e) { Log.log(e); } }
/** * Process the result that came from pushing some text to the interpreter. * * @param result the response from the interpreter after sending some command for it to process. */ protected void processResult(final InterpreterResponse result) { if (result != null) { addToConsoleView(result.out, true); addToConsoleView(result.err, false); history.commit(); try { offset = getLastLineLength(); } catch (BadLocationException e) { Log.log(e); } } appendInvitation(false); }
/** * Clear the document and show the initial prompt. * * @param addInitialCommands indicates if the initial commands should be appended to the document. */ public void clear(boolean addInitialCommands) { startDisconnected(); try { doc.set(""); // $NON-NLS-1$ appendInvitation(true); } finally { stopDisconnected(); } if (addInitialCommands) { try { doc.replace(doc.getLength(), 0, this.initialCommands); } catch (BadLocationException e) { Log.log(e); } } }
/** * Checks if the trigger character should actually a * * @param trigger * @param doc * @param offset * @return */ protected boolean triggerCharAppliesCurrentCompletion(char trigger, IDocument doc, int offset) { if (trigger == '.' && !getApplyCompletionOnDot()) { // do not apply completion when it's triggered by '.', because that's usually not what's // wanted // e.g.: if the user writes sys and the current completion is SystemError, pressing '.' will // apply // the completion, but what the user usually wants is just having sys.xxx and not // SystemError.xxx try { doc.replace(offset, 0, "."); } catch (BadLocationException e) { Log.log(e); } return false; } return true; }
/** * Adds some text that came as an output to stdout or stderr to the console. * * @param out the text that should be added * @param stdout true if it came from stdout and also if it came from stderr */ private void addToConsoleView(String out, boolean stdout) { if (out.length() == 0) { return; // nothing to add! } int start = doc.getLength(); IConsoleStyleProvider styleProvider = viewer.getStyleProvider(); Tuple<List<ScriptStyleRange>, String> style = null; if (styleProvider != null) { if (stdout) { style = styleProvider.createInterpreterOutputStyle(out, start); } else { // stderr style = styleProvider.createInterpreterErrorStyle(out, start); } if (style != null) { for (ScriptStyleRange s : style.o1) { addToPartitioner(s); } } } if (style != null) { appendText(style.o2); } TextSelectionUtils ps = new TextSelectionUtils(doc, start); int cursorLine = ps.getCursorLine(); int numberOfLines = doc.getNumberOfLines(); // right after appending the text, let's notify line trackers for (int i = cursorLine; i < numberOfLines; i++) { try { int offset = ps.getLineOffset(i); int endOffset = ps.getEndLineOffset(i); Region region = new Region(offset, endOffset - offset); for (IConsoleLineTracker lineTracker : this.consoleLineTrackers) { lineTracker.lineAppended(region); } } catch (Exception e) { Log.log(e); } } }
/** * Called when Ctrl is selected during the completions * * @see * org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, * boolean) */ public void selected(ITextViewer viewer, boolean smartToggle) { if (smartToggle) { StyledText text = viewer.getTextWidget(); if (text == null || text.isDisposed()) { return; } int widgetCaret = text.getCaretOffset(); IDocument document = viewer.getDocument(); int finalOffset = widgetCaret; try { if (finalOffset >= document.getLength()) { unselected(viewer); return; } char c; do { c = document.getChar(finalOffset); finalOffset++; } while (isValidChar(c) && finalOffset < document.getLength()); if (c == '(') { fLastIsPar = true; } else { fLastIsPar = false; } if (!isValidChar(c)) { finalOffset--; } this.fLen = finalOffset - widgetCaret; this.getPresentationUpdater().updateStyle(viewer, widgetCaret, this.fLen); } catch (BadLocationException e) { Log.log(e); } } else { unselected(viewer); } }
@Override public void paintControl(PaintEvent e) { if (inDraw || styledText == null || styledText.isDisposed()) { return; } try { inDraw = true; boolean showIndentGuide = this.indentGuide.getShowIndentGuide(); if (!showIndentGuide) { return; } int xOffset = styledText.getHorizontalPixel(); int yOffset = styledText.getTopPixel(); // Important: call all to cache the new values (instead of doing all inside the or below). boolean styledTextContentChanged = getStyledTextContentChangedAndStoreNew(); boolean clientAreaChanged = getClientAreaChangedAndStoreNew(); boolean charCountChanged = getCharCountChangedAndStoreNew(); boolean tabWidthChanged = getTabWidthChangedAndStoreNew(); boolean redrawAll = styledTextContentChanged || clientAreaChanged || charCountChanged || tabWidthChanged || xOffset != lastXOffset || yOffset != lastYOffset; StyledTextContent currentContent = this.content; if (currClientArea == null || currClientArea.width < 5 || currClientArea.height < 5 || currCharCount < 1 || currentContent == null || currTabWidth <= 0) { return; } lastXOffset = xOffset; lastYOffset = yOffset; int topIndex; try { topIndex = JFaceTextUtil.getPartialTopIndex(styledText); } catch (IllegalArgumentException e1) { // Just silence it... // java.lang.IllegalArgumentException: Index out of bounds // at org.eclipse.swt.SWT.error(SWT.java:4458) // at org.eclipse.swt.SWT.error(SWT.java:4392) // at org.eclipse.swt.SWT.error(SWT.java:4363) // at org.eclipse.swt.custom.StyledText.getOffsetAtLine(StyledText.java:4405) // at org.eclipse.jface.text.JFaceTextUtil.getPartialTopIndex(JFaceTextUtil.java:103) // at // org.python.pydev.shared_ui.editor.VerticalIndentGuidesPainter.paintControl(VerticalIndentGuidesPainter.java:93) return; } int bottomIndex = JFaceTextUtil.getPartialBottomIndex(styledText); if (redrawAll) { this.lineToVerticalLinesToDraw = this.indentGuide.computeVerticalLinesToDrawInRegion(styledText, topIndex, bottomIndex); // This is a bit unfortunate: when something changes, we may have to repaint out of the // clipping // region, but even setting the clipping region (e.gc.setClipping), the clipping region may // still // be unchanged (because the system said that it only wants to repaint some specific area // already // and we can't make it bigger -- so, what's left for us is asking for a repaint of the full // area // in this case). if (askFullRedraw) { askFullRedraw = false; if (Math.abs(currClientArea.height - e.gc.getClipping().height) > 40) { // Only do it if the difference is really high (some decorations make it usually a bit // lower than // the actual client area -- usually around 14 in my tests, but make it a bit higher as // the usual // difference when a redraw is needed is pretty high). RunInUiThread.async( new Runnable() { @Override public void run() { StyledText s = styledText; if (s != null && !s.isDisposed()) { s.redraw(); } } }); } else { } } } if (this.lineToVerticalLinesToDraw != null) { try (AutoCloseable temp = configGC(e.gc)) { Collection<List<VerticalLinesToDraw>> values = lineToVerticalLinesToDraw.values(); for (List<VerticalLinesToDraw> list : values) { for (VerticalLinesToDraw verticalLinesToDraw : list) { verticalLinesToDraw.drawLine(e.gc); } } } } } catch (Exception e1) { Log.log(e1); } finally { inDraw = false; } }
/** * Should be called right after adding some text to the console (it'll actually go on, remove the * text just added and add it line-by-line in the document so that it can be correctly treated in * the console). * * @param offset the offset where the addition took place * @param text the text that should be adedd */ protected void proccessAddition(int offset, String text) { // we have to do some gymnastics here to add line-by-line the contents that the user entered. // (mostly because it may have been a copy/paste with multi-lines) String indentString = ""; boolean addedNewLine = false; boolean addedParen = false; boolean addedCloseParen = false; int addedLen = text.length(); if (addedLen == 1) { if (text.equals("\r") || text.equals("\n")) { addedNewLine = true; } else if (text.equals("(")) { addedParen = true; } else if (text.equals(")")) { addedCloseParen = true; } } else if (addedLen == 2) { if (text.equals("\r\n")) { addedNewLine = true; } } String delim = getDelimeter(); int newDeltaCaretPosition = doc.getLength() - (offset + text.length()); // 1st, remove the text the user just entered (and enter it line-by-line later) try { // Remove the just entered text doc.replace(offset, text.length(), ""); // $NON-NLS-1$ // Is the current offset in the command line // NB we do this after the above as the pasted text may have new lines in it boolean offset_in_command_line = offset >= getCommandLineOffset(); // If the offset isn't in the command line, then just append to the existing // command line text if (!offset_in_command_line) { offset = newDeltaCaretPosition = getCommandLineOffset(); // Remove any existing command line text and prepend it to the text // we're inserting text = doc.get(getCommandLineOffset(), getCommandLineLength()) + text; doc.replace(getCommandLineOffset(), getCommandLineLength(), ""); } else { // paste is within the command line text = text + doc.get(offset, doc.getLength() - offset); doc.replace(offset, doc.getLength() - offset, ""); } } catch (BadLocationException e) { text = ""; Log.log(e); } text = text.replaceAll("\r\n|\n|\r", delim); // $NON-NLS-1$ // now, add it line-by-line (it won't even get into the loop if there's no // new line in the text added). int start = 0; int index = -1; List<String> commands = new ArrayList<String>(); while ((index = text.indexOf(delim, start)) != -1) { String cmd = text.substring(start, index); cmd = convertTabs(cmd); commands.add(cmd); start = index + delim.length(); } final String[] finalIndentString = new String[] {indentString}; if (commands.size() > 0) { // Note that we'll disconnect from the document here and reconnect when the last line is // executed. startDisconnected(); String cmd = commands.get(0); execCommand( addedNewLine, delim, finalIndentString, cmd, commands, 0, text, addedParen, start, addedCloseParen, newDeltaCaretPosition); } else { onAfterAllLinesHandled( text, addedParen, start, offset, addedCloseParen, finalIndentString[0], newDeltaCaretPosition); } }