mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-09-14 14:32:10 +02:00
Compare commits
1 Commits
customized
...
125ae58277
Author | SHA1 | Date | |
---|---|---|---|
125ae58277
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +0,0 @@
|
|||||||
* text=auto eol=lf
|
|
1
.idea/codeStyles/Project.xml
generated
1
.idea/codeStyles/Project.xml
generated
@@ -6,7 +6,6 @@
|
|||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
<option name="LINE_SEPARATOR" value=" " />
|
|
||||||
<JavaCodeStyleSettings>
|
<JavaCodeStyleSettings>
|
||||||
<option name="FIELD_NAME_PREFIX" value="my" />
|
<option name="FIELD_NAME_PREFIX" value="my" />
|
||||||
<option name="STATIC_FIELD_NAME_PREFIX" value="our" />
|
<option name="STATIC_FIELD_NAME_PREFIX" value="our" />
|
||||||
|
@@ -353,6 +353,8 @@ tasks {
|
|||||||
val pluginVersion = version
|
val pluginVersion = version
|
||||||
// Don't forget to update plugin.xml
|
// Don't forget to update plugin.xml
|
||||||
patchPluginXml {
|
patchPluginXml {
|
||||||
|
sinceBuild.set("233.11799.30")
|
||||||
|
|
||||||
// Get the latest available change notes from the changelog file
|
// Get the latest available change notes from the changelog file
|
||||||
changeNotes.set(
|
changeNotes.set(
|
||||||
provider {
|
provider {
|
||||||
|
@@ -11,12 +11,11 @@
|
|||||||
ideaVersion=2023.3.2
|
ideaVersion=2023.3.2
|
||||||
downloadIdeaSources=true
|
downloadIdeaSources=true
|
||||||
instrumentPluginCode=true
|
instrumentPluginCode=true
|
||||||
version=chylex-25
|
version=SNAPSHOT
|
||||||
javaVersion=17
|
javaVersion=17
|
||||||
remoteRobotVersion=0.11.21
|
remoteRobotVersion=0.11.21
|
||||||
antlrVersion=4.10.1
|
antlrVersion=4.10.1
|
||||||
|
|
||||||
kotlin.incremental.useClasspathSnapshot=false
|
|
||||||
|
|
||||||
# Please don't forget to update kotlin version in buildscript section
|
# Please don't forget to update kotlin version in buildscript section
|
||||||
# Also update kotlinxSerializationVersion version
|
# Also update kotlinxSerializationVersion version
|
||||||
|
@@ -217,8 +217,6 @@ private object FileTypePatterns {
|
|||||||
|
|
||||||
return if (fileTypeName in htmlLikeFileTypes) {
|
return if (fileTypeName in htmlLikeFileTypes) {
|
||||||
this.htmlPatterns
|
this.htmlPatterns
|
||||||
} else if (fileTypeName == "JAVA" || fileExtension == "java") {
|
|
||||||
this.javaPatterns
|
|
||||||
} else if (fileTypeName == "Ruby" || fileExtension == "rb") {
|
} else if (fileTypeName == "Ruby" || fileExtension == "rb") {
|
||||||
this.rubyPatterns
|
this.rubyPatterns
|
||||||
} else if (fileTypeName == "RHTML" || fileExtension == "erb") {
|
} else if (fileTypeName == "RHTML" || fileExtension == "erb") {
|
||||||
@@ -233,7 +231,7 @@ private object FileTypePatterns {
|
|||||||
} else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") {
|
} else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") {
|
||||||
this.cMakePatterns
|
this.cMakePatterns
|
||||||
} else {
|
} else {
|
||||||
this.htmlPatterns
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +242,6 @@ private object FileTypePatterns {
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val htmlPatterns = createHtmlPatterns()
|
private val htmlPatterns = createHtmlPatterns()
|
||||||
private val javaPatterns = createJavaPatterns()
|
|
||||||
private val rubyPatterns = createRubyPatterns()
|
private val rubyPatterns = createRubyPatterns()
|
||||||
private val rubyAndHtmlPatterns = rubyPatterns + htmlPatterns
|
private val rubyAndHtmlPatterns = rubyPatterns + htmlPatterns
|
||||||
private val phpPatterns = createPhpPatterns()
|
private val phpPatterns = createPhpPatterns()
|
||||||
@@ -274,14 +271,6 @@ private object FileTypePatterns {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createJavaPatterns(): LanguagePatterns {
|
|
||||||
return (
|
|
||||||
LanguagePatterns("\\b(?<!else\\s+)if\\b", "\\belse\\s+if\\b", "\\belse(?!\\s+if)\\b") +
|
|
||||||
LanguagePatterns("\\bdo\\b", "\\bwhile\\b") +
|
|
||||||
LanguagePatterns("\\btry\\b", "\\bcatch\\b", "\\bfinally\\b")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createRubyPatterns(): LanguagePatterns {
|
private fun createRubyPatterns(): LanguagePatterns {
|
||||||
// Original patterns: https://github.com/vim/vim/blob/master/runtime/ftplugin/ruby.vim
|
// Original patterns: https://github.com/vim/vim/blob/master/runtime/ftplugin/ruby.vim
|
||||||
// We use non-capturing groups (?:) since we don't need any back refs. The \\b marker takes care of word boundaries.
|
// We use non-capturing groups (?:) since we don't need any back refs. The \\b marker takes care of word boundaries.
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
package com.maddyhome.idea.vim.extension.surround
|
|
||||||
|
|
||||||
import com.intellij.util.text.CharSequenceSubSequence
|
|
||||||
|
|
||||||
internal data class RepeatedCharSequence(val text: CharSequence, val count: Int) : CharSequence {
|
|
||||||
override val length = text.length * count
|
|
||||||
|
|
||||||
override fun get(index: Int): Char {
|
|
||||||
if (index < 0 || index >= length) throw IndexOutOfBoundsException()
|
|
||||||
return text[index % text.length]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
|
|
||||||
return CharSequenceSubSequence(this, startIndex, endIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return text.repeat(count)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun of(text: CharSequence, count: Int): CharSequence {
|
|
||||||
return when (count) {
|
|
||||||
0 -> ""
|
|
||||||
1 -> text
|
|
||||||
else -> RepeatedCharSequence(text, count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -13,7 +13,6 @@ import com.intellij.openapi.editor.Editor
|
|||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimChangeGroup
|
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.endsWithNewLine
|
import com.maddyhome.idea.vim.api.endsWithNewLine
|
||||||
import com.maddyhome.idea.vim.api.getLeadingCharacterOffset
|
import com.maddyhome.idea.vim.api.getLeadingCharacterOffset
|
||||||
@@ -32,10 +31,7 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMa
|
|||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction
|
||||||
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
|
import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret
|
||||||
import com.maddyhome.idea.vim.helper.runWithEveryCaretAndRestore
|
|
||||||
import com.maddyhome.idea.vim.key.OperatorFunction
|
import com.maddyhome.idea.vim.key.OperatorFunction
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimCaret
|
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper
|
import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper
|
||||||
@@ -84,7 +80,7 @@ internal class VimSurroundExtension : VimExtension {
|
|||||||
override val isRepeatable = true
|
override val isRepeatable = true
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||||
setOperatorFunction(Operator(supportsMultipleCursors = false, count = 1)) // TODO
|
setOperatorFunction(Operator())
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +101,7 @@ internal class VimSurroundExtension : VimExtension {
|
|||||||
val lastNonWhiteSpaceOffset = getLastNonWhitespaceCharacterOffset(editor.text(), lineStartOffset, lineEndOffset)
|
val lastNonWhiteSpaceOffset = getLastNonWhitespaceCharacterOffset(editor.text(), lineStartOffset, lineEndOffset)
|
||||||
if (lastNonWhiteSpaceOffset != null) {
|
if (lastNonWhiteSpaceOffset != null) {
|
||||||
val range = TextRange(lineStartOffset, lastNonWhiteSpaceOffset + 1)
|
val range = TextRange(lineStartOffset, lastNonWhiteSpaceOffset + 1)
|
||||||
performSurround(pair, range, it, count = operatorArguments.count1)
|
performSurround(pair, range, it)
|
||||||
}
|
}
|
||||||
// it.moveToOffset(lineStartOffset)
|
// it.moveToOffset(lineStartOffset)
|
||||||
}
|
}
|
||||||
@@ -125,13 +121,15 @@ internal class VimSurroundExtension : VimExtension {
|
|||||||
|
|
||||||
private class VSurroundHandler : ExtensionHandler {
|
private class VSurroundHandler : ExtensionHandler {
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
override fun execute(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments) {
|
||||||
|
val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart
|
||||||
// NB: Operator ignores SelectionType anyway
|
// NB: Operator ignores SelectionType anyway
|
||||||
if (!Operator(supportsMultipleCursors = true, count = operatorArguments.count1).apply(editor, context, editor.mode.selectionType)) {
|
if (!Operator().apply(editor, context, editor.mode.selectionType)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
// Leave visual mode
|
// Leave visual mode
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij)
|
executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij)
|
||||||
|
editor.ij.caretModel.moveToOffset(selectionStart)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,10 +150,6 @@ internal class VimSurroundExtension : VimExtension {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
||||||
editor.ij.runWithEveryCaretAndRestore { changeAtCaret(editor, context, charFrom, newSurround) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun changeAtCaret(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) {
|
|
||||||
// Save old register values for carets
|
// Save old register values for carets
|
||||||
val surroundings = editor.sortedCarets()
|
val surroundings = editor.sortedCarets()
|
||||||
.map {
|
.map {
|
||||||
@@ -263,40 +257,19 @@ internal class VimSurroundExtension : VimExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Operator(private val supportsMultipleCursors: Boolean, private val count: Int) : OperatorFunction {
|
private class Operator : OperatorFunction {
|
||||||
override fun apply(vimEditor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
|
override fun apply(editor: VimEditor, context: ExecutionContext, selectionType: SelectionType?): Boolean {
|
||||||
val editor = vimEditor.ij
|
val ijEditor = editor.ij
|
||||||
val c = getChar(editor)
|
val c = getChar(ijEditor)
|
||||||
if (c.code == 0) return true
|
if (c.code == 0) return true
|
||||||
|
|
||||||
val pair = getOrInputPair(c, editor) ?: return false
|
val pair = getOrInputPair(c, ijEditor) ?: return false
|
||||||
|
|
||||||
runWriteAction {
|
|
||||||
val change = VimPlugin.getChange()
|
|
||||||
if (supportsMultipleCursors) {
|
|
||||||
editor.runWithEveryCaretAndRestore {
|
|
||||||
applyOnce(editor, change, pair, count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
applyOnce(editor, change, pair, count)
|
|
||||||
// Jump back to start
|
|
||||||
executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: Pair<String, String>, count: Int) {
|
|
||||||
// XXX: Will it work with line-wise or block-wise selections?
|
// XXX: Will it work with line-wise or block-wise selections?
|
||||||
val primaryCaret = editor.caretModel.primaryCaret
|
val range = getSurroundRange(editor.currentCaret()) ?: return false
|
||||||
val range = getSurroundRange(primaryCaret.vim)
|
performSurround(pair, range, editor.currentCaret(), selectionType == SelectionType.LINE_WISE)
|
||||||
if (range != null) {
|
// Jump back to start
|
||||||
val start = RepeatedCharSequence.of(pair.first, count)
|
executeNormalWithoutMapping(injector.parser.parseKeys("`["), ijEditor)
|
||||||
val end = RepeatedCharSequence.of(pair.second, count)
|
return true
|
||||||
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, start)
|
|
||||||
change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.endOffset + start.length, end)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSurroundRange(caret: VimCaret): TextRange? {
|
private fun getSurroundRange(caret: VimCaret): TextRange? {
|
||||||
@@ -381,15 +354,15 @@ private fun getChar(editor: Editor): Char {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, count: Int, tagsOnNewLines: Boolean = false) {
|
private fun performSurround(pair: Pair<String, String>, range: TextRange, caret: VimCaret, tagsOnNewLines: Boolean = false) {
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
val editor = caret.editor
|
val editor = caret.editor
|
||||||
val change = VimPlugin.getChange()
|
val change = VimPlugin.getChange()
|
||||||
val leftSurround = RepeatedCharSequence.of(pair.first + if (tagsOnNewLines) "\n" else "", count)
|
val leftSurround = pair.first + if (tagsOnNewLines) "\n" else ""
|
||||||
|
|
||||||
val isEOF = range.endOffset == editor.text().length
|
val isEOF = range.endOffset == editor.text().length
|
||||||
val hasNewLine = editor.endsWithNewLine()
|
val hasNewLine = editor.endsWithNewLine()
|
||||||
val rightSurround = (if (tagsOnNewLines) {
|
val rightSurround = if (tagsOnNewLines) {
|
||||||
if (isEOF && !hasNewLine) {
|
if (isEOF && !hasNewLine) {
|
||||||
"\n" + pair.second
|
"\n" + pair.second
|
||||||
} else {
|
} else {
|
||||||
@@ -397,7 +370,7 @@ private fun performSurround(pair: Pair<String, String>, range: TextRange, caret:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pair.second
|
pair.second
|
||||||
}).let { RepeatedCharSequence.of(it, count) }
|
}
|
||||||
|
|
||||||
change.insertText(editor, caret, range.startOffset, leftSurround)
|
change.insertText(editor, caret, range.startOffset, leftSurround)
|
||||||
change.insertText(editor, caret, range.endOffset + leftSurround.length, rightSurround)
|
change.insertText(editor, caret, range.endOffset + leftSurround.length, rightSurround)
|
||||||
|
@@ -78,6 +78,7 @@ 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
|
||||||
@@ -394,7 +395,6 @@ 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,7 +419,11 @@ public class ChangeGroup : VimChangeGroupBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val afterAction = {
|
val afterAction = {
|
||||||
caret.moveToOffset(injector.motion.moveCaretToLineStartSkipLeading(editor, startPos.line))
|
val firstLine = editor.offsetToBufferPosition(
|
||||||
|
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) {
|
||||||
|
@@ -83,7 +83,7 @@ public object IjOptions {
|
|||||||
public val trackactionids: ToggleOption = addOption(ToggleOption("trackactionids", GLOBAL, "tai", false))
|
public val trackactionids: ToggleOption = addOption(ToggleOption("trackactionids", GLOBAL, "tai", false))
|
||||||
public val unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true))
|
public val unifyjumps: ToggleOption = addOption(ToggleOption("unifyjumps", GLOBAL, "unifyjumps", true))
|
||||||
public val visualdelay: UnsignedNumberOption = addOption(UnsignedNumberOption("visualdelay", GLOBAL, "visualdelay", 100))
|
public val visualdelay: UnsignedNumberOption = addOption(UnsignedNumberOption("visualdelay", GLOBAL, "visualdelay", 100))
|
||||||
public val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", true, isTemporary = true))
|
public val oldundo: ToggleOption = addOption(ToggleOption("oldundo", GLOBAL, "oldundo", false, isTemporary = true))
|
||||||
public val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", true, isTemporary = true))
|
public val vimscriptFunctionAnnotation: ToggleOption = addOption(ToggleOption("vimscriptfunctionannotation", GLOBAL, "vimscriptfunctionannotation", true, isTemporary = true))
|
||||||
public val commandOrMotionAnnotation: ToggleOption = addOption(ToggleOption("commandormotionannotation", GLOBAL, "commandormotionannotation", true, isTemporary = true))
|
public val commandOrMotionAnnotation: ToggleOption = addOption(ToggleOption("commandormotionannotation", GLOBAL, "commandormotionannotation", true, isTemporary = true))
|
||||||
public val showmodewidget: ToggleOption = addOption(ToggleOption("showmodewidget", GLOBAL, "showmodewidget", false, isTemporary = true))
|
public val showmodewidget: ToggleOption = addOption(ToggleOption("showmodewidget", GLOBAL, "showmodewidget", false, isTemporary = true))
|
||||||
|
@@ -1,68 +0,0 @@
|
|||||||
package com.maddyhome.idea.vim.group
|
|
||||||
|
|
||||||
import com.intellij.codeInsight.daemon.ReferenceImporter
|
|
||||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.application.ReadAction
|
|
||||||
import com.intellij.openapi.command.WriteCommandAction
|
|
||||||
import com.intellij.openapi.editor.Editor
|
|
||||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
|
||||||
import com.intellij.openapi.progress.ProgressIndicator
|
|
||||||
import com.intellij.openapi.progress.ProgressManager
|
|
||||||
import com.intellij.openapi.progress.Task
|
|
||||||
import com.intellij.psi.PsiDocumentManager
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
|
|
||||||
import java.util.function.BooleanSupplier
|
|
||||||
|
|
||||||
internal object MacroAutoImport {
|
|
||||||
fun run(editor: Editor, dataContext: DataContext) {
|
|
||||||
val project = CommonDataKeys.PROJECT.getData(dataContext) ?: return
|
|
||||||
val file = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) ?: return
|
|
||||||
|
|
||||||
if (!FileDocumentManager.getInstance().requestWriting(editor.document, project)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val importers = ReferenceImporter.EP_NAME.extensionList
|
|
||||||
if (importers.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressManager.getInstance().run(object : Task.Backgroundable(project, "Auto import", true) {
|
|
||||||
override fun run(indicator: ProgressIndicator) {
|
|
||||||
val fixes = ReadAction.nonBlocking<List<BooleanSupplier>> {
|
|
||||||
val fixes = mutableListOf<BooleanSupplier>()
|
|
||||||
|
|
||||||
file.accept(object : PsiRecursiveElementWalkingVisitor() {
|
|
||||||
override fun visitElement(element: PsiElement) {
|
|
||||||
for (reference in element.references) {
|
|
||||||
if (reference.resolve() != null) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for (importer in importers) {
|
|
||||||
importer.computeAutoImportAtOffset(editor, file, element.textRange.startOffset, true)
|
|
||||||
?.let(fixes::add)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.visitElement(element)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return@nonBlocking fixes
|
|
||||||
}.executeSynchronously()
|
|
||||||
|
|
||||||
ApplicationManager.getApplication().invokeAndWait {
|
|
||||||
WriteCommandAction.writeCommandAction(project)
|
|
||||||
.withName("Auto Import")
|
|
||||||
.withGroupId("IdeaVimAutoImportAfterMacro")
|
|
||||||
.shouldRecordActionForActiveDocument(true)
|
|
||||||
.run<RuntimeException> {
|
|
||||||
fixes.forEach { it.asBoolean }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@@ -21,7 +21,6 @@ import com.maddyhome.idea.vim.api.injector
|
|||||||
import com.maddyhome.idea.vim.helper.MessageHelper.message
|
import com.maddyhome.idea.vim.helper.MessageHelper.message
|
||||||
import com.maddyhome.idea.vim.macro.VimMacroBase
|
import com.maddyhome.idea.vim.macro.VimMacroBase
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to handle playback of macros
|
* Used to handle playback of macros
|
||||||
@@ -91,9 +90,6 @@ internal class MacroGroup : VimMacroBase() {
|
|||||||
} finally {
|
} finally {
|
||||||
keyStack.removeFirst()
|
keyStack.removeFirst()
|
||||||
}
|
}
|
||||||
if (!isInternalMacro) {
|
|
||||||
MacroAutoImport.run(editor.ij, context.ij)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInternalMacro) {
|
if (isInternalMacro) {
|
||||||
|
@@ -192,8 +192,8 @@ public class SearchGroup extends VimSearchGroupBase implements PersistentStateCo
|
|||||||
* @param patternOffset The pattern offset, e.g. `/{pattern}/{offset}`
|
* @param patternOffset The pattern offset, e.g. `/{pattern}/{offset}`
|
||||||
* @param direction The direction to search
|
* @param direction The direction to search
|
||||||
*/
|
*/
|
||||||
@Override
|
@TestOnly
|
||||||
public void setLastSearchState(@SuppressWarnings("unused") @NotNull VimEditor editor, @NotNull String pattern,
|
public void setLastSearchState(@SuppressWarnings("unused") @NotNull Editor editor, @NotNull String pattern,
|
||||||
@NotNull String patternOffset, Direction direction) {
|
@NotNull String patternOffset, Direction direction) {
|
||||||
setLastUsedPattern(pattern, RE_SEARCH, true);
|
setLastUsedPattern(pattern, RE_SEARCH, true);
|
||||||
lastIgnoreSmartCase = false;
|
lastIgnoreSmartCase = false;
|
||||||
|
@@ -335,7 +335,7 @@ public class EditorHelper {
|
|||||||
|
|
||||||
final int offset = y - ((screenHeight - lineHeight) / lineHeight / 2 * lineHeight);
|
final int offset = y - ((screenHeight - lineHeight) / lineHeight / 2 * lineHeight);
|
||||||
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
|
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
|
||||||
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) + editor.getSettings().getAdditionalLinesCount();
|
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
|
||||||
final int offsetForLastLineAtBottom = getOffsetToScrollVisualLineToBottomOfScreen(editor, lastVisualLine);
|
final int offsetForLastLineAtBottom = getOffsetToScrollVisualLineToBottomOfScreen(editor, lastVisualLine);
|
||||||
|
|
||||||
// For `zz`, we want to use virtual space and move any line, including the last one, to the middle of the screen.
|
// For `zz`, we want to use virtual space and move any line, including the last one, to the middle of the screen.
|
||||||
|
@@ -12,7 +12,6 @@ package com.maddyhome.idea.vim.helper
|
|||||||
|
|
||||||
import com.intellij.codeWithMe.ClientId
|
import com.intellij.codeWithMe.ClientId
|
||||||
import com.intellij.openapi.editor.Caret
|
import com.intellij.openapi.editor.Caret
|
||||||
import com.intellij.openapi.editor.CaretState
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||||
@@ -20,8 +19,6 @@ import com.intellij.util.ui.table.JBTableRowEditor
|
|||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.group.IjOptionConstants
|
import com.maddyhome.idea.vim.group.IjOptionConstants
|
||||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
|
||||||
import com.maddyhome.idea.vim.state.mode.inBlockSelection
|
|
||||||
import java.awt.Component
|
import java.awt.Component
|
||||||
import javax.swing.JComponent
|
import javax.swing.JComponent
|
||||||
import javax.swing.JTable
|
import javax.swing.JTable
|
||||||
@@ -96,41 +93,3 @@ internal val Caret.vimLine: Int
|
|||||||
*/
|
*/
|
||||||
internal val Editor.vimLine: Int
|
internal val Editor.vimLine: Int
|
||||||
get() = this.caretModel.currentCaret.vimLine
|
get() = this.caretModel.currentCaret.vimLine
|
||||||
|
|
||||||
internal inline fun Editor.runWithEveryCaretAndRestore(action: () -> Unit) {
|
|
||||||
val caretModel = this.caretModel
|
|
||||||
val carets = if (this.vim.inBlockSelection) null else caretModel.allCarets
|
|
||||||
if (carets == null || carets.size == 1) {
|
|
||||||
action()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var initialDocumentSize = this.document.textLength
|
|
||||||
var documentSizeDifference = 0
|
|
||||||
|
|
||||||
val caretOffsets = carets.map { it.selectionStart to it.selectionEnd }
|
|
||||||
val restoredCarets = mutableListOf<CaretState>()
|
|
||||||
|
|
||||||
caretModel.removeSecondaryCarets()
|
|
||||||
|
|
||||||
for ((selectionStart, selectionEnd) in caretOffsets) {
|
|
||||||
if (selectionStart == selectionEnd) {
|
|
||||||
caretModel.primaryCaret.moveToOffset(selectionStart + documentSizeDifference)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
caretModel.primaryCaret.setSelection(
|
|
||||||
selectionStart + documentSizeDifference,
|
|
||||||
selectionEnd + documentSizeDifference
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
action()
|
|
||||||
restoredCarets.add(caretModel.caretsAndSelections.single())
|
|
||||||
|
|
||||||
val documentLength = this.document.textLength
|
|
||||||
documentSizeDifference += documentLength - initialDocumentSize
|
|
||||||
initialDocumentSize = documentLength
|
|
||||||
}
|
|
||||||
|
|
||||||
caretModel.caretsAndSelections = restoredCarets
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -14,6 +14,7 @@ import com.maddyhome.idea.vim.api.injector
|
|||||||
import com.maddyhome.idea.vim.api.normalizeVisualColumn
|
import com.maddyhome.idea.vim.api.normalizeVisualColumn
|
||||||
import com.maddyhome.idea.vim.api.options
|
import com.maddyhome.idea.vim.api.options
|
||||||
import com.maddyhome.idea.vim.command.CommandFlags
|
import com.maddyhome.idea.vim.command.CommandFlags
|
||||||
|
import com.maddyhome.idea.vim.state.VimStateMachine
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper.getApproximateScreenHeight
|
import com.maddyhome.idea.vim.helper.EditorHelper.getApproximateScreenHeight
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper.getApproximateScreenWidth
|
import com.maddyhome.idea.vim.helper.EditorHelper.getApproximateScreenWidth
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper.getNonNormalizedVisualLineAtBottomOfScreen
|
import com.maddyhome.idea.vim.helper.EditorHelper.getNonNormalizedVisualLineAtBottomOfScreen
|
||||||
@@ -28,7 +29,6 @@ import com.maddyhome.idea.vim.helper.EditorHelper.scrollVisualLineToBottomOfScre
|
|||||||
import com.maddyhome.idea.vim.helper.EditorHelper.scrollVisualLineToMiddleOfScreen
|
import com.maddyhome.idea.vim.helper.EditorHelper.scrollVisualLineToMiddleOfScreen
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper.scrollVisualLineToTopOfScreen
|
import com.maddyhome.idea.vim.helper.EditorHelper.scrollVisualLineToTopOfScreen
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
@@ -56,7 +56,7 @@ internal object ScrollViewHelper {
|
|||||||
// that this needs to be replaced as a more or less dumb line for line rewrite.
|
// that this needs to be replaced as a more or less dumb line for line rewrite.
|
||||||
val topLine = getVisualLineAtTopOfScreen(editor)
|
val topLine = getVisualLineAtTopOfScreen(editor)
|
||||||
val bottomLine = getVisualLineAtBottomOfScreen(editor)
|
val bottomLine = getVisualLineAtBottomOfScreen(editor)
|
||||||
val lastLine = vimEditor.getVisualLineCount() + editor.settings.additionalLinesCount
|
val lastLine = vimEditor.getVisualLineCount() - 1
|
||||||
|
|
||||||
// We need the non-normalised value here, so we can handle cases such as so=999 to keep the current line centred
|
// We need the non-normalised value here, so we can handle cases such as so=999 to keep the current line centred
|
||||||
val scrollOffset = injector.options(vimEditor).scrolloff
|
val scrollOffset = injector.options(vimEditor).scrolloff
|
||||||
|
@@ -14,7 +14,6 @@ import com.intellij.openapi.command.CommandProcessor
|
|||||||
import com.intellij.openapi.command.undo.UndoManager
|
import com.intellij.openapi.command.undo.UndoManager
|
||||||
import com.intellij.openapi.components.Service
|
import com.intellij.openapi.components.Service
|
||||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
|
||||||
import com.maddyhome.idea.vim.api.ExecutionContext
|
import com.maddyhome.idea.vim.api.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
@@ -22,8 +21,6 @@ import com.maddyhome.idea.vim.common.ChangesListener
|
|||||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
||||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||||
import com.maddyhome.idea.vim.newapi.ij
|
import com.maddyhome.idea.vim.newapi.ij
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
|
||||||
import com.maddyhome.idea.vim.state.mode.inVisualMode
|
|
||||||
import com.maddyhome.idea.vim.undo.UndoRedoBase
|
import com.maddyhome.idea.vim.undo.UndoRedoBase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +39,6 @@ internal class UndoRedoHelper : UndoRedoBase() {
|
|||||||
|
|
||||||
if (injector.globalIjOptions().oldundo) {
|
if (injector.globalIjOptions().oldundo) {
|
||||||
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
|
SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) }
|
||||||
restoreVisualMode(editor)
|
|
||||||
} else {
|
} else {
|
||||||
// TODO refactor me after VIM-308 when restoring selection and caret movement will be ignored by undo
|
// TODO refactor me after VIM-308 when restoring selection and caret movement will be ignored by undo
|
||||||
editor.runWithChangeTracking {
|
editor.runWithChangeTracking {
|
||||||
@@ -78,7 +74,6 @@ internal class UndoRedoHelper : UndoRedoBase() {
|
|||||||
if (undoManager.isRedoAvailable(fileEditor)) {
|
if (undoManager.isRedoAvailable(fileEditor)) {
|
||||||
if (injector.globalIjOptions().oldundo) {
|
if (injector.globalIjOptions().oldundo) {
|
||||||
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
|
SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) }
|
||||||
restoreVisualMode(editor)
|
|
||||||
} else {
|
} else {
|
||||||
undoManager.redo(fileEditor)
|
undoManager.redo(fileEditor)
|
||||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||||
@@ -136,21 +131,4 @@ internal class UndoRedoHelper : UndoRedoBase() {
|
|||||||
val hasChanges: Boolean
|
val hasChanges: Boolean
|
||||||
get() = changeListener.hasChanged || initialPath != editor.getPath()
|
get() = changeListener.hasChanged || initialPath != editor.getPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreVisualMode(editor: VimEditor) {
|
|
||||||
if (!editor.inVisualMode && editor.getSelectionModel().hasSelection()) {
|
|
||||||
val detectedMode = VimPlugin.getVisualMotion().autodetectVisualSubmode(editor)
|
|
||||||
|
|
||||||
// Visual block selection is restored into multiple carets, so multi-carets that form a block are always
|
|
||||||
// identified as visual block mode, leading to false positives.
|
|
||||||
// Since I use visual block mode much less often than multi-carets, this is a judgment call to never restore
|
|
||||||
// visual block mode.
|
|
||||||
val wantedMode = if (detectedMode == SelectionType.BLOCK_WISE)
|
|
||||||
SelectionType.CHARACTER_WISE
|
|
||||||
else
|
|
||||||
detectedMode
|
|
||||||
|
|
||||||
VimPlugin.getVisualMotion().enterVisualMode(editor, wantedMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.helper
|
||||||
|
|
||||||
|
import com.intellij.ide.plugins.StandalonePluginUpdateChecker
|
||||||
|
import com.intellij.openapi.components.Service
|
||||||
|
import com.intellij.openapi.components.service
|
||||||
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
|
import com.maddyhome.idea.vim.group.NotificationService
|
||||||
|
import com.maddyhome.idea.vim.icons.VimIcons
|
||||||
|
|
||||||
|
@Service(Service.Level.APP)
|
||||||
|
internal class VimStandalonePluginUpdateChecker : StandalonePluginUpdateChecker(
|
||||||
|
VimPlugin.getPluginId(),
|
||||||
|
updateTimestampProperty = PROPERTY_NAME,
|
||||||
|
NotificationService.IDEAVIM_STICKY_GROUP,
|
||||||
|
VimIcons.IDEAVIM,
|
||||||
|
) {
|
||||||
|
|
||||||
|
override fun skipUpdateCheck(): Boolean = VimPlugin.isNotEnabled() || "dev" in VimPlugin.getVersion()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val PROPERTY_NAME = "ideavim.statistics.timestamp"
|
||||||
|
val instance: VimStandalonePluginUpdateChecker = service()
|
||||||
|
}
|
||||||
|
}
|
@@ -34,7 +34,6 @@ import com.maddyhome.idea.vim.VimPlugin
|
|||||||
import com.maddyhome.idea.vim.action.VimShortcutKeyAction
|
import com.maddyhome.idea.vim.action.VimShortcutKeyAction
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.group.NotificationService
|
import com.maddyhome.idea.vim.group.NotificationService
|
||||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
|
||||||
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
||||||
import com.maddyhome.idea.vim.helper.vimStateMachine
|
import com.maddyhome.idea.vim.helper.vimStateMachine
|
||||||
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
import com.maddyhome.idea.vim.newapi.globalIjOptions
|
||||||
@@ -96,8 +95,7 @@ internal object IdeaSpecifics {
|
|||||||
if (VimPlugin.isNotEnabled()) return
|
if (VimPlugin.isNotEnabled()) return
|
||||||
|
|
||||||
val editor = editor
|
val editor = editor
|
||||||
if (editor != null) {
|
if (editor != null && action is ChooseItemAction && editor.vimStateMachine?.isRecording == true) {
|
||||||
if (action is ChooseItemAction && editor.vimStateMachine?.isRecording == true) {
|
|
||||||
val prevDocumentLength = completionPrevDocumentLength
|
val prevDocumentLength = completionPrevDocumentLength
|
||||||
val prevDocumentOffset = completionPrevDocumentOffset
|
val prevDocumentOffset = completionPrevDocumentOffset
|
||||||
|
|
||||||
@@ -124,18 +122,15 @@ internal object IdeaSpecifics {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
val commandState = editor.vim.vimStateMachine
|
editor?.let {
|
||||||
|
val commandState = it.vim.vimStateMachine
|
||||||
commandState.mode = Mode.NORMAL()
|
commandState.mode = Mode.NORMAL()
|
||||||
VimPlugin.getChange().insertBeforeCursor(editor.vim, event.dataContext.vim)
|
VimPlugin.getChange().insertBeforeCursor(it.vim, event.dataContext.vim)
|
||||||
KeyHandler.getInstance().reset(editor.vim)
|
KeyHandler.getInstance().reset(it.vim)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
if (EditorHelper.getVisibleArea(editor).let { it.width > 0 && it.height > 0 }) {
|
|
||||||
injector.scroll.scrollCaretIntoView(editor.vim)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.editor = null
|
this.editor = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -74,6 +74,7 @@ import com.maddyhome.idea.vim.handler.correctorRequester
|
|||||||
import com.maddyhome.idea.vim.handler.keyCheckRequests
|
import com.maddyhome.idea.vim.handler.keyCheckRequests
|
||||||
import com.maddyhome.idea.vim.helper.GuicursorChangeListener
|
import com.maddyhome.idea.vim.helper.GuicursorChangeListener
|
||||||
import com.maddyhome.idea.vim.helper.StrictMode
|
import com.maddyhome.idea.vim.helper.StrictMode
|
||||||
|
import com.maddyhome.idea.vim.helper.VimStandalonePluginUpdateChecker
|
||||||
import com.maddyhome.idea.vim.helper.exitSelectMode
|
import com.maddyhome.idea.vim.helper.exitSelectMode
|
||||||
import com.maddyhome.idea.vim.helper.exitVisualMode
|
import com.maddyhome.idea.vim.helper.exitVisualMode
|
||||||
import com.maddyhome.idea.vim.helper.forceBarCursor
|
import com.maddyhome.idea.vim.helper.forceBarCursor
|
||||||
@@ -90,8 +91,6 @@ import com.maddyhome.idea.vim.listener.MouseEventsDataHolder.skipNDragEvents
|
|||||||
import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.add
|
import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.add
|
||||||
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
import com.maddyhome.idea.vim.newapi.IjVimEditor
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
import com.maddyhome.idea.vim.newapi.vim
|
||||||
import com.maddyhome.idea.vim.state.VimStateMachine
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
|
||||||
import com.maddyhome.idea.vim.state.mode.inSelectMode
|
import com.maddyhome.idea.vim.state.mode.inSelectMode
|
||||||
import com.maddyhome.idea.vim.state.mode.mode
|
import com.maddyhome.idea.vim.state.mode.mode
|
||||||
import com.maddyhome.idea.vim.state.mode.selectionType
|
import com.maddyhome.idea.vim.state.mode.selectionType
|
||||||
@@ -305,16 +304,6 @@ internal object VimListenerManager {
|
|||||||
class VimFileEditorManagerListener : FileEditorManagerListener {
|
class VimFileEditorManagerListener : FileEditorManagerListener {
|
||||||
override fun selectionChanged(event: FileEditorManagerEvent) {
|
override fun selectionChanged(event: FileEditorManagerEvent) {
|
||||||
if (VimPlugin.isNotEnabled()) return
|
if (VimPlugin.isNotEnabled()) return
|
||||||
|
|
||||||
val newEditor = event.newEditor
|
|
||||||
if (newEditor is TextEditor) {
|
|
||||||
val editor = newEditor.editor
|
|
||||||
if (editor.isInsertMode) {
|
|
||||||
VimStateMachine.getInstance(editor).mode = Mode.NORMAL()
|
|
||||||
KeyHandler.getInstance().reset(editor.vim)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MotionGroup.fileEditorManagerSelectionChangedCallback(event)
|
MotionGroup.fileEditorManagerSelectionChangedCallback(event)
|
||||||
FileGroup.fileEditorManagerSelectionChangedCallback(event)
|
FileGroup.fileEditorManagerSelectionChangedCallback(event)
|
||||||
SearchGroup.fileEditorManagerSelectionChangedCallback(event)
|
SearchGroup.fileEditorManagerSelectionChangedCallback(event)
|
||||||
@@ -379,6 +368,8 @@ internal object VimListenerManager {
|
|||||||
|
|
||||||
event.editor.putUserData(openingEditorKey, OpeningEditor(openingEditor, owningEditorWindow, isPreview, canBeReused))
|
event.editor.putUserData(openingEditorKey, OpeningEditor(openingEditor, owningEditorWindow, isPreview, canBeReused))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VimStandalonePluginUpdateChecker.instance.pluginUsed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun editorReleased(event: EditorFactoryEvent) {
|
override fun editorReleased(event: EditorFactoryEvent) {
|
||||||
|
@@ -228,12 +228,12 @@
|
|||||||
|
|
||||||
<!-- Change -->
|
<!-- Change -->
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerMotionAction" mappingModes="N" keys="gu"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerMotionAction" mappingModes="N" keys="gu"/>
|
||||||
<!-- <vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerVisualAction" mappingModes="X" keys="u"/>-->
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseLowerVisualAction" mappingModes="X" keys="u"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleCharacterAction" mappingModes="N" keys="~"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleCharacterAction" mappingModes="N" keys="~"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleMotionAction" mappingModes="N" keys="g~"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleMotionAction" mappingModes="N" keys="g~"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleVisualAction" mappingModes="X" keys="~"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseToggleVisualAction" mappingModes="X" keys="~"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperMotionAction" mappingModes="N" keys="gU"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperMotionAction" mappingModes="N" keys="gU"/>
|
||||||
<!-- <vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperVisualAction" mappingModes="X" keys="U"/>-->
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCaseUpperVisualAction" mappingModes="X" keys="U"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCharacterAction" mappingModes="N" keys="r"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCharacterAction" mappingModes="N" keys="r"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCharactersAction" mappingModes="N" keys="s"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeCharactersAction" mappingModes="N" keys="s"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeEndOfLineAction" mappingModes="N" keys="C"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.change.ChangeEndOfLineAction" mappingModes="N" keys="C"/>
|
||||||
@@ -331,8 +331,8 @@
|
|||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.RepeatChangeAction" mappingModes="N" keys="."/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.RepeatChangeAction" mappingModes="N" keys="."/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.ExEntryAction" mappingModes="NXO" keys=":"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.ExEntryAction" mappingModes="NXO" keys=":"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.ResetModeAction" mappingModes="ALL" keys="«C-\»«C-N»"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.ResetModeAction" mappingModes="ALL" keys="«C-\»«C-N»"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.RedoAction" mappingModes="NX" keys="U,«C-R»"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.RedoAction" mappingModes="N" keys="«C-R»"/>
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.UndoAction" mappingModes="NX"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.UndoAction" mappingModes="N"/>
|
||||||
|
|
||||||
<!-- Keys -->
|
<!-- Keys -->
|
||||||
<vimAction implementation="com.maddyhome.idea.vim.action.change.OperatorAction" mappingModes="N" keys="g@"/>
|
<vimAction implementation="com.maddyhome.idea.vim.action.change.OperatorAction" mappingModes="N" keys="g@"/>
|
||||||
|
@@ -1,4 +1,12 @@
|
|||||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<idea-plugin url="https://plugins.jetbrains.com/plugin/164" xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||||
<name>IdeaVim</name>
|
<name>IdeaVim</name>
|
||||||
<id>IdeaVIM</id>
|
<id>IdeaVIM</id>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
@@ -13,13 +21,13 @@
|
|||||||
<li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li>
|
<li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li>
|
||||||
</ul>
|
</ul>
|
||||||
]]></description>
|
]]></description>
|
||||||
<version>chylex</version>
|
<version>SNAPSHOT</version>
|
||||||
<vendor>JetBrains</vendor>
|
<vendor>JetBrains</vendor>
|
||||||
|
|
||||||
<!-- Please search for "[VERSION UPDATE]" in project in case you update the since-build version -->
|
<!-- Please search for "[VERSION UPDATE]" in project in case you update the since-build version -->
|
||||||
<!-- Check for [Version Update] tag in YouTrack as well -->
|
<!-- Check for [Version Update] tag in YouTrack as well -->
|
||||||
<!-- Also, please update the value in build.gradle.kts file-->
|
<!-- Also, please update the value in build.gradle.kts file-->
|
||||||
<idea-version since-build="232"/>
|
<idea-version since-build="233.11799.30"/>
|
||||||
|
|
||||||
<!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform (including CWM) -->
|
<!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform (including CWM) -->
|
||||||
<depends>com.intellij.modules.platform</depends>
|
<depends>com.intellij.modules.platform</depends>
|
||||||
@@ -161,6 +169,5 @@
|
|||||||
</group>
|
</group>
|
||||||
|
|
||||||
<action id="VimFindActionIdAction" class="com.maddyhome.idea.vim.listener.FindActionIdAction"/>
|
<action id="VimFindActionIdAction" class="com.maddyhome.idea.vim.listener.FindActionIdAction"/>
|
||||||
<action id="VimJumpToSource" class="com.intellij.diff.actions.impl.OpenInEditorAction" />
|
|
||||||
</actions>
|
</actions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
@@ -102,7 +102,7 @@ import kotlin.test.assertTrue
|
|||||||
* This is done as we have no mechanism to guarantee compatibility as we update this test case.
|
* This is done as we have no mechanism to guarantee compatibility as we update this test case.
|
||||||
* Feel free to copy this class into your plugin, or copy just needed functions.
|
* Feel free to copy this class into your plugin, or copy just needed functions.
|
||||||
*/
|
*/
|
||||||
@RunInEdt
|
@RunInEdt(writeIntent = true)
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
abstract class VimTestCase {
|
abstract class VimTestCase {
|
||||||
protected lateinit var fixture: CodeInsightTestFixture
|
protected lateinit var fixture: CodeInsightTestFixture
|
||||||
@@ -448,11 +448,6 @@ 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,7 +47,10 @@ 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)
|
||||||
assertRegister('a', "3l")
|
val registerGroup = VimPlugin.getRegister()
|
||||||
|
val register = registerGroup.getRegister('a')
|
||||||
|
assertNotNull<Any>(register)
|
||||||
|
kotlin.test.assertEquals("3l", register.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -55,7 +58,9 @@ 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"))
|
||||||
assertRegister('a', "ipp<Esc>")
|
val register = VimPlugin.getRegister().getRegister('a')
|
||||||
|
assertNotNull<Any>(register)
|
||||||
|
kotlin.test.assertEquals("ipp<Esc>", injector.parser.toKeyNotation(register.keys))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -63,7 +68,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)
|
||||||
assertRegister('a', "i<C-K>OK<Esc>")
|
kotlin.test.assertEquals("i<C-K>OK<Esc>", injector.parser.toKeyNotation(register.keys))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -136,8 +141,8 @@ class MacroActionTest : VimTestCase() {
|
|||||||
assertState("4\n5\n")
|
assertState("4\n5\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
// Broken, see the resulting text
|
||||||
fun `test macro with macro`() {
|
fun `ignore test macro with macro`() {
|
||||||
val content = """
|
val content = """
|
||||||
Lorem Ipsum
|
Lorem Ipsum
|
||||||
|
|
||||||
@@ -147,55 +152,16 @@ class MacroActionTest : VimTestCase() {
|
|||||||
Cras id tellus in ex imperdiet egestas.
|
Cras id tellus in ex imperdiet egestas.
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
configureByText(content)
|
configureByText(content)
|
||||||
typeText(
|
typeText(injector.parser.parseKeys("qa" + "l" + "q" + "qb" + "10@a" + "q" + "2@b"))
|
||||||
injector.parser.parseKeys(
|
|
||||||
"qa" + "l" + "q" +
|
|
||||||
"qb" + "6@a" + "q" +
|
|
||||||
"^" + "3@b"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assertRegister('b', "6@a")
|
val startOffset = content.rangeOf("rocks").startOffset
|
||||||
assertState("""
|
|
||||||
Lorem Ipsum
|
|
||||||
|
|
||||||
Lorem ipsum dolor ${c}sit amet,
|
waitAndAssert {
|
||||||
consectetur adipiscing elit
|
println(fixture.editor.caretModel.offset)
|
||||||
Sed in orci mauris.
|
println(startOffset)
|
||||||
Cras id tellus in ex imperdiet egestas.
|
println()
|
||||||
""".trimIndent())
|
startOffset == fixture.editor.caretModel.offset
|
||||||
}
|
}
|
||||||
|
|
||||||
@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
|
||||||
|
@@ -12,9 +12,8 @@ package org.jetbrains.plugins.ideavim.action.motion.gn
|
|||||||
|
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.Direction
|
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
|
import com.maddyhome.idea.vim.common.Direction
|
||||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
@@ -86,7 +85,7 @@ class GnNextTextObjectTest : VimTestCase() {
|
|||||||
|
|
||||||
private fun doTestWithSearch(keys: List<KeyStroke>, before: String, after: String) {
|
private fun doTestWithSearch(keys: List<KeyStroke>, before: String, after: String) {
|
||||||
configureByText(before)
|
configureByText(before)
|
||||||
VimPlugin.getSearch().setLastSearchState(fixture.editor.vim, "test", "", Direction.FORWARDS)
|
VimPlugin.getSearch().setLastSearchState(fixture.editor, "test", "", Direction.FORWARDS)
|
||||||
typeText(keys)
|
typeText(keys)
|
||||||
assertState(after)
|
assertState(after)
|
||||||
assertState(Mode.NORMAL())
|
assertState(Mode.NORMAL())
|
||||||
|
@@ -12,9 +12,8 @@ package org.jetbrains.plugins.ideavim.action.motion.gn
|
|||||||
|
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.Direction
|
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
|
import com.maddyhome.idea.vim.common.Direction
|
||||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
@@ -64,7 +63,7 @@ class GnPreviousTextObjectTest : VimTestCase() {
|
|||||||
|
|
||||||
private fun doTestWithSearch(keys: List<KeyStroke>, before: String, after: String) {
|
private fun doTestWithSearch(keys: List<KeyStroke>, before: String, after: String) {
|
||||||
configureByText(before)
|
configureByText(before)
|
||||||
VimPlugin.getSearch().setLastSearchState(fixture.editor.vim, "test", "", Direction.FORWARDS)
|
VimPlugin.getSearch().setLastSearchState(fixture.editor, "test", "", Direction.FORWARDS)
|
||||||
typeText(keys)
|
typeText(keys)
|
||||||
assertState(after)
|
assertState(after)
|
||||||
assertState(Mode.NORMAL())
|
assertState(Mode.NORMAL())
|
||||||
|
@@ -11,10 +11,9 @@ import com.intellij.idea.TestFor
|
|||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.action.motion.search.SearchWholeWordForwardAction
|
import com.maddyhome.idea.vim.action.motion.search.SearchWholeWordForwardAction
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.Direction
|
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.common.Direction
|
||||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
@@ -58,7 +57,7 @@ class VisualSelectNextSearchTest : VimTestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun testWithoutSpaces() {
|
fun testWithoutSpaces() {
|
||||||
configureByText("test<caret>test")
|
configureByText("test<caret>test")
|
||||||
VimPlugin.getSearch().setLastSearchState(fixture.editor.vim, "test", "", Direction.FORWARDS)
|
VimPlugin.getSearch().setLastSearchState(fixture.editor, "test", "", Direction.FORWARDS)
|
||||||
typeText(injector.parser.parseKeys("gn"))
|
typeText(injector.parser.parseKeys("gn"))
|
||||||
assertOffset(7)
|
assertOffset(7)
|
||||||
assertSelection("test")
|
assertSelection("test")
|
||||||
|
@@ -11,10 +11,9 @@ import com.intellij.idea.TestFor
|
|||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.action.motion.search.SearchWholeWordForwardAction
|
import com.maddyhome.idea.vim.action.motion.search.SearchWholeWordForwardAction
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.common.Direction
|
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
|
||||||
import com.maddyhome.idea.vim.state.mode.Mode
|
import com.maddyhome.idea.vim.state.mode.Mode
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
|
import com.maddyhome.idea.vim.common.Direction
|
||||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
@@ -55,7 +54,7 @@ class VisualSelectPreviousSearchTest : VimTestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun testWithoutSpaces() {
|
fun testWithoutSpaces() {
|
||||||
configureByText("tes<caret>ttest")
|
configureByText("tes<caret>ttest")
|
||||||
VimPlugin.getSearch().setLastSearchState(fixture.editor.vim, "test", "", Direction.FORWARDS)
|
VimPlugin.getSearch().setLastSearchState(fixture.editor, "test", "", Direction.FORWARDS)
|
||||||
typeText(injector.parser.parseKeys("gN"))
|
typeText(injector.parser.parseKeys("gN"))
|
||||||
assertOffset(0)
|
assertOffset(0)
|
||||||
assertSelection("test")
|
assertSelection("test")
|
||||||
|
@@ -10,7 +10,6 @@ package org.jetbrains.plugins.ideavim.action.motion.search
|
|||||||
|
|
||||||
import com.maddyhome.idea.vim.VimPlugin
|
import com.maddyhome.idea.vim.VimPlugin
|
||||||
import com.maddyhome.idea.vim.common.Direction
|
import com.maddyhome.idea.vim.common.Direction
|
||||||
import com.maddyhome.idea.vim.newapi.vim
|
|
||||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||||
@@ -168,7 +167,7 @@ class SearchAgainPreviousActionTest : VimTestCase() {
|
|||||||
|
|
||||||
private fun doTestWithSearch(keys: String, before: String, after: String) {
|
private fun doTestWithSearch(keys: String, before: String, after: String) {
|
||||||
doTest(keys, before, after) {
|
doTest(keys, before, after) {
|
||||||
VimPlugin.getSearch().setLastSearchState(it.vim, "all", "", Direction.FORWARDS)
|
VimPlugin.getSearch().setLastSearchState(it, "all", "", Direction.FORWARDS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -102,9 +102,8 @@ 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.
|
// We only record unmapped keystrokes. If we've recursed to handle mapping, don't record anything.
|
||||||
// If we've recursed to handle mapping, or executing a macro, don't record anything.
|
var shouldRecord = handleKeyRecursionCount == 0 && editorState.isRecording
|
||||||
var shouldRecord = handleKeyRecursionCount == 0 && editorState.isRecording && !injector.macro.isExecutingMacro
|
|
||||||
handleKeyRecursionCount++
|
handleKeyRecursionCount++
|
||||||
try {
|
try {
|
||||||
LOG.trace("Start key processing...")
|
LOG.trace("Start key processing...")
|
||||||
|
@@ -16,7 +16,7 @@ import com.maddyhome.idea.vim.command.Command
|
|||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||||
|
|
||||||
@CommandOrMotion(keys = ["U", "<C-R>"], modes = [Mode.NORMAL, Mode.VISUAL])
|
@CommandOrMotion(keys = ["<C-R>"], modes = [Mode.NORMAL])
|
||||||
public class RedoAction : VimActionHandler.SingleExecution() {
|
public class RedoAction : VimActionHandler.SingleExecution() {
|
||||||
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
|
override val type: Command.Type = Command.Type.OTHER_SELF_SYNCHRONIZED
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ import com.maddyhome.idea.vim.handler.VimActionHandler
|
|||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import javax.swing.KeyStroke
|
import javax.swing.KeyStroke
|
||||||
|
|
||||||
@CommandOrMotion(keys = ["u", "<Undo>"], modes = [Mode.NORMAL, Mode.VISUAL])
|
@CommandOrMotion(keys = ["u", "<Undo>"], modes = [Mode.NORMAL])
|
||||||
public class UndoAction : VimActionHandler.SingleExecution(), ComplicatedKeysAction {
|
public class UndoAction : VimActionHandler.SingleExecution(), ComplicatedKeysAction {
|
||||||
override val keyStrokesSet: Set<List<KeyStroke>> = setOf(
|
override val keyStrokesSet: Set<List<KeyStroke>> = setOf(
|
||||||
injector.parser.parseKeys("u"),
|
injector.parser.parseKeys("u"),
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package com.maddyhome.idea.vim.action.change.change
|
package com.maddyhome.idea.vim.action.change.change
|
||||||
|
|
||||||
import com.intellij.vim.annotations.CommandOrMotion
|
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.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
@@ -21,7 +22,7 @@ import com.maddyhome.idea.vim.helper.CharacterHelper
|
|||||||
/**
|
/**
|
||||||
* @author vlan
|
* @author vlan
|
||||||
*/
|
*/
|
||||||
@CommandOrMotion(keys = [], modes = [])
|
@CommandOrMotion(keys = ["u"], modes = [Mode.VISUAL])
|
||||||
public class ChangeCaseLowerVisualAction : VisualOperatorActionHandler.ForEachCaret() {
|
public class ChangeCaseLowerVisualAction : VisualOperatorActionHandler.ForEachCaret() {
|
||||||
override val type: Command.Type = Command.Type.CHANGE
|
override val type: Command.Type = Command.Type.CHANGE
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package com.maddyhome.idea.vim.action.change.change
|
package com.maddyhome.idea.vim.action.change.change
|
||||||
|
|
||||||
import com.intellij.vim.annotations.CommandOrMotion
|
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.ExecutionContext
|
||||||
import com.maddyhome.idea.vim.api.VimCaret
|
import com.maddyhome.idea.vim.api.VimCaret
|
||||||
import com.maddyhome.idea.vim.api.VimEditor
|
import com.maddyhome.idea.vim.api.VimEditor
|
||||||
@@ -21,7 +22,7 @@ import com.maddyhome.idea.vim.helper.CharacterHelper
|
|||||||
/**
|
/**
|
||||||
* @author vlan
|
* @author vlan
|
||||||
*/
|
*/
|
||||||
@CommandOrMotion(keys = [], modes = [])
|
@CommandOrMotion(keys = ["U"], modes = [Mode.VISUAL])
|
||||||
public class ChangeCaseUpperVisualAction : VisualOperatorActionHandler.ForEachCaret() {
|
public class ChangeCaseUpperVisualAction : VisualOperatorActionHandler.ForEachCaret() {
|
||||||
override val type: Command.Type = Command.Type.CHANGE
|
override val type: Command.Type = Command.Type.CHANGE
|
||||||
|
|
||||||
|
@@ -30,7 +30,6 @@ public class FilterVisualLinesAction : VimActionHandler.SingleExecution() {
|
|||||||
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_MOT_LINEWISE)
|
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_MOT_LINEWISE)
|
||||||
|
|
||||||
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
override fun execute(editor: VimEditor, context: ExecutionContext, cmd: Command, operatorArguments: OperatorArguments): Boolean {
|
||||||
injector.markService.setVisualSelectionMarks(editor)
|
|
||||||
injector.processGroup.startFilterCommand(editor, context, cmd)
|
injector.processGroup.startFilterCommand(editor, context, cmd)
|
||||||
editor.exitVisualMode()
|
editor.exitVisualMode()
|
||||||
return true
|
return true
|
||||||
|
@@ -82,13 +82,6 @@ public sealed class TillCharacterMotion(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
injector.motion.setLastFTCmd(tillCharacterMotionType, argument.character)
|
injector.motion.setLastFTCmd(tillCharacterMotionType, argument.character)
|
||||||
|
|
||||||
val offset = if (!finishBeforeCharacter) ""
|
|
||||||
else if (direction == Direction.FORWARDS) "s-1"
|
|
||||||
else "s+1"
|
|
||||||
|
|
||||||
injector.searchGroup.setLastSearchState(editor, argument.character.let { if (it == '.') "\\." else it.toString() }, offset, direction)
|
|
||||||
|
|
||||||
return res.toMotionOrError()
|
return res.toMotionOrError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -144,7 +144,7 @@ public interface VimChangeGroup {
|
|||||||
operatorArguments: OperatorArguments,
|
operatorArguments: OperatorArguments,
|
||||||
)
|
)
|
||||||
|
|
||||||
public fun insertText(editor: VimEditor, caret: VimCaret, offset: Int, str: CharSequence): VimCaret
|
public fun insertText(editor: VimEditor, caret: VimCaret, offset: Int, str: String): VimCaret
|
||||||
|
|
||||||
public fun insertText(editor: VimEditor, caret: VimCaret, str: String): VimCaret
|
public fun insertText(editor: VimEditor, caret: VimCaret, str: String): VimCaret
|
||||||
|
|
||||||
|
@@ -203,7 +203,7 @@ public abstract class VimChangeGroupBase : VimChangeGroup {
|
|||||||
* @param caret The caret to start insertion in
|
* @param caret The caret to start insertion in
|
||||||
* @param str The text to insert
|
* @param str The text to insert
|
||||||
*/
|
*/
|
||||||
override fun insertText(editor: VimEditor, caret: VimCaret, offset: Int, str: CharSequence): VimCaret {
|
override fun insertText(editor: VimEditor, caret: VimCaret, offset: Int, str: String): VimCaret {
|
||||||
(editor as MutableVimEditor).insertText(Offset(offset), str)
|
(editor as MutableVimEditor).insertText(Offset(offset), str)
|
||||||
val newCaret = caret.moveToInlayAwareOffset(offset + str.length)
|
val newCaret = caret.moveToInlayAwareOffset(offset + str.length)
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@ import com.maddyhome.idea.vim.vimscript.model.VimLContext
|
|||||||
public interface VimSearchGroup {
|
public interface VimSearchGroup {
|
||||||
public var lastSearchPattern: String?
|
public var lastSearchPattern: String?
|
||||||
public var lastSubstitutePattern: String?
|
public var lastSubstitutePattern: String?
|
||||||
public fun setLastSearchState(editor: VimEditor, pattern: String, patternOffset: String, direction: Direction?)
|
|
||||||
public fun findUnderCaret(editor: VimEditor): TextRange?
|
public fun findUnderCaret(editor: VimEditor): TextRange?
|
||||||
public fun searchBackward(editor: VimEditor, offset: Int, count: Int): TextRange?
|
public fun searchBackward(editor: VimEditor, offset: Int, count: Int): TextRange?
|
||||||
public fun getNextSearchRange(editor: VimEditor, count: Int, forwards: Boolean): TextRange?
|
public fun getNextSearchRange(editor: VimEditor, count: Int, forwards: Boolean): TextRange?
|
||||||
|
@@ -255,13 +255,8 @@ public class ToActionMappingInfo(
|
|||||||
LOG.debug("Executing 'ToAction' mapping...")
|
LOG.debug("Executing 'ToAction' mapping...")
|
||||||
val editorDataContext = injector.executionContextManager.onEditor(editor, context)
|
val editorDataContext = injector.executionContextManager.onEditor(editor, context)
|
||||||
val dataContext = injector.executionContextManager.onCaret(editor.currentCaret(), editorDataContext)
|
val dataContext = injector.executionContextManager.onCaret(editor.currentCaret(), editorDataContext)
|
||||||
|
|
||||||
val commandBuilder = editor.vimStateMachine.commandBuilder
|
|
||||||
for (i in 0 until commandBuilder.count.coerceAtLeast(1)) {
|
|
||||||
injector.actionExecutor.executeAction(action, dataContext)
|
injector.actionExecutor.executeAction(action, dataContext)
|
||||||
}
|
}
|
||||||
commandBuilder.resetCount()
|
|
||||||
}
|
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
private val LOG = vimLogger<ToActionMappingInfo>()
|
private val LOG = vimLogger<ToActionMappingInfo>()
|
||||||
|
@@ -19,6 +19,7 @@ import com.maddyhome.idea.vim.api.VimMarkService
|
|||||||
import com.maddyhome.idea.vim.api.getText
|
import com.maddyhome.idea.vim.api.getText
|
||||||
import com.maddyhome.idea.vim.api.injector
|
import com.maddyhome.idea.vim.api.injector
|
||||||
import com.maddyhome.idea.vim.command.OperatorArguments
|
import com.maddyhome.idea.vim.command.OperatorArguments
|
||||||
|
import com.maddyhome.idea.vim.state.mode.SelectionType
|
||||||
import com.maddyhome.idea.vim.common.TextRange
|
import com.maddyhome.idea.vim.common.TextRange
|
||||||
import com.maddyhome.idea.vim.ex.ExException
|
import com.maddyhome.idea.vim.ex.ExException
|
||||||
import com.maddyhome.idea.vim.ex.InvalidRangeException
|
import com.maddyhome.idea.vim.ex.InvalidRangeException
|
||||||
@@ -28,7 +29,6 @@ import com.maddyhome.idea.vim.helper.Msg
|
|||||||
import com.maddyhome.idea.vim.mark.Mark
|
import com.maddyhome.idea.vim.mark.Mark
|
||||||
import com.maddyhome.idea.vim.mark.VimMark
|
import com.maddyhome.idea.vim.mark.VimMark
|
||||||
import com.maddyhome.idea.vim.put.PutData
|
import com.maddyhome.idea.vim.put.PutData
|
||||||
import com.maddyhome.idea.vim.state.mode.SelectionType
|
|
||||||
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@@ -49,13 +49,22 @@ public data class MoveTextCommand(val ranges: Ranges, val argument: String) : Co
|
|||||||
val caretPosition = caret.getBufferPosition()
|
val caretPosition = caret.getBufferPosition()
|
||||||
|
|
||||||
val goToLineCommand = injector.vimscriptParser.parseCommand(argument) ?: throw ExException("E16: Invalid range")
|
val goToLineCommand = injector.vimscriptParser.parseCommand(argument) ?: throw ExException("E16: Invalid range")
|
||||||
val lineRange = getLineRange(editor, caret)
|
|
||||||
|
|
||||||
val line = min(editor.fileSize().toInt(), normalizeLine(editor, caret, goToLineCommand, lineRange))
|
|
||||||
val range = getTextRange(editor, caret, false)
|
val range = getTextRange(editor, caret, false)
|
||||||
val shift = line + 1 - editor.offsetToBufferPosition(range.startOffset).line
|
|
||||||
|
|
||||||
val text = editor.getText(range)
|
/*
|
||||||
|
FIXME: see VIM-2884. It's absolutely not the best way to resolve this bug
|
||||||
|
*/
|
||||||
|
caret.moveToOffset(range.startOffset)
|
||||||
|
|
||||||
|
val lineRange = getLineRange(editor, caret)
|
||||||
|
val line = min(editor.fileSize().toInt(), normalizeLine(editor, caret, goToLineCommand, lineRange))
|
||||||
|
val linesMoved = lineRange.endLine - lineRange.startLine + 1
|
||||||
|
if (line < -1 || line + linesMoved >= editor.lineCount()) {
|
||||||
|
caret.moveToBufferPosition(caretPosition)
|
||||||
|
throw ExException("E16: Invalid range")
|
||||||
|
}
|
||||||
|
val shift = line + 1 - editor.offsetToBufferPosition(range.startOffset).line
|
||||||
|
|
||||||
val localMarks = injector.markService.getAllLocalMarks(caret)
|
val localMarks = injector.markService.getAllLocalMarks(caret)
|
||||||
.filter { range.contains(it.offset(editor)) }
|
.filter { range.contains(it.offset(editor)) }
|
||||||
@@ -69,24 +78,33 @@ public data class MoveTextCommand(val ranges: Ranges, val argument: String) : Co
|
|||||||
val selectionStartOffset = lastSelectionInfo.start?.let { editor.bufferPositionToOffset(it) }
|
val selectionStartOffset = lastSelectionInfo.start?.let { editor.bufferPositionToOffset(it) }
|
||||||
val selectionEndOffset = lastSelectionInfo.end?.let { editor.bufferPositionToOffset(it) }
|
val selectionEndOffset = lastSelectionInfo.end?.let { editor.bufferPositionToOffset(it) }
|
||||||
|
|
||||||
editor.deleteString(range)
|
val text = editor.getText(range)
|
||||||
|
|
||||||
val textData = PutData.TextData(text, SelectionType.LINE_WISE, emptyList(), null)
|
val textData = PutData.TextData(text, SelectionType.LINE_WISE, emptyList(), null)
|
||||||
val putData = PutData(
|
|
||||||
textData,
|
val dropNewLineInEnd = (line + linesMoved == editor.lineCount() - 1 && text.last() == '\n') ||
|
||||||
null,
|
(lineRange.endLine == editor.lineCount() - 1)
|
||||||
1,
|
|
||||||
insertTextBeforeCaret = false,
|
editor.deleteString(range)
|
||||||
rawIndent = true,
|
val putData = if (line == -1) {
|
||||||
caretAfterInsertedText = false,
|
caret.moveToOffset(0)
|
||||||
putToLine = line
|
PutData(textData, null, 1, insertTextBeforeCaret = true, rawIndent = true, caretAfterInsertedText = false)
|
||||||
)
|
} else {
|
||||||
|
PutData(textData, null, 1, insertTextBeforeCaret = false, rawIndent = true, caretAfterInsertedText = false, putToLine = line)
|
||||||
|
}
|
||||||
injector.put.putTextForCaret(editor, caret, context, putData)
|
injector.put.putTextForCaret(editor, caret, context, putData)
|
||||||
|
|
||||||
|
if (dropNewLineInEnd) {
|
||||||
|
assert(editor.text().last() == '\n')
|
||||||
|
editor.deleteString(TextRange(editor.text().length - 1, editor.text().length))
|
||||||
|
}
|
||||||
|
|
||||||
globalMarks.forEach { shiftGlobalMark(editor, it, shift) }
|
globalMarks.forEach { shiftGlobalMark(editor, it, shift) }
|
||||||
localMarks.forEach { shiftLocalMark(caret, it, shift) }
|
localMarks.forEach { shiftLocalMark(caret, it, shift) }
|
||||||
shiftSelectionInfo(caret, selectionStartOffset, selectionEndOffset, lastSelectionInfo, shift, range)
|
shiftSelectionInfo(caret, selectionStartOffset, selectionEndOffset, lastSelectionInfo, shift, range)
|
||||||
|
|
||||||
|
val newCaretPosition = shiftBufferPosition(caretPosition, shift)
|
||||||
|
caret.moveToBufferPosition(newCaretPosition)
|
||||||
|
|
||||||
return ExecutionResult.Success
|
return ExecutionResult.Success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user