1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-08-17 16:31:45 +02:00

Compare commits

...

18 Commits
0.62 ... 0.64

Author SHA1 Message Date
Alex Plate
c656da5c75 Prepare to 0.64 release 2020-12-23 09:49:45 +03:00
Alex Plate
dcedf6abca Mute another broken test 2020-12-18 15:03:25 +03:00
Alex Plate
849a71bdac Update changes 2020-12-18 13:18:08 +03:00
Alex Plate
534cc1d1fe Disable broken test 2020-12-18 12:26:10 +03:00
Alex Plate
40ec6c53fa Revert "Add statistic collection for some options"
Classes of the collector are incompatible with 202

This reverts commit b7cb3c09
2020-12-18 11:57:06 +03:00
Alex Plate
b7cb3c0945 Add statistic collection for some options 2020-12-17 23:13:54 +03:00
Alex Plate
69d3c7b754 resetCaset function should not change the shape of other editors
This commit fixes the following issues:
1) Windows splitting
- Start insert mode in editor
- Split editor
- Go back to the previous editor. The caret has a block shape, but insert mode

2) VCS updates
In 2021.1 VCS creates a diff window right after the file was changed.
So, the case described above happens here as well.
2020-12-17 10:53:43 +03:00
Alex Plate
542f11804e Update detekt baseline 2020-12-17 10:14:11 +03:00
Alex Plate
8526054aa8 Update changes 2020-12-17 10:05:04 +03:00
Alex Plate
93700bddc7 Update deprecated methods according to the new minimal IJ requirements 2020-12-17 10:04:52 +03:00
Matt Ellis
494500041b Rearrange and document the public search API
No code changes, just moved everything
2020-12-17 10:02:16 +03:00
Matt Ellis
011a5a3b23 Remove unnecessary UNSET direction enum value 2020-12-17 10:02:16 +03:00
Matt Ellis
03726858f0 Move find methods to SearchHelper 2020-12-17 10:02:16 +03:00
Alex Plate
c8c42cc4b2 Update plugin verifier versions 2020-12-16 13:00:32 +03:00
Alex Plate
0b22b454e6 Prepare to 0.63 release 2020-12-16 12:56:25 +03:00
vladimir.petrenko
f4fe03c582 CWM-927 disable vim for client's hidden editor on host
to provide compatibility with Code With Me plugin
2020-12-16 12:27:34 +03:00
Alex Plate
964e87fd6a Update minimap IJ version to 202 2020-12-16 11:39:49 +03:00
Alex Plate
ec4c0a0d0d Update teamcity configurations to deprecate 201 branch 2020-12-16 11:38:52 +03:00
30 changed files with 1096 additions and 813 deletions

View File

