mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-03-04 21:32:52 +01:00
Support comments in brace matching
In Vim, '%' can be used to jump between the '/*' and '*/' of block comments. Support this functionality in a language-independent manner.
This commit is contained in:
parent
3650ab85df
commit
82a9587b4f
src/com/maddyhome/idea/vim/helper
test/org/jetbrains/plugins/ideavim
@ -109,7 +109,7 @@ public class PsiHelper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiFile getFile(@NotNull Editor editor) {
|
||||
public static PsiFile getFile(@NotNull Editor editor) {
|
||||
VirtualFile vf = EditorData.getVirtualFile(editor);
|
||||
if (vf != null) {
|
||||
Project proj = editor.getProject();
|
||||
|
@ -18,9 +18,14 @@
|
||||
|
||||
package com.maddyhome.idea.vim.helper;
|
||||
|
||||
import com.intellij.lang.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.maddyhome.idea.vim.common.TextRange;
|
||||
import com.maddyhome.idea.vim.option.ListOption;
|
||||
import com.maddyhome.idea.vim.option.OptionChangeEvent;
|
||||
@ -143,6 +148,54 @@ public class SearchHelper {
|
||||
return new TextRange(bstart, bend);
|
||||
}
|
||||
|
||||
private static int findMatchingBlockCommentPair(@NotNull PsiElement element,
|
||||
int pos,
|
||||
@Nullable String commentPrefix,
|
||||
@Nullable String commentSuffix) {
|
||||
if (commentPrefix == null || commentSuffix == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Don't act on partial comments
|
||||
if (!element.getText().startsWith(commentPrefix) || !element.getText().endsWith(commentSuffix)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final int endOffset = element.getTextOffset() + element.getTextLength();
|
||||
if (pos < element.getTextOffset() + commentPrefix.length()) {
|
||||
return endOffset;
|
||||
}
|
||||
else if (pos >= endOffset - commentSuffix.length()) {
|
||||
return element.getTextOffset();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int findMatchingBlockCommentPair(PsiElement element, int pos) {
|
||||
final Language language = PsiUtil.findLanguageFromElement(element);
|
||||
final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(language);
|
||||
|
||||
element = PsiTreeUtil.getParentOfType(element, PsiComment.class, false);
|
||||
if (element == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = findMatchingBlockCommentPair(element, pos, commenter.getBlockCommentPrefix(),
|
||||
commenter.getBlockCommentSuffix());
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(commenter instanceof CodeDocumentationAwareCommenter)) {
|
||||
return -1;
|
||||
}
|
||||
final CodeDocumentationAwareCommenter docCommenter = (CodeDocumentationAwareCommenter)commenter;
|
||||
|
||||
return findMatchingBlockCommentPair(element, pos, docCommenter.getDocumentationCommentPrefix(),
|
||||
docCommenter.getDocumentationCommentSuffix());
|
||||
}
|
||||
|
||||
/**
|
||||
* This looks on the current line, starting at the cursor position for one of {, }, (, ), [, or ]. It then searches
|
||||
* forward or backward, as appropriate for the associated match pair. String in double quotes are skipped over.
|
||||
@ -153,10 +206,23 @@ public class SearchHelper {
|
||||
* were found on the remainder of the current line.
|
||||
*/
|
||||
public static int findMatchingPairOnCurrentLine(@NotNull Editor editor) {
|
||||
int pos = editor.getCaretModel().getOffset();
|
||||
|
||||
// If on '/*' of a block comment, jump to '*/' of that comment, or vice versa
|
||||
PsiFile psiFile = PsiHelper.getFile(editor);
|
||||
if (psiFile != null) {
|
||||
PsiElement element = psiFile.findElementAt(pos);
|
||||
if (element != null) {
|
||||
int ret = findMatchingBlockCommentPair(element, pos);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int line = editor.getCaretModel().getLogicalPosition().line;
|
||||
int end = EditorHelper.getLineEndOffset(editor, line, true);
|
||||
CharSequence chars = editor.getDocument().getCharsSequence();
|
||||
int pos = editor.getCaretModel().getOffset();
|
||||
int loc = -1;
|
||||
// Search the remainder of the current line for one of the candidate characters
|
||||
while (pos < end) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.jetbrains.plugins.ideavim;
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.ide.highlighter.XmlFileType;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.editor.Caret;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@ -90,6 +91,12 @@ public abstract class VimTestCase extends UsefulTestCase {
|
||||
return myFixture.getEditor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Editor configureByXmlText(@NotNull String content) {
|
||||
myFixture.configureByText(XmlFileType.INSTANCE, content);
|
||||
return myFixture.getEditor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Editor typeText(@NotNull final List<KeyStroke> keys) {
|
||||
final Editor editor = myFixture.getEditor();
|
||||
|
@ -426,6 +426,76 @@ public class MotionActionTest extends VimTestCase {
|
||||
assertOffset(3);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentMatchXmlCommentStart() {
|
||||
configureByXmlText("<caret><!-- foo -->");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(11);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentDoesntMatchPartialXmlComment() {
|
||||
configureByXmlText("<!<caret>-- ");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(2);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentMatchXmlCommentEnd() {
|
||||
configureByXmlText("<!-- foo --<caret>>");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(0);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentMatchJavaCommentStart() {
|
||||
configureByJavaText("/<caret>* foo */");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(8);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentDoesntMatchPartialJavaComment() {
|
||||
configureByJavaText("<caret>/* ");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(0);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentMatchJavaCommentEnd() {
|
||||
configureByJavaText("/* foo <caret>*/");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(0);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentMatchJavaDocCommentStart() {
|
||||
configureByJavaText("/*<caret>* foo */");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(9);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentMatchJavaDocCommentEnd() {
|
||||
configureByJavaText("/** foo *<caret>/");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(0);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentDoesntMatchAfterCommentStart() {
|
||||
configureByJavaText("/*<caret> foo */");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(2);
|
||||
}
|
||||
|
||||
// |%|
|
||||
public void testPercentDoesntMatchBeforeCommentEnd() {
|
||||
configureByJavaText("/* foo <caret> */");
|
||||
typeText(parseKeys("%"));
|
||||
assertOffset(7);
|
||||
}
|
||||
|
||||
// |[(|
|
||||
public void testUnmatchedOpenParenthesis() {
|
||||
typeTextInFile(parseKeys("[("),
|
||||
|
Loading…
Reference in New Issue
Block a user