mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-08-17 16:31:45 +02:00
Compare commits
58 Commits
0.61.1-EAP
...
0.64
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c656da5c75 | ||
![]() |
dcedf6abca | ||
![]() |
849a71bdac | ||
![]() |
534cc1d1fe | ||
![]() |
40ec6c53fa | ||
![]() |
b7cb3c0945 | ||
![]() |
69d3c7b754 | ||
![]() |
542f11804e | ||
![]() |
8526054aa8 | ||
![]() |
93700bddc7 | ||
![]() |
494500041b | ||
![]() |
011a5a3b23 | ||
![]() |
03726858f0 | ||
![]() |
c8c42cc4b2 | ||
![]() |
0b22b454e6 | ||
![]() |
f4fe03c582 | ||
![]() |
964e87fd6a | ||
![]() |
ec4c0a0d0d | ||
![]() |
f9cf62472c | ||
![]() |
ace584d294 | ||
![]() |
5cd669202b | ||
![]() |
4a09848720 | ||
![]() |
f998f1be9f | ||
![]() |
3352bdfabb | ||
![]() |
ce43a9648f | ||
![]() |
440a0bf393 | ||
![]() |
64a7555f42 | ||
![]() |
3aa6fe3dc0 | ||
![]() |
3522228d45 | ||
![]() |
9b42d9a5c6 | ||
![]() |
4e8d98f956 | ||
![]() |
f6c3d27bbc | ||
![]() |
21daf83fbd | ||
![]() |
7f1203c207 | ||
![]() |
89b1f90973 | ||
![]() |
8002a5497f | ||
![]() |
770d12d79b | ||
![]() |
7e4ac22d23 | ||
![]() |
4f4b26d3e1 | ||
![]() |
4ea7c421a8 | ||
![]() |
3c8b7e2de4 | ||
![]() |
b13acaf823 | ||
![]() |
709cd6ad6e | ||
![]() |
1316ccc56f | ||
![]() |
881ddd0e11 | ||
![]() |
49611ee6b9 | ||
![]() |
539465bb56 | ||
![]() |
bc54a73d69 | ||
![]() |
5eb12f5d14 | ||
![]() |
557e47650f | ||
![]() |
f50753bfd7 | ||
![]() |
7a164d6d5f | ||
![]() |
60bc936cd9 | ||
![]() |
d097e636ea | ||
![]() |
3ce2bbb624 | ||
![]() |
4926d2554e | ||
![]() |
eae135acba | ||
![]() |
8ce3801b87 |
@@ -9,6 +9,7 @@
|
||||
<ID>ComplexMethod:OptionsManager.kt$OptionsManager$ fun parseOptionLine(editor: Editor?, args: String, failOnBad: Boolean): Boolean</ID>
|
||||
<ID>ComplexMethod:PutGroup.kt$PutGroup$private fun prepareDocumentAndGetStartOffsets(editor: Editor, caret: Caret, typeInRegister: SelectionType, data: PutData, additionalData: Map<String, Any>): List<Int></ID>
|
||||
<ID>ComplexMethod:SearchHelperKt.kt$// bounds are considered inside corresponding quotes fun checkInString(chars: CharSequence, currentPos: Int, str: Boolean): Boolean</ID>
|
||||
<ID>ComplexMethod:SearchHighlightsHelper.kt$ private fun updateSearchHighlights( pattern: String?, shouldIgnoreSmartCase: Boolean, showHighlights: Boolean, initialOffset: Int, searchRange: LineRange?, forwards: Boolean, forceUpdate: Boolean ): Int</ID>
|
||||
<ID>ComplexMethod:TabCloseHandler.kt$TabCloseHandler$ private fun getTabIndexToClose(arg: String, current: Int, last: Int): Int?</ID>
|
||||
<ID>ComplexMethod:VimExchangeExtension.kt$VimExchangeExtension.Operator$private fun compareExchanges(x: Exchange, y: Exchange): ExchangeCompareResult</ID>
|
||||
<ID>ComplexMethod:VimMultipleCursorsExtension.kt$VimMultipleCursorsExtension.NextOccurrenceHandler$override fun executeInWriteAction(editor: Editor, context: DataContext)</ID>
|
||||
@@ -16,6 +17,8 @@
|
||||
<ID>LongMethod:CmdHandler.kt$CmdHandler$private fun addAlias(cmd: ExCommand, editor: Editor?): 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: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 `/<Up>` 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:AddBlockInlaysAction.kt$AddBlockInlaysAction$0.9f</ID>
|
||||
<ID>MagicNumber:AddBlockInlaysAction.kt$AddBlockInlaysAction$1.75f</ID>
|
||||
@@ -35,7 +38,6 @@
|
||||
<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$7</ID>
|
||||
<ID>MagicNumber:EditorHelper.kt$10</ID>
|
||||
<ID>MagicNumber:ExKeyBindings.kt$ExKeyBindings$0x05</ID>
|
||||
<ID>MagicNumber:ExKeyBindings.kt$ExKeyBindings$0x08</ID>
|
||||
<ID>MagicNumber:HistoryHandler.kt$HistoryHandler$7</ID>
|
||||
@@ -50,6 +52,7 @@
|
||||
<ID>MagicNumber:OptionsManager.kt$OptionsManager$19</ID>
|
||||
<ID>MagicNumber:OptionsManager.kt$OptionsManager$20</ID>
|
||||
<ID>MagicNumber:OptionsManager.kt$OptionsManager$3</ID>
|
||||
<ID>MagicNumber:OptionsManager.kt$OptionsManager$50</ID>
|
||||
<ID>MagicNumber:OptionsManager.kt$OptionsManager$80</ID>
|
||||
<ID>MagicNumber:ProcessExEntryAction.kt$ProcessExEntryAction$0x0a</ID>
|
||||
<ID>MagicNumber:RegistersHandler.kt$RegistersHandler$200</ID>
|
||||
@@ -61,7 +64,7 @@
|
||||
<ID>MagicNumber:VimHighlightedYank.kt$VimHighlightedYank.HighlightHandler$3</ID>
|
||||
<ID>MagicNumber:VimHighlightedYank.kt$VimHighlightedYank.HighlightHandler$4</ID>
|
||||
<ID>MatchingDeclarationName:CommandDefinition.kt$CommandName</ID>
|
||||
<ID>MaxLineLength:ExBeanClass.kt$ExBeanClass$logger<ExBeanClass>().error("IdeaVim doesn't accept contributions to `vimActions` extension points. Please create a plugin using `VimExtension`. Plugin to blame: $pluginId")</ID>
|
||||
<ID>MaxLineLength:ExBeanClass.kt$ExBeanClass$logger<ExBeanClass>().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: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.AppendToIdeaVimRcAction$private inner</ID>
|
||||
@@ -79,67 +82,18 @@
|
||||
<ID>MaxLineLength:VimShortcutKeyAction.kt$VimShortcutKeyAction.Companion$ImmutableSet.builder<KeyStroke>().addAll(getKeyStrokes(KeyEvent.VK_ENTER, 0)).addAll(getKeyStrokes(KeyEvent.VK_ESCAPE, 0)) .addAll(getKeyStrokes(KeyEvent.VK_TAB, 0)).addAll(getKeyStrokes(KeyEvent.VK_BACK_SPACE, 0, InputEvent.CTRL_DOWN_MASK)) .addAll(getKeyStrokes(KeyEvent.VK_INSERT, 0)).addAll(getKeyStrokes(KeyEvent.VK_DELETE, 0, InputEvent.CTRL_DOWN_MASK)) .addAll(getKeyStrokes(KeyEvent.VK_UP, 0, InputEvent.CTRL_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK)).addAll(getKeyStrokes(KeyEvent.VK_DOWN, 0, InputEvent.CTRL_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK)) .addAll(getKeyStrokes(KeyEvent.VK_LEFT, 0, InputEvent.CTRL_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.CTRL_DOWN_MASK or InputEvent.SHIFT_DOWN_MASK)) .addAll(getKeyStrokes(KeyEvent.VK_RIGHT, 0, InputEvent.CTRL_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.CTRL_DOWN_MASK or InputEvent.SHIFT_DOWN_MASK)) .addAll(getKeyStrokes(KeyEvent.VK_HOME, 0, InputEvent.CTRL_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.CTRL_DOWN_MASK or InputEvent.SHIFT_DOWN_MASK))</ID>
|
||||
<ID>MemberNameEqualsClassName:Ranges.kt$Ranges$private val ranges: MutableList<Range> = mutableListOf()</ID>
|
||||
<ID>NestedBlockDepth:OptionsManager.kt$OptionsManager$ fun parseOptionLine(editor: Editor?, args: String, failOnBad: Boolean): Boolean</ID>
|
||||
<ID>ReturnCount:ActionBeanClass.kt$ActionBeanClass$fun getParsedModes(): Set<MappingMode>?</ID>
|
||||
<ID>ReturnCount:Alias.kt$Alias$fun getCommand(input: String, count: Int): String</ID>
|
||||
<ID>ReturnCount:CmdFilterHandler.kt$CmdFilterHandler$override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean</ID>
|
||||
<ID>ReturnCount:CmdHandler.kt$CmdHandler$private fun addAlias(cmd: ExCommand, editor: Editor?): Boolean</ID>
|
||||
<ID>ReturnCount:CommandGroup.kt$CommandGroup$fun isAlias(command: String): Boolean</ID>
|
||||
<ID>ReturnCount:DeleteJoinLinesAction.kt$DeleteJoinLinesAction$override fun execute(editor: Editor, context: DataContext, count: Int, rawCount: Int, argument: Argument?): Boolean</ID>
|
||||
<ID>ReturnCount:DeleteJoinLinesSpacesAction.kt$DeleteJoinLinesSpacesAction$override fun execute(editor: Editor, context: DataContext, count: Int, rawCount: Int, argument: Argument?): Boolean</ID>
|
||||
<ID>ReturnCount:DeleteJoinVisualLinesAction.kt$DeleteJoinVisualLinesAction$override fun executeForAllCarets(editor: Editor, context: DataContext, cmd: Command, caretsAndSelections: Map<Caret, VimSelection>): Boolean</ID>
|
||||
<ID>ReturnCount:DeleteJoinVisualLinesSpacesAction.kt$DeleteJoinVisualLinesSpacesAction$override fun executeForAllCarets(editor: Editor, context: DataContext, cmd: Command, caretsAndSelections: Map<Caret, VimSelection>): Boolean</ID>
|
||||
<ID>ReturnCount:DeleteMotionAction.kt$DeleteMotionAction$override fun execute(editor: Editor, caret: Caret, context: DataContext, count: Int, rawCount: Int, argument: Argument?): Boolean</ID>
|
||||
<ID>ReturnCount:EditFileHandler.kt$EditFileHandler$override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean</ID>
|
||||
<ID>ReturnCount:EditorHelper.kt$ fun Editor.isPrimaryEditor(): Boolean</ID>
|
||||
<ID>ReturnCount:ExRanges.kt$Range.Companion$ @JvmStatic fun createRange(str: String, offset: Int, move: Boolean): Array<Range>?</ID>
|
||||
<ID>ReturnCount:FilterMotionAction.kt$FilterMotionAction$override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean</ID>
|
||||
<ID>ReturnCount:GotoCharacterHandler.kt$GotoCharacterHandler$override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean</ID>
|
||||
<ID>ReturnCount:Helper.kt$@Suppress("IncorrectParentDisposable") fun Editor.isTemplateActive(): Boolean</ID>
|
||||
<ID>ReturnCount:HistoryHandler.kt$HistoryHandler$override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean</ID>
|
||||
<ID>ReturnCount:IdeaSelectionControl.kt$IdeaSelectionControl$ fun predictMode(editor: Editor, selectionSource: VimListenerManager.SelectionSource): CommandState.Mode</ID>
|
||||
<ID>ReturnCount:MapHandler.kt$MapHandler$@Throws(ExException::class) private fun executeCommand(cmd: ExCommand, editor: Editor?): Boolean</ID>
|
||||
<ID>ReturnCount:Marks.kt$IntellijMark$private fun getProject(): Project?</ID>
|
||||
<ID>ReturnCount:Marks.kt$VimMark.Companion$@JvmStatic fun create(key: Char?, logicalLine: Int?, col: Int?, filename: String?, protocol: String?): VimMark?</ID>
|
||||
<ID>ReturnCount:ModalEntry.kt$ModalEntry.<no name provided>$override fun dispatchKeyEvent(e: KeyEvent): Boolean</ID>
|
||||
<ID>ReturnCount:MotionScrollLastScreenLinePageStartAction.kt$MotionScrollLastScreenLinePageStartAction$override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean</ID>
|
||||
<ID>ReturnCount:OperatorAction.kt$OperatorAction$override fun execute(editor: Editor, context: DataContext, cmd: Command): Boolean</ID>
|
||||
<ID>ReturnCount:OptionsManager.kt$OptionsManager$ fun parseOptionLine(editor: Editor?, args: String, failOnBad: Boolean): Boolean</ID>
|
||||
<ID>ReturnCount:PutGroup.kt$PutGroup$private fun getProviderForPasteViaIde(context: DataContext, typeInRegister: SelectionType, data: PutData): PasteProvider?</ID>
|
||||
<ID>ReturnCount:PutGroup.kt$PutGroup$private fun prepareDocumentAndGetStartOffsets(editor: Editor, caret: Caret, typeInRegister: SelectionType, data: PutData, additionalData: Map<String, Any>): List<Int></ID>
|
||||
<ID>ReturnCount:PutLinesHandler.kt$PutLinesHandler$override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean</ID>
|
||||
<ID>ReturnCount:ReloadVimRc.kt$VimRcFileState$fun equalTo(document: Document): Boolean</ID>
|
||||
<ID>ReturnCount:RepeatHandler.kt$RepeatHandler$@Throws(ExException::class) override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean</ID>
|
||||
<ID>ReturnCount:SelectMotionRightAction.kt$SelectMotionRightAction$override fun getOffset(editor: Editor, caret: Caret, context: DataContext, count: Int, rawCount: Int, argument: Argument?): Int</ID>
|
||||
<ID>ReturnCount:ShowCmd.kt$ShowCmd$fun getFullText(editor: Editor?): String</ID>
|
||||
<ID>ReturnCount:TabCloseHandler.kt$TabCloseHandler$ private fun getTabIndexToClose(arg: String, current: Int, last: Int): Int?</ID>
|
||||
<ID>ReturnCount:TextObjectActionHandler.kt$TextObjectActionHandler$ final override fun baseExecute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean</ID>
|
||||
<ID>ReturnCount:UndoRedoHelper.kt$UndoRedoHelper$fun redo(context: DataContext): Boolean</ID>
|
||||
<ID>ReturnCount:UndoRedoHelper.kt$UndoRedoHelper$fun undo(context: DataContext): Boolean</ID>
|
||||
<ID>ReturnCount:VimExchangeExtension.kt$VimExchangeExtension.Operator$override fun apply(editor: Editor, context: DataContext, selectionType: SelectionType): Boolean</ID>
|
||||
<ID>ReturnCount:VimExtensionFacade.kt$VimExtensionFacade$ @JvmStatic fun inputString(editor: Editor, prompt: String, finishOn: Char?): String</ID>
|
||||
<ID>ReturnCount:VimMultipleCursorsExtension.kt$VimMultipleCursorsExtension.AllOccurrencesHandler$override fun executeInWriteAction(editor: Editor, context: DataContext)</ID>
|
||||
<ID>ReturnCount:VimMultipleCursorsExtension.kt$VimMultipleCursorsExtension.NextOccurrenceHandler$override fun executeInWriteAction(editor: Editor, context: DataContext)</ID>
|
||||
<ID>ReturnCount:VimMultipleCursorsExtension.kt$VimMultipleCursorsExtension.SkipOccurrenceHandler$override fun executeInWriteAction(editor: Editor, context: DataContext)</ID>
|
||||
<ID>ReturnCount:VimScriptParser.kt$VimScriptParser$@Throws(ExException::class) fun evaluate(expression: String, globals: Map<String?, Any?>): Any</ID>
|
||||
<ID>ReturnCount:VimScriptParser.kt$VimScriptParser$fun findOrCreateIdeaVimRc(): File?</ID>
|
||||
<ID>ReturnCount:VimShortcutKeyAction.kt$VimShortcutKeyAction$private fun getKeyStroke(e: AnActionEvent): KeyStroke?</ID>
|
||||
<ID>ReturnCount:VimShortcutKeyAction.kt$VimShortcutKeyAction$private fun isEnabled(e: AnActionEvent): Boolean</ID>
|
||||
<ID>ReturnCount:VimSurroundExtension.kt$VimSurroundExtension.CSurroundHandler$override fun execute(editor: Editor, context: DataContext)</ID>
|
||||
<ID>ReturnCount:VimSurroundExtension.kt$VimSurroundExtension.Operator$override fun apply(editor: Editor, context: DataContext, selectionType: SelectionType): Boolean</ID>
|
||||
<ID>ReturnCount:VisualBlockAppendAction.kt$VisualBlockAppendAction$override fun executeForAllCarets(editor: Editor, context: DataContext, cmd: Command, caretsAndSelections: Map<Caret, VimSelection>): Boolean</ID>
|
||||
<ID>ReturnCount:VisualBlockInsertAction.kt$VisualBlockInsertAction$override fun executeForAllCarets(editor: Editor, context: DataContext, cmd: Command, caretsAndSelections: Map<Caret, VimSelection>): Boolean</ID>
|
||||
<ID>ReturnCount:VisualMotionGroup.kt$VisualMotionGroup$ fun toggleVisual(editor: Editor, count: Int, rawCount: Int, subMode: CommandState.SubMode): Boolean</ID>
|
||||
<ID>ReturnCount:VisualMotionGroup.kt$VisualMotionGroup$fun autodetectVisualSubmode(editor: Editor): CommandState.SubMode</ID>
|
||||
<ID>ReturnCount:VisualMotionGroup.kt$VisualMotionGroup$fun selectPreviousVisualMode(editor: Editor): Boolean</ID>
|
||||
<ID>ReturnCount:VisualMotionGroup.kt$VisualMotionGroup$fun swapVisualSelections(editor: Editor): Boolean</ID>
|
||||
<ID>ReturnCount:VisualMotionGroup.kt$VisualMotionGroup$private fun seemsLikeBlockMode(editor: Editor): Boolean</ID>
|
||||
<ID>ReturnCount:VisualOperatorActionHandler.kt$VisualOperatorActionHandler$final override fun baseExecute(editor: Editor, caret: Caret, context: DataContext, cmd: Command): Boolean</ID>
|
||||
<ID>ReturnCount:YankGroup.kt$YankGroup$ fun yankMotion(editor: Editor, context: DataContext, count: Int, rawCount: Int, argument: Argument): Boolean</ID>
|
||||
<ID>ThrowsCount:CommandHandler.kt$CommandHandler$private fun checkArgs(cmd: ExCommand)</ID>
|
||||
<ID>TooManyFunctions:CommandBuilder.kt$CommandBuilder</ID>
|
||||
<ID>TooManyFunctions:CommandState.kt$CommandState</ID>
|
||||
<ID>TooManyFunctions:PutGroup.kt$PutGroup</ID>
|
||||
<ID>TooManyFunctions:Ranges.kt$Ranges</ID>
|
||||
<ID>TooManyFunctions:SearchHighlightsHelper.kt$com.maddyhome.idea.vim.helper.SearchHighlightsHelper.kt</ID>
|
||||
<ID>TooManyFunctions:VisualGroup.kt$com.maddyhome.idea.vim.group.visual.VisualGroup.kt</ID>
|
||||
<ID>TooManyFunctions:VisualMotionGroup.kt$VisualMotionGroup</ID>
|
||||
</CurrentIssues>
|
||||
|
1
.idea/inspectionProfiles/Project_Default.xml
generated
1
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -29,7 +29,6 @@
|
||||
<option name="m_requireAnnotationsFirst" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PluginXmlI18n" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="StaticMethodOnlyUsedInOneClass" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnstableApiUsage" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
</profile>
|
||||
</component>
|
1
.idea/inspectionProfiles/Qodana.xml
generated
1
.idea/inspectionProfiles/Qodana.xml
generated
@@ -41,7 +41,6 @@
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="StaticMethodOnlyUsedInOneClass" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SuperTearDownInFinally" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnstableApiUsage" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
</profile>
|
||||
|
20
.teamcity/_Self/Project.kt
vendored
20
.teamcity/_Self/Project.kt
vendored
@@ -13,10 +13,12 @@ import _Self.buildTypes.TestsForIntelliJ20192
|
||||
import _Self.buildTypes.TestsForIntelliJ20193
|
||||
import _Self.buildTypes.TestsForIntelliJ20201
|
||||
import _Self.buildTypes.TestsForIntelliJ20202
|
||||
import _Self.buildTypes.TestsForIntelliJ20203
|
||||
import _Self.buildTypes.TestsForIntelliJEAP
|
||||
import _Self.vcsRoots.Branch_181
|
||||
import _Self.vcsRoots.Branch_183
|
||||
import _Self.vcsRoots.Branch_191_193
|
||||
import _Self.vcsRoots.Branch_201
|
||||
import _Self.vcsRoots.GitHubPullRequest
|
||||
import jetbrains.buildServer.configs.kotlin.v2019_2.Project
|
||||
|
||||
@@ -25,11 +27,22 @@ object Project : Project({
|
||||
|
||||
vcsRoot(Branch_183)
|
||||
vcsRoot(Branch_181)
|
||||
vcsRoot(GitHubPullRequest)
|
||||
vcsRoot(Branch_191_193)
|
||||
vcsRoot(Branch_201)
|
||||
vcsRoot(GitHubPullRequest)
|
||||
|
||||
buildType(GitHubPullRequests)
|
||||
|
||||
buildType(Release)
|
||||
buildType(ReleaseEap)
|
||||
|
||||
buildType(TestsForIntelliJ20202)
|
||||
buildType(TestsForIntelliJ20203)
|
||||
buildType(TestsForIntelliJEAP)
|
||||
|
||||
buildType(Nvim)
|
||||
buildType(PluginVerifier)
|
||||
|
||||
buildType(TestsForIntelliJ20201)
|
||||
buildType(TestsForIntelliJ20191)
|
||||
buildType(TestsForIntelliJ20181)
|
||||
@@ -37,11 +50,6 @@ object Project : Project({
|
||||
buildType(TestsForIntelliJ20182)
|
||||
buildType(TestsForIntelliJ20193)
|
||||
buildType(TestsForIntelliJ20183)
|
||||
buildType(Nvim)
|
||||
buildType(ReleaseEap)
|
||||
buildType(TestsForIntelliJ20202)
|
||||
buildType(TestsForIntelliJEAP)
|
||||
buildType(PluginVerifier)
|
||||
|
||||
features {
|
||||
feature {
|
||||
|
2
.teamcity/_Self/buildTypes/ActiveTests.kt
vendored
2
.teamcity/_Self/buildTypes/ActiveTests.kt
vendored
@@ -41,5 +41,5 @@ sealed class ActiveTests(buildName: String, ijVersion: String) : BuildType({
|
||||
})
|
||||
|
||||
object TestsForIntelliJEAP : ActiveTests("Tests for IntelliJ Latest EAP", "LATEST-EAP-SNAPSHOT")
|
||||
object TestsForIntelliJ20203 : ActiveTests("Tests for IntelliJ 2020.3", "2020.3")
|
||||
object TestsForIntelliJ20202 : ActiveTests("Tests for IntelliJ 2020.2", "2020.2")
|
||||
object TestsForIntelliJ20201 : ActiveTests("Tests for IntelliJ 2020.1", "2020.1")
|
||||
|
@@ -16,7 +16,7 @@ object GitHubPullRequests : BuildType({
|
||||
|
||||
params {
|
||||
param("env.ORG_GRADLE_PROJECT_downloadIdeaSources", "false")
|
||||
param("env.ORG_GRADLE_PROJECT_ideaVersion", "2020.1")
|
||||
param("env.ORG_GRADLE_PROJECT_ideaVersion", "2020.3")
|
||||
param("env.ORG_GRADLE_PROJECT_instrumentPluginCode", "false")
|
||||
}
|
||||
|
||||
|
2
.teamcity/_Self/buildTypes/Release.kt
vendored
2
.teamcity/_Self/buildTypes/Release.kt
vendored
@@ -10,7 +10,7 @@ object Release : BuildType({
|
||||
description = "Build and publish IdeaVim plugin"
|
||||
|
||||
artifactRules = "build/distributions/*"
|
||||
buildNumberPattern = "0.61"
|
||||
buildNumberPattern = "0.64"
|
||||
|
||||
params {
|
||||
param("env.ORG_GRADLE_PROJECT_ideaVersion", "2020.2")
|
||||
|
2
.teamcity/_Self/buildTypes/ReleaseEap.kt
vendored
2
.teamcity/_Self/buildTypes/ReleaseEap.kt
vendored
@@ -13,7 +13,7 @@ object ReleaseEap : BuildType({
|
||||
description = "Build and publish EAP of IdeaVim plugin"
|
||||
|
||||
artifactRules = "build/distributions/*"
|
||||
buildNumberPattern = "0.61.%build.counter%"
|
||||
buildNumberPattern = "0.64.%build.counter%"
|
||||
|
||||
params {
|
||||
param("env.ORG_GRADLE_PROJECT_ideaVersion", "2020.2")
|
||||
|
46
.teamcity/_Self/buildTypes/TestsForIntelliJ_201.kt
vendored
Normal file
46
.teamcity/_Self/buildTypes/TestsForIntelliJ_201.kt
vendored
Normal 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
12
.teamcity/_Self/vcsRoots/Branch_201.kt
vendored
Normal 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
|
||||
})
|
@@ -331,6 +331,14 @@ Contributors:
|
||||
[![icon][github]](https://github.com/antekone)
|
||||
|
||||
Grzegorz Antoniak
|
||||
* [![icon][mail]](mailto:shaunpatterson@gmail.com)
|
||||
[![icon][github]](https://github.com/shaunpatterson)
|
||||
|
||||
Shaun Patterson
|
||||
* [![icon][mail]](mailto:vladimir.petrenko@jetbrains.com)
|
||||
[![icon][github]](https://github.com/vladimir-petrenko)
|
||||
|
||||
Vladimir Petrenko
|
||||
|
||||
If you are a contributor and your name is not listed here, feel free to
|
||||
contact the maintainers.
|
||||
|
31
CHANGES.md
31
CHANGES.md
@@ -22,18 +22,42 @@ 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
|
||||
usual beta standards.
|
||||
|
||||
## To Be Released
|
||||
## 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
|
||||
|
||||
### Features:
|
||||
|
||||
* Support `unmap` and `mapclear` commands [VIM-1491](https://youtrack.jetbrains.com/issue/VIM-1491)
|
||||
* Support mappings in ex panel (`cmap`) [VIM-1227](https://youtrack.jetbrains.com/issue/VIM-1227)
|
||||
|
||||
### Changes:
|
||||
* `octal` is now disabled by default for `nrformats`. [VIM-2181](https://youtrack.jetbrains.com/issue/VIM-2181)
|
||||
|
||||
### Fixes:
|
||||
* [VIM-2113](https://youtrack.jetbrains.com/issue/VIM-2113) Fix `cit` for empty tags
|
||||
* [VIM-2114](https://youtrack.jetbrains.com/issue/VIM-2114) Unnamed register isn't changed after deleting empty tag
|
||||
* [VIM-1475](https://youtrack.jetbrains.com/issue/VIM-1475) Enable block caret to be used in insert mode.
|
||||
* [VIM-2170](https://youtrack.jetbrains.com/issue/VIM-2170) Fix an alternative range format for `s` command
|
||||
* [VIM-1913](https://youtrack.jetbrains.com/issue/VIM-1913)
|
||||
[VIM-2154](https://youtrack.jetbrains.com/issue/VIM-2154) Several fixes for AppCode templates
|
||||
* [VIM-1756](https://youtrack.jetbrains.com/issue/VIM-1756) Fix startsel from insert mode
|
||||
|
||||
### Merged PRs:
|
||||
* [249](https://github.com/JetBrains/ideavim/pull/249) by [Jan Palus](https://github.com/jpalus): VIM-2113 Increase tag range only in visual mode
|
||||
@@ -41,6 +65,9 @@ usual beta standards.
|
||||
* [256](https://github.com/JetBrains/ideavim/pull/256) by [Brandon Conway](https://github.com/brandoncc): Fix typo
|
||||
* [254](https://github.com/JetBrains/ideavim/pull/254) by [Grzegorz Antoniak](https://github.com/antekone): VIM-1475: Add an option to use block caret in insert mode
|
||||
* [225](https://github.com/JetBrains/ideavim/pull/225) by [sumoooru2](https://github.com/sumoooru2): Implement cmap
|
||||
* [258](https://github.com/JetBrains/ideavim/pull/258) by [Matt Ellis](https://github.com/citizenmatt): Show the correct handler class in :map
|
||||
* [257](https://github.com/JetBrains/ideavim/pull/257) by [Matt Ellis](https://github.com/citizenmatt): Extract SearchHighlightsHelper from SearchGroup
|
||||
* [251](https://github.com/JetBrains/ideavim/pull/251) by [Shaun Patterson](https://github.com/shaunpatterson): VIM-1756: startSel works in insert mode
|
||||
|
||||
## 0.61, 2020-11-12
|
||||
|
||||
|
37
README.md
37
README.md
@@ -144,21 +144,38 @@ set idearefactormode=keep
|
||||
map <leader>f <Plug>(easymotion-s)
|
||||
map <leader>e <Plug>(easymotion-f)
|
||||
|
||||
map <leader>d :action Debug<CR>
|
||||
map <leader>r :action RenameElement<CR>
|
||||
map <leader>c :action Stop<CR>
|
||||
map <leader>z :action ToggleDistractionFreeMode<CR>
|
||||
map <leader>d <Action>(Debug)
|
||||
map <leader>r <Action>(RenameElement)
|
||||
map <leader>c <Action>(Stop)
|
||||
map <leader>z <Action>(ToggleDistractionFreeMode)
|
||||
|
||||
map <leader>s :action SelectInProjectView<CR>
|
||||
map <leader>a :action Annotate<CR>
|
||||
map <leader>h :action Vcs.ShowTabbedFileHistory<CR>
|
||||
map <S-Space> :action GotoNextError<CR>
|
||||
map <leader>s <Action>(SelectInProjectView)
|
||||
map <leader>a <Action>(Annotate)
|
||||
map <leader>h <Action>(Vcs.ShowTabbedFileHistory)
|
||||
map <S-Space> <Action>(GotoNextError)
|
||||
|
||||
map <leader>b :action ToggleLineBreakpoint<CR>
|
||||
map <leader>o :action FileStructurePopup<CR>
|
||||
map <leader>b <Action>(ToggleLineBreakpoint)
|
||||
map <leader>o <Action>(FileStructurePopup)
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Suggested options</strong> (click to see)</summary>
|
||||
|
||||
Here is also a list of the suggested options from [defaults.vim](https://github.com/vim/vim/blob/master/runtime/defaults.vim)
|
||||
|
||||
```vim
|
||||
" Show a few lines of context around the cursor. Note that this makes the
|
||||
" text scroll if you mouse-click near the start or end of the window.
|
||||
set scrolloff=5
|
||||
|
||||
" Do incremental searching
|
||||
set incsearch
|
||||
|
||||
" Don't use Ex mode, use Q for formatting.
|
||||
map Q gq
|
||||
```
|
||||
</details>
|
||||
|
||||
|
||||
You can read your `~/.vimrc` file from `~/.ideavimrc` with this command:
|
||||
|
@@ -59,7 +59,7 @@ runIdeForUiTests {
|
||||
}
|
||||
|
||||
runPluginVerifier {
|
||||
ideVersions = ["IC-2020.1.4", "IC-2020.2.3"]
|
||||
ideVersions = ["IC-2020.2.3", "IC-2020.3"]
|
||||
downloadDirectory = "${project.buildDir}/pluginVerifier/ides"
|
||||
teamCityOutputFormat = true
|
||||
}
|
||||
|
@@ -28,9 +28,9 @@
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionRightMatchCharAction" mappingModes="NXO" keys="f"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionRightTillMatchCharAction" mappingModes="NXO" keys="t"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionHomeAction" mappingModes="NV" keys="«Home»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftHomeAction" mappingModes="NV" keys="«S-Home»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftHomeAction" mappingModes="INV" keys="«S-Home»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionEndAction" mappingModes="NVO" keys="«End»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftEndAction" mappingModes="NV" keys="«S-End»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftEndAction" mappingModes="INV" keys="«S-End»"/>
|
||||
<!-- Up/Down -->
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.updown.MotionDownAction" mappingModes="NXO" keys="j"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.updown.MotionDownCtrlNAction" mappingModes="NXO" keys="«C-N»"/>
|
||||
@@ -152,10 +152,10 @@
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.scroll.MotionScrollColumnRightAction" mappingModes="NXO" keys="zh,z«Left»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.scroll.MotionScrollHalfWidthLeftAction" mappingModes="NXO" keys="zL"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.scroll.MotionScrollHalfWidthRightAction" mappingModes="NXO" keys="zH"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.updown.MotionShiftDownAction" mappingModes="NV" keys="«S-Down»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.updown.MotionShiftUpAction" mappingModes="NV" keys="«S-Up»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftRightAction" mappingModes="NV" keys="«S-Right»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftLeftAction" mappingModes="NV" keys="«S-Left»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.updown.MotionShiftDownAction" mappingModes="INV" keys="«S-Down»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.updown.MotionShiftUpAction" mappingModes="INV" keys="«S-Up»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftRightAction" mappingModes="INV" keys="«S-Right»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.leftright.MotionShiftLeftAction" mappingModes="INV" keys="«S-Left»"/>
|
||||
<!-- Visual -->
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.visual.VisualExitModeAction" mappingModes="X" keys="«Esc»,«C-[»,«C-C»"/>
|
||||
<vimAction implementation="com.maddyhome.idea.vim.action.motion.visual.VisualToggleCharacterModeAction" mappingModes="NX" keys="v"/>
|
||||
|
@@ -2,62 +2,21 @@
|
||||
<name>IdeaVim</name>
|
||||
<id>IdeaVIM</id>
|
||||
<change-notes><![CDATA[
|
||||
<h3>Features:</h3>
|
||||
<h3>Merged PRs:</h3>
|
||||
<ul>
|
||||
<li>Support <code>unmap</code> and <code>mapclear</code> commands
|
||||
<a href="https://youtrack.jetbrains.com/issue/VIM-1491">VIM-1491</a>
|
||||
</li>
|
||||
<li>Support mappings in ex panel (<code>cmap</code>)
|
||||
<a href="https://youtrack.jetbrains.com/issue/VIM-1227">VIM-1227</a>
|
||||
<li>
|
||||
<a href="https://github.com/JetBrains/ideavim/pull/260">260</a>
|
||||
by <a href="https://github.com/citizenmatt">Matt Ellis</a>: Refactor SearchGroup
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Fixes:</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://youtrack.jetbrains.com/issue/VIM-2113">VIM-2113</a>
|
||||
Fix <code>cit</code> for empty tags
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://youtrack.jetbrains.com/issue/VIM-2114">VIM-2114</a>
|
||||
Unnamed register isn't changed after deleting empty tag
|
||||
</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
|
||||
<a href="https://youtrack.jetbrains.com/issue/VIM-2194">VIM-2194</a>
|
||||
Fix caret shape during editing a new file
|
||||
</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>
|
||||
</ul>
|
||||
<br/>
|
||||
<p>See also the complete <a href="https://github.com/JetBrains/ideavim/blob/master/CHANGES.md">changelog</a>.</p>
|
||||
]]>
|
||||
</change-notes>
|
||||
<description><![CDATA[
|
||||
@@ -77,7 +36,7 @@
|
||||
|
||||
<!-- Please search for "[VERSION UPDATE]" in project in case you update the since-build version -->
|
||||
<!-- 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 -->
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
@@ -111,7 +70,6 @@
|
||||
<statusBarWidgetFactory implementation="com.maddyhome.idea.vim.ui.StatusBarIconFactory"/>
|
||||
<statusBarWidgetFactory implementation="com.maddyhome.idea.vim.ui.ShowCmdStatusBarWidgetFactory" order="first"/>
|
||||
|
||||
<applicationService serviceImplementation="com.maddyhome.idea.vim.config.VimLocalConfig"/>
|
||||
<applicationService serviceImplementation="com.maddyhome.idea.vim.VimPlugin"/>
|
||||
|
||||
<!-- Initialise as early as possible so that we're ready to edit quickly. This is especially important for Rider,
|
||||
|
@@ -140,6 +140,6 @@ public class EventFacade {
|
||||
}
|
||||
|
||||
private @NotNull TypedAction getTypedAction() {
|
||||
return EditorActionManager.getInstance().getTypedAction();
|
||||
return TypedAction.getInstance();
|
||||
}
|
||||
}
|
||||
|
@@ -45,8 +45,8 @@ import com.maddyhome.idea.vim.handler.EditorActionHandlerBase;
|
||||
import com.maddyhome.idea.vim.helper.*;
|
||||
import com.maddyhome.idea.vim.key.*;
|
||||
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.ex.ExEntryPanel;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -319,7 +319,7 @@ public class KeyHandler {
|
||||
}
|
||||
}
|
||||
reset(editor);
|
||||
ChangeGroup.resetCaret(editor, VimPlugin.getEditor().isBarCursor());
|
||||
ChangeGroup.resetCaret(editor, false);
|
||||
}
|
||||
|
||||
private boolean handleKeyMapping(final @NotNull Editor editor,
|
||||
@@ -692,7 +692,7 @@ public class KeyHandler {
|
||||
@NotNull CommandNode node,
|
||||
CommandState editorState) {
|
||||
// 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 Argument.Type expectedArgumentType = commandBuilder.getExpectedArgumentType();
|
||||
|
||||
@@ -739,7 +739,7 @@ public class KeyHandler {
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -934,6 +934,7 @@ public class KeyHandler {
|
||||
if (editorState.getSubMode() == CommandState.SubMode.SINGLE_COMMAND &&
|
||||
(!cmd.getFlags().contains(CommandFlags.FLAG_EXPECT_MORE))) {
|
||||
editorState.popModes();
|
||||
VisualGroupKt.resetShape(CommandStateHelper.getMode(editor), editor);
|
||||
}
|
||||
|
||||
if (editorState.getCommandBuilder().isDone()) {
|
||||
|
@@ -53,7 +53,7 @@ public class RegisterActions {
|
||||
|
||||
public static @Nullable EditorActionHandlerBase findAction(@NotNull String id) {
|
||||
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) {
|
||||
|
@@ -19,6 +19,7 @@ package com.maddyhome.idea.vim;
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.openapi.Disposable;
|
||||
@@ -40,7 +41,6 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.maddyhome.idea.vim.config.VimLocalConfig;
|
||||
import com.maddyhome.idea.vim.config.VimState;
|
||||
import com.maddyhome.idea.vim.config.migration.ApplicationConfigurationMigrator;
|
||||
import com.maddyhome.idea.vim.ex.CommandParser;
|
||||
@@ -105,11 +105,6 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
public void initialize() {
|
||||
LOG.debug("initComponent");
|
||||
|
||||
// Initialize a legacy local config.
|
||||
if (previousStateVersion == 5) {
|
||||
//noinspection deprecation
|
||||
VimLocalConfig.Companion.initialize();
|
||||
}
|
||||
if (enabled) {
|
||||
Application application = ApplicationManager.getApplication();
|
||||
if (application.isUnitTestMode()) {
|
||||
@@ -168,7 +163,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
}
|
||||
|
||||
public static @Nullable RegisterGroup getRegisterIfCreated() {
|
||||
return ServiceManager.getServiceIfCreated(RegisterGroup.class);
|
||||
return ApplicationManager.getApplication().getServiceIfCreated(RegisterGroup.class);
|
||||
}
|
||||
|
||||
public static @NotNull FileGroup getFile() {
|
||||
@@ -180,7 +175,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
}
|
||||
|
||||
public static @Nullable SearchGroup getSearchIfCreated() {
|
||||
return ServiceManager.getServiceIfCreated(SearchGroup.class);
|
||||
return ApplicationManager.getApplication().getServiceIfCreated(SearchGroup.class);
|
||||
}
|
||||
|
||||
public static @NotNull ProcessGroup getProcess() {
|
||||
@@ -204,7 +199,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
}
|
||||
|
||||
public static @Nullable KeyGroup getKeyIfCreated() {
|
||||
return ServiceManager.getServiceIfCreated(KeyGroup.class);
|
||||
return ApplicationManager.getApplication().getServiceIfCreated(KeyGroup.class);
|
||||
}
|
||||
|
||||
public static @NotNull WindowGroup getWindow() {
|
||||
@@ -216,7 +211,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
}
|
||||
|
||||
public static @Nullable EditorGroup getEditorIfCreated() {
|
||||
return ServiceManager.getServiceIfCreated(EditorGroup.class);
|
||||
return ApplicationManager.getApplication().getServiceIfCreated(EditorGroup.class);
|
||||
}
|
||||
|
||||
public static @NotNull VisualMotionGroup getVisualMotion() {
|
||||
@@ -263,7 +258,7 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
|
||||
}
|
||||
|
||||
public static @NotNull String getVersion() {
|
||||
final IdeaPluginDescriptor plugin = PluginManager.getPlugin(getPluginId());
|
||||
final IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(getPluginId());
|
||||
if (!ApplicationManager.getApplication().isInternal()) {
|
||||
return plugin != null ? plugin.getVersion() : "SNAPSHOT";
|
||||
}
|
||||
|
@@ -41,6 +41,7 @@ import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere
|
||||
import com.maddyhome.idea.vim.helper.isPrimaryEditor
|
||||
import com.maddyhome.idea.vim.helper.isTemplateActive
|
||||
import com.maddyhome.idea.vim.key.ShortcutOwner
|
||||
import com.maddyhome.idea.vim.listener.IdeaSpecifics.AppCodeTemplates.appCodeTemplateCaptured
|
||||
import com.maddyhome.idea.vim.listener.IdeaSpecifics.aceJumpActive
|
||||
import com.maddyhome.idea.vim.option.OptionsManager
|
||||
import java.awt.event.InputEvent
|
||||
@@ -99,6 +100,8 @@ class VimShortcutKeyAction : AnAction(), DumbAware {
|
||||
|
||||
if (keyCode == KeyEvent.VK_TAB && editor.isTemplateActive()) return false
|
||||
|
||||
if ((keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_ENTER) && editor.appCodeTemplateCaptured()) return false
|
||||
|
||||
if (editor.inInsertMode) { // XXX: <Tab> won't be recorded in macros
|
||||
if (keyCode == KeyEvent.VK_TAB) {
|
||||
VimPlugin.getChange().tabAction = true
|
||||
|
@@ -27,6 +27,7 @@ import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.Command
|
||||
import com.maddyhome.idea.vim.ex.CommandParser
|
||||
import com.maddyhome.idea.vim.ex.ExException
|
||||
import com.maddyhome.idea.vim.group.RegisterGroup
|
||||
import com.maddyhome.idea.vim.handler.VimActionHandler
|
||||
|
||||
class PlaybackRegisterAction : VimActionHandler.SingleExecution() {
|
||||
@@ -44,7 +45,7 @@ class PlaybackRegisterAction : VimActionHandler.SingleExecution() {
|
||||
'@' -> {
|
||||
application.runWriteAction { res.set(VimPlugin.getMacro().playbackLastRegister(editor, context, project, cmd.count)) }
|
||||
}
|
||||
':' -> { // No write action
|
||||
RegisterGroup.LAST_COMMAND_REGISTER -> { // No write action
|
||||
try {
|
||||
res.set(CommandParser.getInstance().processLastCommand(editor, context, cmd.count))
|
||||
} catch (e: ExException) {
|
||||
|
@@ -47,9 +47,7 @@ class MotionScrollPageDownAction : VimActionHandler.SingleExecution() {
|
||||
class MotionScrollPageDownInsertModeAction : VimActionHandler.SingleExecution(), ComplicatedKeysAction {
|
||||
|
||||
override val keyStrokesSet: Set<List<KeyStroke>> = setOf(
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.SHIFT_DOWN_MASK)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_KP_DOWN, KeyEvent.SHIFT_DOWN_MASK))
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0))
|
||||
)
|
||||
|
||||
override val type: Command.Type = Command.Type.OTHER_READONLY
|
||||
|
@@ -47,9 +47,7 @@ class MotionScrollPageUpAction : VimActionHandler.SingleExecution() {
|
||||
class MotionScrollPageUpInsertModeAction : VimActionHandler.SingleExecution(), ComplicatedKeysAction {
|
||||
|
||||
override val keyStrokesSet: Set<List<KeyStroke>> = setOf(
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.SHIFT_DOWN_MASK)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_KP_UP, KeyEvent.SHIFT_DOWN_MASK))
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0))
|
||||
)
|
||||
|
||||
override val type: Command.Type = Command.Type.OTHER_READONLY
|
||||
|
@@ -25,6 +25,7 @@ import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.CommandFlags
|
||||
import com.maddyhome.idea.vim.command.MotionType
|
||||
import com.maddyhome.idea.vim.handler.MotionActionHandler
|
||||
import com.maddyhome.idea.vim.helper.Direction
|
||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||
import java.util.*
|
||||
|
||||
@@ -37,7 +38,7 @@ class SearchWholeWordBackwardAction : MotionActionHandler.ForEachCaret() {
|
||||
count: Int,
|
||||
rawCount: Int,
|
||||
argument: Argument?): Int {
|
||||
return VimPlugin.getSearch().searchWord(editor, caret, count, true, -1)
|
||||
return VimPlugin.getSearch().searchWord(editor, caret, count, true, Direction.BACKWARDS)
|
||||
}
|
||||
|
||||
override val motionType: MotionType = MotionType.EXCLUSIVE
|
||||
|
@@ -25,6 +25,7 @@ import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.CommandFlags
|
||||
import com.maddyhome.idea.vim.command.MotionType
|
||||
import com.maddyhome.idea.vim.handler.MotionActionHandler
|
||||
import com.maddyhome.idea.vim.helper.Direction
|
||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||
import java.util.*
|
||||
|
||||
@@ -37,7 +38,7 @@ class SearchWholeWordForwardAction : MotionActionHandler.ForEachCaret() {
|
||||
count: Int,
|
||||
rawCount: Int,
|
||||
argument: Argument?): Int {
|
||||
return VimPlugin.getSearch().searchWord(editor, caret, count, true, 1)
|
||||
return VimPlugin.getSearch().searchWord(editor, caret, count, true, Direction.FORWARDS)
|
||||
}
|
||||
|
||||
override val motionType: MotionType = MotionType.EXCLUSIVE
|
||||
|
@@ -25,6 +25,7 @@ import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.CommandFlags
|
||||
import com.maddyhome.idea.vim.command.MotionType
|
||||
import com.maddyhome.idea.vim.handler.MotionActionHandler
|
||||
import com.maddyhome.idea.vim.helper.Direction
|
||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||
import java.util.*
|
||||
|
||||
@@ -37,7 +38,7 @@ class SearchWordBackwardAction : MotionActionHandler.ForEachCaret() {
|
||||
count: Int,
|
||||
rawCount: Int,
|
||||
argument: Argument?): Int {
|
||||
return VimPlugin.getSearch().searchWord(editor, caret, count, false, -1)
|
||||
return VimPlugin.getSearch().searchWord(editor, caret, count, false, Direction.BACKWARDS)
|
||||
}
|
||||
|
||||
override val motionType: MotionType = MotionType.EXCLUSIVE
|
||||
|
@@ -25,6 +25,7 @@ import com.maddyhome.idea.vim.command.Argument
|
||||
import com.maddyhome.idea.vim.command.CommandFlags
|
||||
import com.maddyhome.idea.vim.command.MotionType
|
||||
import com.maddyhome.idea.vim.handler.MotionActionHandler
|
||||
import com.maddyhome.idea.vim.helper.Direction
|
||||
import com.maddyhome.idea.vim.helper.enumSetOf
|
||||
import java.util.*
|
||||
|
||||
@@ -37,7 +38,7 @@ class SearchWordForwardAction : MotionActionHandler.ForEachCaret() {
|
||||
count: Int,
|
||||
rawCount: Int,
|
||||
argument: Argument?): Int {
|
||||
return VimPlugin.getSearch().searchWord(editor, caret, count, false, 1)
|
||||
return VimPlugin.getSearch().searchWord(editor, caret, count, false, Direction.FORWARDS)
|
||||
}
|
||||
|
||||
override val motionType: MotionType = MotionType.EXCLUSIVE
|
||||
|
@@ -51,9 +51,7 @@ class MotionWordLeftInsertAction : MotionActionHandler.ForEachCaret(), Complicat
|
||||
|
||||
override val keyStrokesSet: Set<List<KeyStroke>> = setOf(
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.CTRL_DOWN_MASK)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, KeyEvent.CTRL_DOWN_MASK)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.SHIFT_DOWN_MASK)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, KeyEvent.SHIFT_DOWN_MASK))
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, KeyEvent.CTRL_DOWN_MASK))
|
||||
)
|
||||
|
||||
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_SAVE_STROKE)
|
||||
|
@@ -51,9 +51,7 @@ class MotionWordRightInsertAction : MotionActionHandler.ForEachCaret(), Complica
|
||||
|
||||
override val keyStrokesSet: Set<List<KeyStroke>> = setOf(
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.CTRL_DOWN_MASK)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, KeyEvent.CTRL_DOWN_MASK)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.SHIFT_DOWN_MASK)),
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, KeyEvent.SHIFT_DOWN_MASK))
|
||||
listOf(KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, KeyEvent.CTRL_DOWN_MASK))
|
||||
)
|
||||
|
||||
override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_SAVE_STROKE)
|
||||
|
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.maddyhome.idea.vim.config
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent
|
||||
import com.intellij.openapi.components.RoamingType
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.components.State
|
||||
import com.intellij.openapi.components.Storage
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import org.jdom.Element
|
||||
|
||||
/**
|
||||
* @author Alex Plate
|
||||
*/
|
||||
|
||||
@State(name = "VimLocalSettings", storages = [
|
||||
Storage("\$APP_CONFIG$$/vim_local_settings.xml", roamingType = RoamingType.DISABLED, deprecated = true),
|
||||
Storage("\$APP_CONFIG$/vim_local_settings.xml", roamingType = RoamingType.DISABLED, deprecated = true)
|
||||
])
|
||||
@Deprecated("The data from this class will be stored in vim_settings")
|
||||
class VimLocalConfig : PersistentStateComponent<Element> {
|
||||
override fun getState(): Element? = null
|
||||
|
||||
override fun loadState(state: Element) {
|
||||
// This is initialization of state from the legacy configuration structure.
|
||||
// This code should be performed only once on settings migration.
|
||||
// After the migration is done, the file with settings gets removed and this method won't be called again.
|
||||
VimPlugin.getMark().readData(state)
|
||||
VimPlugin.getRegister().readData(state)
|
||||
VimPlugin.getSearch().readData(state)
|
||||
VimPlugin.getHistory().readData(state)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun initialize() {
|
||||
@Suppress("DEPRECATION")
|
||||
ServiceManager.getService(VimLocalConfig::class.java)
|
||||
}
|
||||
}
|
||||
}
|
@@ -24,13 +24,12 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
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.TextRange;
|
||||
import com.maddyhome.idea.vim.ex.handler.GotoLineHandler;
|
||||
import com.maddyhome.idea.vim.ex.ranges.Range;
|
||||
import com.maddyhome.idea.vim.ex.ranges.Ranges;
|
||||
import com.maddyhome.idea.vim.group.HistoryGroup;
|
||||
import com.maddyhome.idea.vim.group.RegisterGroup;
|
||||
import com.maddyhome.idea.vim.helper.MessageHelper;
|
||||
import com.maddyhome.idea.vim.helper.Msg;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -177,8 +176,7 @@ public class CommandParser {
|
||||
ThrowableComputable<Object, ExException> runCommand = () -> {
|
||||
boolean ok = handler.process(editor, context, command, count);
|
||||
if (ok && !handler.getArgFlags().getFlags().contains(CommandHandler.Flag.DONT_SAVE_LAST)) {
|
||||
VimPlugin.getRegister().storeTextInternal(editor, new TextRange(-1, -1), cmd,
|
||||
SelectionType.CHARACTER_WISE, ':', false);
|
||||
VimPlugin.getRegister().storeTextSpecial(RegisterGroup.LAST_COMMAND_REGISTER, cmd);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -210,7 +208,7 @@ public class CommandParser {
|
||||
}
|
||||
}
|
||||
final ExBeanClass handlerHolder = node.getCommandHandler();
|
||||
return handlerHolder != null ? handlerHolder.getHandler() : null;
|
||||
return handlerHolder != null ? handlerHolder.getInstance() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,8 +556,8 @@ public class CommandParser {
|
||||
if (handlerHolder.getNames() != null) {
|
||||
names = CommandDefinitionKt.commands(handlerHolder.getNames().split(","));
|
||||
}
|
||||
else if (handlerHolder.getHandler() instanceof ComplicatedNameExCommand) {
|
||||
names = ((ComplicatedNameExCommand)handlerHolder.getHandler()).getNames();
|
||||
else if (handlerHolder.getInstance() instanceof ComplicatedNameExCommand) {
|
||||
names = ((ComplicatedNameExCommand)handlerHolder.getInstance()).getNames();
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Cannot create an ex command: " + handlerHolder);
|
||||
|
@@ -18,29 +18,23 @@
|
||||
|
||||
package com.maddyhome.idea.vim.ex
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
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.maddyhome.idea.vim.VimPlugin
|
||||
|
||||
// [Version Update] 202+
|
||||
@Suppress("DEPRECATION")
|
||||
class ExBeanClass : AbstractExtensionPointBean() {
|
||||
class ExBeanClass : BaseKeyedLazyInstance<CommandHandler>() {
|
||||
@Attribute("implementation")
|
||||
var implementation: String? = null
|
||||
|
||||
@Attribute("names")
|
||||
var names: String? = null
|
||||
|
||||
val handler: CommandHandler by lazy {
|
||||
this.instantiateClass<CommandHandler>(
|
||||
implementation ?: "", ApplicationManager.getApplication().picoContainer)
|
||||
}
|
||||
override fun getImplementationClassName(): String? = implementation
|
||||
|
||||
fun register() {
|
||||
if (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")
|
||||
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: ${this.pluginDescriptor.pluginId}")
|
||||
return
|
||||
}
|
||||
CommandParser.getInstance().addHandler(this)
|
||||
|
@@ -18,19 +18,13 @@
|
||||
|
||||
package com.maddyhome.idea.vim.extension
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.extensions.AbstractExtensionPointBean
|
||||
import com.intellij.serviceContainer.BaseKeyedLazyInstance
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
import com.intellij.util.xmlb.annotations.Tag
|
||||
import com.intellij.util.xmlb.annotations.XCollection
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
// [Version Update] 202+
|
||||
@Suppress("DEPRECATION")
|
||||
class ExtensionBeanClass : AbstractExtensionPointBean() {
|
||||
init {
|
||||
println()
|
||||
}
|
||||
class ExtensionBeanClass : BaseKeyedLazyInstance<VimExtension>() {
|
||||
|
||||
@Attribute("implementation")
|
||||
var implementation: String? = null
|
||||
|
||||
@@ -46,14 +40,7 @@ class ExtensionBeanClass : AbstractExtensionPointBean() {
|
||||
@XCollection
|
||||
var aliases: List<Alias>? = null
|
||||
|
||||
var initialized = AtomicBoolean(false)
|
||||
|
||||
val handler: VimExtension by lazy {
|
||||
initialized.set(true)
|
||||
this.instantiateClass<VimExtension>(
|
||||
implementation ?: "", ApplicationManager.getApplication().picoContainer
|
||||
)
|
||||
}
|
||||
override fun getImplementationClassName(): String? = implementation
|
||||
}
|
||||
|
||||
@Tag("alias")
|
||||
|
@@ -41,9 +41,7 @@ object VimExtensionRegistrar {
|
||||
|
||||
VimExtension.EP_NAME.extensions.forEach(this::registerExtension)
|
||||
|
||||
// [VERSION UPDATE] 202+
|
||||
@Suppress("DEPRECATION")
|
||||
VimExtension.EP_NAME.getPoint(null).addExtensionPointListener(object : ExtensionPointListener<ExtensionBeanClass> {
|
||||
VimExtension.EP_NAME.point.addExtensionPointListener(object : ExtensionPointListener<ExtensionBeanClass> {
|
||||
override fun extensionAdded(extension: ExtensionBeanClass, pluginDescriptor: PluginDescriptor) {
|
||||
registerExtension(extension)
|
||||
}
|
||||
@@ -56,7 +54,7 @@ object VimExtensionRegistrar {
|
||||
|
||||
@Synchronized
|
||||
private fun registerExtension(extensionBean: ExtensionBeanClass) {
|
||||
val name = extensionBean.name ?: extensionBean.handler.name
|
||||
val name = extensionBean.name ?: extensionBean.instance.name
|
||||
if (name in registeredExtensions) return
|
||||
|
||||
registeredExtensions.add(name)
|
||||
@@ -64,10 +62,10 @@ object VimExtensionRegistrar {
|
||||
val option = ToggleOption(name, name, false)
|
||||
option.addOptionChangeListener { _, _ ->
|
||||
if (isSet(name)) {
|
||||
extensionBean.handler.init()
|
||||
extensionBean.instance.init()
|
||||
logger.info("IdeaVim extension '$name' initialized")
|
||||
} else {
|
||||
extensionBean.handler.dispose()
|
||||
extensionBean.instance.dispose()
|
||||
}
|
||||
}
|
||||
addOption(option)
|
||||
@@ -75,13 +73,11 @@ object VimExtensionRegistrar {
|
||||
|
||||
@Synchronized
|
||||
private fun unregisterExtension(extension: ExtensionBeanClass) {
|
||||
val name = extension.name ?: extension.handler.name
|
||||
val name = extension.name ?: extension.instance.name
|
||||
if (name !in registeredExtensions) return
|
||||
registeredExtensions.remove(name)
|
||||
removeAliases(extension)
|
||||
if (extension.initialized.get()) {
|
||||
extension.handler.dispose()
|
||||
}
|
||||
extension.instance.dispose()
|
||||
removeOption(name)
|
||||
remove(name)
|
||||
logger.info("IdeaVim extension '$name' disposed")
|
||||
@@ -95,7 +91,7 @@ object VimExtensionRegistrar {
|
||||
private fun registerAliases(extension: ExtensionBeanClass) {
|
||||
extension.aliases
|
||||
?.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) {
|
||||
|
@@ -33,6 +33,7 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping
|
||||
import com.maddyhome.idea.vim.extension.VimExtensionHandler
|
||||
import com.maddyhome.idea.vim.group.MotionGroup
|
||||
import com.maddyhome.idea.vim.group.visual.vimSetSelection
|
||||
import com.maddyhome.idea.vim.helper.Direction
|
||||
import com.maddyhome.idea.vim.helper.EditorHelper
|
||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||
import com.maddyhome.idea.vim.helper.SearchHelper.findWordUnderCursor
|
||||
@@ -48,18 +49,23 @@ import java.util.*
|
||||
// [VERSION UPDATE] 203+ Annotation should be replaced with @NlsSafe
|
||||
@NonNls
|
||||
private const val NEXT_WHOLE_OCCURRENCE = "<Plug>NextWholeOccurrence"
|
||||
|
||||
// [VERSION UPDATE] 203+ Annotation should be replaced with @NlsSafe
|
||||
@NonNls
|
||||
private const val NEXT_OCCURRENCE = "<Plug>NextOccurrence"
|
||||
|
||||
// [VERSION UPDATE] 203+ Annotation should be replaced with @NlsSafe
|
||||
@NonNls
|
||||
private const val SKIP_OCCURRENCE = "<Plug>SkipOccurrence"
|
||||
|
||||
// [VERSION UPDATE] 203+ Annotation should be replaced with @NlsSafe
|
||||
@NonNls
|
||||
private const val REMOVE_OCCURRENCE = "<Plug>RemoveOccurrence"
|
||||
|
||||
// [VERSION UPDATE] 203+ Annotation should be replaced with @NlsSafe
|
||||
@NonNls
|
||||
private const val ALL_WHOLE_OCCURRENCES = "<Plug>AllWholeOccurrences"
|
||||
|
||||
// [VERSION UPDATE] 203+ Annotation should be replaced with @NlsSafe
|
||||
@NonNls
|
||||
private const val ALL_OCCURRENCES = "<Plug>AllOccurrences"
|
||||
@@ -75,11 +81,23 @@ class VimMultipleCursorsExtension : VimExtension {
|
||||
|
||||
override fun init() {
|
||||
putExtensionHandlerMapping(MappingMode.NXO, parseKeys(NEXT_WHOLE_OCCURRENCE), owner, NextOccurrenceHandler(), false)
|
||||
putExtensionHandlerMapping(MappingMode.NXO, parseKeys(NEXT_OCCURRENCE), owner, NextOccurrenceHandler(whole = false), false)
|
||||
putExtensionHandlerMapping(MappingMode.NXO, parseKeys(ALL_WHOLE_OCCURRENCES), owner, AllOccurrencesHandler(), false )
|
||||
putExtensionHandlerMapping(MappingMode.NXO, parseKeys(ALL_OCCURRENCES), owner, AllOccurrencesHandler(whole = false), false )
|
||||
putExtensionHandlerMapping(MappingMode.X, parseKeys(SKIP_OCCURRENCE), owner, SkipOccurrenceHandler(), false )
|
||||
putExtensionHandlerMapping(MappingMode.X, parseKeys(REMOVE_OCCURRENCE), owner, RemoveOccurrenceHandler(), false )
|
||||
putExtensionHandlerMapping(
|
||||
MappingMode.NXO,
|
||||
parseKeys(NEXT_OCCURRENCE),
|
||||
owner,
|
||||
NextOccurrenceHandler(whole = false),
|
||||
false
|
||||
)
|
||||
putExtensionHandlerMapping(MappingMode.NXO, parseKeys(ALL_WHOLE_OCCURRENCES), owner, AllOccurrencesHandler(), false)
|
||||
putExtensionHandlerMapping(
|
||||
MappingMode.NXO,
|
||||
parseKeys(ALL_OCCURRENCES),
|
||||
owner,
|
||||
AllOccurrencesHandler(whole = false),
|
||||
false
|
||||
)
|
||||
putExtensionHandlerMapping(MappingMode.X, parseKeys(SKIP_OCCURRENCE), owner, SkipOccurrenceHandler(), false)
|
||||
putExtensionHandlerMapping(MappingMode.X, parseKeys(REMOVE_OCCURRENCE), owner, RemoveOccurrenceHandler(), false)
|
||||
|
||||
putKeyMapping(MappingMode.NXO, parseKeys("<A-n>"), owner, parseKeys(NEXT_WHOLE_OCCURRENCE), true)
|
||||
putKeyMapping(MappingMode.NXO, parseKeys("g<A-n>"), owner, parseKeys(NEXT_OCCURRENCE), true)
|
||||
@@ -100,7 +118,8 @@ class VimMultipleCursorsExtension : VimExtension {
|
||||
inner class NextOccurrenceHandler(val whole: Boolean = true) : WriteActionHandler() {
|
||||
override fun executeInWriteAction(editor: Editor, context: DataContext) {
|
||||
val caretModel = editor.caretModel
|
||||
val patternComparator = if (OptionsManager.ignorecase.isSet) String.CASE_INSENSITIVE_ORDER else Comparator(String::compareTo)
|
||||
val patternComparator =
|
||||
if (OptionsManager.ignorecase.isSet) String.CASE_INSENSITIVE_ORDER else Comparator(String::compareTo)
|
||||
|
||||
if (!editor.inVisualMode) {
|
||||
if (caretModel.caretCount > 1) return
|
||||
@@ -138,10 +157,18 @@ class VimMultipleCursorsExtension : VimExtension {
|
||||
val primaryCaret = editor.caretModel.primaryCaret
|
||||
val nextOffset = VimPlugin.getSearch().searchNextFromOffset(editor, primaryCaret.offset + 1, 1)
|
||||
val pattern = patterns.first()
|
||||
if (nextOffset == -1 || patternComparator.compare(EditorHelper.getText(editor, nextOffset, nextOffset + pattern.length), pattern) != 0) {
|
||||
if (nextOffset == -1 || patternComparator.compare(
|
||||
EditorHelper.getText(
|
||||
editor,
|
||||
nextOffset,
|
||||
nextOffset + pattern.length
|
||||
), pattern
|
||||
) != 0
|
||||
) {
|
||||
if (caretModel.caretCount > 1) return
|
||||
|
||||
val newNextOffset = VimPlugin.getSearch().search(editor, pattern, 1, EnumSet.of(CommandFlags.FLAG_SEARCH_FWD), false)
|
||||
val newNextOffset =
|
||||
VimPlugin.getSearch().search(editor, pattern, 1, EnumSet.of(CommandFlags.FLAG_SEARCH_FWD), false)
|
||||
|
||||
if (newNextOffset != -1) {
|
||||
val caret = editor.caretModel.addCaret(editor.offsetToVisualPosition(newNextOffset)) ?: return
|
||||
@@ -172,7 +199,8 @@ class VimMultipleCursorsExtension : VimExtension {
|
||||
val primaryCaret = caretModel.primaryCaret
|
||||
var nextOffset = if (editor.inVisualMode) {
|
||||
val selectedText = primaryCaret.selectedText ?: return
|
||||
val nextOffset = VimPlugin.getSearch().search(editor, selectedText, 1, EnumSet.of(CommandFlags.FLAG_SEARCH_FWD), false)
|
||||
val nextOffset =
|
||||
VimPlugin.getSearch().search(editor, selectedText, 1, EnumSet.of(CommandFlags.FLAG_SEARCH_FWD), false)
|
||||
nextOffset
|
||||
} else {
|
||||
val range = findWordUnderCursor(editor, primaryCaret) ?: return
|
||||
@@ -242,7 +270,7 @@ class VimMultipleCursorsExtension : VimExtension {
|
||||
val wordRange = VimPlugin.getMotion().getWordRange(editor, caret, 1, false, false)
|
||||
caret.vimSetSelection(wordRange.startOffset, wordRange.endOffsetInclusive, true)
|
||||
|
||||
val offset = VimPlugin.getSearch().searchWord(editor, caret, 1, whole, 1)
|
||||
val offset = VimPlugin.getSearch().searchWord(editor, caret, 1, whole, Direction.FORWARDS)
|
||||
MotionGroup.moveCaret(editor, caret, range.endOffset - 1)
|
||||
|
||||
return offset
|
||||
|
@@ -1765,27 +1765,7 @@ public class ChangeGroup {
|
||||
}
|
||||
|
||||
public static void resetCaret(@NotNull Editor editor, boolean insert) {
|
||||
Document doc = editor.getDocument();
|
||||
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);
|
||||
}
|
||||
editor.getSettings().setBlockCursor(!insert);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -27,9 +27,11 @@ import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.event.CaretEvent;
|
||||
import com.intellij.openapi.editor.event.CaretListener;
|
||||
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
|
||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.maddyhome.idea.vim.KeyHandler;
|
||||
import com.maddyhome.idea.vim.VimPlugin;
|
||||
import com.maddyhome.idea.vim.group.visual.VisualGroupKt;
|
||||
import com.maddyhome.idea.vim.helper.*;
|
||||
import com.maddyhome.idea.vim.option.OptionChangeListener;
|
||||
import com.maddyhome.idea.vim.option.OptionsManager;
|
||||
@@ -204,8 +206,8 @@ public class EditorGroup implements PersistentStateComponent<Element> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBarCursor() {
|
||||
return !isBlockCursor;
|
||||
public boolean isBarCursorSettings() {
|
||||
return !EditorSettingsExternalizable.getInstance().isBlockCursor();
|
||||
}
|
||||
|
||||
public void editorCreated(@NotNull Editor editor) {
|
||||
@@ -222,7 +224,7 @@ public class EditorGroup implements PersistentStateComponent<Element> {
|
||||
VimPlugin.getChange().insertBeforeCursor(editor, new EditorDataContext(editor, null));
|
||||
KeyHandler.getInstance().reset(editor);
|
||||
}
|
||||
editor.getSettings().setBlockCursor(!CommandStateHelper.inInsertMode(editor) || isBlockCursor);
|
||||
VisualGroupKt.resetShape(CommandStateHelper.getMode(editor), editor);
|
||||
editor.getSettings().setRefrainFromScrolling(REFRAIN_FROM_SCROLLING_VIM_VALUE);
|
||||
}
|
||||
|
||||
|
@@ -307,17 +307,17 @@ public class KeyGroup implements PersistentStateComponent<Element> {
|
||||
|
||||
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. " +
|
||||
"Please create a plugin using `VimExtension`. " +
|
||||
"Plugin to blame: " +
|
||||
actionHolder.getPluginId());
|
||||
actionHolder.getPluginDescriptor().getPluginId());
|
||||
return;
|
||||
}
|
||||
|
||||
Set<List<KeyStroke>> actionKeys = actionHolder.getParsedKeys();
|
||||
if (actionKeys == null) {
|
||||
final EditorActionHandlerBase action = actionHolder.getAction();
|
||||
final EditorActionHandlerBase action = actionHolder.getInstance();
|
||||
if (action instanceof ComplicatedKeysAction) {
|
||||
actionKeys = ((ComplicatedKeysAction)action).getKeyStrokesSet();
|
||||
}
|
||||
@@ -337,7 +337,7 @@ public class KeyGroup implements PersistentStateComponent<Element> {
|
||||
prefixes = new HashMap<>();
|
||||
}
|
||||
for (List<KeyStroke> keys : actionKeys) {
|
||||
checkCommand(actionModes, actionHolder.getAction(), keys);
|
||||
checkCommand(actionModes, actionHolder.getInstance(), keys);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -41,6 +41,7 @@ import com.maddyhome.idea.vim.group.visual.VisualGroupKt;
|
||||
import com.maddyhome.idea.vim.handler.MotionActionHandler;
|
||||
import com.maddyhome.idea.vim.handler.TextObjectActionHandler;
|
||||
import com.maddyhome.idea.vim.helper.*;
|
||||
import com.maddyhome.idea.vim.listener.IdeaSpecifics;
|
||||
import com.maddyhome.idea.vim.option.NumberOption;
|
||||
import com.maddyhome.idea.vim.option.OptionChangeListener;
|
||||
import com.maddyhome.idea.vim.option.OptionsManager;
|
||||
@@ -318,6 +319,8 @@ public class MotionGroup {
|
||||
else {
|
||||
ModeHelper.exitVisualMode(editor);
|
||||
}
|
||||
|
||||
IdeaSpecifics.AppCodeTemplates.onMovement(editor, caret, oldOffset < offset);
|
||||
}
|
||||
|
||||
private @Nullable Editor selectEditor(@NotNull Editor editor, @NotNull Mark mark) {
|
||||
|
@@ -18,7 +18,6 @@
|
||||
|
||||
package com.maddyhome.idea.vim.group;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.intellij.codeInsight.editorActions.CopyPastePostProcessor;
|
||||
import com.intellij.codeInsight.editorActions.CopyPastePreProcessor;
|
||||
import com.intellij.codeInsight.editorActions.TextBlockTransferable;
|
||||
@@ -81,18 +80,33 @@ import java.util.stream.Collectors;
|
||||
@Storage(value = "$APP_CONFIG$/vim_settings_local.xml", roamingType = RoamingType.DISABLED)
|
||||
})
|
||||
public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
private static final @NonNls String WRITABLE_REGISTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-*+_/\"";
|
||||
private static final String READONLY_REGISTERS = ":.%#=/";
|
||||
private static final @NonNls String RECORDABLE_REGISTER = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
private static final String PLAYBACK_REGISTER = RECORDABLE_REGISTER + "\".*+";
|
||||
public static final char UNNAMED_REGISTER = '"';
|
||||
public static final char LAST_SEARCH_REGISTER = '/'; // IdeaVim does not supporting writing to this register
|
||||
public static final char LAST_COMMAND_REGISTER = ':';
|
||||
private static final char LAST_INSERTED_TEXT_REGISTER = '.';
|
||||
public static final char SMALL_DELETION_REGISTER = '-';
|
||||
private static final char BLACK_HOLE_REGISTER = '_';
|
||||
private static final char ALTERNATE_BUFFER_REGISTER = '#'; // Not supported
|
||||
private static final char EXPRESSION_BUFFER_REGISTER = '='; // Not supported
|
||||
private static final char CURRENT_FILENAME_REGISTER = '%'; // Not supported
|
||||
private static final @NonNls String CLIPBOARD_REGISTERS = "*+";
|
||||
private static final @NonNls String NUMBERED_REGISTERS = "0123456789";
|
||||
private static final @NonNls String NAMED_REGISTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
private static final @NonNls String WRITABLE_REGISTERS = NUMBERED_REGISTERS + NAMED_REGISTERS + CLIPBOARD_REGISTERS
|
||||
+ SMALL_DELETION_REGISTER + BLACK_HOLE_REGISTER + UNNAMED_REGISTER + LAST_SEARCH_REGISTER;
|
||||
private static final String READONLY_REGISTERS = ""
|
||||
+ CURRENT_FILENAME_REGISTER + LAST_COMMAND_REGISTER + LAST_INSERTED_TEXT_REGISTER + ALTERNATE_BUFFER_REGISTER
|
||||
+ EXPRESSION_BUFFER_REGISTER; // Expression buffer is not actually readonly
|
||||
private static final @NonNls String RECORDABLE_REGISTERS = NUMBERED_REGISTERS + NAMED_REGISTERS;
|
||||
private static final String PLAYBACK_REGISTERS = RECORDABLE_REGISTERS + UNNAMED_REGISTER + CLIPBOARD_REGISTERS + LAST_INSERTED_TEXT_REGISTER;
|
||||
private static final String VALID_REGISTERS = WRITABLE_REGISTERS + READONLY_REGISTERS;
|
||||
private static final List<Character> CLIPBOARD_REGISTERS = ImmutableList.of('*', '+');
|
||||
|
||||
private static final Logger logger = Logger.getInstance(RegisterGroup.class.getName());
|
||||
|
||||
public static final char UNNAMED_REGISTER = '"';
|
||||
private final @NotNull HashMap<Character, Register> registers = new HashMap<>();
|
||||
private char defaultRegister = UNNAMED_REGISTER;
|
||||
private char lastRegister = defaultRegister;
|
||||
private final @NotNull HashMap<Character, Register> registers = new HashMap<>();
|
||||
private char recordRegister = 0;
|
||||
private @Nullable List<KeyStroke> recordList = null;
|
||||
|
||||
@@ -173,10 +187,35 @@ public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean storeTextInternal(@NotNull Editor editor, @NotNull TextRange range, @NotNull String text,
|
||||
@NotNull SelectionType type, char register, boolean isDelete) {
|
||||
// Null register doesn't get saved
|
||||
if (lastRegister == '_') return true;
|
||||
/**
|
||||
* Stores text, character wise, in the given special register
|
||||
*
|
||||
* <p>This method is intended to support writing to registers when the text cannot be yanked from an editor. This is
|
||||
* expected to only be used to update the search and command registers. It will not update named registers.</p>
|
||||
*
|
||||
* <p>While this method allows setting the unnamed register, this should only be done from tests, and only when it's
|
||||
* not possible to yank or cut from the fixture editor. This method will skip additional text processing, and won't
|
||||
* update other registers such as the small delete register or reorder the numbered registers. It is much more
|
||||
* preferable to yank from the fixture editor.</p>
|
||||
*
|
||||
* @param register The register to use for storing the text. Cannot be a normal text register
|
||||
* @param text The text to store, without further processing
|
||||
* @return True if the text is stored, false if the passed register is not supported
|
||||
*/
|
||||
public boolean storeTextSpecial(char register, @NotNull String text) {
|
||||
if (READONLY_REGISTERS.indexOf(register) == -1 && register != LAST_SEARCH_REGISTER
|
||||
&& register != UNNAMED_REGISTER) {
|
||||
return false;
|
||||
}
|
||||
registers.put(register, new Register(register, SelectionType.CHARACTER_WISE, text, new ArrayList<>()));
|
||||
if (logger.isDebugEnabled()) logger.debug("register '" + register + "' contains: \"" + text + "\"");
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean storeTextInternal(@NotNull Editor editor, @NotNull TextRange range, @NotNull String text,
|
||||
@NotNull SelectionType type, char register, boolean isDelete) {
|
||||
// Null register doesn't get saved, but acts like it was
|
||||
if (lastRegister == BLACK_HOLE_REGISTER) return true;
|
||||
|
||||
int start = range.getStartOffset();
|
||||
int end = range.getEndOffset();
|
||||
@@ -219,7 +258,7 @@ public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
if (logger.isDebugEnabled()) logger.debug("register '" + register + "' contains: \"" + processedText + "\"");
|
||||
}
|
||||
|
||||
if (CLIPBOARD_REGISTERS.contains(register)) {
|
||||
if (CLIPBOARD_REGISTERS.indexOf(register) >= 0) {
|
||||
ClipboardHandler.setClipboardText(processedText, new ArrayList<>(transferableData), text);
|
||||
}
|
||||
|
||||
@@ -248,7 +287,7 @@ public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
|
||||
// Deletes smaller than one line and without specified register go the the "-" register
|
||||
if (smallInlineDeletion && register == defaultRegister) {
|
||||
registers.put('-', new Register('-', type, processedText, new ArrayList<>(transferableData)));
|
||||
registers.put(SMALL_DELETION_REGISTER, new Register(SMALL_DELETION_REGISTER, type, processedText, new ArrayList<>(transferableData)));
|
||||
}
|
||||
}
|
||||
// Yanks also go to register 0 if the default register was used
|
||||
@@ -338,7 +377,7 @@ public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
}
|
||||
|
||||
public @Nullable Register getPlaybackRegister(char r) {
|
||||
if (PLAYBACK_REGISTER.indexOf(r) != 0) {
|
||||
if (PLAYBACK_REGISTERS.indexOf(r) != 0) {
|
||||
return getRegister(r);
|
||||
}
|
||||
else {
|
||||
@@ -351,7 +390,7 @@ public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
if (Character.isUpperCase(r)) {
|
||||
r = Character.toLowerCase(r);
|
||||
}
|
||||
return CLIPBOARD_REGISTERS.contains(r) ? refreshClipboardRegister(r) : registers.get(r);
|
||||
return CLIPBOARD_REGISTERS.indexOf(r) >= 0 ? refreshClipboardRegister(r) : registers.get(r);
|
||||
}
|
||||
|
||||
public void saveRegister(char r, Register register) {
|
||||
@@ -359,7 +398,7 @@ public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
if (Character.isUpperCase(r)) {
|
||||
r = Character.toLowerCase(r);
|
||||
}
|
||||
if (CLIPBOARD_REGISTERS.contains(r)) {
|
||||
if (CLIPBOARD_REGISTERS.indexOf(r) >= 0) {
|
||||
ClipboardHandler.setClipboardText(register.getText(), new ArrayList<>(register.getTransferableData()), register.getRawText());
|
||||
}
|
||||
registers.put(r, register);
|
||||
@@ -383,7 +422,8 @@ public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
|
||||
public @NotNull List<Register> getRegisters() {
|
||||
final List<Register> res = new ArrayList<>(registers.values());
|
||||
for (Character r : CLIPBOARD_REGISTERS) {
|
||||
for (int i = 0; i < CLIPBOARD_REGISTERS.length(); i++) {
|
||||
final char r = CLIPBOARD_REGISTERS.charAt(i);
|
||||
final Register register = refreshClipboardRegister(r);
|
||||
if (register != null) {
|
||||
res.add(register);
|
||||
@@ -394,7 +434,7 @@ public class RegisterGroup implements PersistentStateComponent<Element> {
|
||||
}
|
||||
|
||||
public boolean startRecording(Editor editor, char register) {
|
||||
if (RECORDABLE_REGISTER.indexOf(register) != -1) {
|
||||
if (RECORDABLE_REGISTERS.indexOf(register) != -1) {
|
||||
CommandState.getInstance(editor).setRecording(true);
|
||||
recordRegister = register;
|
||||
recordList = new ArrayList<>();
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -163,7 +163,7 @@ fun updateCaretState(editor: Editor) {
|
||||
|
||||
fun CommandState.Mode.resetShape(editor: Editor) = when (this) {
|
||||
CommandState.Mode.COMMAND, CommandState.Mode.VISUAL, CommandState.Mode.REPLACE -> ChangeGroup.resetCaret(editor, false)
|
||||
CommandState.Mode.SELECT, CommandState.Mode.INSERT -> ChangeGroup.resetCaret(editor, VimPlugin.getEditor().isBarCursor)
|
||||
CommandState.Mode.SELECT, CommandState.Mode.INSERT -> ChangeGroup.resetCaret(editor, VimPlugin.getEditor().isBarCursorSettings)
|
||||
CommandState.Mode.CMD_LINE, CommandState.Mode.OP_PENDING -> Unit
|
||||
}
|
||||
|
||||
|
@@ -18,8 +18,7 @@
|
||||
|
||||
package com.maddyhome.idea.vim.handler
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.extensions.AbstractExtensionPointBean
|
||||
import com.intellij.serviceContainer.BaseKeyedLazyInstance
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
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.
|
||||
* So, all actions are loaded on demand, including classes in classloader.
|
||||
*/
|
||||
// [VERSION UPDATE] 202+
|
||||
@Suppress("DEPRECATION")
|
||||
class ActionBeanClass : AbstractExtensionPointBean() {
|
||||
class ActionBeanClass : BaseKeyedLazyInstance<EditorActionHandlerBase>() {
|
||||
@Attribute("implementation")
|
||||
var implementation: String? = null
|
||||
|
||||
@@ -61,17 +58,14 @@ class ActionBeanClass : AbstractExtensionPointBean() {
|
||||
|
||||
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>>? {
|
||||
val myKeys = keys ?: return null
|
||||
val escapedKeys = myKeys.splitByComma()
|
||||
return EditorActionHandlerBase.parseKeysSet(escapedKeys)
|
||||
}
|
||||
|
||||
override fun getImplementationClassName(): String? = implementation
|
||||
|
||||
fun getParsedModes(): Set<MappingMode>? {
|
||||
val myModes = modes ?: return null
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
package com.maddyhome.idea.vim.helper
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.command.CommandState
|
||||
import com.maddyhome.idea.vim.option.OptionsManager
|
||||
|
||||
@@ -40,12 +41,23 @@ val CommandState.Mode.isEndAllowedIgnoringOnemore: Boolean
|
||||
CommandState.Mode.COMMAND, CommandState.Mode.CMD_LINE, CommandState.Mode.REPLACE, CommandState.Mode.OP_PENDING -> false
|
||||
}
|
||||
|
||||
val CommandState.Mode.isBlockCaret
|
||||
/**
|
||||
* Should this caret behave like the block caret?
|
||||
* Keep in mind that in insert mode the caret can have a block shape, but it doesn't behave like the block one
|
||||
* If you're looking for a shape, check [isBlockCaretShape]
|
||||
*/
|
||||
val CommandState.Mode.isBlockCaretBehaviour
|
||||
get() = when (this) {
|
||||
CommandState.Mode.VISUAL, CommandState.Mode.COMMAND, CommandState.Mode.OP_PENDING -> true
|
||||
CommandState.Mode.INSERT, CommandState.Mode.CMD_LINE, CommandState.Mode.REPLACE, CommandState.Mode.SELECT -> false
|
||||
}
|
||||
|
||||
val CommandState.Mode.isBlockCaretShape
|
||||
get() = when (this) {
|
||||
CommandState.Mode.VISUAL, CommandState.Mode.COMMAND, CommandState.Mode.OP_PENDING -> true
|
||||
CommandState.Mode.INSERT, CommandState.Mode.CMD_LINE, CommandState.Mode.REPLACE, CommandState.Mode.SELECT -> !VimPlugin.getEditor().isBarCursorSettings
|
||||
}
|
||||
|
||||
val CommandState.Mode.hasVisualSelection
|
||||
get() = when (this) {
|
||||
CommandState.Mode.VISUAL, CommandState.Mode.SELECT -> true
|
||||
|
@@ -20,7 +20,7 @@
|
||||
|
||||
package com.maddyhome.idea.vim.helper
|
||||
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.codeWithMe.ClientId
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||
@@ -29,7 +29,6 @@ import com.maddyhome.idea.vim.option.OptionsManager
|
||||
import java.awt.Component
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JTable
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
val Editor.fileSize: Int
|
||||
get() = document.textLength
|
||||
@@ -40,31 +39,14 @@ val Editor.fileSize: Int
|
||||
*/
|
||||
val Editor.isIdeaVimDisabledHere: Boolean
|
||||
get() {
|
||||
var res = true
|
||||
val start = System.currentTimeMillis()
|
||||
val times = mutableListOf<Pair<Long, String>>()
|
||||
val timeForCalculation = measureTimeMillis {
|
||||
res = (disabledInDialog.apply { times += System.currentTimeMillis() to "Disabled in dialog" }
|
||||
|
||||
|| (!OptionsManager.ideavimsupport.contains("singleline")
|
||||
.apply { times += System.currentTimeMillis() to "first single line check" }
|
||||
&& isDatabaseCell(times).apply { times += System.currentTimeMillis() to "is db cell" })
|
||||
|
||||
|| (!OptionsManager.ideavimsupport.contains("singleline")
|
||||
.apply { times += System.currentTimeMillis() to "second single line check" }
|
||||
&& isOneLineMode.apply { times += System.currentTimeMillis() to "is one line" })
|
||||
)
|
||||
}
|
||||
if (timeForCalculation > 10) {
|
||||
val timeDiffs = times.map { it.second + ": " + (it.first - start) }
|
||||
val message = "Time for calculation of 'isIdeaVimDisabledHere' took $timeForCalculation ms. Time diff: $timeDiffs"
|
||||
logger<Editor>().error(message)
|
||||
}
|
||||
return res
|
||||
return disabledInDialog
|
||||
|| (!ClientId.isCurrentlyUnderLocalId) // CWM-927
|
||||
|| (!OptionsManager.ideavimsupport.contains("singleline") && isDatabaseCell())
|
||||
|| (!OptionsManager.ideavimsupport.contains("singleline") && isOneLineMode)
|
||||
}
|
||||
|
||||
private fun Editor.isDatabaseCell(times: MutableList<Pair<Long, String>>): Boolean {
|
||||
return isTableCellEditor(this.component, times)
|
||||
private fun Editor.isDatabaseCell(): Boolean {
|
||||
return isTableCellEditor(this.component)
|
||||
}
|
||||
|
||||
private val Editor.disabledInDialog: Boolean
|
||||
@@ -81,15 +63,10 @@ fun Editor.isPrimaryEditor(): Boolean {
|
||||
}
|
||||
|
||||
// Optimized clone of com.intellij.ide.ui.laf.darcula.DarculaUIUtil.isTableCellEditor
|
||||
private fun isTableCellEditor(c: Component, times: MutableList<Pair<Long, String>>): Boolean {
|
||||
return (java.lang.Boolean.TRUE == (c as JComponent).getClientProperty("JComboBox.isTableCellEditor"))
|
||||
.apply { times += System.currentTimeMillis() to "is property tru" } ||
|
||||
|
||||
(findParentByCondition(c) { it is JTable } != null)
|
||||
.apply { times += System.currentTimeMillis() to "is not null" } &&
|
||||
|
||||
private fun isTableCellEditor(c: Component): Boolean {
|
||||
return (java.lang.Boolean.TRUE == (c as JComponent).getClientProperty("JComboBox.isTableCellEditor")) ||
|
||||
(findParentByCondition(c) { it is JTable } != null) &&
|
||||
(findParentByCondition(c) { it is JBTableRowEditor } == null)
|
||||
.apply { times += System.currentTimeMillis() to "is null" }
|
||||
}
|
||||
|
||||
private const val PARENT_BY_CONDITION_DEPTH = 10
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
package com.maddyhome.idea.vim.helper;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.lang.CodeDocumentationAwareCommenter;
|
||||
import com.intellij.lang.Commenter;
|
||||
import com.intellij.lang.Language;
|
||||
@@ -29,10 +30,14 @@ import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.maddyhome.idea.vim.VimPlugin;
|
||||
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.option.ListOption;
|
||||
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 org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -44,11 +49,357 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.maddyhome.idea.vim.helper.SearchHelperKtKt.checkInString;
|
||||
import static com.maddyhome.idea.vim.helper.SearchHelperKtKt.shouldIgnoreCase;
|
||||
|
||||
/**
|
||||
* Helper methods for searching text
|
||||
*/
|
||||
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) {
|
||||
int start;
|
||||
int end;
|
||||
@@ -103,7 +454,7 @@ public class SearchHelper {
|
||||
int pos = caret.getOffset();
|
||||
int loc = blockChars.indexOf(type);
|
||||
// What direction should we go now (-1 is backward, 1 is forward)
|
||||
Direction dir = loc % 2 == 0 ? Direction.BACK : Direction.FORWARD;
|
||||
Direction dir = loc % 2 == 0 ? Direction.BACKWARDS : Direction.FORWARDS;
|
||||
// Which character did we find and which should we now search for
|
||||
char match = blockChars.charAt(loc);
|
||||
char found = blockChars.charAt(loc - dir.toInt());
|
||||
@@ -163,10 +514,10 @@ public class SearchHelper {
|
||||
int endOffset = quoteRange.getEndOffset();
|
||||
CharSequence subSequence = chars.subSequence(startOffset, endOffset);
|
||||
int inQuotePos = pos - startOffset;
|
||||
int inQuoteStart = findBlockLocation(subSequence, close, type, Direction.BACK, inQuotePos, count, false);
|
||||
int inQuoteStart = findBlockLocation(subSequence, close, type, Direction.BACKWARDS, inQuotePos, count, false);
|
||||
if (inQuoteStart != -1) {
|
||||
startPosInStringFound = true;
|
||||
int inQuoteEnd = findBlockLocation(subSequence, type, close, Direction.FORWARD, inQuoteStart, 1, false);
|
||||
int inQuoteEnd = findBlockLocation(subSequence, type, close, Direction.FORWARDS, inQuoteStart, 1, false);
|
||||
if (inQuoteEnd != -1) {
|
||||
bstart = inQuoteStart + startOffset;
|
||||
bend = inQuoteEnd + startOffset;
|
||||
@@ -176,9 +527,9 @@ public class SearchHelper {
|
||||
}
|
||||
|
||||
if (!startPosInStringFound) {
|
||||
bstart = findBlockLocation(chars, close, type, Direction.BACK, pos, count, false);
|
||||
bstart = findBlockLocation(chars, close, type, Direction.BACKWARDS, pos, count, false);
|
||||
if (bstart != -1) {
|
||||
bend = findBlockLocation(chars, type, close, Direction.FORWARD, bstart, 1, false);
|
||||
bend = findBlockLocation(chars, type, close, Direction.FORWARDS, bstart, 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +645,7 @@ public class SearchHelper {
|
||||
// If we found one ...
|
||||
if (loc >= 0) {
|
||||
// What direction should we go now (-1 is backward, 1 is forward)
|
||||
Direction dir = loc % 2 == 0 ? Direction.FORWARD : Direction.BACK;
|
||||
Direction dir = loc % 2 == 0 ? Direction.FORWARDS : Direction.BACKWARDS;
|
||||
// Which character did we find and which should we now search for
|
||||
char found = getPairChars().charAt(loc);
|
||||
char match = getPairChars().charAt(loc + dir.toInt());
|
||||
@@ -327,7 +678,7 @@ public class SearchHelper {
|
||||
boolean allowInString) {
|
||||
int res = -1;
|
||||
int initialPos = pos;
|
||||
Function<Integer, Integer> inCheckPosF = x -> dir == Direction.BACK && x > 0 ? x - 1 : x + 1;
|
||||
Function<Integer, Integer> inCheckPosF = x -> dir == Direction.BACKWARDS && x > 0 ? x - 1 : x + 1;
|
||||
final int inCheckPos = inCheckPosF.apply(pos);
|
||||
boolean inString = checkInString(chars, inCheckPos, true);
|
||||
boolean initialInString = inString;
|
||||
@@ -391,30 +742,16 @@ public class SearchHelper {
|
||||
return backslashCounter % 2 == 0;
|
||||
}
|
||||
|
||||
public enum Direction {
|
||||
BACK(-1), FORWARD(1);
|
||||
|
||||
private final int value;
|
||||
|
||||
Direction(int i) {
|
||||
value = i;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public enum NumberType {
|
||||
BIN, OCT, DEC, HEX, ALPHA
|
||||
}
|
||||
|
||||
private static int findNextQuoteInLine(@NotNull CharSequence chars, int pos, char quote) {
|
||||
return findQuoteInLine(chars, pos, quote, Direction.FORWARD);
|
||||
return findQuoteInLine(chars, pos, quote, Direction.FORWARDS);
|
||||
}
|
||||
|
||||
private static int findPreviousQuoteInLine(@NotNull CharSequence chars, int pos, char quote) {
|
||||
return findQuoteInLine(chars, pos, quote, Direction.BACK);
|
||||
return findQuoteInLine(chars, pos, quote, Direction.BACKWARDS);
|
||||
}
|
||||
|
||||
private static int findFirstQuoteInLine(@NotNull Editor editor, int pos, char quote) {
|
||||
@@ -428,8 +765,8 @@ public class SearchHelper {
|
||||
|
||||
private static int countCharactersInLine(@NotNull CharSequence chars, int pos, char c) {
|
||||
int cnt = 0;
|
||||
while (pos > 0 && (chars.charAt(pos + Direction.BACK.toInt()) != '\n')) {
|
||||
pos = findCharacterPosition(chars, pos + Direction.BACK.toInt(), c, false, true, Direction.BACK);
|
||||
while (pos > 0 && (chars.charAt(pos + Direction.BACKWARDS.toInt()) != '\n')) {
|
||||
pos = findCharacterPosition(chars, pos + Direction.BACKWARDS.toInt(), c, false, true, Direction.BACKWARDS);
|
||||
if (pos != -1) {
|
||||
cnt++;
|
||||
}
|
||||
|
@@ -18,14 +18,37 @@
|
||||
|
||||
package com.maddyhome.idea.vim.helper
|
||||
|
||||
import com.maddyhome.idea.vim.helper.SearchHelper.Direction
|
||||
import com.maddyhome.idea.vim.helper.SearchHelper.findPositionOfFirstCharacter
|
||||
import com.maddyhome.idea.vim.option.OptionsManager.ignorecase
|
||||
import com.maddyhome.idea.vim.option.OptionsManager.smartcase
|
||||
|
||||
enum class Direction(private val value: Int) {
|
||||
BACKWARDS(-1), FORWARDS(1);
|
||||
|
||||
fun toInt(): Int = value
|
||||
fun reverse(): Direction = when (this) {
|
||||
BACKWARDS -> FORWARDS
|
||||
FORWARDS -> BACKWARDS
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromInt(value: Int) = when (value) {
|
||||
BACKWARDS.value -> BACKWARDS
|
||||
FORWARDS.value -> FORWARDS
|
||||
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)
|
||||
|
||||
// bounds are considered inside corresponding quotes
|
||||
fun checkInString(chars: CharSequence, currentPos: Int, str: Boolean): Boolean {
|
||||
val begin = findPositionOfFirstCharacter(chars, currentPos, setOf('\n'), false, Direction.BACK)?.second ?: 0
|
||||
val begin = findPositionOfFirstCharacter(chars, currentPos, setOf('\n'), false, Direction.BACKWARDS)?.second ?: 0
|
||||
val changes = quoteChanges(chars, begin)
|
||||
// TODO: here we need to keep only the latest element in beforePos (if any) and
|
||||
// don't need atAndAfterPos to be eagerly collected
|
||||
@@ -105,7 +128,7 @@ private fun quoteChanges(chars: CharSequence, begin: Int) = sequence {
|
||||
// in that situation it may be double quote inside single quotes, so we cannot threat it as double quote pair open/close
|
||||
var inQuote: Boolean? = false
|
||||
val charsToSearch = setOf('\'', '"', '\n')
|
||||
var found = findPositionOfFirstCharacter(chars, begin, charsToSearch, false, Direction.FORWARD)
|
||||
var found = findPositionOfFirstCharacter(chars, begin, charsToSearch, false, Direction.FORWARDS)
|
||||
while (found != null && found.first != '\n') {
|
||||
val i = found.second
|
||||
|
||||
@@ -158,6 +181,23 @@ private fun quoteChanges(chars: CharSequence, begin: Int) = sequence {
|
||||
}
|
||||
}
|
||||
yield(State(i, c, inQuote, lastOpenSingleQuotePos))
|
||||
found = findPositionOfFirstCharacter(chars, i + Direction.FORWARD.toInt(), charsToSearch, false, Direction.FORWARD)
|
||||
found = findPositionOfFirstCharacter(chars, i + Direction.FORWARDS.toInt(), charsToSearch, false, Direction.FORWARDS)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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))
|
||||
}
|
||||
|
266
src/com/maddyhome/idea/vim/helper/SearchHighlightsHelper.kt
Normal file
266
src/com/maddyhome/idea/vim/helper/SearchHighlightsHelper.kt
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@file:JvmName("SearchHighlightsHelper")
|
||||
|
||||
package com.maddyhome.idea.vim.helper
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.EditorFactory
|
||||
import com.intellij.openapi.editor.colors.EditorColors
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme
|
||||
import com.intellij.openapi.editor.markup.EffectType
|
||||
import com.intellij.openapi.editor.markup.HighlighterLayer
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter
|
||||
import com.intellij.openapi.editor.markup.TextAttributes
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.ui.ColorUtil
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.ex.ranges.LineRange
|
||||
import com.maddyhome.idea.vim.option.OptionsManager.hlsearch
|
||||
import com.maddyhome.idea.vim.option.OptionsManager.wrapscan
|
||||
import org.jetbrains.annotations.Contract
|
||||
import java.awt.Color
|
||||
import java.awt.Font
|
||||
import java.util.*
|
||||
|
||||
fun updateSearchHighlights(
|
||||
pattern: String?,
|
||||
shouldIgnoreSmartCase: Boolean,
|
||||
showHighlights: Boolean,
|
||||
forceUpdate: Boolean
|
||||
) {
|
||||
updateSearchHighlights(pattern, shouldIgnoreSmartCase, showHighlights, -1, null, true, forceUpdate)
|
||||
}
|
||||
|
||||
fun updateIncsearchHighlights(
|
||||
editor: Editor,
|
||||
pattern: String,
|
||||
forwards: Boolean,
|
||||
caretOffset: Int,
|
||||
searchRange: LineRange?
|
||||
): Int {
|
||||
val searchStartOffset =
|
||||
if (searchRange != null) EditorHelper.getLineStartOffset(editor, searchRange.startLine) else caretOffset
|
||||
val showHighlights = hlsearch.isSet
|
||||
return updateSearchHighlights(pattern, false, showHighlights, searchStartOffset, searchRange, forwards, false)
|
||||
}
|
||||
|
||||
fun addSubstitutionConfirmationHighlight(editor: Editor, start: Int, end: Int): RangeHighlighter {
|
||||
val color = TextAttributes(
|
||||
editor.colorsScheme.getColor(EditorColors.SELECTION_FOREGROUND_COLOR),
|
||||
editor.colorsScheme.getColor(EditorColors.SELECTION_BACKGROUND_COLOR),
|
||||
editor.colorsScheme.getColor(EditorColors.CARET_COLOR),
|
||||
EffectType.ROUNDED_BOX, Font.PLAIN
|
||||
)
|
||||
return editor.markupModel.addRangeHighlighter(
|
||||
start, end, HighlighterLayer.SELECTION,
|
||||
color, HighlighterTargetArea.EXACT_RANGE
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes current search highlights for all editors of currently active text editor/document
|
||||
*/
|
||||
private fun updateSearchHighlights(
|
||||
pattern: String?, shouldIgnoreSmartCase: Boolean, showHighlights: Boolean,
|
||||
initialOffset: Int, searchRange: LineRange?, forwards: Boolean, forceUpdate: Boolean
|
||||
): Int {
|
||||
var currentMatchOffset = -1
|
||||
val projectManager = ProjectManager.getInstanceIfCreated() ?: return currentMatchOffset
|
||||
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 `/<Up>` 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return currentMatchOffset
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove current search highlights if hlSearch is false, or if the pattern is changed
|
||||
*/
|
||||
@Contract("_, _, false -> true; _, null, true -> false")
|
||||
private fun shouldRemoveSearchHighlights(editor: Editor, newPattern: String?, hlSearch: Boolean): Boolean {
|
||||
return !hlSearch || newPattern != null && newPattern != editor.vimLastSearch
|
||||
}
|
||||
|
||||
private fun removeSearchHighlights(editor: Editor) {
|
||||
editor.vimLastSearch = null
|
||||
val ehl = editor.vimLastHighlighters ?: return
|
||||
for (rh in ehl) {
|
||||
editor.markupModel.removeHighlighter(rh)
|
||||
}
|
||||
editor.vimLastHighlighters = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Add search highlights if hlSearch is true and the pattern is changed
|
||||
*/
|
||||
@Contract("_, _, false -> false; _, null, true -> false")
|
||||
private fun shouldAddAllSearchHighlights(editor: Editor, newPattern: String?, hlSearch: Boolean): Boolean {
|
||||
return hlSearch && newPattern != null && newPattern != editor.vimLastSearch && newPattern != ""
|
||||
}
|
||||
|
||||
private fun findClosestMatch(editor: Editor, results: List<TextRange>, initialOffset: Int, forwards: Boolean): Int {
|
||||
if (results.isEmpty() || initialOffset == -1) {
|
||||
return -1
|
||||
}
|
||||
val size = editor.fileSize
|
||||
val max = Collections.max(results) { r1: TextRange, r2: TextRange ->
|
||||
val d1 = distance(r1, initialOffset, forwards, size)
|
||||
val d2 = distance(r2, initialOffset, forwards, size)
|
||||
if (d1 < 0 && d2 >= 0) {
|
||||
return@max Int.MAX_VALUE
|
||||
}
|
||||
d2 - d1
|
||||
}
|
||||
if (!wrapscan.isSet) {
|
||||
val start = max.startOffset
|
||||
if (forwards && start < initialOffset) {
|
||||
return -1
|
||||
} else if (start >= initialOffset) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return max.startOffset
|
||||
}
|
||||
|
||||
private fun distance(range: TextRange, pos: Int, forwards: Boolean, size: Int): Int {
|
||||
val start = range.startOffset
|
||||
return if (start <= pos) {
|
||||
if (forwards) size - pos + start else pos - start
|
||||
} else {
|
||||
if (forwards) start - pos else pos + size - start
|
||||
}
|
||||
}
|
||||
|
||||
fun highlightSearchResults(editor: Editor, pattern: String, results: List<TextRange>, currentMatchOffset: Int) {
|
||||
var highlighters = editor.vimLastHighlighters
|
||||
if (highlighters == null) {
|
||||
highlighters = mutableListOf()
|
||||
editor.vimLastHighlighters = highlighters
|
||||
}
|
||||
for (range in results) {
|
||||
val current = range.startOffset == currentMatchOffset
|
||||
val highlighter = highlightMatch(editor, range.startOffset, range.endOffset, current, pattern)
|
||||
highlighters.add(highlighter)
|
||||
}
|
||||
editor.vimIncsearchCurrentMatchOffset = currentMatchOffset
|
||||
}
|
||||
|
||||
private fun highlightMatch(editor: Editor, start: Int, end: Int, current: Boolean, tooltip: String): RangeHighlighter {
|
||||
var attributes = editor.colorsScheme.getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES)
|
||||
if (current) {
|
||||
// This mimics what IntelliJ does with the Find live preview
|
||||
attributes = attributes.clone()
|
||||
attributes.effectType = EffectType.ROUNDED_BOX
|
||||
attributes.effectColor = editor.colorsScheme.getColor(EditorColors.CARET_COLOR)
|
||||
}
|
||||
if (attributes.errorStripeColor == null) {
|
||||
attributes.errorStripeColor = getFallbackErrorStripeColor(attributes, editor.colorsScheme)
|
||||
}
|
||||
val highlighter = editor.markupModel.addRangeHighlighter(
|
||||
start, end, HighlighterLayer.SELECTION - 1,
|
||||
attributes, HighlighterTargetArea.EXACT_RANGE
|
||||
)
|
||||
highlighter.errorStripeTooltip = tooltip
|
||||
return highlighter
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a valid error stripe colour based on editor background
|
||||
*
|
||||
*
|
||||
* Based on HighlightManager#addRangeHighlight behaviour, which we can't use because it will hide highlights
|
||||
* when hitting Escape.
|
||||
*/
|
||||
private fun getFallbackErrorStripeColor(attributes: TextAttributes, colorsScheme: EditorColorsScheme): Color? {
|
||||
if (attributes.backgroundColor != null) {
|
||||
val isDark = ColorUtil.isDark(colorsScheme.defaultBackground)
|
||||
return if (isDark) attributes.backgroundColor.brighter() else attributes.backgroundColor.darker()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Add search highlight for current match if hlsearch is false and we're performing incsearch highlights
|
||||
*/
|
||||
@Contract("_, true, _ -> false")
|
||||
private fun shouldAddCurrentMatchSearchHighlight(pattern: String?, hlSearch: Boolean, initialOffset: Int): Boolean {
|
||||
return !hlSearch && isIncrementalSearchHighlights(initialOffset) && pattern != null && pattern.isNotEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep the current match offset if the pattern is still valid and we're performing incremental search highlights
|
||||
* This will keep the caret position when editing the offset in e.g. `/foo/e+1`
|
||||
*/
|
||||
@Contract("null, _ -> false")
|
||||
private fun shouldMaintainCurrentMatchOffset(pattern: String?, initialOffset: Int): Boolean {
|
||||
return pattern != null && pattern.isNotEmpty() && isIncrementalSearchHighlights(initialOffset)
|
||||
}
|
||||
|
||||
/**
|
||||
* initialOffset is only valid if we're highlighting incsearch
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private fun isIncrementalSearchHighlights(initialOffset: Int) = initialOffset != -1
|
@@ -80,7 +80,7 @@ fun unInitializeEditor(editor: Editor) {
|
||||
}
|
||||
|
||||
var Editor.vimLastSearch: String? by userData()
|
||||
var Editor.vimLastHighlighters: Collection<RangeHighlighter>? by userData()
|
||||
var Editor.vimLastHighlighters: MutableCollection<RangeHighlighter>? by userData()
|
||||
var Editor.vimIncsearchCurrentMatchOffset: Int? by userData()
|
||||
/***
|
||||
* @see :help visualmode()
|
||||
|
@@ -107,7 +107,7 @@ class ToHandlerMappingInfo(
|
||||
isRecursive: Boolean,
|
||||
owner: MappingOwner
|
||||
) : MappingInfo(fromKeys, isRecursive, owner) {
|
||||
override fun getPresentableString(): String = "call ${this.javaClass.canonicalName}"
|
||||
override fun getPresentableString(): String = "call ${extensionHandler.javaClass.canonicalName}"
|
||||
|
||||
override fun execute(editor: Editor, context: DataContext) {
|
||||
val processor = CommandProcessor.getInstance()
|
||||
|
@@ -32,12 +32,14 @@ import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.actionSystem.IdeActions
|
||||
import com.intellij.openapi.actionSystem.ex.AnActionListener
|
||||
import com.intellij.openapi.editor.Caret
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager
|
||||
import com.intellij.openapi.editor.event.CaretEvent
|
||||
import com.intellij.openapi.editor.event.CaretListener
|
||||
import com.intellij.openapi.project.DumbAwareToggleAction
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.util.PlatformUtils
|
||||
import com.maddyhome.idea.vim.EventFacade
|
||||
import com.maddyhome.idea.vim.KeyHandler
|
||||
@@ -47,10 +49,12 @@ import com.maddyhome.idea.vim.group.visual.IdeaSelectionControl
|
||||
import com.maddyhome.idea.vim.group.visual.moveCaretOneCharLeftFromSelectionEnd
|
||||
import com.maddyhome.idea.vim.helper.EditorDataContext
|
||||
import com.maddyhome.idea.vim.helper.commandState
|
||||
import com.maddyhome.idea.vim.helper.fileSize
|
||||
import com.maddyhome.idea.vim.helper.getTopLevelEditor
|
||||
import com.maddyhome.idea.vim.helper.inNormalMode
|
||||
import com.maddyhome.idea.vim.option.IdeaRefactorMode
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import java.beans.PropertyChangeEvent
|
||||
import java.beans.PropertyChangeListener
|
||||
|
||||
@@ -191,6 +195,92 @@ object IdeaSpecifics {
|
||||
.javaClass.name.startsWith("org.acejump.")
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region AppCode templates
|
||||
/**
|
||||
* A collection of hacks to improve the interaction with fancy AppCode templates
|
||||
*/
|
||||
object AppCodeTemplates {
|
||||
private val facedAppCodeTemplate = Key.create<IntRange>("FacedAppCodeTemplate")
|
||||
|
||||
private const val TEMPLATE_START = "<#T##"
|
||||
private const val TEMPLATE_END = "#>"
|
||||
|
||||
@JvmStatic
|
||||
fun onMovement(
|
||||
editor: @NotNull Editor,
|
||||
caret: @NotNull Caret,
|
||||
toRight: Boolean
|
||||
) {
|
||||
if (!PlatformUtils.isAppCode()) return
|
||||
|
||||
val offset = caret.offset
|
||||
val offsetRightEnd = offset + TEMPLATE_START.length
|
||||
val offsetLeftEnd = offset - 1
|
||||
val templateRange = caret.getUserData(facedAppCodeTemplate)
|
||||
if (templateRange == null) {
|
||||
if (offsetRightEnd < editor.fileSize
|
||||
&& editor.document.charsSequence.subSequence(offset, offsetRightEnd).toString() == TEMPLATE_START) {
|
||||
caret.shake()
|
||||
|
||||
val templateEnd = editor.findTemplateEnd(offset) ?: return
|
||||
|
||||
caret.putUserData(facedAppCodeTemplate, offset..templateEnd)
|
||||
}
|
||||
if (offsetLeftEnd >= 0
|
||||
&& editor.document.charsSequence.subSequence(offsetLeftEnd, offset + 1).toString() == TEMPLATE_END) {
|
||||
caret.shake()
|
||||
|
||||
val templateStart = editor.findTemplateStart(offsetLeftEnd) ?: return
|
||||
|
||||
caret.putUserData(facedAppCodeTemplate, templateStart..offset)
|
||||
}
|
||||
} else {
|
||||
if (offset in templateRange) {
|
||||
if (toRight) {
|
||||
caret.moveToOffset(templateRange.last + 1)
|
||||
} else {
|
||||
caret.moveToOffset(templateRange.first)
|
||||
}
|
||||
}
|
||||
caret.putUserData(facedAppCodeTemplate, null)
|
||||
caret.shake()
|
||||
}
|
||||
}
|
||||
|
||||
fun Editor.appCodeTemplateCaptured(): Boolean {
|
||||
if (!PlatformUtils.isAppCode()) return false
|
||||
return this.caretModel.allCarets.any { it.getUserData(facedAppCodeTemplate) != null }
|
||||
}
|
||||
|
||||
private fun Caret.shake() {
|
||||
moveCaretRelatively(1, 0, false, false)
|
||||
moveCaretRelatively(-1, 0, false, false)
|
||||
}
|
||||
|
||||
private fun Editor.findTemplateEnd(start: Int): Int? {
|
||||
val charSequence = this.document.charsSequence
|
||||
val length = charSequence.length
|
||||
for (i in start until length - 1) {
|
||||
if (charSequence[i] == TEMPLATE_END[0] && charSequence[i+1] == TEMPLATE_END[1]) {
|
||||
return i + 1
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun Editor.findTemplateStart(start: Int): Int? {
|
||||
val charSequence = this.document.charsSequence
|
||||
val templateLastIndex = TEMPLATE_START.length
|
||||
for (i in start downTo templateLastIndex) {
|
||||
if (charSequence.subSequence(i - templateLastIndex, i + 1).toString() == TEMPLATE_START) {
|
||||
return i - templateLastIndex
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
//region Find action ID
|
||||
|
@@ -253,11 +253,11 @@ object VimListenerManager {
|
||||
if (onLineEnd(caret)) {
|
||||
// UX protection for case when user performs a small dragging while putting caret on line end
|
||||
caret.removeSelection()
|
||||
ChangeGroup.resetCaret(e.editor, VimPlugin.getEditor().isBarCursor)
|
||||
ChangeGroup.resetCaret(e.editor, true)
|
||||
}
|
||||
}
|
||||
if (mouseDragging && e.editor.caretModel.primaryCaret.hasSelection()) {
|
||||
ChangeGroup.resetCaret(e.editor, VimPlugin.getEditor().isBarCursor)
|
||||
ChangeGroup.resetCaret(e.editor, true)
|
||||
|
||||
if (!cutOffFixed && ComponentMouseListener.cutOffEnd) {
|
||||
cutOffFixed = true
|
||||
|
@@ -32,7 +32,7 @@ import com.maddyhome.idea.vim.helper.EditorHelper
|
||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||
import com.maddyhome.idea.vim.helper.Msg
|
||||
import com.maddyhome.idea.vim.helper.hasVisualSelection
|
||||
import com.maddyhome.idea.vim.helper.isBlockCaret
|
||||
import com.maddyhome.idea.vim.helper.isBlockCaretBehaviour
|
||||
import com.maddyhome.idea.vim.helper.mode
|
||||
import com.maddyhome.idea.vim.helper.subMode
|
||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
||||
@@ -52,7 +52,7 @@ object OptionsManager {
|
||||
val clipboard = addOption(ListOption(ClipboardOptionsData.name, ClipboardOptionsData.abbr, arrayOf(ClipboardOptionsData.ideaput, "autoselect,exclude:cons\\|linux"), null))
|
||||
val digraph = addOption(ToggleOption("digraph", "dg", false))
|
||||
val gdefault = addOption(ToggleOption("gdefault", "gd", false))
|
||||
val history = addOption(NumberOption("history", "hi", 20, 1, Int.MAX_VALUE))
|
||||
val history = addOption(NumberOption("history", "hi", 50, 1, Int.MAX_VALUE))
|
||||
val hlsearch = addOption(ToggleOption("hlsearch", "hls", false))
|
||||
val ideamarks = addOption(IdeaMarkskOptionsData.option)
|
||||
val ignorecase = addOption(ToggleOption(IgnoreCaseOptionsData.name, IgnoreCaseOptionsData.abbr, false))
|
||||
@@ -62,7 +62,7 @@ object OptionsManager {
|
||||
val lookupKeys = addOption(ListOption(LookupKeysData.name, LookupKeysData.name, LookupKeysData.defaultValues, null))
|
||||
val matchpairs = addOption(ListOption("matchpairs", "mps", arrayOf("(:)", "{:}", "[:]"), ".:."))
|
||||
val more = addOption(ToggleOption("more", "more", true))
|
||||
val nrformats = addOption(BoundListOption("nrformats", "nf", arrayOf("octal", "hex"), arrayOf("octal", "hex", "alpha")))
|
||||
val nrformats = addOption(BoundListOption("nrformats", "nf", arrayOf("hex"), arrayOf("octal", "hex", "alpha"))) // Octal is disabled as in neovim
|
||||
val number = addOption(ToggleOption("number", "nu", false))
|
||||
val relativenumber = addOption(ToggleOption("relativenumber", "rnu", false))
|
||||
val scroll = addOption(NumberOption("scroll", "scr", 0))
|
||||
@@ -491,7 +491,7 @@ object IdeaRefactorMode {
|
||||
}
|
||||
}
|
||||
|
||||
if (editor.mode.isBlockCaret) {
|
||||
if (editor.mode.isBlockCaretBehaviour) {
|
||||
TemplateManagerImpl.getTemplateState(editor)?.currentVariableRange?.let { segmentRange ->
|
||||
if (!segmentRange.isEmpty && segmentRange.endOffset == editor.caretModel.offset && editor.caretModel.offset != 0) {
|
||||
editor.caretModel.moveToOffset(editor.caretModel.offset - 1)
|
||||
|
@@ -669,7 +669,7 @@
|
||||
* |c_<S-Up>| {@link com.maddyhome.idea.vim.ui.ex.HistoryUpAction}
|
||||
* |c_<Tab>| TO BE IMPLEMENTED
|
||||
* |c_<Up>| {@link com.maddyhome.idea.vim.ui.ex.HistoryUpFilterAction}
|
||||
* |c_digraph| {char1} <BS> {char2} {@link com.maddyhome.idea.vim.ui.ex.StartDigraphAction}
|
||||
* |c_digraph| {char1} <BS> {char2}
|
||||
* |c_wildchar| TO BE IMPLEMENTED
|
||||
* |'cedit'| TO BE IMPLEMENTED
|
||||
*
|
||||
|
@@ -28,12 +28,12 @@ import com.intellij.openapi.editor.toolbar.floating.FloatingToolbarComponent
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.util.containers.IntArrayList
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser
|
||||
import com.maddyhome.idea.vim.helper.MessageHelper
|
||||
import com.maddyhome.idea.vim.ui.ReloadFloatingToolbarActionGroup.Companion.ACTION_GROUP
|
||||
import icons.VimIcons
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@@ -49,8 +49,6 @@ import java.util.regex.Pattern
|
||||
|
||||
object VimRcFileState {
|
||||
// List of hashes of non-empty trimmed lines
|
||||
// [VERSION UPDATE] 202+
|
||||
@Suppress("DEPRECATION")
|
||||
private val state = IntArrayList()
|
||||
|
||||
// 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
|
||||
if (fileModificationStamp == modificationStamp) return true
|
||||
|
||||
val stateSize = state.size()
|
||||
val stateSize = state.size
|
||||
var i = 0
|
||||
VimScriptParser.readText(document.charsSequence).forEach { line ->
|
||||
if (i >= stateSize) return false
|
||||
if (state.get(i) != line.hashCode()) return false
|
||||
if (state.getInt(i) != line.hashCode()) return false
|
||||
i++
|
||||
}
|
||||
if (i < stateSize) return false
|
||||
|
@@ -33,6 +33,7 @@ import com.maddyhome.idea.vim.ex.CommandParser;
|
||||
import com.maddyhome.idea.vim.ex.ExCommand;
|
||||
import com.maddyhome.idea.vim.ex.ranges.LineRange;
|
||||
import com.maddyhome.idea.vim.group.MotionGroup;
|
||||
import com.maddyhome.idea.vim.helper.SearchHighlightsHelper;
|
||||
import com.maddyhome.idea.vim.helper.UiHelper;
|
||||
import com.maddyhome.idea.vim.option.OptionsManager;
|
||||
import com.maddyhome.idea.vim.regexp.CharPointer;
|
||||
@@ -279,6 +280,9 @@ public class ExEntryPanel extends JPanel {
|
||||
searchText = argument.substring(1);
|
||||
}
|
||||
if (searchText.length() == 0) {
|
||||
// Reset back to the original search highlights after deleting a search from a substitution command.
|
||||
// E.g. Highlight `whatever`, type `:%s/foo` + highlight `foo`, delete back to `:%s/` and reset highlights
|
||||
// back to `whatever`
|
||||
VimPlugin.getSearch().resetIncsearchHighlights();
|
||||
return;
|
||||
}
|
||||
@@ -294,7 +298,7 @@ public class ExEntryPanel extends JPanel {
|
||||
pattern = p.substring(end.pointer() - p.pointer());
|
||||
|
||||
VimPlugin.getEditor().closeEditorSearchSession(editor);
|
||||
final int matchOffset = VimPlugin.getSearch().updateIncsearchHighlights(editor, pattern, forwards, caretOffset, searchRange);
|
||||
final int matchOffset = SearchHighlightsHelper.updateIncsearchHighlights(editor, pattern, forwards, caretOffset, searchRange);
|
||||
if (matchOffset != -1) {
|
||||
MotionGroup.moveCaret(editor, editor.getCaretModel().getPrimaryCaret(), matchOffset);
|
||||
}
|
||||
|
@@ -37,6 +37,9 @@ class RegisterActionsTest : VimTestCase() {
|
||||
}
|
||||
|
||||
fun `test action in disabled plugin`() {
|
||||
setupChecks {
|
||||
caretShape = false
|
||||
}
|
||||
val keys = StringHelper.parseKeys("jklwB") // just random keys
|
||||
val before = "I ${c}found it in a legendary land"
|
||||
val after = "I ${c}found it in a legendary land"
|
||||
|
@@ -55,6 +55,9 @@ import com.maddyhome.idea.vim.helper.StringHelper.parseKeys
|
||||
import com.maddyhome.idea.vim.helper.StringHelper.stringToKeys
|
||||
import com.maddyhome.idea.vim.helper.TestInputModel
|
||||
import com.maddyhome.idea.vim.helper.inBlockSubMode
|
||||
import com.maddyhome.idea.vim.helper.isBlockCaretBehaviour
|
||||
import com.maddyhome.idea.vim.helper.isBlockCaretShape
|
||||
import com.maddyhome.idea.vim.helper.mode
|
||||
import com.maddyhome.idea.vim.key.MappingOwner
|
||||
import com.maddyhome.idea.vim.key.ToKeysMappingInfo
|
||||
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
|
||||
@@ -65,7 +68,6 @@ import com.maddyhome.idea.vim.option.OptionsManager.resetAllOptions
|
||||
import com.maddyhome.idea.vim.option.ToggleOption
|
||||
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
|
||||
import org.junit.Assert
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
import javax.swing.KeyStroke
|
||||
|
||||
@@ -93,6 +95,7 @@ abstract class VimTestCase : UsefulTestCase() {
|
||||
VimPlugin.getSearch().resetState()
|
||||
if (!VimPlugin.isEnabled()) VimPlugin.setEnabled(true)
|
||||
ideastrictmode.set()
|
||||
Checks.reset()
|
||||
|
||||
// Make sure the entry text field gets a bounds, or we won't be able to work out caret location
|
||||
ExEntryPanel.getInstance().entry.setBounds(0, 0, 100, 25)
|
||||
@@ -427,6 +430,7 @@ abstract class VimTestCase : UsefulTestCase() {
|
||||
assertCaretsColour()
|
||||
assertMode(modeAfter)
|
||||
assertSubMode(subModeAfter)
|
||||
if (Checks.caretShape) assertEquals(myFixture.editor.mode.isBlockCaretShape, myFixture.editor.settings.isBlockCursor)
|
||||
}
|
||||
|
||||
protected val fileManager: FileEditorManagerEx
|
||||
@@ -440,6 +444,11 @@ abstract class VimTestCase : UsefulTestCase() {
|
||||
return EditorTestUtil.addInlay(myFixture.editor, offset, relatesToPrecedingText, widthInColumns * columnWidth)!!
|
||||
}
|
||||
|
||||
// Disable or enable checks for the particular test
|
||||
protected inline fun setupChecks(setup: Checks.() -> Unit) {
|
||||
Checks.setup()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val c = EditorTestUtil.CARET_TAG
|
||||
const val s = EditorTestUtil.SELECTION_START_TAG
|
||||
@@ -480,4 +489,12 @@ abstract class VimTestCase : UsefulTestCase() {
|
||||
|
||||
fun String.dotToTab(): String = replace('.', '\t')
|
||||
}
|
||||
|
||||
object Checks {
|
||||
var caretShape: Boolean = true
|
||||
|
||||
fun reset() {
|
||||
caretShape = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ import static com.maddyhome.idea.vim.helper.StringHelper.parseKeys;
|
||||
public class ReformatCodeTest extends VimTestCase {
|
||||
|
||||
/*
|
||||
[VERSION UPDATE] 2020.2+
|
||||
[VERSION UPDATE] 203+
|
||||
public void testEmpty() {
|
||||
configureByJavaText("<caret>");
|
||||
typeText(parseKeys("gqq"));
|
||||
|
@@ -40,7 +40,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
|
||||
final RegisterGroup registerGroup = VimPlugin.getRegister();
|
||||
registerGroup.setKeys('a', stringToKeys(DUMMY_TEXT));
|
||||
registerGroup.setKeys('-', stringToKeys(DUMMY_TEXT));
|
||||
registerGroup.setKeys(RegisterGroup.SMALL_DELETION_REGISTER, stringToKeys(DUMMY_TEXT));
|
||||
for (char c = '0'; c <= '9'; c++) {
|
||||
registerGroup.setKeys(c, stringToKeys(DUMMY_TEXT));
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
public void testSmallDelete() {
|
||||
typeTextInFile(parseKeys("de"), "one <caret>two three\n");
|
||||
|
||||
assertEquals("two", getRegisterText('-'));
|
||||
assertEquals("two", getRegisterText(RegisterGroup.SMALL_DELETION_REGISTER));
|
||||
// Text smaller than line doesn't go to numbered registers (except special cases)
|
||||
assertRegisterNotChanged('1');
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("d%"), "(one<caret> two) three\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |(| Special case for small delete
|
||||
@@ -68,7 +68,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("d("), "One. Two<caret>. Three.\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |)| Special case for small delete
|
||||
@@ -76,7 +76,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("d)"), "One. <caret>Two. Three.\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |`| Special case for small delete
|
||||
@@ -84,7 +84,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("ma", "b", "d`a"), "one two<caret> three\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |/| Special case for small delete
|
||||
@@ -92,7 +92,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("d/", "o", "<Enter>"), "one <caret>two three\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |?| Special case for small delete
|
||||
@@ -100,7 +100,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("d?", "t", "<Enter>"), "one two<caret> three\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |n| Special case for small delete
|
||||
@@ -108,7 +108,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("/", "t", "<Enter>", "dn"), "<caret>one two three\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |N| Special case for small delete
|
||||
@@ -116,7 +116,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("/", "t", "<Enter>", "dN"), "one tw<caret>o three\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |{| Special case for small delete
|
||||
@@ -124,7 +124,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("d{"), "one<caret> two three");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
// |d| |}| Special case for small delete
|
||||
@@ -132,7 +132,7 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
typeTextInFile(parseKeys("d}"), "one<caret> two three");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterChanged('-');
|
||||
assertRegisterChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
public void testSmallDeleteInRegister() {
|
||||
@@ -141,14 +141,14 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
// Small deletes (less than a line) with register specified go to that register and to numbered registers
|
||||
assertRegisterChanged('a');
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterNotChanged('-');
|
||||
assertRegisterNotChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
public void testLineDelete() {
|
||||
typeTextInFile(parseKeys("dd"), "one <caret>two three\n");
|
||||
|
||||
assertRegisterChanged('1');
|
||||
assertRegisterNotChanged('-');
|
||||
assertRegisterNotChanged(RegisterGroup.SMALL_DELETION_REGISTER);
|
||||
}
|
||||
|
||||
public void testLineDeleteInRegister() {
|
||||
@@ -190,5 +190,4 @@ public class SpecialRegistersTest extends VimTestCase {
|
||||
|
||||
return register.getText();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.ideavim.action.change.change.number
|
||||
|
||||
import com.maddyhome.idea.vim.command.CommandState
|
||||
import com.maddyhome.idea.vim.helper.VimBehaviorDiffers
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
|
||||
class ChangeNumberIncActionTest : VimTestCase() {
|
||||
@VimBehaviorDiffers(originalVimAfter = "11X0")
|
||||
fun `test inc fancy number`() {
|
||||
doTest("<C-A>", "1${c}0X0", "10X1", CommandState.Mode.COMMAND, CommandState.SubMode.NONE)
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.ideavim.action.change.insert
|
||||
|
||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
|
||||
import com.maddyhome.idea.vim.command.CommandState
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
|
||||
class InsertBeforeCursorActionTest : VimTestCase() {
|
||||
fun `test check caret shape`() {
|
||||
doTest("i", "123", "123", CommandState.Mode.INSERT, CommandState.SubMode.NONE)
|
||||
assertFalse(myFixture.editor.settings.isBlockCursor)
|
||||
}
|
||||
|
||||
fun `test check caret shape for block caret`() {
|
||||
EditorSettingsExternalizable.getInstance().isBlockCursor = true
|
||||
try {
|
||||
doTest("i", "123", "123", CommandState.Mode.INSERT, CommandState.SubMode.NONE)
|
||||
assertTrue(myFixture.editor.settings.isBlockCursor)
|
||||
} finally {
|
||||
EditorSettingsExternalizable.getInstance().isBlockCursor = false
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||
* Copyright (C) 2003-2020 The IdeaVim authors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.ideavim.action.change.insert
|
||||
|
||||
import com.maddyhome.idea.vim.command.CommandState
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
|
||||
class InsertSingleCommandActionTest : VimTestCase() {
|
||||
fun `test enter visual`() {
|
||||
doTest(
|
||||
listOf("i", "<C-O>", "vlll", "<Esc>"),
|
||||
"I found ${c}it in a legendary land",
|
||||
"I found it ${c}in a legendary land",
|
||||
CommandState.Mode.INSERT,
|
||||
CommandState.SubMode.NONE
|
||||
)
|
||||
}
|
||||
}
|
@@ -21,8 +21,13 @@ package org.jetbrains.plugins.ideavim.action.motion.visual
|
||||
import com.maddyhome.idea.vim.command.CommandState
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
|
||||
class VisualExitModeAction : VimTestCase() {
|
||||
class VisualExitModeActionTest : VimTestCase() {
|
||||
fun `test exit visual mode after line end`() {
|
||||
doTest("vl<Esc>", "12${c}3", "12${c}3", CommandState.Mode.COMMAND, CommandState.SubMode.NONE)
|
||||
}
|
||||
|
||||
fun `test double exit`() {
|
||||
doTest("vl<Esc><Esc>", "12${c}3", "12${c}3", CommandState.Mode.COMMAND, CommandState.SubMode.NONE)
|
||||
assertTrue(myFixture.editor.settings.isBlockCursor)
|
||||
}
|
||||
}
|
@@ -90,7 +90,7 @@ class VisualToggleBlockModeActionTest : VimTestCase() {
|
||||
}
|
||||
|
||||
/*
|
||||
[VERSION UPDATE] 2020.2+
|
||||
[VERSION UPDATE] 203+
|
||||
fun `test on empty file`() {
|
||||
doTest("<C-V>", "", "",
|
||||
CommandState.Mode.VISUAL, CommandState.SubMode.VISUAL_BLOCK)
|
||||
|
@@ -65,6 +65,9 @@ class CommandParserTest : VimTestCase() {
|
||||
}
|
||||
|
||||
fun `test execute in disabled state`() {
|
||||
setupChecks {
|
||||
caretShape = false
|
||||
}
|
||||
val keys = commandToKeys(">>")
|
||||
val before = "I ${c}found it in a legendary land"
|
||||
val after = "I ${c}found it in a legendary land"
|
||||
|
@@ -21,8 +21,11 @@ package org.jetbrains.plugins.ideavim.ex.handler;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.maddyhome.idea.vim.ex.ExOutputModel;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Naoto Ikeno
|
||||
*/
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
package org.jetbrains.plugins.ideavim.extension
|
||||
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.maddyhome.idea.vim.VimPlugin
|
||||
@@ -50,15 +51,14 @@ class OpMappingTest : VimTestCase() {
|
||||
|
||||
extension = TestExtension.createBean()
|
||||
|
||||
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+
|
||||
VimExtension.EP_NAME.getPoint(null).registerExtension(extension)
|
||||
VimExtension.EP_NAME.point.registerExtension(extension, VimPlugin.getInstance())
|
||||
enableExtensions("TestExtension")
|
||||
}
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+
|
||||
VimExtension.EP_NAME.getPoint(null).unregisterExtension(extension)
|
||||
@Suppress("DEPRECATION")
|
||||
VimExtension.EP_NAME.point.unregisterExtension(extension)
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
@@ -137,15 +137,14 @@ class OpMappingTest : VimTestCase() {
|
||||
typeText(parseKeys("Q"))
|
||||
myFixture.checkResult("I${c} found it in a legendary land")
|
||||
|
||||
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+
|
||||
VimExtension.EP_NAME.getPoint(null).unregisterExtension(extension)
|
||||
assertEmpty(VimPlugin.getKey().getKeyMappingByOwner(extension.handler.owner))
|
||||
@Suppress("DEPRECATION")
|
||||
VimExtension.EP_NAME.point.unregisterExtension(extension)
|
||||
assertEmpty(VimPlugin.getKey().getKeyMappingByOwner(extension.instance.owner))
|
||||
typeText(parseKeys("Q"))
|
||||
myFixture.checkResult("I${c} found it in a legendary land")
|
||||
|
||||
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+
|
||||
VimExtension.EP_NAME.getPoint(null).registerExtension(extension)
|
||||
assertEmpty(VimPlugin.getKey().getKeyMappingByOwner(extension.handler.owner))
|
||||
VimExtension.EP_NAME.point.registerExtension(extension, VimPlugin.getInstance())
|
||||
assertEmpty(VimPlugin.getKey().getKeyMappingByOwner(extension.instance.owner))
|
||||
enableExtensions("TestExtension")
|
||||
typeText(parseKeys("Q"))
|
||||
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")
|
||||
|
||||
enterCommand("set noTestExtension")
|
||||
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+
|
||||
VimExtension.EP_NAME.getPoint(null).unregisterExtension(extension)
|
||||
@Suppress("DEPRECATION")
|
||||
VimExtension.EP_NAME.point.unregisterExtension(extension)
|
||||
typeText(parseKeys("Q"))
|
||||
myFixture.checkResult("I${c} found it in a legendary land")
|
||||
|
||||
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+
|
||||
VimExtension.EP_NAME.getPoint(null).registerExtension(extension)
|
||||
VimExtension.EP_NAME.point.registerExtension(extension, VimPlugin.getInstance())
|
||||
enableExtensions("TestExtension")
|
||||
typeText(parseKeys("Q"))
|
||||
myFixture.checkResult("I ${c}found it in a legendary land")
|
||||
@@ -178,13 +176,12 @@ class PlugExtensionsTest : VimTestCase() {
|
||||
super.setUp()
|
||||
|
||||
extension = TestExtension.createBean()
|
||||
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+
|
||||
VimExtension.EP_NAME.getPoint(null).registerExtension(extension)
|
||||
VimExtension.EP_NAME.point.registerExtension(extension, VimPlugin.getInstance())
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
@Suppress("DEPRECATION") // [VERSION UPDATE] 202+
|
||||
VimExtension.EP_NAME.getPoint(null).unregisterExtension(extension)
|
||||
@Suppress("DEPRECATION")
|
||||
VimExtension.EP_NAME.point.unregisterExtension(extension)
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
@@ -212,7 +209,7 @@ class PlugExtensionsTest : VimTestCase() {
|
||||
}
|
||||
|
||||
private val ExtensionBeanClass.ext: TestExtension
|
||||
get() = this.handler as TestExtension
|
||||
get() = this.instance as TestExtension
|
||||
|
||||
private class TestExtension : VimExtension {
|
||||
|
||||
@@ -296,6 +293,7 @@ private class TestExtension : VimExtension {
|
||||
val beanClass = ExtensionBeanClass()
|
||||
beanClass.implementation = TestExtension::class.java.canonicalName
|
||||
beanClass.aliases = listOf(Alias().also { it.name = "MyTest" })
|
||||
beanClass.pluginDescriptor = PluginManagerCore.getPlugin(VimPlugin.getPluginId())!!
|
||||
return beanClass
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import com.maddyhome.idea.vim.VimPlugin
|
||||
import com.maddyhome.idea.vim.command.CommandState
|
||||
import com.maddyhome.idea.vim.command.SelectionType
|
||||
import com.maddyhome.idea.vim.common.TextRange
|
||||
import com.maddyhome.idea.vim.group.RegisterGroup
|
||||
import com.maddyhome.idea.vim.helper.StringHelper.parseKeys
|
||||
import com.maddyhome.idea.vim.helper.VimBehaviorDiffers
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
@@ -57,7 +58,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
val text = ""
|
||||
|
||||
configureByText(text)
|
||||
VimPlugin.getRegister().storeTextInternal(myFixture.editor, TextRange(0, 0), "one", SelectionType.CHARACTER_WISE, '"', false)
|
||||
VimPlugin.getRegister().storeTextSpecial(RegisterGroup.UNNAMED_REGISTER, "one")
|
||||
typeText(parseKeys("griw"))
|
||||
myFixture.checkResult("on${c}e")
|
||||
}
|
||||
@@ -66,7 +67,7 @@ class ReplaceWithRegisterTest : VimTestCase() {
|
||||
val text = "${c}one"
|
||||
|
||||
configureByText(text)
|
||||
VimPlugin.getRegister().storeText(myFixture.editor, "" rangeOf "", SelectionType.CHARACTER_WISE, false)
|
||||
VimPlugin.getRegister().storeTextSpecial(RegisterGroup.UNNAMED_REGISTER, "")
|
||||
typeText(parseKeys("griw"))
|
||||
myFixture.checkResult(c)
|
||||
}
|
||||
|
@@ -41,6 +41,6 @@ class InfoFileTest : VimTestCase() {
|
||||
}
|
||||
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.maddyhome.idea.vim.helper.StringHelper
|
||||
import com.maddyhome.idea.vim.helper.StringHelper.parseKeys
|
||||
import com.maddyhome.idea.vim.option.OptionsManager
|
||||
import org.jetbrains.jetCheck.Generator
|
||||
import org.jetbrains.jetCheck.ImperativeCommand
|
||||
import org.jetbrains.jetCheck.PropertyChecker
|
||||
@@ -30,6 +31,8 @@ import org.jetbrains.plugins.ideavim.NeovimTesting
|
||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.sign
|
||||
|
||||
class IncrementDecrementTest : VimPropertyTest() {
|
||||
@TestWithoutNeovim(SkipNeovimReason.DIFFERENT)
|
||||
@@ -48,6 +51,7 @@ class IncrementDecrementTest : VimPropertyTest() {
|
||||
}
|
||||
|
||||
fun testPlayingWithNumbersGenerateNumber() {
|
||||
OptionsManager.nrformats.append("octal")
|
||||
PropertyChecker.checkScenarios {
|
||||
ImperativeCommand { env ->
|
||||
val number = env.generateValue(testNumberGenerator, "Generate %s number")
|
||||
@@ -85,15 +89,10 @@ private class IncrementDecrementActions(private val editor: Editor, val test: Vi
|
||||
|
||||
val differentFormNumberGenerator = Generator.from { env ->
|
||||
val form = env.generate(Generator.sampledFrom(/*2,*/ 8, 10, 16))
|
||||
env.generate(Generator.integers().map {
|
||||
val str = it.toString(form)
|
||||
val prefix = when (form) {
|
||||
2 -> "0b"
|
||||
8 -> "0"
|
||||
16 -> "0x"
|
||||
else -> ""
|
||||
}
|
||||
if (str[0] == '-') "-$prefix${str.substring(1)}" else "$prefix$str"
|
||||
env.generate(Generator.integers().suchThat { it != Int.MIN_VALUE }.map {
|
||||
val sign = it.sign
|
||||
val stringNumber = it.absoluteValue.toString(form)
|
||||
if (sign < 0) "-$stringNumber" else stringNumber
|
||||
})
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user