diff --git a/python/src/com/jetbrains/python/console/PyConsoleStartFolding.java b/python/src/com/jetbrains/python/console/PyConsoleStartFolding.java new file mode 100644 index 000000000000..289fcdbd7c82 --- /dev/null +++ b/python/src/com/jetbrains/python/console/PyConsoleStartFolding.java @@ -0,0 +1,105 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.console; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.FoldRegion; +import com.intellij.openapi.editor.FoldingModel; +import com.intellij.openapi.editor.event.DocumentAdapter; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.ex.FoldingListener; +import com.intellij.util.DocumentUtil; +import com.jetbrains.python.console.pydev.ConsoleCommunicationListener; +import org.jetbrains.annotations.NotNull; + +public class PyConsoleStartFolding extends DocumentAdapter implements ConsoleCommunicationListener, FoldingListener { + private PythonConsoleView myConsoleView; + private boolean isFirstCommandWasExecuted = false; + private boolean doNotAddFoldingAgain = false; + private FoldRegion myStartFoldRegion; + private static final String DEFAULT_FOLDING_MESSAGE = "Python Console"; + private int startLineOffset = 0; + + public PyConsoleStartFolding(PythonConsoleView consoleView) { + super(); + myConsoleView = consoleView; + } + + public void setStartLineOffset(int startLineOffset) { + this.startLineOffset = startLineOffset; + } + + @Override + public void documentChanged(DocumentEvent event) { + addFolding(); + } + + private void addFolding() { + Document document = myConsoleView.getEditor().getDocument(); + if (doNotAddFoldingAgain || document.getTextLength() == 0) { + return; + } + FoldingModel foldingModel = myConsoleView.getEditor().getFoldingModel(); + foldingModel.runBatchFoldingOperation(() -> { + int start = startLineOffset; + String placeholderText = DEFAULT_FOLDING_MESSAGE; + int firstLine = document.getLineNumber(startLineOffset); + for (int line = firstLine; line < document.getLineCount(); line++) { + String lineText = document.getText(DocumentUtil.getLineTextRange(document, line)); + if (lineText.startsWith("Python")) { + placeholderText = lineText; + start = document.getLineStartOffset(line); + break; + } + } + + if (myStartFoldRegion != null) { + foldingModel.removeFoldRegion(myStartFoldRegion); + } + FoldRegion foldRegion = foldingModel.addFoldRegion(start, document.getTextLength() - 1, placeholderText); + if (foldRegion != null) { + foldRegion.setExpanded(false); + myStartFoldRegion = foldRegion; + } + }); + if (isFirstCommandWasExecuted) { + document.removeDocumentListener(this); + } + } + + @Override + public void commandExecuted(boolean more) { + isFirstCommandWasExecuted = true; + } + + @Override + public void inputRequested() { + + } + + @Override + public void onFoldRegionStateChange(@NotNull FoldRegion region) { + if (region.equals(myStartFoldRegion) && region.isExpanded()) { + myConsoleView.getEditor().getComponent().updateUI(); + doNotAddFoldingAgain = true; + } + } + + @Override + public void onFoldProcessingEnd() { + + } +} diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunnerImpl.java b/python/src/com/jetbrains/python/console/PydevConsoleRunnerImpl.java index b551bc98f5b9..50231dbe5f59 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleRunnerImpl.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleRunnerImpl.java @@ -588,7 +588,6 @@ public class PydevConsoleRunnerImpl implements PydevConsoleRunner { myConsoleView.attachToProcess(myProcessHandler); createContentDescriptorAndActions(); - // Run myProcessHandler.startNotify(); }); @@ -635,6 +634,7 @@ public class PydevConsoleRunnerImpl implements PydevConsoleRunner { final List actions = fillToolBarActions(toolbarActions, contentDescriptor); registerActionShortcuts(actions, myConsoleView.getConsoleEditor().getComponent()); registerActionShortcuts(actions, panel); + getConsoleView().addConsoleFolding(false); showContentDescriptor(contentDescriptor); } diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java index 2fef442ee2df..cf2734e57a2c 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java @@ -33,6 +33,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.ex.FoldingModelEx; import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter; import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.markup.HighlighterTargetArea; @@ -114,6 +115,30 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable getFile().putCopyableUserData(PydevConsoleRunner.CONSOLE_KEY, communication); } + private PyConsoleStartFolding createConsoleFolding() { + PyConsoleStartFolding startFolding = new PyConsoleStartFolding(this); + myExecuteActionHandler.getConsoleCommunication().addCommunicationListener(startFolding); + getEditor().getDocument().addDocumentListener(startFolding); + ((FoldingModelEx)getEditor().getFoldingModel()).addListener(startFolding, this); + return startFolding; + } + + public void addConsoleFolding(boolean isDebugConsole) { + try { + if (isDebugConsole && myExecuteActionHandler != null) { + PyConsoleStartFolding folding = createConsoleFolding(); + // in debug console we should add folding from the place where the folding was turned on + folding.setStartLineOffset(getEditor().getDocument().getTextLength()); + } + else { + myInitialized.doWhenDone(this::createConsoleFolding); + } + } + catch (Exception e) { + LOG.error(e.getMessage()); + } + } + public void setExecutionHandler(@NotNull PydevConsoleExecuteActionHandler consoleExecuteActionHandler) { myExecuteActionHandler = consoleExecuteActionHandler; } diff --git a/python/src/com/jetbrains/python/console/PythonDebugLanguageConsoleView.java b/python/src/com/jetbrains/python/console/PythonDebugLanguageConsoleView.java index 076c268cc7c7..04129d41ce12 100644 --- a/python/src/com/jetbrains/python/console/PythonDebugLanguageConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonDebugLanguageConsoleView.java @@ -73,6 +73,7 @@ public class PythonDebugLanguageConsoleView extends DuplexConsoleView