mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2024-11-25 07:42:59 +01:00
Compare commits
5 Commits
0612367c59
...
07659cc64d
Author | SHA1 | Date | |
---|---|---|---|
07659cc64d | |||
c089bd4bd3 | |||
b96708fdb8 | |||
e3bed58a29 | |||
b8cf11257c |
@ -11,7 +11,7 @@
|
|||||||
ideaVersion=2023.3.2
|
ideaVersion=2023.3.2
|
||||||
downloadIdeaSources=true
|
downloadIdeaSources=true
|
||||||
instrumentPluginCode=true
|
instrumentPluginCode=true
|
||||||
version=chylex-23
|
version=chylex-24
|
||||||
javaVersion=17
|
javaVersion=17
|
||||||
remoteRobotVersion=0.11.21
|
remoteRobotVersion=0.11.21
|
||||||
antlrVersion=4.10.1
|
antlrVersion=4.10.1
|
||||||
|
@ -78,7 +78,6 @@ import java.math.BigInteger
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides all the insert/replace related functionality
|
* Provides all the insert/replace related functionality
|
||||||
@ -395,6 +394,7 @@ public class ChangeGroup : VimChangeGroupBase() {
|
|||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
) {
|
) {
|
||||||
|
val startPos = editor.offsetToBufferPosition(caret.offset.point)
|
||||||
val startOffset = editor.getLineStartForOffset(range.startOffset)
|
val startOffset = editor.getLineStartForOffset(range.startOffset)
|
||||||
val endOffset = editor.getLineEndForOffset(range.endOffset)
|
val endOffset = editor.getLineEndForOffset(range.endOffset)
|
||||||
val ijEditor = (editor as IjVimEditor).editor
|
val ijEditor = (editor as IjVimEditor).editor
|
||||||
@ -419,11 +419,7 @@ public class ChangeGroup : VimChangeGroupBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val afterAction = {
|
val afterAction = {
|
||||||
val firstLine = editor.offsetToBufferPosition(
|
caret.moveToOffset(injector.motion.moveCaretToLineStartSkipLeading(editor, startPos.line))
|
||||||
min(startOffset.toDouble(), endOffset.toDouble()).toInt()
|
|
||||||
).line
|
|
||||||
val newOffset = injector.motion.moveCaretToLineStartSkipLeading(editor, firstLine)
|
|
||||||
caret.moveToOffset(newOffset)
|
|
||||||
restoreCursor(editor, caret, (caret as IjVimCaret).caret.logicalPosition.line)
|
restoreCursor(editor, caret, (caret as IjVimCaret).caret.logicalPosition.line)
|
||||||
}
|
}
|
||||||
if (project != null) {
|
if (project != null) {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
package com.maddyhome.idea.vim.helper;
|
package com.maddyhome.idea.vim.helper;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx;
|
||||||
import com.intellij.lang.CodeDocumentationAwareCommenter;
|
import com.intellij.lang.CodeDocumentationAwareCommenter;
|
||||||
import com.intellij.lang.Commenter;
|
import com.intellij.lang.Commenter;
|
||||||
import com.intellij.lang.Language;
|
import com.intellij.lang.Language;
|
||||||
@ -16,15 +17,15 @@ import com.intellij.lang.LanguageCommenters;
|
|||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.openapi.editor.Caret;
|
import com.intellij.openapi.editor.Caret;
|
||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.psi.PsiComment;
|
import com.intellij.psi.PsiComment;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import com.intellij.spellchecker.SpellCheckerSeveritiesProvider;
|
||||||
import com.maddyhome.idea.vim.VimPlugin;
|
import com.maddyhome.idea.vim.VimPlugin;
|
||||||
import com.maddyhome.idea.vim.api.EngineEditorHelperKt;
|
import com.maddyhome.idea.vim.api.EngineEditorHelperKt;
|
||||||
import com.maddyhome.idea.vim.api.VimEditor;
|
import com.maddyhome.idea.vim.api.VimEditor;
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode;
|
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine;
|
|
||||||
import com.maddyhome.idea.vim.common.CharacterPosition;
|
import com.maddyhome.idea.vim.common.CharacterPosition;
|
||||||
import com.maddyhome.idea.vim.common.Direction;
|
import com.maddyhome.idea.vim.common.Direction;
|
||||||
import com.maddyhome.idea.vim.common.TextRange;
|
import com.maddyhome.idea.vim.common.TextRange;
|
||||||
@ -32,6 +33,12 @@ import com.maddyhome.idea.vim.newapi.IjVimCaret;
|
|||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
import com.maddyhome.idea.vim.newapi.IjVimEditor;
|
||||||
import com.maddyhome.idea.vim.regexp.CharPointer;
|
import com.maddyhome.idea.vim.regexp.CharPointer;
|
||||||
import com.maddyhome.idea.vim.regexp.RegExp;
|
import com.maddyhome.idea.vim.regexp.RegExp;
|
||||||
|
import com.maddyhome.idea.vim.state.VimStateMachine;
|
||||||
|
import com.maddyhome.idea.vim.state.mode.Mode;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntComparator;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntIterator;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSortedSet;
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -1523,6 +1530,42 @@ public class SearchHelper {
|
|||||||
return PsiHelper.findMethodEnd(editor, caret.getOffset(), count);
|
return PsiHelper.findMethodEnd(editor, caret.getOffset(), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int findMisspelledWords(@NotNull Editor editor,
|
||||||
|
int startOffset,
|
||||||
|
int endOffset,
|
||||||
|
int skipCount,
|
||||||
|
IntComparator offsetOrdering) {
|
||||||
|
Project project = editor.getProject();
|
||||||
|
if (project == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntSortedSet offsets = new IntRBTreeSet(offsetOrdering);
|
||||||
|
DaemonCodeAnalyzerEx.processHighlights(editor.getDocument(), project, SpellCheckerSeveritiesProvider.TYPO,
|
||||||
|
startOffset, endOffset, highlight -> {
|
||||||
|
if (highlight.getSeverity() == SpellCheckerSeveritiesProvider.TYPO) {
|
||||||
|
int offset = highlight.getStartOffset();
|
||||||
|
if (offset >= startOffset && offset <= endOffset) {
|
||||||
|
offsets.add(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (offsets.isEmpty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipCount >= offsets.size()) {
|
||||||
|
return offsets.lastInt();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
IntIterator offsetIterator = offsets.iterator();
|
||||||
|
offsetIterator.skip(skipCount);
|
||||||
|
return offsetIterator.nextInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static @NotNull String parseMatchPairsOption(final VimEditor vimEditor) {
|
private static @NotNull String parseMatchPairsOption(final VimEditor vimEditor) {
|
||||||
List<String> pairs = options(injector, vimEditor).getMatchpairs();
|
List<String> pairs = options(injector, vimEditor).getMatchpairs();
|
||||||
StringBuilder res = new StringBuilder();
|
StringBuilder res = new StringBuilder();
|
||||||
|
@ -95,41 +95,43 @@ internal object IdeaSpecifics {
|
|||||||
if (VimPlugin.isNotEnabled()) return
|
if (VimPlugin.isNotEnabled()) return
|
||||||
|
|
||||||
val editor = editor
|
val editor = editor
|
||||||
if (editor != null && action is ChooseItemAction && editor.vimStateMachine?.isRecording == true) {
|
if (editor != null) {
|
||||||
val prevDocumentLength = completionPrevDocumentLength
|
if (action is ChooseItemAction && editor.vimStateMachine?.isRecording == true) {
|
||||||
val prevDocumentOffset = completionPrevDocumentOffset
|
val prevDocumentLength = completionPrevDocumentLength
|
||||||
|
val prevDocumentOffset = completionPrevDocumentOffset
|
||||||
|
|
||||||
if (prevDocumentLength != null && prevDocumentOffset != null) {
|
if (prevDocumentLength != null && prevDocumentOffset != null) {
|
||||||
val register = VimPlugin.getRegister()
|
val register = VimPlugin.getRegister()
|
||||||
val addedTextLength = editor.document.textLength - prevDocumentLength
|
val addedTextLength = editor.document.textLength - prevDocumentLength
|
||||||
val caretShift = addedTextLength - (editor.caretModel.primaryCaret.offset - prevDocumentOffset)
|
val caretShift = addedTextLength - (editor.caretModel.primaryCaret.offset - prevDocumentOffset)
|
||||||
val leftArrow = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)
|
val leftArrow = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)
|
||||||
|
|
||||||
register.recordText(editor.document.getText(TextRange(prevDocumentOffset, prevDocumentOffset + addedTextLength)))
|
register.recordText(editor.document.getText(TextRange(prevDocumentOffset, prevDocumentOffset + addedTextLength)))
|
||||||
repeat(caretShift.coerceAtLeast(0)) {
|
repeat(caretShift.coerceAtLeast(0)) {
|
||||||
register.recordKeyStroke(leftArrow)
|
register.recordKeyStroke(leftArrow)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.completionPrevDocumentLength = null
|
||||||
|
this.completionPrevDocumentOffset = null
|
||||||
}
|
}
|
||||||
|
|
||||||
this.completionPrevDocumentLength = null
|
//region Enter insert mode after surround with if
|
||||||
this.completionPrevDocumentOffset = null
|
if (surrounderAction == action.javaClass.name && surrounderItems.any {
|
||||||
}
|
action.templatePresentation.text.endsWith(
|
||||||
|
it,
|
||||||
//region Enter insert mode after surround with if
|
)
|
||||||
if (surrounderAction == action.javaClass.name && surrounderItems.any {
|
}
|
||||||
action.templatePresentation.text.endsWith(
|
) {
|
||||||
it,
|
val commandState = editor.vim.vimStateMachine
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
editor?.let {
|
|
||||||
val commandState = it.vim.vimStateMachine
|
|
||||||
commandState.mode = Mode.NORMAL()
|
commandState.mode = Mode.NORMAL()
|
||||||
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
|
VimPlugin.getChange().insertBeforeCursor(editor.vim, event.dataContext.vim)
|
||||||
KeyHandler.getInstance().reset(it.vim)
|
KeyHandler.getInstance().reset(editor.vim)
|
||||||
}
|
}
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
injector.scroll.scrollCaretIntoView(editor.vim)
|
||||||
}
|
}
|
||||||
//endregion
|
|
||||||
|
|
||||||
this.editor = null
|
this.editor = null
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ import com.maddyhome.idea.vim.api.VimSearchHelperBase
|
|||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.helper.SearchHelper
|
import com.maddyhome.idea.vim.helper.SearchHelper
|
||||||
import com.maddyhome.idea.vim.helper.SearchOptions
|
import com.maddyhome.idea.vim.helper.SearchOptions
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntComparator
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntComparators
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -93,4 +95,26 @@ internal class IjVimSearchHelper : VimSearchHelperBase() {
|
|||||||
): TextRange? {
|
): TextRange? {
|
||||||
return SearchHelper.findBlockRange(editor.ij, caret.ij, type, count, isOuter)
|
return SearchHelper.findBlockRange(editor.ij, caret.ij, type, count, isOuter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findMisspelledWord(editor: VimEditor, caret: ImmutableVimCaret, count: Int): Int {
|
||||||
|
val startOffset: Int
|
||||||
|
val endOffset: Int
|
||||||
|
val skipCount: Int
|
||||||
|
val offsetOrdering: IntComparator
|
||||||
|
|
||||||
|
if (count < 0) {
|
||||||
|
startOffset = 0
|
||||||
|
endOffset = caret.offset.point - 1
|
||||||
|
skipCount = -count - 1
|
||||||
|
offsetOrdering = IntComparators.OPPOSITE_COMPARATOR
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
startOffset = caret.offset.point + 1
|
||||||
|
endOffset = editor.ij.document.textLength
|
||||||
|
skipCount = count - 1
|
||||||
|
offsetOrdering = IntComparators.NATURAL_COMPARATOR
|
||||||
|
}
|
||||||
|
|
||||||
|
return SearchHelper.findMisspelledWords(editor.ij, startOffset, endOffset, skipCount, offsetOrdering)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@
|
|||||||
* |[m| {@link com.maddyhome.idea.vim.action.motion.text.MotionMethodPreviousStartAction}
|
* |[m| {@link com.maddyhome.idea.vim.action.motion.text.MotionMethodPreviousStartAction}
|
||||||
* |[p| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextAfterCursorNoIndentAction}
|
* |[p| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextAfterCursorNoIndentAction}
|
||||||
* |[p| {@link com.maddyhome.idea.vim.action.copy.PutTextAfterCursorNoIndentAction}
|
* |[p| {@link com.maddyhome.idea.vim.action.copy.PutTextAfterCursorNoIndentAction}
|
||||||
* |[s| TO BE IMPLEMENTED
|
* |[s| {@link com.maddyhome.idea.vim.action.motion.text.MotionMisspelledWordPreviousAction}
|
||||||
* |[z| TO BE IMPLEMENTED
|
* |[z| TO BE IMPLEMENTED
|
||||||
* |[{| {@link com.maddyhome.idea.vim.action.motion.text.MotionUnmatchedBraceOpenAction}
|
* |[{| {@link com.maddyhome.idea.vim.action.motion.text.MotionUnmatchedBraceOpenAction}
|
||||||
* |]_CTRL-D| TO BE IMPLEMENTED
|
* |]_CTRL-D| TO BE IMPLEMENTED
|
||||||
@ -358,7 +358,7 @@
|
|||||||
* |]m| {@link com.maddyhome.idea.vim.action.motion.text.MotionMethodNextStartAction}
|
* |]m| {@link com.maddyhome.idea.vim.action.motion.text.MotionMethodNextStartAction}
|
||||||
* |]p| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextAfterCursorNoIndentAction}
|
* |]p| {@link com.maddyhome.idea.vim.action.copy.PutVisualTextAfterCursorNoIndentAction}
|
||||||
* |]p| {@link com.maddyhome.idea.vim.action.copy.PutTextAfterCursorNoIndentAction}
|
* |]p| {@link com.maddyhome.idea.vim.action.copy.PutTextAfterCursorNoIndentAction}
|
||||||
* |]s| TO BE IMPLEMENTED
|
* |]s| {@link com.maddyhome.idea.vim.action.motion.text.MotionMisspelledWordNextAction}
|
||||||
* |]z| TO BE IMPLEMENTED
|
* |]z| TO BE IMPLEMENTED
|
||||||
* |]}| {@link com.maddyhome.idea.vim.action.motion.text.MotionUnmatchedBraceCloseAction}
|
* |]}| {@link com.maddyhome.idea.vim.action.motion.text.MotionUnmatchedBraceCloseAction}
|
||||||
*
|
*
|
||||||
|
@ -94,6 +94,8 @@
|
|||||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.text.MotionMethodPreviousStartAction" mappingModes="NXO" keys="[m"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.motion.text.MotionMethodPreviousStartAction" mappingModes="NXO" keys="[m"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.text.MotionMethodNextEndAction" mappingModes="NXO" keys="]M"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.motion.text.MotionMethodNextEndAction" mappingModes="NXO" keys="]M"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.text.MotionMethodNextStartAction" mappingModes="NXO" keys="]m"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.motion.text.MotionMethodNextStartAction" mappingModes="NXO" keys="]m"/>
|
||||||
|
<vimAction implementation="com.maddyhome.idea.vim.action.motion.text.MotionMisspelledWordPreviousAction" mappingModes="NXO" keys="[s"/>
|
||||||
|
<vimAction implementation="com.maddyhome.idea.vim.action.motion.text.MotionMisspelledWordNextAction" mappingModes="NXO" keys="]s"/>
|
||||||
<!-- Text Objects -->
|
<!-- Text Objects -->
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.object.MotionOuterWordAction" mappingModes="XO" keys="aw"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.motion.object.MotionOuterWordAction" mappingModes="XO" keys="aw"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.object.MotionOuterBigWordAction" mappingModes="XO" keys="aW"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.motion.object.MotionOuterBigWordAction" mappingModes="XO" keys="aW"/>
|
||||||
|
@ -448,6 +448,11 @@ abstract class VimTestCase {
|
|||||||
return NeovimTesting.getMark(char)
|
return NeovimTesting.getMark(char)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun assertRegister(char: Char, expected: String?) {
|
||||||
|
val actual = injector.registerGroup.getRegister(char)?.keys?.let(injector.parser::toKeyNotation)
|
||||||
|
assertEquals(expected, actual, "Wrong register contents")
|
||||||
|
}
|
||||||
|
|
||||||
protected fun assertState(modeAfter: Mode) {
|
protected fun assertState(modeAfter: Mode) {
|
||||||
assertMode(modeAfter)
|
assertMode(modeAfter)
|
||||||
assertCaretsVisualAttributes()
|
assertCaretsVisualAttributes()
|
||||||
|
@ -47,10 +47,7 @@ class MacroActionTest : VimTestCase() {
|
|||||||
val editor = typeTextInFile(injector.parser.parseKeys("qa" + "3l" + "q"), "on<caret>e two three\n")
|
val editor = typeTextInFile(injector.parser.parseKeys("qa" + "3l" + "q"), "on<caret>e two three\n")
|
||||||
val commandState = editor.vim.vimStateMachine
|
val commandState = editor.vim.vimStateMachine
|
||||||
kotlin.test.assertFalse(commandState.isRecording)
|
kotlin.test.assertFalse(commandState.isRecording)
|
||||||
val registerGroup = VimPlugin.getRegister()
|
assertRegister('a', "3l")
|
||||||
val register = registerGroup.getRegister('a')
|
|
||||||
assertNotNull<Any>(register)
|
|
||||||
kotlin.test.assertEquals("3l", register.text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -58,9 +55,7 @@ class MacroActionTest : VimTestCase() {
|
|||||||
configureByText("")
|
configureByText("")
|
||||||
enterCommand("imap pp hello")
|
enterCommand("imap pp hello")
|
||||||
typeText(injector.parser.parseKeys("qa" + "i" + "pp<Esc>" + "q"))
|
typeText(injector.parser.parseKeys("qa" + "i" + "pp<Esc>" + "q"))
|
||||||
val register = VimPlugin.getRegister().getRegister('a')
|
assertRegister('a', "ipp<Esc>")
|
||||||
assertNotNull<Any>(register)
|
|
||||||
kotlin.test.assertEquals("ipp<Esc>", injector.parser.toKeyNotation(register.keys))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -68,7 +63,7 @@ class MacroActionTest : VimTestCase() {
|
|||||||
typeTextInFile(injector.parser.parseKeys("qa" + "i" + "<C-K>OK<Esc>" + "q"), "")
|
typeTextInFile(injector.parser.parseKeys("qa" + "i" + "<C-K>OK<Esc>" + "q"), "")
|
||||||
val register = VimPlugin.getRegister().getRegister('a')
|
val register = VimPlugin.getRegister().getRegister('a')
|
||||||
assertNotNull<Any>(register)
|
assertNotNull<Any>(register)
|
||||||
kotlin.test.assertEquals("i<C-K>OK<Esc>", injector.parser.toKeyNotation(register.keys))
|
assertRegister('a', "i<C-K>OK<Esc>")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -141,8 +136,8 @@ class MacroActionTest : VimTestCase() {
|
|||||||
assertState("4\n5\n")
|
assertState("4\n5\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broken, see the resulting text
|
@Test
|
||||||
fun `ignore test macro with macro`() {
|
fun `test macro with macro`() {
|
||||||
val content = """
|
val content = """
|
||||||
Lorem Ipsum
|
Lorem Ipsum
|
||||||
|
|
||||||
@ -152,16 +147,55 @@ class MacroActionTest : VimTestCase() {
|
|||||||
Cras id tellus in ex imperdiet egestas.
|
Cras id tellus in ex imperdiet egestas.
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
configureByText(content)
|
configureByText(content)
|
||||||
typeText(injector.parser.parseKeys("qa" + "l" + "q" + "qb" + "10@a" + "q" + "2@b"))
|
typeText(
|
||||||
|
injector.parser.parseKeys(
|
||||||
|
"qa" + "l" + "q" +
|
||||||
|
"qb" + "6@a" + "q" +
|
||||||
|
"^" + "3@b"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val startOffset = content.rangeOf("rocks").startOffset
|
assertRegister('b', "6@a")
|
||||||
|
assertState("""
|
||||||
|
Lorem Ipsum
|
||||||
|
|
||||||
waitAndAssert {
|
Lorem ipsum dolor ${c}sit amet,
|
||||||
println(fixture.editor.caretModel.offset)
|
consectetur adipiscing elit
|
||||||
println(startOffset)
|
Sed in orci mauris.
|
||||||
println()
|
Cras id tellus in ex imperdiet egestas.
|
||||||
startOffset == fixture.editor.caretModel.offset
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test macro with macro with macro`() {
|
||||||
|
val content = """
|
||||||
|
Lorem Ipsum
|
||||||
|
|
||||||
|
${c}Lorem ipsum dolor sit amet,
|
||||||
|
consectetur adipiscing elit
|
||||||
|
Sed in orci mauris.
|
||||||
|
Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimIndent()
|
||||||
|
configureByText(content)
|
||||||
|
typeText(
|
||||||
|
injector.parser.parseKeys(
|
||||||
|
"qa" + "l" + "q" +
|
||||||
|
"qb" + "3@a" + "q" +
|
||||||
|
"qc" + "2@b" + "q" +
|
||||||
|
"^" + "3@c"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertRegister('b', "3@a")
|
||||||
|
assertRegister('c', "2@b")
|
||||||
|
assertState("""
|
||||||
|
Lorem Ipsum
|
||||||
|
|
||||||
|
Lorem ipsum dolor ${c}sit amet,
|
||||||
|
consectetur adipiscing elit
|
||||||
|
Sed in orci mauris.
|
||||||
|
Cras id tellus in ex imperdiet egestas.
|
||||||
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -102,8 +102,9 @@ public class KeyHandler {
|
|||||||
// If this is a "regular" character keystroke, get the character
|
// If this is a "regular" character keystroke, get the character
|
||||||
val chKey: Char = if (key.keyChar == KeyEvent.CHAR_UNDEFINED) 0.toChar() else key.keyChar
|
val chKey: Char = if (key.keyChar == KeyEvent.CHAR_UNDEFINED) 0.toChar() else key.keyChar
|
||||||
|
|
||||||
// We only record unmapped keystrokes. If we've recursed to handle mapping, don't record anything.
|
// We only record unmapped keystrokes.
|
||||||
var shouldRecord = handleKeyRecursionCount == 0 && editorState.isRecording
|
// If we've recursed to handle mapping, or executing a macro, don't record anything.
|
||||||
|
var shouldRecord = handleKeyRecursionCount == 0 && editorState.isRecording && !injector.macro.isExecutingMacro
|
||||||
handleKeyRecursionCount++
|
handleKeyRecursionCount++
|
||||||
try {
|
try {
|
||||||
LOG.trace("Start key processing...")
|
LOG.trace("Start key processing...")
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2023 The IdeaVim authors
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style
|
||||||
|
* license that can be found in the LICENSE.txt file or at
|
||||||
|
* https://opensource.org/licenses/MIT.
|
||||||
|
*/
|
||||||
|
package com.maddyhome.idea.vim.action.motion.text
|
||||||
|
|
||||||
|
import com.intellij.vim.annotations.CommandOrMotion
|
||||||
|
import com.intellij.vim.annotations.Mode
|
||||||
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
|
import com.maddyhome.idea.vim.api.ImmutableVimCaret
|
||||||
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
|
import com.maddyhome.idea.vim.api.injector
|
||||||
|
import com.maddyhome.idea.vim.command.Argument
|
||||||
|
import com.maddyhome.idea.vim.command.CommandFlags
|
||||||
|
import com.maddyhome.idea.vim.command.MotionType
|
||||||
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
|
import com.maddyhome.idea.vim.handler.Motion
|
||||||
|
import com.maddyhome.idea.vim.handler.MotionActionHandler
|
||||||
|
import com.maddyhome.idea.vim.handler.toMotionOrError
|
||||||
|
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@CommandOrMotion(keys = ["]s"], modes = [Mode.NORMAL, Mode.VISUAL, Mode.OP_PENDING])
|
||||||
|
public class MotionMisspelledWordNextAction : MotionActionHandler.ForEachCaret() {
|
||||||
|
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_SAVE_JUMP)
|
||||||
|
|
||||||
|
override fun getOffset(
|
||||||
|
editor: VimEditor,
|
||||||
|
caret: ImmutableVimCaret,
|
||||||
|
context: ExecutionContext,
|
||||||
|
argument: Argument?,
|
||||||
|
operatorArguments: OperatorArguments,
|
||||||
|
): Motion {
|
||||||
|
return injector.searchHelper.findMisspelledWord(editor, caret, operatorArguments.count1).toMotionOrError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val motionType: MotionType = MotionType.EXCLUSIVE
|
||||||
|
}
|
||||||
|
|
||||||
|
@CommandOrMotion(keys = ["[s"], modes = [Mode.NORMAL, Mode.VISUAL, Mode.OP_PENDING])
|
||||||
|
public class MotionMisspelledWordPreviousAction : MotionActionHandler.ForEachCaret() {
|
||||||
|
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_SAVE_JUMP)
|
||||||
|
|
||||||
|
override fun getOffset(
|
||||||
|
editor: VimEditor,
|
||||||
|
caret: ImmutableVimCaret,
|
||||||
|
context: ExecutionContext,
|
||||||
|
argument: Argument?,
|
||||||
|
operatorArguments: OperatorArguments,
|
||||||
|
): Motion {
|
||||||
|
return injector.searchHelper.findMisspelledWord(editor, caret, -operatorArguments.count1).toMotionOrError()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val motionType: MotionType = MotionType.EXCLUSIVE
|
||||||
|
}
|
@ -197,4 +197,10 @@ public interface VimSearchHelper {
|
|||||||
count: Int,
|
count: Int,
|
||||||
isOuter: Boolean,
|
isOuter: Boolean,
|
||||||
): TextRange?
|
): TextRange?
|
||||||
|
|
||||||
|
public fun findMisspelledWord(
|
||||||
|
editor: VimEditor,
|
||||||
|
caret: ImmutableVimCaret,
|
||||||
|
count: Int,
|
||||||
|
): Int
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user