@@ -18,7 +18,7 @@
<ID>LongMethod:HistoryHandler.kt$HistoryHandler$override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean</ID> <ID>LongMethod:HistoryHandler.kt$HistoryHandler$override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean</ID>
<ID>LongMethod:OptionsManager.kt$OptionsManager$ fun parseOptionLine(editor: Editor?, args: String, failOnBad: Boolean): Boolean</ID> <ID>LongMethod:OptionsManager.kt$OptionsManager$ fun parseOptionLine(editor: Editor?, args: String, failOnBad: Boolean): Boolean</ID>
<ID>LongMethod:VimMultipleCursorsExtension.kt$VimMultipleCursorsExtension.NextOccurrenceHandler$override fun executeInWriteAction(editor: Editor, context: DataContext)</ID> <ID>LongMethod:VimMultipleCursorsExtension.kt$VimMultipleCursorsExtension.NextOccurrenceHandler$override fun executeInWriteAction(editor: Editor, context: DataContext)</ID>
<ID>LoopWithTooManyJumpStatements:SearchHighlightsHelper.kt$for (project in projectManager.openProjects) { val current = FileEditorManager.getInstance(project).selectedTextEditor ?: continue // [VERSION UPDATE] 202+ Use editors val editors = EditorFactory.getInstance().getEditors(current.document, project) ?: continue for (editor in editors) { // Try to keep existing highlights if possible. Update if hlsearch has changed or if the pattern has changed. // Force update for the situations where the text is the same, but the ignore case values have changed. // E.g. Use `*` to search for a word (which ignores smartcase), then use `/&lt;Up&gt;` to search for the same pattern, // which will match smartcase. Or changing the smartcase/ignorecase settings if (shouldRemoveSearchHighlights(editor, pattern, showHighlights) || forceUpdate) { removeSearchHighlights(editor) } if (pattern == null) continue if (shouldAddAllSearchHighlights(editor, pattern, showHighlights)) { // hlsearch (+ incsearch/noincsearch) val startLine = searchRange?.startLine ?: 0 val endLine = searchRange?.endLine ?: -1 val results = SearchGroup.findAll(editor, pattern, startLine, endLine, shouldIgnoreCase(pattern, shouldIgnoreSmartCase)) if (results.isNotEmpty()) { currentMatchOffset = findClosestMatch(editor, results, initialOffset, forwards) highlightSearchResults(editor, pattern, results, currentMatchOffset) } editor.vimLastSearch = pattern } else if (shouldAddCurrentMatchSearchHighlight(pattern, showHighlights, initialOffset)) { // nohlsearch + incsearch val searchOptions = EnumSet.of(SearchOptions.WHOLE_FILE) if (wrapscan.isSet) searchOptions.add(SearchOptions.WRAP) if (shouldIgnoreSmartCase) searchOptions.add(SearchOptions.IGNORE_SMARTCASE) if (!forwards) searchOptions.add(SearchOptions.BACKWARDS) val result = SearchGroup.findIt(editor, pattern, initialOffset, 1, searchOptions) if (result != null) { currentMatchOffset = result.startOffset val results = listOf(result) highlightSearchResults(editor, pattern, results, currentMatchOffset) } } else if (shouldMaintainCurrentMatchOffset(pattern, initialOffset)) { // incsearch. If nothing has changed (e.g. we've edited offset values in `/foo/e+2`) make sure we return the // current match offset so the caret remains at the current incsarch match val offset = editor.vimIncsearchCurrentMatchOffset if (offset != null) { currentMatchOffset = offset } } } }</ID> <ID>LoopWithTooManyJumpStatements:SearchHighlightsHelper.kt$for (project in projectManager.openProjects) { val current = FileEditorManager.getInstance(project).selectedTextEditor ?: continue // [VERSION UPDATE] 202+ Use editors val editors = EditorFactory.getInstance().getEditors(current.document, project) ?: continue for (editor in editors) { // Try to keep existing highlights if possible. Update if hlsearch has changed or if the pattern has changed. // Force update for the situations where the text is the same, but the ignore case values have changed. // E.g. Use `*` to search for a word (which ignores smartcase), then use `/&lt;Up&gt;` to search for the same pattern, // which will match smartcase. Or changing the smartcase/ignorecase settings if (shouldRemoveSearchHighlights(editor, pattern, showHighlights) || forceUpdate) { removeSearchHighlights(editor) } if (pattern == null) continue if (shouldAddAllSearchHighlights(editor, pattern, showHighlights)) { // hlsearch (+ incsearch/noincsearch) val startLine = searchRange?.startLine ?: 0 val endLine = searchRange?.endLine ?: -1 val results = SearchHelper.findAll(editor, pattern, startLine, endLine, shouldIgnoreCase(pattern, shouldIgnoreSmartCase)) if (results.isNotEmpty()) { currentMatchOffset = findClosestMatch(editor, results, initialOffset, forwards) highlightSearchResults(editor, pattern, results, currentMatchOffset) } editor.vimLastSearch = pattern } else if (shouldAddCurrentMatchSearchHighlight(pattern, showHighlights, initialOffset)) { // nohlsearch + incsearch val searchOptions = EnumSet.of(SearchOptions.WHOLE_FILE) if (wrapscan.isSet) searchOptions.add(SearchOptions.WRAP) if (shouldIgnoreSmartCase) searchOptions.add(SearchOptions.IGNORE_SMARTCASE) if (!forwards) searchOptions.add(SearchOptions.BACKWARDS) val result = SearchHelper.findPattern(editor, pattern, initialOffset, 1, searchOptions) if (result != null) { currentMatchOffset = result.startOffset val results = listOf(result) highlightSearchResults(editor, pattern, results, currentMatchOffset) } } else if (shouldMaintainCurrentMatchOffset(pattern, initialOffset)) { // incsearch. If nothing has changed (e.g. we've edited offset values in `/foo/e+2`) make sure we return the // current match offset so the caret remains at the current incsarch match val offset = editor.vimIncsearchCurrentMatchOffset if (offset != null) { currentMatchOffset = offset } } } }</ID>
<ID>MagicNumber:ActionListHandler.kt$ActionListHandler$50</ID> <ID>MagicNumber:ActionListHandler.kt$ActionListHandler$50</ID>
<ID>MagicNumber:AddBlockInlaysAction.kt$AddBlockInlaysAction$0.9f</ID> <ID>MagicNumber:AddBlockInlaysAction.kt$AddBlockInlaysAction$0.9f</ID>
<ID>MagicNumber:AddBlockInlaysAction.kt$AddBlockInlaysAction$1.75f</ID> <ID>MagicNumber:AddBlockInlaysAction.kt$AddBlockInlaysAction$1.75f</ID>
@@ -38,7 +38,6 @@
<ID>MagicNumber:CommandBuilder.kt$CommandBuilder$999999999</ID> <ID>MagicNumber:CommandBuilder.kt$CommandBuilder$999999999</ID>
<ID>MagicNumber:ConfigurationMigrators.kt$Version 6 to 7 config migration$6</ID> <ID>MagicNumber:ConfigurationMigrators.kt$Version 6 to 7 config migration$6</ID>
<ID>MagicNumber:ConfigurationMigrators.kt$Version 6 to 7 config migration$7</ID> <ID>MagicNumber:ConfigurationMigrators.kt$Version 6 to 7 config migration$7</ID>
<ID>MagicNumber:EditorHelper.kt$10</ID>
<ID>MagicNumber:ExKeyBindings.kt$ExKeyBindings$0x05</ID> <ID>MagicNumber:ExKeyBindings.kt$ExKeyBindings$0x05</ID>
<ID>MagicNumber:ExKeyBindings.kt$ExKeyBindings$0x08</ID> <ID>MagicNumber:ExKeyBindings.kt$ExKeyBindings$0x08</ID>
<ID>MagicNumber:HistoryHandler.kt$HistoryHandler$7</ID> <ID>MagicNumber:HistoryHandler.kt$HistoryHandler$7</ID>
@@ -65,8 +64,7 @@
<ID>MagicNumber:VimHighlightedYank.kt$VimHighlightedYank.HighlightHandler$3</ID> <ID>MagicNumber:VimHighlightedYank.kt$VimHighlightedYank.HighlightHandler$3</ID>
<ID>MagicNumber:VimHighlightedYank.kt$VimHighlightedYank.HighlightHandler$4</ID> <ID>MagicNumber:VimHighlightedYank.kt$VimHighlightedYank.HighlightHandler$4</ID>
<ID>MatchingDeclarationName:CommandDefinition.kt$CommandName</ID> <ID>MatchingDeclarationName:CommandDefinition.kt$CommandName</ID>
<ID>MatchingDeclarationName:SearchHelperKt.kt$Direction</ID> <ID>MaxLineLength:ExBeanClass.kt$ExBeanClass$logger&lt;ExBeanClass&gt;().error("IdeaVim doesn't accept contributions to `vimActions` extension points. Please create a plugin using `VimExtension`. Plugin to blame: ${this.pluginDescriptor.pluginId}")</ID>
<ID>MaxLineLength:ExBeanClass.kt$ExBeanClass$logger&lt;ExBeanClass&gt;().error("IdeaVim doesn't accept contributions to `vimActions` extension points. Please create a plugin using `VimExtension`. Plugin to blame: $pluginId")</ID>
<ID>MaxLineLength:ExRanges.kt$SearchRange$override</ID> <ID>MaxLineLength:ExRanges.kt$SearchRange$override</ID>
<ID>MaxLineLength:NotificationService.kt$NotificationService$notification.addAction(AppendToIdeaVimRcAction(notification, "set clipboard+=ideaput", "ideaput") { OptionsManager.clipboard.append(ClipboardOptionsData.ideaput) })</ID> <ID>MaxLineLength:NotificationService.kt$NotificationService$notification.addAction(AppendToIdeaVimRcAction(notification, "set clipboard+=ideaput", "ideaput") { OptionsManager.clipboard.append(ClipboardOptionsData.ideaput) })</ID>
<ID>MaxLineLength:NotificationService.kt$NotificationService.AppendToIdeaVimRcAction$private inner</ID> <ID>MaxLineLength:NotificationService.kt$NotificationService.AppendToIdeaVimRcAction$private inner</ID>

View File

@@ -18,6 +18,7 @@ import _Self.buildTypes.TestsForIntelliJEAP
import _Self.vcsRoots.Branch_181 import _Self.vcsRoots.Branch_181
import _Self.vcsRoots.Branch_183 import _Self.vcsRoots.Branch_183
import _Self.vcsRoots.Branch_191_193 import _Self.vcsRoots.Branch_191_193
import _Self.vcsRoots.Branch_201
import _Self.vcsRoots.GitHubPullRequest import _Self.vcsRoots.GitHubPullRequest
import jetbrains.buildServer.configs.kotlin.v2019_2.Project import jetbrains.buildServer.configs.kotlin.v2019_2.Project
@@ -26,15 +27,15 @@ object Project : Project({
vcsRoot(Branch_183) vcsRoot(Branch_183)
vcsRoot(Branch_181) vcsRoot(Branch_181)
vcsRoot(GitHubPullRequest)
vcsRoot(Branch_191_193) vcsRoot(Branch_191_193)
vcsRoot(Branch_201)
vcsRoot(GitHubPullRequest)
buildType(GitHubPullRequests) buildType(GitHubPullRequests)
buildType(Release) buildType(Release)
buildType(ReleaseEap) buildType(ReleaseEap)
buildType(TestsForIntelliJ20201)
buildType(TestsForIntelliJ20202) buildType(TestsForIntelliJ20202)
buildType(TestsForIntelliJ20203) buildType(TestsForIntelliJ20203)
buildType(TestsForIntelliJEAP) buildType(TestsForIntelliJEAP)
@@ -42,6 +43,7 @@ object Project : Project({
buildType(Nvim) buildType(Nvim)
buildType(PluginVerifier) buildType(PluginVerifier)
buildType(TestsForIntelliJ20201)
buildType(TestsForIntelliJ20191) buildType(TestsForIntelliJ20191)
buildType(TestsForIntelliJ20181) buildType(TestsForIntelliJ20181)
buildType(TestsForIntelliJ20192) buildType(TestsForIntelliJ20192)

View File

@@ -43,4 +43,3 @@ sealed class ActiveTests(buildName: String, ijVersion: String) : BuildType({
object TestsForIntelliJEAP : ActiveTests("Tests for IntelliJ Latest EAP", "LATEST-EAP-SNAPSHOT") object TestsForIntelliJEAP : ActiveTests("Tests for IntelliJ Latest EAP", "LATEST-EAP-SNAPSHOT")
object TestsForIntelliJ20203 : ActiveTests("Tests for IntelliJ 2020.3", "2020.3") object TestsForIntelliJ20203 : ActiveTests("Tests for IntelliJ 2020.3", "2020.3")
object TestsForIntelliJ20202 : ActiveTests("Tests for IntelliJ 2020.2", "2020.2") object TestsForIntelliJ20202 : ActiveTests("Tests for IntelliJ 2020.2", "2020.2")
object TestsForIntelliJ20201 : ActiveTests("Tests for IntelliJ 2020.1", "2020.1")

View File

@@ -10,7 +10,7 @@ object Release : BuildType({
description = "Build and publish IdeaVim plugin" description = "Build and publish IdeaVim plugin"
artifactRules = "build/distributions/*" artifactRules = "build/distributions/*"
buildNumberPattern = "0.62" buildNumberPattern = "0.64"
params { params {
param("env.ORG_GRADLE_PROJECT_ideaVersion", "2020.2") param("env.ORG_GRADLE_PROJECT_ideaVersion", "2020.2")

View File

@@ -13,7 +13,7 @@ object ReleaseEap : BuildType({
description = "Build and publish EAP of IdeaVim plugin" description = "Build and publish EAP of IdeaVim plugin"
artifactRules = "build/distributions/*" artifactRules = "build/distributions/*"
buildNumberPattern = "0.62.%build.counter%" buildNumberPattern = "0.64.%build.counter%"
params { params {
param("env.ORG_GRADLE_PROJECT_ideaVersion", "2020.2") param("env.ORG_GRADLE_PROJECT_ideaVersion", "2020.2")

View File

@@ -0,0 +1,46 @@
@file:Suppress("ClassName")
package _Self.buildTypes
import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType
import jetbrains.buildServer.configs.kotlin.v2019_2.CheckoutMode
import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.gradle
import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.vcs
sealed class TestsForIntelliJ_201_branch(private val version: String) : BuildType({
name = "Tests for IntelliJ $version"
params {
param("env.ORG_GRADLE_PROJECT_downloadIdeaSources", "false")
param("env.ORG_GRADLE_PROJECT_ideaVersion", "IC-$version")
param("env.ORG_GRADLE_PROJECT_instrumentPluginCode", "false")
param("env.ORG_GRADLE_PROJECT_javaVersion", "1.8")
}
vcs {
root(_Self.vcsRoots.Branch_201)
checkoutMode = CheckoutMode.ON_SERVER
}
steps {
gradle {
tasks = "clean test"
buildFile = ""
enableStacktrace = true
param("org.jfrog.artifactory.selectedDeployableServer.defaultModuleVersionConfiguration", "GLOBAL")
}
}
triggers {
vcs {
branchFilter = ""
}
}
requirements {
noLessThanVer("teamcity.agent.jvm.version", "1.8")
}
})
object TestsForIntelliJ20201 : TestsForIntelliJ_201_branch("2020.1")

12
.teamcity/_Self/vcsRoots/Branch_201.kt vendored Normal file
View File

@@ -0,0 +1,12 @@
@file:Suppress("ClassName")
package _Self.vcsRoots
import jetbrains.buildServer.configs.kotlin.v2019_2.vcs.GitVcsRoot
object Branch_201 : GitVcsRoot({
name = "https://github.com/JetBrains/ideavim (branch 201)"
url = "https://github.com/JetBrains/ideavim.git"
branch = "201"
useMirrors = false
})

View File

@@ -335,6 +335,10 @@ Contributors:
[![icon][github]](https://github.com/shaunpatterson) [![icon][github]](https://github.com/shaunpatterson)
&nbsp; &nbsp;
Shaun Patterson Shaun Patterson
* [![icon][mail]](mailto:vladimir.petrenko@jetbrains.com)
[![icon][github]](https://github.com/vladimir-petrenko)
&nbsp;
Vladimir Petrenko
If you are a contributor and your name is not listed here, feel free to If you are a contributor and your name is not listed here, feel free to
contact the maintainers. contact the maintainers.

View File

@@ -22,6 +22,25 @@ It is important to distinguish EAP from traditional pre-release software.
Please note that the quality of EAP versions may at times be way below even Please note that the quality of EAP versions may at times be way below even
usual beta standards. usual beta standards.
## 0.64, 2020-12-23
### Merged PRs:
* [260](https://github.com/JetBrains/ideavim/pull/260) by [Matt Ellis](https://github.com/citizenmatt): Refactor SearchGroup
### Fixes:
* [VIM-2194](https://youtrack.jetbrains.com/issue/VIM-2194) Fix caret shape during editing a new file
## 0.63, 2020-12-16
### Changes:
* Update the minimal required IJ version: 2020.2+
### Fixes:
* [CWM-927](https://youtrack.jetbrains.com/issue/CWM-927) Fix typing for CodeWithMe and IdeaVim
### Merged PRs:
* [259](https://github.com/JetBrains/ideavim/pull/259) by [Vladimir Petrenko](https://github.com/vladimir-petrenko): CWM-927 disable vim for client's hidden editor on host
## 0.62, 2020-12-15 ## 0.62, 2020-12-15
### Features: ### Features:

View File

@@ -59,7 +59,7 @@ runIdeForUiTests {
} }
runPluginVerifier { runPluginVerifier {
ideVersions = ["IC-2020.1.4", "IC-2020.2.3"] ideVersions = ["IC-2020.2.3", "IC-2020.3"]
downloadDirectory = "${project.buildDir}/pluginVerifier/ides" downloadDirectory = "${project.buildDir}/pluginVerifier/ides"
teamCityOutputFormat = true teamCityOutputFormat = true
} }

View File

@@ -2,63 +2,20 @@
<name>IdeaVim</name> <name>IdeaVim</name>
<id>IdeaVIM</id> <id>IdeaVIM</id>
<change-notes><![CDATA[ <change-notes><![CDATA[
<h3>Features:</h3> <h3>Merged PRs:</h3>
<ul> <ul>
<li>Support <code>unmap</code> and <code>mapclear</code> commands <a <li>
href="https://youtrack.jetbrains.com/issue/VIM-1491">VIM-1491</a></li> <a href="https://github.com/JetBrains/ideavim/pull/260">260</a>
<li>Support mappings in ex panel (<code>cmap</code>) <a by <a href="https://github.com/citizenmatt">Matt Ellis</a>: Refactor SearchGroup
href="https://youtrack.jetbrains.com/issue/VIM-1227">VIM-1227</a></li> </li>
</ul>
<h3>Changes:</h3>
<ul>
<li><code>octal</code> is now disabled by default for <code>nrformats</code>. <a
href="https://youtrack.jetbrains.com/issue/VIM-2181">VIM-2181</a></li>
</ul> </ul>
<h3>Fixes:</h3> <h3>Fixes:</h3>
<ul> <ul>
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2113">VIM-2113</a> Fix <code>cit</code> for empty tags</li> <li>
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2114">VIM-2114</a> Unnamed register isn't changed after deleting <a href="https://youtrack.jetbrains.com/issue/VIM-2194">VIM-2194</a>
empty tag Fix caret shape during editing a new file
</li> </li>
<li><a href="https://youtrack.jetbrains.com/issue/VIM-1475">VIM-1475</a> Enable block caret to be used in insert mode.
</li>
<li><a href="https://youtrack.jetbrains.com/issue/VIM-2170">VIM-2170</a> Fix an alternative range format for
<code>s</code> command
</li>
<li><a href="https://youtrack.jetbrains.com/issue/VIM-1913">VIM-1913</a>
<a href="https://youtrack.jetbrains.com/issue/VIM-2154">VIM-2154</a> Several fixes for AppCode templates
</li>
<li><a href="https://youtrack.jetbrains.com/issue/VIM-1756">VIM-1756</a> Fix startsel from insert mode</li>
</ul>
<h3>Merged PRs:</h3>
<ul>
<li><a href="https://github.com/JetBrains/ideavim/pull/249">249</a> by <a href="https://github.com/jpalus">Jan
Palus</a>: VIM-2113 Increase tag range only in visual mode
</li>
<li><a href="https://github.com/JetBrains/ideavim/pull/250">250</a> by <a href="https://github.com/jpalus">Jan
Palus</a>: VIM-2114 Do not override registers when deleting empty range
</li>
<li><a href="https://github.com/JetBrains/ideavim/pull/256">256</a> by <a href="https://github.com/brandoncc">Brandon
Conway</a>: Fix typo
</li>
<li><a href="https://github.com/JetBrains/ideavim/pull/254">254</a> by <a href="https://github.com/antekone">Grzegorz
Antoniak</a>: VIM-1475: Add an option to use block caret in insert mode
</li>
<li><a href="https://github.com/JetBrains/ideavim/pull/225">225</a> by <a href="https://github.com/sumoooru2">sumoooru2</a>:
Implement cmap
</li>
<li><a href="https://github.com/JetBrains/ideavim/pull/258">258</a> by <a href="https://github.com/citizenmatt">Matt
Ellis</a>: Show the correct handler class in :map
</li>
<li><a href="https://github.com/JetBrains/ideavim/pull/257">257</a> by <a href="https://github.com/citizenmatt">Matt
Ellis</a>: Extract SearchHighlightsHelper from SearchGroup
</li>
<li><a href="https://github.com/JetBrains/ideavim/pull/251">251</a> by <a href="https://github.com/shaunpatterson">Shaun
Patterson</a>: VIM-1756: startSel works in insert mode
</li>
</ul> </ul>
]]> ]]>
</change-notes> </change-notes>
@@ -79,7 +36,7 @@
<!-- 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 -->
<idea-version since-build="201.5985.41"/> <idea-version since-build="202.5103.13"/>
<!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform --> <!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform -->
<depends>com.intellij.modules.lang</depends> <depends>com.intellij.modules.lang</depends>

View File

@@ -45,8 +45,8 @@ import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
import com.maddyhome.idea.vim.helper.*; import com.maddyhome.idea.vim.helper.*;
import com.maddyhome.idea.vim.key.*; import com.maddyhome.idea.vim.key.*;
import com.maddyhome.idea.vim.option.OptionsManager; import com.maddyhome.idea.vim.option.OptionsManager;
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel;
import com.maddyhome.idea.vim.ui.ShowCmd; import com.maddyhome.idea.vim.ui.ShowCmd;
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -692,7 +692,7 @@ public class KeyHandler {
@NotNull CommandNode node, @NotNull CommandNode node,
CommandState editorState) { CommandState editorState) {
// The user entered a valid command. Create the command and add it to the stack. // The user entered a valid command. Create the command and add it to the stack.
final EditorActionHandlerBase action = node.getActionHolder().getAction(); final EditorActionHandlerBase action = node.getActionHolder().getInstance();
final CommandBuilder commandBuilder = editorState.getCommandBuilder(); final CommandBuilder commandBuilder = editorState.getCommandBuilder();
final Argument.Type expectedArgumentType = commandBuilder.getExpectedArgumentType(); final Argument.Type expectedArgumentType = commandBuilder.getExpectedArgumentType();
@@ -739,7 +739,7 @@ public class KeyHandler {
} }
private boolean stopMacroRecord(CommandNode node, @NotNull CommandState editorState) { private boolean stopMacroRecord(CommandNode node, @NotNull CommandState editorState) {
return editorState.isRecording() && node.getActionHolder().getAction() instanceof ToggleRecordingAction; return editorState.isRecording() && node.getActionHolder().getInstance() instanceof ToggleRecordingAction;
} }
private void startWaitingForArgument(Editor editor, private void startWaitingForArgument(Editor editor,

View File

@@ -53,7 +53,7 @@ public class RegisterActions {
public static @Nullable EditorActionHandlerBase findAction(@NotNull String id) { public static @Nullable EditorActionHandlerBase findAction(@NotNull String id) {
return VIM_ACTIONS_EP.extensions().filter(vimActionBean -> vimActionBean.getActionId().equals(id)).findFirst() return VIM_ACTIONS_EP.extensions().filter(vimActionBean -> vimActionBean.getActionId().equals(id)).findFirst()
.map(ActionBeanClass::getAction).orElse(null); .map(ActionBeanClass::getInstance).orElse(null);
} }
public static @NotNull EditorActionHandlerBase findActionOrDie(@NotNull String id) { public static @NotNull EditorActionHandlerBase findActionOrDie(@NotNull String id) {

View File

@@ -24,7 +24,6 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.ThrowableComputable;
import com.maddyhome.idea.vim.VimPlugin; import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.SelectionType;
import com.maddyhome.idea.vim.common.Register; import com.maddyhome.idea.vim.common.Register;
import com.maddyhome.idea.vim.ex.handler.GotoLineHandler; import com.maddyhome.idea.vim.ex.handler.GotoLineHandler;
import com.maddyhome.idea.vim.ex.ranges.Range; import com.maddyhome.idea.vim.ex.ranges.Range;
@@ -209,7 +208,7 @@ public class CommandParser {
} }
} }
final ExBeanClass handlerHolder = node.getCommandHandler(); final ExBeanClass handlerHolder = node.getCommandHandler();
return handlerHolder != null ? handlerHolder.getHandler() : null; return handlerHolder != null ? handlerHolder.getInstance() : null;
} }
/** /**
@@ -557,8 +556,8 @@ public class CommandParser {
if (handlerHolder.getNames() != null) { if (handlerHolder.getNames() != null) {
names = CommandDefinitionKt.commands(handlerHolder.getNames().split(",")); names = CommandDefinitionKt.commands(handlerHolder.getNames().split(","));
} }
else if (handlerHolder.getHandler() instanceof ComplicatedNameExCommand) { else if (handlerHolder.getInstance() instanceof ComplicatedNameExCommand) {
names = ((ComplicatedNameExCommand)handlerHolder.getHandler()).getNames(); names = ((ComplicatedNameExCommand)handlerHolder.getInstance()).getNames();
} }
else { else {
throw new RuntimeException("Cannot create an ex command: " + handlerHolder); throw new RuntimeException("Cannot create an ex command: " + handlerHolder);

View File

@@ -18,29 +18,23 @@
package com.maddyhome.idea.vim.ex package com.maddyhome.idea.vim.ex
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.extensions.AbstractExtensionPointBean import com.intellij.serviceContainer.BaseKeyedLazyInstance
import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Attribute
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
// [Version Update] 202+ class ExBeanClass : BaseKeyedLazyInstance<CommandHandler>() {
@Suppress("DEPRECATION")
class ExBeanClass : AbstractExtensionPointBean() {
@Attribute("implementation") @Attribute("implementation")
var implementation: String? = null var implementation: String? = null
@Attribute("names") @Attribute("names")
var names: String? = null var names: String? = null
val handler: CommandHandler by lazy { override fun getImplementationClassName(): String? = implementation
this.instantiateClass<CommandHandler>(
implementation ?: "", ApplicationManager.getApplication().picoContainer)
}
fun register() { fun register() {
if (pluginId != VimPlugin.getPluginId()) { if (this.pluginDescriptor.pluginId != VimPlugin.getPluginId()) {
logger<ExBeanClass>().error("IdeaVim doesn't accept contributions to `vimActions` extension points. Please create a plugin using `VimExtension`. Plugin to blame: $pluginId") logger<ExBeanClass>().error("IdeaVim doesn't accept contributions to `vimActions` extension points. Please create a plugin using `VimExtension`. Plugin to blame: ${this.pluginDescriptor.pluginId}")
return return
} }
CommandParser.getInstance().addHandler(this) CommandParser.getInstance().addHandler(this)

View File

@@ -18,19 +18,13 @@
package com.maddyhome.idea.vim.extension package com.maddyhome.idea.vim.extension
import com.intellij.openapi.application.ApplicationManager import com.intellij.serviceContainer.BaseKeyedLazyInstance
import com.intellij.openapi.extensions.AbstractExtensionPointBean
import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Attribute
import com.intellij.util.xmlb.annotations.Tag import com.intellij.util.xmlb.annotations.Tag
import com.intellij.util.xmlb.annotations.XCollection import com.intellij.util.xmlb.annotations.XCollection
import java.util.concurrent.atomic.AtomicBoolean
// [Version Update] 202+ class ExtensionBeanClass : BaseKeyedLazyInstance<VimExtension>() {
@Suppress("DEPRECATION")
class ExtensionBeanClass : AbstractExtensionPointBean() {
init {
println()
}
@Attribute("implementation") @Attribute("implementation")
var implementation: String? = null var implementation: String? = null
@@ -46,14 +40,7 @@ class ExtensionBeanClass : AbstractExtensionPointBean() {
@XCollection @XCollection
var aliases: List<Alias>? = null var aliases: List<Alias>? = null
var initialized = AtomicBoolean(false) override fun getImplementationClassName(): String? = implementation
val handler: VimExtension by lazy {
initialized.set(true)
this.instantiateClass<VimExtension>(
implementation ?: "", ApplicationManager.getApplication().picoContainer
)
}
} }
@Tag("alias") @Tag("alias")

View File

@@ -41,9 +41,7 @@ object VimExtensionRegistrar {
VimExtension.EP_NAME.extensions.forEach(this::registerExtension) VimExtension.EP_NAME.extensions.forEach(this::registerExtension)
// [VERSION UPDATE] 202+ VimExtension.EP_NAME.point.addExtensionPointListener(object : ExtensionPointListener<ExtensionBeanClass> {
@Suppress("DEPRECATION")
VimExtension.EP_NAME.getPoint(null).addExtensionPointListener(object : ExtensionPointListener<ExtensionBeanClass> {
override fun extensionAdded(extension: ExtensionBeanClass, pluginDescriptor: PluginDescriptor) { override fun extensionAdded(extension: ExtensionBeanClass, pluginDescriptor: PluginDescriptor) {
registerExtension(extension) registerExtension(extension)
} }
@@ -56,7 +54,7 @@ object VimExtensionRegistrar {
@Synchronized @Synchronized
private fun registerExtension(extensionBean: ExtensionBeanClass) { private fun registerExtension(extensionBean: ExtensionBeanClass) {
val name = extensionBean.name ?: extensionBean.handler.name val name = extensionBean.name ?: extensionBean.instance.name
if (name in registeredExtensions) return if (name in registeredExtensions) return
registeredExtensions.add(name) registeredExtensions.add(name)
@@ -64,10 +62,10 @@ object VimExtensionRegistrar {
val option = ToggleOption(name, name, false) val option = ToggleOption(name, name, false)
option.addOptionChangeListener { _, _ -> option.addOptionChangeListener { _, _ ->
if (isSet(name)) { if (isSet(name)) {
extensionBean.handler.init() extensionBean.instance.init()
logger.info("IdeaVim extension '$name' initialized") logger.info("IdeaVim extension '$name' initialized")
} else { } else {
extensionBean.handler.dispose() extensionBean.instance.dispose()
} }
} }
addOption(option) addOption(option)
@@ -75,13 +73,11 @@ object VimExtensionRegistrar {
@Synchronized @Synchronized
private fun unregisterExtension(extension: ExtensionBeanClass) { private fun unregisterExtension(extension: ExtensionBeanClass) {
val name = extension.name ?: extension.handler.name val name = extension.name ?: extension.instance.name
if (name !in registeredExtensions) return if (name !in registeredExtensions) return
registeredExtensions.remove(name) registeredExtensions.remove(name)
removeAliases(extension) removeAliases(extension)
if (extension.initialized.get()) { extension.instance.dispose()
extension.handler.dispose()
}
removeOption(name) removeOption(name)
remove(name) remove(name)
logger.info("IdeaVim extension '$name' disposed") logger.info("IdeaVim extension '$name' disposed")
@@ -95,7 +91,7 @@ object VimExtensionRegistrar {
private fun registerAliases(extension: ExtensionBeanClass) { private fun registerAliases(extension: ExtensionBeanClass) {
extension.aliases extension.aliases
?.mapNotNull { it.name } ?.mapNotNull { it.name }
?.forEach { alias -> extensionAliases[alias] = extension.name ?: extension.handler.name } ?.forEach { alias -> extensionAliases[alias] = extension.name ?: extension.instance.name }
} }
private fun removeAliases(extension: ExtensionBeanClass) { private fun removeAliases(extension: ExtensionBeanClass) {

View File

@@ -1765,27 +1765,7 @@ public class ChangeGroup {
} }
public static void resetCaret(@NotNull Editor editor, boolean insert) { public static void resetCaret(@NotNull Editor editor, boolean insert) {
Document doc = editor.getDocument(); editor.getSettings().setBlockCursor(!insert);
VirtualFile vf = FileDocumentManager.getInstance().getFile(doc);
if (vf != null) {
resetCaret(vf, editor.getProject(), insert);
}
else {
editor.getSettings().setBlockCursor(!insert);
}
}
private static void resetCaret(@NotNull VirtualFile virtualFile, Project proj, boolean insert) {
logger.debug("Reset caret to a " + (insert ? "non-block" : "block") + " shape");
Document doc = FileDocumentManager.getInstance().getDocument(virtualFile);
if (doc == null) return; // Must be no text editor (such as image)
Editor[] editors = EditorFactory.getInstance().getEditors(doc, proj);
if (logger.isDebugEnabled()) {
logger.debug("There are " + editors.length + " editors for virtual file " + virtualFile.getName());
}
for (Editor editor : editors) {
editor.getSettings().setBlockCursor(!insert);
}
} }
/** /**

View File

@@ -307,17 +307,17 @@ public class KeyGroup implements PersistentStateComponent<Element> {
public void registerCommandAction(@NotNull ActionBeanClass actionHolder) { public void registerCommandAction(@NotNull ActionBeanClass actionHolder) {
if (!VimPlugin.getPluginId().equals(actionHolder.getPluginId())) { if (!VimPlugin.getPluginId().equals(actionHolder.getPluginDescriptor().getPluginId())) {
logger.error("IdeaVim doesn't accept contributions to `vimActions` extension points. " + logger.error("IdeaVim doesn't accept contributions to `vimActions` extension points. " +
"Please create a plugin using `VimExtension`. " + "Please create a plugin using `VimExtension`. " +
"Plugin to blame: " + "Plugin to blame: " +
actionHolder.getPluginId()); actionHolder.getPluginDescriptor().getPluginId());
return; return;
} }
Set<List<KeyStroke>> actionKeys = actionHolder.getParsedKeys(); Set<List<KeyStroke>> actionKeys = actionHolder.getParsedKeys();
if (actionKeys == null) { if (actionKeys == null) {
final EditorActionHandlerBase action = actionHolder.getAction(); final EditorActionHandlerBase action = actionHolder.getInstance();
if (action instanceof ComplicatedKeysAction) { if (action instanceof ComplicatedKeysAction) {
actionKeys = ((ComplicatedKeysAction)action).getKeyStrokesSet(); actionKeys = ((ComplicatedKeysAction)action).getKeyStrokesSet();
} }
@@ -337,7 +337,7 @@ public class KeyGroup implements PersistentStateComponent<Element> {
prefixes = new HashMap<>(); prefixes = new HashMap<>();
} }
for (List<KeyStroke> keys : actionKeys) { for (List<KeyStroke> keys : actionKeys) {
checkCommand(actionModes, actionHolder.getAction(), keys); checkCommand(actionModes, actionHolder.getInstance(), keys);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -18,8 +18,7 @@
package com.maddyhome.idea.vim.handler package com.maddyhome.idea.vim.handler
import com.intellij.openapi.application.ApplicationManager import com.intellij.serviceContainer.BaseKeyedLazyInstance
import com.intellij.openapi.extensions.AbstractExtensionPointBean
import com.intellij.util.SmartList import com.intellij.util.SmartList
import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Attribute
import com.maddyhome.idea.vim.command.MappingMode import com.maddyhome.idea.vim.command.MappingMode
@@ -47,9 +46,7 @@ import javax.swing.KeyStroke
* The reason is startup performance. Using the extension points you don't even have to load classes of actions. * The reason is startup performance. Using the extension points you don't even have to load classes of actions.
* So, all actions are loaded on demand, including classes in classloader. * So, all actions are loaded on demand, including classes in classloader.
*/ */
// [VERSION UPDATE] 202+ class ActionBeanClass : BaseKeyedLazyInstance<EditorActionHandlerBase>() {
@Suppress("DEPRECATION")
class ActionBeanClass : AbstractExtensionPointBean() {
@Attribute("implementation") @Attribute("implementation")
var implementation: String? = null var implementation: String? = null
@@ -61,17 +58,14 @@ class ActionBeanClass : AbstractExtensionPointBean() {
val actionId: String get() = implementation?.let { EditorActionHandlerBase.getActionId(it) } ?: "" val actionId: String get() = implementation?.let { EditorActionHandlerBase.getActionId(it) } ?: ""
val action: EditorActionHandlerBase by lazy {
this.instantiateClass<EditorActionHandlerBase>(
implementation ?: "", ApplicationManager.getApplication().picoContainer)
}
fun getParsedKeys(): Set<List<KeyStroke>>? { fun getParsedKeys(): Set<List<KeyStroke>>? {
val myKeys = keys ?: return null val myKeys = keys ?: return null
val escapedKeys = myKeys.splitByComma() val escapedKeys = myKeys.splitByComma()
return EditorActionHandlerBase.parseKeysSet(escapedKeys) return EditorActionHandlerBase.parseKeysSet(escapedKeys)
} }
override fun getImplementationClassName(): String? = implementation
fun getParsedModes(): Set<MappingMode>? { fun getParsedModes(): Set<MappingMode>? {
val myModes = modes ?: return null val myModes = modes ?: return null

View File

@@ -20,6 +20,7 @@
package com.maddyhome.idea.vim.helper package com.maddyhome.idea.vim.helper
import com.intellij.codeWithMe.ClientId
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
@@ -39,6 +40,7 @@ val Editor.fileSize: Int
val Editor.isIdeaVimDisabledHere: Boolean val Editor.isIdeaVimDisabledHere: Boolean
get() { get() {
return disabledInDialog return disabledInDialog
|| (!ClientId.isCurrentlyUnderLocalId) // CWM-927
|| (!OptionsManager.ideavimsupport.contains("singleline") && isDatabaseCell()) || (!OptionsManager.ideavimsupport.contains("singleline") && isDatabaseCell())
|| (!OptionsManager.ideavimsupport.contains("singleline") && isOneLineMode) || (!OptionsManager.ideavimsupport.contains("singleline") && isOneLineMode)
} }

View File

@@ -18,6 +18,7 @@
package com.maddyhome.idea.vim.helper; package com.maddyhome.idea.vim.helper;
import com.google.common.collect.Lists;
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;
@@ -29,10 +30,14 @@ 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.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.CommandState; import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.common.CharacterPosition;
import com.maddyhome.idea.vim.common.TextRange; import com.maddyhome.idea.vim.common.TextRange;
import com.maddyhome.idea.vim.option.ListOption; import com.maddyhome.idea.vim.option.ListOption;
import com.maddyhome.idea.vim.option.OptionsManager; import com.maddyhome.idea.vim.option.OptionsManager;
import com.maddyhome.idea.vim.regexp.CharPointer;
import com.maddyhome.idea.vim.regexp.RegExp;
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;
@@ -44,11 +49,357 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static com.maddyhome.idea.vim.helper.SearchHelperKtKt.checkInString; import static com.maddyhome.idea.vim.helper.SearchHelperKtKt.checkInString;
import static com.maddyhome.idea.vim.helper.SearchHelperKtKt.shouldIgnoreCase;
/** /**
* Helper methods for searching text * Helper methods for searching text
*/ */
public class SearchHelper { public class SearchHelper {
/**
* Find text matching the given pattern.
*
* @param editor The editor to search in
* @param pattern The pattern to search for
* @param startOffset The offset to start searching from
* @param count Find the nth next occurrence of the pattern. Must be 1 or greater.
* @param searchOptions A set of options, such as direction and wrap
* @return A TextRange representing the result, or null
*/
@Nullable
public static TextRange findPattern(@NotNull Editor editor,
@Nullable String pattern,
int startOffset,
int count,
EnumSet<SearchOptions> searchOptions) {
if (pattern == null || pattern.length() == 0) {
logger.warn("Pattern is null or empty. Cannot perform search");
return null;
}
Direction dir = searchOptions.contains(SearchOptions.BACKWARDS) ? Direction.BACKWARDS : Direction.FORWARDS;
//RE sp;
RegExp sp;
RegExp.regmmatch_T regmatch = new RegExp.regmmatch_T();
regmatch.rmm_ic = shouldIgnoreCase(pattern, searchOptions.contains(SearchOptions.IGNORE_SMARTCASE));
sp = new RegExp();
regmatch.regprog = sp.vim_regcomp(pattern, 1);
if (regmatch.regprog == null) {
if (logger.isDebugEnabled()) logger.debug("bad pattern: " + pattern);
return null;
}
/*
int extra_col = 1;
int startcol = -1;
boolean found = false;
boolean match_ok = true;
LogicalPosition pos = editor.offsetToLogicalPosition(startOffset);
LogicalPosition endpos = null;
//REMatch match = null;
*/
CharacterPosition lpos = CharacterPosition.Companion.fromOffset(editor, startOffset);
RegExp.lpos_T pos = new RegExp.lpos_T();
pos.lnum = lpos.line;
pos.col = lpos.column;
int found;
int lnum; /* no init to shut up Apollo cc */
//RegExp.regmmatch_T regmatch;
CharPointer ptr;
int matchcol;
RegExp.lpos_T matchpos;
RegExp.lpos_T endpos = new RegExp.lpos_T();
int loop;
RegExp.lpos_T start_pos;
boolean at_first_line;
int extra_col = dir == Direction.FORWARDS ? 1 : 0;
boolean match_ok;
long nmatched;
//int submatch = 0;
boolean first_match = true;
int lineCount = EditorHelper.getLineCount(editor);
int startLine = 0;
int endLine = lineCount;
do /* loop for count */ {
start_pos = new RegExp.lpos_T(pos); /* remember start pos for detecting no match */
found = 0; /* default: not found */
at_first_line = true; /* default: start in first line */
if (pos.lnum == -1) /* correct lnum for when starting in line 0 */ {
pos.lnum = 0;
pos.col = 0;
at_first_line = false; /* not in first line now */
}
/*
* Start searching in current line, unless searching backwards and
* we're in column 0.
*/
if (dir == Direction.BACKWARDS && start_pos.col == 0) {
lnum = pos.lnum - 1;
at_first_line = false;
}
else {
lnum = pos.lnum;
}
int lcount = EditorHelper.getLineCount(editor);
for (loop = 0; loop <= 1; ++loop) /* loop twice if 'wrapscan' set */ {
if (!searchOptions.contains(SearchOptions.WHOLE_FILE)) {
startLine = lnum;
endLine = lnum + 1;
}
for (; lnum >= startLine && lnum < endLine; lnum += dir.toInt(), at_first_line = false) {
/*
* Look for a match somewhere in the line.
*/
nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, 0);
if (nmatched > 0) {
/* match may actually be in another line when using \zs */
matchpos = new RegExp.lpos_T(regmatch.startpos[0]);
endpos = new RegExp.lpos_T(regmatch.endpos[0]);
ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum + matchpos.lnum));
/*
* Forward search in the first line: match should be after
* the start position. If not, continue at the end of the
* match (this is vi compatible) or on the next char.
*/
if (dir == Direction.FORWARDS && at_first_line) {
match_ok = true;
/*
* When match lands on a NUL the cursor will be put
* one back afterwards, compare with that position,
* otherwise "/$" will get stuck on end of line.
*/
while (matchpos.lnum == 0
&& (searchOptions.contains(SearchOptions.WANT_ENDPOS) && first_match
? (nmatched == 1 && endpos.col - 1 < start_pos.col + extra_col)
: (matchpos.col - (ptr.charAt(matchpos.col) == '\u0000' ? 1 : 0) < start_pos.col + extra_col))) {
if (nmatched > 1) {
/* end is in next line, thus no match in
* this line */
match_ok = false;
break;
}
matchcol = endpos.col;
/* for empty match: advance one char */
if (matchcol == matchpos.col && ptr.charAt(matchcol) != '\u0000') {
++matchcol;
}
if (ptr.charAt(matchcol) == '\u0000' ||
(nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, matchcol)) == 0) {
match_ok = false;
break;
}
matchpos = new RegExp.lpos_T(regmatch.startpos[0]);
endpos = new RegExp.lpos_T(regmatch.endpos[0]);
/* Need to get the line pointer again, a
* multi-line search may have made it invalid. */
ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum));
}
if (!match_ok) {
continue;
}
}
if (dir == Direction.BACKWARDS) {
/*
* Now, if there are multiple matches on this line,
* we have to get the last one. Or the last one before
* the cursor, if we're on that line.
* When putting the new cursor at the end, compare
* relative to the end of the match.
*/
match_ok = false;
for (;;) {
if (loop != 0 ||
(searchOptions.contains(SearchOptions.WANT_ENDPOS)
? (lnum + regmatch.endpos[0].lnum < start_pos.lnum || (lnum + regmatch.endpos[0].lnum == start_pos.lnum && regmatch.endpos[0].col - 1 < start_pos.col + extra_col))
: (lnum + regmatch.startpos[0].lnum < start_pos.lnum || (lnum + regmatch.startpos[0].lnum == start_pos.lnum && regmatch.startpos[0].col < start_pos.col + extra_col)))) {
/* Remember this position, we use it if it's
* the last match in the line. */
match_ok = true;
matchpos = new RegExp.lpos_T(regmatch.startpos[0]);
endpos = new RegExp.lpos_T(regmatch.endpos[0]);
}
else {
break;
}
/*
* We found a valid match, now check if there is
* another one after it.
* If vi-compatible searching, continue at the end
* of the match, otherwise continue one position
* forward.
*/
if (nmatched > 1) {
break;
}
matchcol = endpos.col;
/* for empty match: advance one char */
if (matchcol == matchpos.col && ptr.charAt(matchcol) != '\u0000') {
++matchcol;
}
if (ptr.charAt(matchcol) == '\u0000' ||
(nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum + matchpos.lnum, matchcol)) == 0) {
break;
}
/* Need to get the line pointer again, a
* multi-line search may have made it invalid. */
ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum + matchpos.lnum));
}
/*
* If there is only a match after the cursor, skip
* this match.
*/
if (!match_ok) {
continue;
}
}
pos.lnum = lnum + matchpos.lnum;
pos.col = matchpos.col;
endpos.lnum = lnum + endpos.lnum;
found = 1;
first_match = false;
/* Set variables used for 'incsearch' highlighting. */
//search_match_lines = endpos.lnum - (lnum - first_lnum);
//search_match_endcol = endpos.col;
break;
}
//line_breakcheck(); /* stop if ctrl-C typed */
//if (got_int)
// break;
if (loop != 0 && lnum == start_pos.lnum) {
break; /* if second loop, stop where started */
}
}
at_first_line = false;
/*
* stop the search if wrapscan isn't set, after an interrupt and
* after a match
*/
if (!searchOptions.contains(SearchOptions.WRAP) || found != 0) {
break;
}
/*
* If 'wrapscan' is set we continue at the other end of the file.
* If 'shortmess' does not contain 's', we give a message.
* This message is also remembered in keep_msg for when the screen
* is redrawn. The keep_msg is cleared whenever another message is
* written.
*/
if (dir == Direction.BACKWARDS) /* start second loop at the other end */ {
lnum = lineCount - 1;
//if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
// give_warning((char_u *)_(top_bot_msg), TRUE);
}
else {
lnum = 0;
//if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
// give_warning((char_u *)_(bot_top_msg), TRUE);
}
}
//if (got_int || called_emsg || break_loop)
// break;
}
while (--count > 0 && found != 0); /* stop after count matches or no match */
if (found == 0) /* did not find it */ {
//if ((options & SEARCH_MSG) == SEARCH_MSG)
if (searchOptions.contains(SearchOptions.SHOW_MESSAGES)) {
if (searchOptions.contains(SearchOptions.WRAP)) {
VimPlugin.showMessage(MessageHelper.message(Msg.e_patnotf2, pattern));
}
else if (lnum <= 0) {
VimPlugin.showMessage(MessageHelper.message(Msg.E384, pattern));
}
else {
VimPlugin.showMessage(MessageHelper.message(Msg.E385, pattern));
}
}
return null;
}
//return new TextRange(editor.logicalPositionToOffset(new LogicalPosition(pos.lnum, pos.col)),
// editor.logicalPositionToOffset(new LogicalPosition(endpos.lnum, endpos.col)));
//return new TextRange(editor.logicalPositionToOffset(new LogicalPosition(pos.lnum, 0)) + pos.col,
// editor.logicalPositionToOffset(new LogicalPosition(endpos.lnum, 0)) + endpos.col);
return new TextRange(new CharacterPosition(pos.lnum, pos.col).toOffset(editor),
new CharacterPosition(endpos.lnum, endpos.col).toOffset(editor));
}
/**
* Find all occurrences of the pattern.
*
* @param editor The editor to search in
* @param pattern The pattern to search for
* @param startLine The start line of the range to search for, or -1 for the whole document
* @param endLine The end line of the range to search for, or -1 for the whole document
* @param ignoreCase Case sensitive or insensitive searching
* @return A list of TextRange objects representing the results
*/
public static @NotNull List<TextRange> findAll(@NotNull Editor editor,
@NotNull String pattern,
int startLine,
int endLine,
boolean ignoreCase) {
final List<TextRange> results = Lists.newArrayList();
final int lineCount = EditorHelper.getLineCount(editor);
final int actualEndLine = endLine == -1 ? lineCount : endLine;
final RegExp.regmmatch_T regMatch = new RegExp.regmmatch_T();
final RegExp regExp = new RegExp();
regMatch.regprog = regExp.vim_regcomp(pattern, 1);
if (regMatch.regprog == null) {
return results;
}
regMatch.rmm_ic = ignoreCase;
int col = 0;
for (int line = startLine; line <= actualEndLine; ) {
int matchedLines = regExp.vim_regexec_multi(regMatch, editor, lineCount, line, col);
if (matchedLines > 0) {
final CharacterPosition startPos = new CharacterPosition(line + regMatch.startpos[0].lnum,
regMatch.startpos[0].col);
final CharacterPosition endPos = new CharacterPosition(line + regMatch.endpos[0].lnum,
regMatch.endpos[0].col);
int start = startPos.toOffset(editor);
int end = endPos.toOffset(editor);
results.add(new TextRange(start, end));
if (start != end) {
line += matchedLines - 1;
col = endPos.column;
}
else {
line += matchedLines;
col = 0;
}
}
else {
line++;
col = 0;
}
}
return results;
}
public static boolean anyNonWhitespace(@NotNull Editor editor, int offset, int dir) { public static boolean anyNonWhitespace(@NotNull Editor editor, int offset, int dir) {
int start; int start;
int end; int end;

View File

@@ -23,24 +23,27 @@ import com.maddyhome.idea.vim.option.OptionsManager.ignorecase
import com.maddyhome.idea.vim.option.OptionsManager.smartcase import com.maddyhome.idea.vim.option.OptionsManager.smartcase
enum class Direction(private val value: Int) { enum class Direction(private val value: Int) {
BACKWARDS(-1), FORWARDS(1), UNSET(0); BACKWARDS(-1), FORWARDS(1);
fun toInt(): Int = value fun toInt(): Int = value
fun reverse(): Direction = when (this) { fun reverse(): Direction = when (this) {
BACKWARDS -> FORWARDS BACKWARDS -> FORWARDS
FORWARDS -> BACKWARDS FORWARDS -> BACKWARDS
UNSET -> UNSET
} }
companion object { companion object {
fun fromInt(value: Int) = when (value) { fun fromInt(value: Int) = when (value) {
BACKWARDS.value -> BACKWARDS BACKWARDS.value -> BACKWARDS
FORWARDS.value -> FORWARDS FORWARDS.value -> FORWARDS
else -> UNSET else -> FORWARDS
} }
} }
} }
enum class SearchOptions {
BACKWARDS, WANT_ENDPOS, WRAP, SHOW_MESSAGES, WHOLE_FILE, IGNORE_SMARTCASE
}
private data class State(val position: Int, val trigger: Char, val inQuote: Boolean?, val lastOpenSingleQuotePos: Int) private data class State(val position: Int, val trigger: Char, val inQuote: Boolean?, val lastOpenSingleQuotePos: Int)
// bounds are considered inside corresponding quotes // bounds are considered inside corresponding quotes
@@ -182,7 +185,19 @@ private fun quoteChanges(chars: CharSequence, begin: Int) = sequence {
} }
} }
fun shouldIgnoreCase(pattern: String, ignoreSmartCase: Boolean): Boolean { /**
val sc = smartcase.isSet && !ignoreSmartCase * Check ignorecase and smartcase options to see if a case insensitive search should be performed with the given pattern.
*
* When ignorecase is not set, this will always return false - perform a case sensitive search.
*
* Otherwise, check smartcase. When set, the search will be case insensitive if the pattern contains only lowercase
* characters, and case sensitive (returns false) if the pattern contains any lowercase characters.
*
* The smartcase option can be ignored, e.g. when searching for the whole word under the cursor. This always performs a
* case insensitive search, so `\<Work\>` will match `Work` and `work`. But when choosing the same pattern from search
* history, the smartcase option is applied, and `\<Work\>` will only match `Work`.
*/
fun shouldIgnoreCase(pattern: String, ignoreSmartCaseOption: Boolean): Boolean {
val sc = smartcase.isSet && !ignoreSmartCaseOption
return ignorecase.isSet && !(sc && StringHelper.containsUpperCase(pattern)) return ignorecase.isSet && !(sc && StringHelper.containsUpperCase(pattern))
} }

View File

@@ -34,8 +34,6 @@ import com.intellij.openapi.project.ProjectManager
import com.intellij.ui.ColorUtil import com.intellij.ui.ColorUtil
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.ex.ranges.LineRange import com.maddyhome.idea.vim.ex.ranges.LineRange
import com.maddyhome.idea.vim.group.SearchGroup
import com.maddyhome.idea.vim.group.SearchGroup.SearchOptions
import com.maddyhome.idea.vim.option.OptionsManager.hlsearch import com.maddyhome.idea.vim.option.OptionsManager.hlsearch
import com.maddyhome.idea.vim.option.OptionsManager.wrapscan import com.maddyhome.idea.vim.option.OptionsManager.wrapscan
import org.jetbrains.annotations.Contract import org.jetbrains.annotations.Contract
@@ -107,7 +105,7 @@ private fun updateSearchHighlights(
val startLine = searchRange?.startLine ?: 0 val startLine = searchRange?.startLine ?: 0
val endLine = searchRange?.endLine ?: -1 val endLine = searchRange?.endLine ?: -1
val results = val results =
SearchGroup.findAll(editor, pattern, startLine, endLine, shouldIgnoreCase(pattern, shouldIgnoreSmartCase)) SearchHelper.findAll(editor, pattern, startLine, endLine, shouldIgnoreCase(pattern, shouldIgnoreSmartCase))
if (results.isNotEmpty()) { if (results.isNotEmpty()) {
currentMatchOffset = findClosestMatch(editor, results, initialOffset, forwards) currentMatchOffset = findClosestMatch(editor, results, initialOffset, forwards)
highlightSearchResults(editor, pattern, results, currentMatchOffset) highlightSearchResults(editor, pattern, results, currentMatchOffset)
@@ -119,7 +117,7 @@ private fun updateSearchHighlights(
if (wrapscan.isSet) searchOptions.add(SearchOptions.WRAP) if (wrapscan.isSet) searchOptions.add(SearchOptions.WRAP)
if (shouldIgnoreSmartCase) searchOptions.add(SearchOptions.IGNORE_SMARTCASE) if (shouldIgnoreSmartCase) searchOptions.add(SearchOptions.IGNORE_SMARTCASE)
if (!forwards) searchOptions.add(SearchOptions.BACKWARDS) if (!forwards) searchOptions.add(SearchOptions.BACKWARDS)
val result = SearchGroup.findIt(editor, pattern, initialOffset, 1, searchOptions) val result = SearchHelper.findPattern(editor, pattern, initialOffset, 1, searchOptions)
if (result != null) { if (result != null) {
currentMatchOffset = result.startOffset currentMatchOffset = result.startOffset
val results = listOf(result) val results = listOf(result)

View File

@@ -28,12 +28,12 @@ import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent
import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.DumbAwareAction import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.containers.IntArrayList
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser
import com.maddyhome.idea.vim.helper.MessageHelper import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.ui.ReloadFloatingToolbarActionGroup.Companion.ACTION_GROUP import com.maddyhome.idea.vim.ui.ReloadFloatingToolbarActionGroup.Companion.ACTION_GROUP
import icons.VimIcons import icons.VimIcons
import it.unimi.dsi.fastutil.ints.IntArrayList
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import java.util.regex.Pattern import java.util.regex.Pattern
@@ -49,8 +49,6 @@ import java.util.regex.Pattern
object VimRcFileState { object VimRcFileState {
// List of hashes of non-empty trimmed lines // List of hashes of non-empty trimmed lines
// [VERSION UPDATE] 202+
@Suppress("DEPRECATION")
private val state = IntArrayList() private val state = IntArrayList()
// ModificationStamp. Can be taken only from document. Doesn't play a big role, but can help speed up [equalTo] // ModificationStamp. Can be taken only from document. Doesn't play a big role, but can help speed up [equalTo]
@@ -74,11 +72,11 @@ object VimRcFileState {
val fileModificationStamp = document.modificationStamp val fileModificationStamp = document.modificationStamp
if (fileModificationStamp == modificationStamp) return true if (fileModificationStamp == modificationStamp) return true
val stateSize = state.size() val stateSize = state.size
var i = 0 var i = 0
VimScriptParser.readText(document.charsSequence).forEach { line -> VimScriptParser.readText(document.charsSequence).forEach { line ->
if (i >= stateSize) return false if (i >= stateSize) return false
if (state.get(i) != line.hashCode()) return false if (state.getInt(i) != line.hashCode()) return false
i++ i++
} }
if (i < stateSize) return false if (i < stateSize) return false

View File

@@ -25,7 +25,7 @@ import static com.maddyhome.idea.vim.helper.StringHelper.parseKeys;
public class ReformatCodeTest extends VimTestCase { public class ReformatCodeTest extends VimTestCase {
/* /*
[VERSION UPDATE] 2020.2+ [VERSION UPDATE] 203+
public void testEmpty() { public void testEmpty() {
configureByJavaText("<caret>"); configureByJavaText("<caret>");
typeText(parseKeys("gqq")); typeText(parseKeys("gqq"));

View File

@@ -90,7 +90,7 @@ class VisualToggleBlockModeActionTest : VimTestCase() {
} }
/* /*
[VERSION UPDATE] 2020.2+ [VERSION UPDATE] 203+
fun `test on empty file`() { fun `test on empty file`() {
doTest("<C-V>", "", "", doTest("<C-V>", "", "",
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_BLOCK) CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_BLOCK)

View File

@@ -18,6 +18,7 @@
package org.jetbrains.plugins.ideavim.extension package org.jetbrains.plugins.ideavim.extension
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
@@ -50,15 +51,14 @@ class OpMappingTest : VimTestCase() {
extension = TestExtension.createBean() extension = TestExtension.createBean()
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+ VimExtension.EP_NAME.point.registerExtension(extension, VimPlugin.getInstance())
VimExtension.EP_NAME.getPoint(null).registerExtension(extension)
enableExtensions("TestExtension") enableExtensions("TestExtension")
} }
} }
override fun tearDown() { override fun tearDown() {
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+ @Suppress("DEPRECATION")
VimExtension.EP_NAME.getPoint(null).unregisterExtension(extension) VimExtension.EP_NAME.point.unregisterExtension(extension)
super.tearDown() super.tearDown()
} }
@@ -137,15 +137,14 @@ class OpMappingTest : VimTestCase() {
typeText(parseKeys("Q")) typeText(parseKeys("Q"))
myFixture.checkResult("I${c} found it in a legendary land") myFixture.checkResult("I${c} found it in a legendary land")
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+ @Suppress("DEPRECATION")
VimExtension.EP_NAME.getPoint(null).unregisterExtension(extension) VimExtension.EP_NAME.point.unregisterExtension(extension)
assertEmpty(VimPlugin.getKey().getKeyMappingByOwner(extension.handler.owner)) assertEmpty(VimPlugin.getKey().getKeyMappingByOwner(extension.instance.owner))
typeText(parseKeys("Q")) typeText(parseKeys("Q"))
myFixture.checkResult("I${c} found it in a legendary land") myFixture.checkResult("I${c} found it in a legendary land")
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+ VimExtension.EP_NAME.point.registerExtension(extension, VimPlugin.getInstance())
VimExtension.EP_NAME.getPoint(null).registerExtension(extension) assertEmpty(VimPlugin.getKey().getKeyMappingByOwner(extension.instance.owner))
assertEmpty(VimPlugin.getKey().getKeyMappingByOwner(extension.handler.owner))
enableExtensions("TestExtension") enableExtensions("TestExtension")
typeText(parseKeys("Q")) typeText(parseKeys("Q"))
myFixture.checkResult("I ${c}found it in a legendary land") myFixture.checkResult("I ${c}found it in a legendary land")
@@ -157,13 +156,12 @@ class OpMappingTest : VimTestCase() {
myFixture.checkResult("I${c} found it in a legendary land") myFixture.checkResult("I${c} found it in a legendary land")
enterCommand("set noTestExtension") enterCommand("set noTestExtension")
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+ @Suppress("DEPRECATION")
VimExtension.EP_NAME.getPoint(null).unregisterExtension(extension) VimExtension.EP_NAME.point.unregisterExtension(extension)
typeText(parseKeys("Q")) typeText(parseKeys("Q"))
myFixture.checkResult("I${c} found it in a legendary land") myFixture.checkResult("I${c} found it in a legendary land")
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+ VimExtension.EP_NAME.point.registerExtension(extension, VimPlugin.getInstance())
VimExtension.EP_NAME.getPoint(null).registerExtension(extension)
enableExtensions("TestExtension") enableExtensions("TestExtension")
typeText(parseKeys("Q")) typeText(parseKeys("Q"))
myFixture.checkResult("I ${c}found it in a legendary land") myFixture.checkResult("I ${c}found it in a legendary land")
@@ -178,13 +176,12 @@ class PlugExtensionsTest : VimTestCase() {
super.setUp() super.setUp()
extension = TestExtension.createBean() extension = TestExtension.createBean()
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+ VimExtension.EP_NAME.point.registerExtension(extension, VimPlugin.getInstance())
VimExtension.EP_NAME.getPoint(null).registerExtension(extension)
} }
override fun tearDown() { override fun tearDown() {
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+ @Suppress("DEPRECATION")
VimExtension.EP_NAME.getPoint(null).unregisterExtension(extension) VimExtension.EP_NAME.point.unregisterExtension(extension)
super.tearDown() super.tearDown()
} }
@@ -212,7 +209,7 @@ class PlugExtensionsTest : VimTestCase() {
} }
private val ExtensionBeanClass.ext: TestExtension private val ExtensionBeanClass.ext: TestExtension
get() = this.handler as TestExtension get() = this.instance as TestExtension
private class TestExtension : VimExtension { private class TestExtension : VimExtension {
@@ -296,6 +293,7 @@ private class TestExtension : VimExtension {
val beanClass = ExtensionBeanClass() val beanClass = ExtensionBeanClass()
beanClass.implementation = TestExtension::class.java.canonicalName beanClass.implementation = TestExtension::class.java.canonicalName
beanClass.aliases = listOf(Alias().also { it.name = "MyTest" }) beanClass.aliases = listOf(Alias().also { it.name = "MyTest" })
beanClass.pluginDescriptor = PluginManagerCore.getPlugin(VimPlugin.getPluginId())!!
return beanClass return beanClass
} }
} }

View File

@@ -41,6 +41,6 @@ class InfoFileTest : VimTestCase() {
} }
private inline fun forEachAction(supply: (action: EditorActionHandlerBase) -> Unit) { private inline fun forEachAction(supply: (action: EditorActionHandlerBase) -> Unit) {
VIM_ACTIONS_EP.extensions.map { it.action }.forEach { supply(it) } VIM_ACTIONS_EP.extensions.map { it.instance }.forEach { supply(it) }
} }
} }