Enable forward carets traversing

This commit is contained in:
Alexander Zolotov
2015-01-15 11:50:42 +03:00
parent 9a7bfa228c
commit f241b699b8
14 changed files with 46 additions and 38 deletions
@@ -485,7 +485,7 @@ class Foo {
writeCommand(runnable)
}
private writeCommand(Runnable runnable) {
private static writeCommand(Runnable runnable) {
WriteCommandAction.runWriteCommandAction(null, runnable)
}
@@ -894,7 +894,7 @@ class Foo {
class Foo {
{
System.out.println();
sout
System.out.println();
System.out.println();
}
}
@@ -924,8 +924,7 @@ class Foo {
class Foo {
{
System.out.println();
sout
System.out.println();
System.out.println();
}
}
@@ -956,7 +955,7 @@ class Foo {
class Foo {
{
System.out.println();
sout
System.out.println();
System.out.println();
}
}
@@ -37,16 +37,16 @@ import org.jetbrains.annotations.NotNull;
/**
* Base class for PSI-aware editor actions that need to support multiple carets.
* Recognizes multi-root PSI and injected fragments, so different carets might be processed in context of different
* {@link com.intellij.openapi.editor.Editor} and {@link com.intellij.psi.PsiFile} instances.
* {@link Editor} and {@link PsiFile} instances.
* <p>
* Implementations should implement {@link #getHandler()} method, and might override {@link
* #isValidFor(com.intellij.openapi.project.Project, com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.psi.PsiFile)} method.
* #isValidFor(Project, Editor, Caret, PsiFile)} method.
*
* @see com.intellij.codeInsight.actions.MultiCaretCodeInsightActionHandler
* @see MultiCaretCodeInsightActionHandler
*/
public abstract class MultiCaretCodeInsightAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
public void actionPerformed(@NotNull AnActionEvent e) {
final Project project = e.getProject();
if (project == null) {
return;
@@ -82,7 +82,7 @@ public abstract class MultiCaretCodeInsightAction extends AnAction {
}
@Override
public void update(AnActionEvent e) {
public void update(@NotNull AnActionEvent e) {
final Presentation presentation = e.getPresentation();
Project project = e.getProject();
@@ -132,7 +132,7 @@ public abstract class MultiCaretCodeInsightAction extends AnAction {
handler.invoke(project, editor, caret, file);
}
}
}, true);
});
}
/**
@@ -22,11 +22,11 @@ import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
/**
* Delegate class that performs actual work for {@link com.intellij.codeInsight.actions.MultiCaretCodeInsightAction}
* Delegate class that performs actual work for {@link MultiCaretCodeInsightAction}
*/
public abstract class MultiCaretCodeInsightActionHandler {
/**
* Invoked for each caret in editor (in bottom-to-top order). <code>project</code> value is the same for all carets, <code>editor</code>
* Invoked for each caret in editor (in top-to-bottom order). <code>project</code> value is the same for all carets, <code>editor</code>
* and <code>file</code> values can be different in presence of multi-root PSI and injected fragments. For injected fragments
* caret instance will belong to corresponding injected editor.
*/
@@ -621,7 +621,7 @@ public class CodeCompletionHandlerBase {
injectedMap);
contexts.add(currentContext);
}
}, true);
});
context = contexts.get(contexts.size() - 1);
if (context.shouldAddCompletionChar() && context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@@ -54,6 +54,7 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -198,7 +199,7 @@ public class TypedHandler extends TypedActionHandlerBase {
}
}
else if ('"' == charTyped || '\'' == charTyped || '`' == charTyped/* || '/' == charTyped*/) {
if (handleQuote(editor, charTyped, dataContext, file)) return;
if (handleQuote(editor, charTyped, file)) return;
}
long modificationStampBeforeTyping = editor.getDocument().getModificationStamp();
@@ -233,7 +234,7 @@ public class TypedHandler extends TypedActionHandlerBase {
indentOpenedParenth(project, editor);
}
}
}, true);
});
}
private static void type(Editor editor, char charTyped) {
@@ -252,6 +253,12 @@ public class TypedHandler extends TypedActionHandlerBase {
AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, null);
}
}
public static void commitDocumentIfCurrentCaretIsNotTheFirstOne(@NotNull Editor editor, @NotNull Project project) {
if (ContainerUtil.getFirstItem(editor.getCaretModel().getAllCarets()) != editor.getCaretModel().getCurrentCaret()) {
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
}
}
private static boolean isAutoPopup(@NotNull Editor editor, @NotNull PsiFile file, char charTyped) {
final int offset = editor.getCaretModel().getOffset() - 1;
@@ -425,7 +432,7 @@ public class TypedHandler extends TypedActionHandlerBase {
return true;
}
private boolean handleQuote(@NotNull Editor editor, char quote, @NotNull DataContext dataContext, @NotNull PsiFile file) {
private static boolean handleQuote(@NotNull Editor editor, char quote, @NotNull PsiFile file) {
if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_QUOTE) return false;
final QuoteHandler quoteHandler = getQuoteHandler(file, editor);
if (quoteHandler == null) return false;
@@ -122,18 +122,18 @@ public class CommentByLineCommentHandler extends MultiCaretCodeInsightActionHand
Block lastBlock = myBlocks.isEmpty() ? null : myBlocks.get(myBlocks.size() - 1);
Block currentBlock;
if (lastBlock == null || lastBlock.editor != editor || lastBlock.psiFile != file || endLine < (lastBlock.startLine - 1)) {
if (lastBlock == null || lastBlock.editor != editor || lastBlock.psiFile != file || startLine > (lastBlock.endLine + 1)) {
currentBlock = new Block();
currentBlock.editor = editor;
currentBlock.psiFile = file;
currentBlock.endLine = endLine;
currentBlock.startLine = startLine;
myBlocks.add(currentBlock);
}
else {
currentBlock = lastBlock;
}
currentBlock.carets.add(caret);
currentBlock.startLine = startLine;
currentBlock.endLine = endLine;
boolean wholeLinesSelected = !hasSelection ||
startOffset == document.getLineStartOffset(document.getLineNumber(startOffset)) &&
@@ -15,7 +15,9 @@
*/
package com.intellij.openapi.editor.actionSystem;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretAction;
import com.intellij.openapi.editor.Editor;
@@ -25,11 +27,11 @@ import org.jetbrains.annotations.Nullable;
/**
* Interface for actions activated by keystrokes in the editor.
* Implementations should override
* {@link #execute(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
* {@link #execute(Editor, Caret, DataContext)}
* .
* <p>
* Two types of handlers are supported: the ones which are executed once, and the ones which are executed for each caret. The latter can be
* created using {@link com.intellij.openapi.editor.actionSystem.EditorActionHandler#EditorActionHandler(boolean)} constructor.
* created using {@link EditorActionHandler#EditorActionHandler(boolean)} constructor.
*
* @see EditorActionManager#setActionHandler(String, EditorActionHandler)
*/
@@ -49,10 +51,10 @@ public abstract class EditorActionHandler {
/**
* @deprecated Implementations should override
* {@link #isEnabledForCaret(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
* {@link #isEnabledForCaret(Editor, Caret, DataContext)}
* instead,
* client code should invoke
* {@link #isEnabled(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
* {@link #isEnabled(Editor, Caret, DataContext)}
* instead.
*/
public boolean isEnabled(Editor editor, final DataContext dataContext) {
@@ -135,9 +137,9 @@ public abstract class EditorActionHandler {
}
/**
* @deprecated To implement action logic, override
* {@link #doExecute(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)},
* {@link #doExecute(Editor, Caret, DataContext)},
* to invoke the handler, call
* {@link #execute(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}.
* {@link #execute(Editor, Caret, DataContext)}.
*/
public void execute(Editor editor, DataContext dataContext) {
if (inExecution) {
@@ -205,7 +207,7 @@ public abstract class EditorActionHandler {
}
});
}
}, true);
});
}
else {
if (contextCaret == null) {
@@ -1,3 +1,2 @@
s<caret> text<caret>o<caret>r text
an<caret>er l<caret>
yet a<caret>her line
s<caret>text<caret>o<caret>r text
an<caret>er l<caret>yet a<caret>her line
@@ -1,2 +1,2 @@
Ab<caret>CaDabra<caret>Hum<caret>ump Hu<caret>mp
Ab<caret>Dabra<caret>Hum<caret>ump Hu<caret>mp
<caret>
@@ -1,3 +1,3 @@
<caret>t
<caret>some <caret>t
o<caret>er t<caret>t
<caret> line<caret>yet another line
@@ -1,6 +1,6 @@
some
<caret>te
<caret>xt
<caret>xt
other
<caret>
@@ -1,2 +1,2 @@
so <caret>me t <caret>t
so <caret>me t <caret>t
<caret> <caret> text
@@ -31,10 +31,11 @@ public class XmlEqTypedHandler extends TypedHandlerDelegate {
@Override
public Result beforeCharTyped(char c, Project project, Editor editor, PsiFile file, FileType fileType) {
if (WebEditorOptions.getInstance().isInsertQuotesForAttributeValue()) {
boolean inXml = file.getLanguage() instanceof XMLLanguage || file.getViewProvider().getBaseLanguage() instanceof XMLLanguage;
if (c == '=' && inXml) {
TypedHandler.commitDocumentIfCurrentCaretIsNotTheFirstOne(editor, project);
PsiElement at = file.findElementAt(editor.getCaretModel().getOffset() - 1);
PsiElement atParent = at != null ? at.getParent() : null;
if(atParent instanceof XmlAttribute && ((XmlAttribute)atParent).getValueElement() == null) {
@@ -60,7 +60,7 @@ public class XmlTypedHandlersTest extends LightPlatformCodeInsightFixtureTestCas
"</bar>");
}
public void _testCloseTagOnSlashWithMultiCaretsInDifferentContexts() {
public void testCloseTagOnSlashWithMultiCaretsInDifferentContexts() {
doTest("<bar>\n" +
"<foo><<caret>\n" +
"<fiz><<caret>\n" +
@@ -70,7 +70,7 @@ public class XmlTypedHandlersTest extends LightPlatformCodeInsightFixtureTestCas
"</bar>");
}
public void _testCloseTagOnGtWithMultiCaretsInDifferentContexts() {
public void testCloseTagOnGtWithMultiCaretsInDifferentContexts() {
doTest("<bar>\n" +
"<foo<caret>\n" +
"<fiz<caret>\n" +