mirror of
				https://github.com/chylex/IntelliJ-IdeaVim.git
				synced 2025-10-31 11:17:13 +01:00 
			
		
		
		
	Compare commits
	
		
			26 Commits
		
	
	
		
			customized
			...
			1791692d92
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1791692d92 | ||
|   | ba23c9ab5e | ||
|   | f96ab37bcb | ||
|   | 0da34bbb34 | ||
|   | 51e7c745ea | ||
|   | 8347251572 | ||
|   | ce8512f4e0 | ||
|   | a724a19d00 | ||
|   | 7eae7a98e8 | ||
|   | fe9566eebd | ||
|   | b69756730f | ||
|   | 6cd1a60b53 | ||
|   | 9d935e47b5 | ||
|   | a7d5372d06 | ||
|   | a575942c81 | ||
|   | 3cf6c53a8e | ||
|   | 91d86680de | ||
|   | d1d082fb99 | ||
|   | 2c634d1bf0 | ||
|   | 02a6fe4dc9 | ||
|   | 223d681526 | ||
|   | f42ef1c2fc | ||
|   | f4817b2111 | ||
|   | 6f5def0abf | ||
|   | f0fcd7f133 | ||
|   | 6115adb72e | 
							
								
								
									
										24
									
								
								.teamcity/patches/buildTypes/Build.kts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								.teamcity/patches/buildTypes/Build.kts
									
									
									
									
										vendored
									
									
								
							| @@ -4,7 +4,7 @@ import jetbrains.buildServer.configs.kotlin.v2019_2.* | ||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType | ||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.golang | ||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.buildSteps.script | ||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.vcs | ||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.schedule | ||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.ui.* | ||||
|  | ||||
| /* | ||||
| @@ -17,17 +17,33 @@ create(DslContext.projectId, BuildType({ | ||||
|     name = "IdeaVim compatibility with external plugins" | ||||
|  | ||||
|     vcs { | ||||
|         root(RelativeId("HttpsGithubComAlexPl292IdeaVimCompatibilityRefsHeadsMaster")) | ||||
|         root(DslContext.settingsRoot) | ||||
|     } | ||||
|  | ||||
|     steps { | ||||
|         script { | ||||
|             scriptContent = "go run test.go" | ||||
|             name = "Check" | ||||
|             scriptContent = """ | ||||
|                 java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}org.jetbrains.IdeaVim-EasyMotion' [latest-IU] -team-city | ||||
|                 java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}io.github.mishkun.ideavimsneak' [latest-IU] -team-city | ||||
|                 java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}eu.theblob42.idea.whichkey' [latest-IU] -team-city | ||||
|                 java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}IdeaVimExtension' [latest-IU] -team-city | ||||
|                 # Outdated java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}github.zgqq.intellij-enhance' [latest-IU] -team-city | ||||
|                 java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}com.github.copilot' [latest-IU] -team-city | ||||
|                 java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}com.github.dankinsoid.multicursor' [latest-IU] -team-city | ||||
|                 java -jar verifier/verifier-cli-dev-all.jar check-plugin '${'$'}com.joshestein.ideavim-quickscope' [latest-IU] -team-city | ||||
|             """.trimIndent() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     triggers { | ||||
|         vcs { | ||||
|         schedule { | ||||
|             schedulingPolicy = daily { | ||||
|                 hour = 4 | ||||
|             } | ||||
|             branchFilter = "" | ||||
|             triggerBuild = always() | ||||
|             withPendingChangesOnly = false | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -48,13 +48,13 @@ import com.maddyhome.idea.vim.group.visual.VisualMotionGroup; | ||||
| import com.maddyhome.idea.vim.helper.MacKeyRepeat; | ||||
| import com.maddyhome.idea.vim.listener.VimListenerManager; | ||||
| import com.maddyhome.idea.vim.newapi.IjVimInjector; | ||||
| import com.maddyhome.idea.vim.options.OptionService; | ||||
| import com.maddyhome.idea.vim.ui.StatusBarIconFactory; | ||||
| import com.maddyhome.idea.vim.ui.VimEmulationConfigurable; | ||||
| import com.maddyhome.idea.vim.ui.ex.ExEntryPanel; | ||||
| import com.maddyhome.idea.vim.vimscript.services.FunctionStorage; | ||||
| import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService; | ||||
| import com.maddyhome.idea.vim.vimscript.services.VimVariableService; | ||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService; | ||||
| import com.maddyhome.idea.vim.vimscript.services.VariableService; | ||||
| import org.jdom.Element; | ||||
| import org.jetbrains.annotations.Nls; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| @@ -226,8 +226,8 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable | ||||
|     return (PutGroup)VimInjectorKt.getInjector().getPut(); | ||||
|   } | ||||
|  | ||||
|   public static @NotNull VimVariableService getVariableService() { | ||||
|     return ApplicationManager.getApplication().getService(VimVariableService.class); | ||||
|   public static @NotNull VariableService getVariableService() { | ||||
|     return ApplicationManager.getApplication().getService(VariableService.class); | ||||
|   } | ||||
|  | ||||
|   public static @NotNull OptionService getOptionService() { | ||||
|   | ||||
| @@ -34,8 +34,8 @@ import com.maddyhome.idea.vim.group.visual.VimSelection | ||||
| import com.maddyhome.idea.vim.handler.VimActionHandler | ||||
| import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler | ||||
| import com.maddyhome.idea.vim.helper.MessageHelper | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.enumSetOf | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.newapi.ij | ||||
| import java.util.* | ||||
|  | ||||
|   | ||||
| @@ -30,6 +30,15 @@ class CommandState(private val machine: VimStateMachine) { | ||||
|   val isOperatorPending: Boolean | ||||
|     get() = machine.isOperatorPending | ||||
|  | ||||
|   val mode: CommandState.Mode | ||||
|     get() = machine.mode.ij | ||||
|  | ||||
|   val commandBuilder: CommandBuilder | ||||
|     get() = machine.commandBuilder | ||||
|  | ||||
|   val mappingState: MappingState | ||||
|     get() = machine.mappingState | ||||
|  | ||||
|   enum class Mode { | ||||
|     // Basic modes | ||||
|     COMMAND, VISUAL, SELECT, INSERT, CMD_LINE, /*EX*/ | ||||
| @@ -50,7 +59,6 @@ class CommandState(private val machine: VimStateMachine) { | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| val CommandState.SubMode.engine: VimStateMachine.SubMode | ||||
|   get() = when (this) { | ||||
|     CommandState.SubMode.NONE -> VimStateMachine.SubMode.NONE | ||||
| @@ -73,7 +81,6 @@ val CommandState.Mode.engine: VimStateMachine.Mode | ||||
|     CommandState.Mode.INSERT_SELECT -> VimStateMachine.Mode.INSERT_SELECT | ||||
|   } | ||||
|  | ||||
|  | ||||
| val VimStateMachine.Mode.ij: CommandState.Mode | ||||
|   get() = when (this) { | ||||
|     VimStateMachine.Mode.COMMAND -> CommandState.Mode.COMMAND | ||||
|   | ||||
| @@ -23,6 +23,7 @@ import com.intellij.openapi.editor.Editor | ||||
| import com.maddyhome.idea.vim.KeyHandler | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.action.change.Extension | ||||
| import com.maddyhome.idea.vim.api.VimCaret | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.common.CommandAlias | ||||
| @@ -59,8 +60,8 @@ object VimExtensionFacade { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|   * COMPATIBILITY-LAYER: Additional method | ||||
|   */ | ||||
|    * COMPATIBILITY-LAYER: Additional method | ||||
|    */ | ||||
|   /** The 'map' command for mapping keys to handlers defined in extensions. */ | ||||
|   @JvmStatic | ||||
|   fun putExtensionHandlerMapping( | ||||
| @@ -182,12 +183,24 @@ object VimExtensionFacade { | ||||
|     return reg.keys | ||||
|   } | ||||
|  | ||||
|   @JvmStatic | ||||
|   fun getRegisterForCaret(register: Char, caret: VimCaret): List<KeyStroke>? { | ||||
|     val reg = caret.registerStorage.getRegister(register) ?: return null | ||||
|     return reg.keys | ||||
|   } | ||||
|  | ||||
|   /** Set the current contents of the given register */ | ||||
|   @JvmStatic | ||||
|   fun setRegister(register: Char, keys: List<KeyStroke?>?) { | ||||
|     VimPlugin.getRegister().setKeys(register, keys?.filterNotNull() ?: emptyList()) | ||||
|   } | ||||
|  | ||||
|   /** Set the current contents of the given register */ | ||||
|   @JvmStatic | ||||
|   fun setRegisterForCaret(register: Char, caret: VimCaret, keys: List<KeyStroke?>?) { | ||||
|     caret.registerStorage.setKeys(register, keys?.filterNotNull() ?: emptyList()) | ||||
|   } | ||||
|  | ||||
|   /** Set the current contents of the given register */ | ||||
|   @JvmStatic | ||||
|   fun setRegister(register: Char, keys: List<KeyStroke?>?, type: SelectionType) { | ||||
|   | ||||
| @@ -25,9 +25,9 @@ import com.maddyhome.idea.vim.api.VimExtensionRegistrator | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.ex.ExException | ||||
| import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove | ||||
| import com.maddyhome.idea.vim.option.ToggleOption | ||||
| import com.maddyhome.idea.vim.options.OptionChangeListener | ||||
| import com.maddyhome.idea.vim.options.OptionScope | ||||
| import com.maddyhome.idea.vim.option.ToggleOption | ||||
| import com.maddyhome.idea.vim.statistic.PluginState | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | ||||
|  | ||||
|   | ||||
| @@ -34,13 +34,14 @@ import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.Argument | ||||
| import com.maddyhome.idea.vim.command.Command | ||||
| import com.maddyhome.idea.vim.command.CommandFlags | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.TextObjectVisualType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.common.CommandAliasHandler | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import com.maddyhome.idea.vim.ex.ranges.Ranges | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.extension.VimExtension | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.addCommand | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | ||||
| @@ -48,7 +49,6 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMa | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.handler.TextObjectActionHandler | ||||
| import com.maddyhome.idea.vim.helper.EditorHelper | ||||
| import com.maddyhome.idea.vim.helper.PsiHelper | ||||
|   | ||||
| @@ -31,10 +31,11 @@ import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.ExecutionContext | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.extension.VimExtension | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister | ||||
| @@ -42,7 +43,6 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMa | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegister | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.helper.EditorHelper | ||||
| import com.maddyhome.idea.vim.helper.fileSize | ||||
| import com.maddyhome.idea.vim.helper.moveToInlayAwareLogicalPosition | ||||
|   | ||||
| @@ -33,21 +33,21 @@ import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.Argument | ||||
| import com.maddyhome.idea.vim.command.Command | ||||
| import com.maddyhome.idea.vim.command.CommandFlags | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.MotionType | ||||
| import com.maddyhome.idea.vim.command.OperatorArguments | ||||
| import com.maddyhome.idea.vim.common.Direction | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.extension.VimExtension | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.handler.Motion | ||||
| import com.maddyhome.idea.vim.handler.MotionActionHandler | ||||
| import com.maddyhome.idea.vim.handler.toMotionOrError | ||||
| import com.maddyhome.idea.vim.helper.EditorHelper | ||||
| import com.maddyhome.idea.vim.helper.PsiHelper | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.enumSetOf | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.newapi.ij | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
| import java.util.* | ||||
|   | ||||
| @@ -29,8 +29,8 @@ import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.ExecutionContext | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.extension.VimExtension | ||||
|   | ||||
| @@ -44,11 +44,11 @@ import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.common.CommandAlias | ||||
| import com.maddyhome.idea.vim.common.CommandAliasHandler | ||||
| import com.maddyhome.idea.vim.common.CommandNode | ||||
| import com.maddyhome.idea.vim.common.CommandPartNode | ||||
| import com.maddyhome.idea.vim.common.Node | ||||
| import com.maddyhome.idea.vim.common.RootNode | ||||
| import com.maddyhome.idea.vim.common.addLeafs | ||||
| import com.maddyhome.idea.vim.key.CommandNode | ||||
| import com.maddyhome.idea.vim.key.CommandPartNode | ||||
| import com.maddyhome.idea.vim.key.Node | ||||
| import com.maddyhome.idea.vim.key.RootNode | ||||
| import com.maddyhome.idea.vim.key.addLeafs | ||||
| import com.maddyhome.idea.vim.ex.ranges.Ranges | ||||
| import com.maddyhome.idea.vim.extension.VimExtension | ||||
| import com.maddyhome.idea.vim.group.KeyGroup | ||||
|   | ||||
| @@ -24,10 +24,10 @@ import com.maddyhome.idea.vim.api.ExecutionContext | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.extension.VimExtension | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.group.MotionGroup | ||||
| import com.maddyhome.idea.vim.helper.EditorHelper | ||||
| import com.maddyhome.idea.vim.helper.SearchHelper | ||||
|   | ||||
| @@ -65,15 +65,14 @@ class ReplaceWithRegister : VimExtension { | ||||
|  | ||||
|   private class RwrVisual : ExtensionHandler { | ||||
|     override fun execute(editor: VimEditor, context: ExecutionContext) { | ||||
|       val caretsAndSelections = mutableMapOf<VimCaret, VimSelection>() | ||||
|       val typeInEditor = SelectionType.fromSubMode(editor.subMode) | ||||
|       editor.forEachCaret { caret -> | ||||
|         val selectionStart = caret.selectionStart | ||||
|         val selectionEnd = caret.selectionEnd | ||||
|  | ||||
|         caretsAndSelections += caret to VimSelection.create(selectionStart, selectionEnd - 1, typeInEditor, editor) | ||||
|         val visualSelection = caret to VimSelection.create(selectionStart, selectionEnd - 1, typeInEditor, editor) | ||||
|         doReplace(editor.ij, caret, PutData.VisualSelection(mapOf(visualSelection), typeInEditor)) | ||||
|       } | ||||
|       doReplace(editor.ij, PutData.VisualSelection(caretsAndSelections, typeInEditor)) | ||||
|       editor.exitVisualModeNative() | ||||
|     } | ||||
|   } | ||||
| @@ -97,11 +96,11 @@ class ReplaceWithRegister : VimExtension { | ||||
|         val lineStart = editor.getLineStartOffset(logicalLine) | ||||
|         val lineEnd = editor.getLineEndOffset(logicalLine, true) | ||||
|  | ||||
|         caretsAndSelections += caret to VimSelection.create(lineStart, lineEnd, SelectionType.LINE_WISE, editor) | ||||
|       } | ||||
|         val visualSelection = caret to VimSelection.create(lineStart, lineEnd, SelectionType.LINE_WISE, editor) | ||||
|         caretsAndSelections += visualSelection | ||||
|  | ||||
|       val visualSelection = PutData.VisualSelection(caretsAndSelections, SelectionType.LINE_WISE) | ||||
|       doReplace(editor.ij, visualSelection) | ||||
|         doReplace(editor.ij, caret, PutData.VisualSelection(mapOf(visualSelection), SelectionType.LINE_WISE)) | ||||
|       } | ||||
|  | ||||
|       editor.forEachCaret { caret -> | ||||
|         val vimStart = caretsAndSelections[caret]?.vimStart | ||||
| @@ -126,7 +125,8 @@ class ReplaceWithRegister : VimExtension { | ||||
|         ), | ||||
|         selectionType | ||||
|       ) | ||||
|       doReplace(editor, visualSelection) | ||||
|       // todo multicaret | ||||
|       doReplace(editor, editor.vim.primaryCaret(), visualSelection) | ||||
|       return true | ||||
|     } | ||||
|  | ||||
| @@ -147,8 +147,9 @@ class ReplaceWithRegister : VimExtension { | ||||
|     @NonNls | ||||
|     private const val RWR_VISUAL = "<Plug>ReplaceWithRegisterVisual" | ||||
|  | ||||
|     private fun doReplace(editor: Editor, visualSelection: PutData.VisualSelection) { | ||||
|       val savedRegister = VimPlugin.getRegister().lastRegister ?: return | ||||
|     private fun doReplace(editor: Editor, caret: VimCaret, visualSelection: PutData.VisualSelection) { | ||||
|       val lastRegisterChar = injector.registerGroup.lastRegisterChar | ||||
|       val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return | ||||
|  | ||||
|       var usedType = savedRegister.type | ||||
|       var usedText = savedRegister.text | ||||
| @@ -173,8 +174,8 @@ class ReplaceWithRegister : VimExtension { | ||||
|         VimPlugin.getPut().putText(IjVimEditor(editor), IjExecutionContext(EditorDataContext.init(editor)), putData) | ||||
|       } | ||||
|  | ||||
|       VimPlugin.getRegister().saveRegister(savedRegister.name, savedRegister) | ||||
|       VimPlugin.getRegister().saveRegister(VimPlugin.getRegister().defaultRegister, savedRegister) | ||||
|       caret.registerStorage.saveRegister(savedRegister.name, savedRegister) | ||||
|       caret.registerStorage.saveRegister(VimPlugin.getRegister().defaultRegister, savedRegister) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -22,23 +22,23 @@ import com.intellij.openapi.application.runWriteAction | ||||
| import com.intellij.openapi.editor.Editor | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.ExecutionContext | ||||
| import com.maddyhome.idea.vim.api.VimCaret | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.extension.VimExtension | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegisterForCaret | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputKeyStroke | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputString | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegister | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.helper.EditorHelper | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.key.OperatorFunction | ||||
| import com.maddyhome.idea.vim.newapi.IjVimCaret | ||||
| @@ -46,6 +46,7 @@ import com.maddyhome.idea.vim.newapi.IjVimEditor | ||||
| import com.maddyhome.idea.vim.newapi.ij | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
| import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper | ||||
| import com.maddyhome.idea.vim.put.PutData | ||||
| import org.jetbrains.annotations.NonNls | ||||
| import java.awt.event.KeyEvent | ||||
| import javax.swing.KeyStroke | ||||
| @@ -115,33 +116,70 @@ class VimSurroundExtension : VimExtension { | ||||
|       if (charTo.code == 0) return | ||||
|  | ||||
|       val newSurround = getOrInputPair(charTo, editor.ij) ?: return | ||||
|       runWriteAction { change(editor.ij, charFrom, newSurround) } | ||||
|       runWriteAction { change(editor, context, charFrom, newSurround) } | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|       fun change(editor: Editor, charFrom: Char, newSurround: Pair<String, String>?) { | ||||
|         // We take over the " register, so preserve it | ||||
|         val oldValue: List<KeyStroke>? = getRegister(REGISTER) | ||||
|         // Empty the " register | ||||
|         setRegister(REGISTER, null) | ||||
|         // Extract the inner value | ||||
|         perform("di" + pick(charFrom), editor) | ||||
|         val innerValue: MutableList<KeyStroke> = getRegister(REGISTER)?.toMutableList() ?: mutableListOf() | ||||
|         // If the surrounding characters were not found, the register will be empty | ||||
|         if (innerValue.isNotEmpty()) { | ||||
|           // Delete the surrounding | ||||
|           perform("da" + pick(charFrom), editor) | ||||
|           // Insert the surrounding characters and paste | ||||
|           if (newSurround != null) { | ||||
|             innerValue.addAll(0, injector.parser.parseKeys(newSurround.first)) | ||||
|             innerValue.addAll(injector.parser.parseKeys(newSurround.second)) | ||||
|       fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) { | ||||
|         // Save old register values for carets | ||||
|         val surroundings = editor.sortedCarets() | ||||
|           .map { | ||||
|             val oldValue: List<KeyStroke>? = getRegisterForCaret(REGISTER, it) | ||||
|             setRegisterForCaret(REGISTER, it, null) | ||||
|             SurroundingInfo(it, null, oldValue, null) | ||||
|           } | ||||
|  | ||||
|         // Delete surrounding's content | ||||
|         perform("di" + pick(charFrom), editor.ij) | ||||
|  | ||||
|         // Add info about surrounding's inner text and location | ||||
|         surroundings.forEach { | ||||
|           val registerValue = getRegisterForCaret(REGISTER, it.caret) | ||||
|           val innerValue = if (registerValue.isNullOrEmpty()) null else registerValue | ||||
|           it.innerText = innerValue | ||||
|  | ||||
|           val lineEndOffset = injector.engineEditorHelper.getLineEndOffset(editor, it.caret.getLine().line, false) | ||||
|           if (lineEndOffset == it.caret.offset.point) { | ||||
|             it.isLineEnd = true | ||||
|           } | ||||
|           pasteSurround(innerValue, editor) | ||||
|           // Jump back to start | ||||
|           executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor) | ||||
|         } | ||||
|         // Restore the old value | ||||
|         setRegister(REGISTER, oldValue) | ||||
|  | ||||
|         // Remove surrounding | ||||
|         perform("da" + pick(charFrom), editor.ij) | ||||
|  | ||||
|         surroundings.forEach { | ||||
|           if (it.innerText == null && getRegisterForCaret(REGISTER, it.caret)?.isNotEmpty() == true) { | ||||
|             it.innerText = emptyList() | ||||
|           } | ||||
|  | ||||
|           // caret should be placed at the first char of inserted text | ||||
|           // the best solution would be using [ mark after the paste, but marks are not supported by multicaret | ||||
|           // todo | ||||
|           if (it.innerText != null) { | ||||
|             it.offset = it.caret.offset.point | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         surroundings | ||||
|           .filter { it.innerText != null } // we do nothing with carets that are not inside the surrounding | ||||
|           .map { surrounding -> | ||||
|             val innerValue = injector.parser.toPrintableString(surrounding.innerText!!) | ||||
|             val text = newSurround?.let { it.first + innerValue + it.second } ?: innerValue | ||||
|             val textData = PutData.TextData(text, SelectionType.CHARACTER_WISE, emptyList()) | ||||
|             val putData = PutData(textData, null, 1, insertTextBeforeCaret = !surrounding.isLineEnd, rawIndent = true, caretAfterInsertedText = false) | ||||
|  | ||||
|             surrounding.caret to putData | ||||
|           }.forEach { | ||||
|             injector.put.putTextForCaret(editor, it.first, context, it.second) | ||||
|           } | ||||
|  | ||||
|         surroundings.forEach { | ||||
|           it.restoreRegister() | ||||
|         } | ||||
|  | ||||
|         if (surroundings.size == 1) { | ||||
|           surroundings.first().moveCaret() | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       private fun perform(sequence: String, editor: Editor) { | ||||
| @@ -149,21 +187,6 @@ class VimSurroundExtension : VimExtension { | ||||
|           .use { executeNormalWithoutMapping(injector.parser.parseKeys("\"" + REGISTER + sequence), editor) } | ||||
|       } | ||||
|  | ||||
|       private fun pasteSurround( | ||||
|         innerValue: List<KeyStroke?>, | ||||
|         editor: Editor, | ||||
|       ) { // This logic is direct from vim-surround | ||||
|         val offset = editor.caretModel.offset | ||||
|         val lineEndOffset = EditorHelper.getLineEndForOffset(editor, offset) | ||||
|         val motionEndMark = VimPlugin.getMark().getMark(editor.vim, ']') | ||||
|         val motionEndOffset = if (motionEndMark != null) { | ||||
|           EditorHelper.getOffset(editor, motionEndMark.logicalLine, motionEndMark.col) | ||||
|         } else -1 | ||||
|         val pasteCommand = if (motionEndOffset == lineEndOffset && offset + 1 == lineEndOffset) "p" else "P" | ||||
|         setRegister(REGISTER, innerValue) | ||||
|         perform(pasteCommand, editor) | ||||
|       } | ||||
|  | ||||
|       private fun pick(charFrom: Char) = when (charFrom) { | ||||
|         'a' -> '>' | ||||
|         'r' -> ']' | ||||
| @@ -172,6 +195,18 @@ class VimSurroundExtension : VimExtension { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private data class SurroundingInfo(val caret: VimCaret, var innerText: List<KeyStroke>?, val oldRegisterContent: List<KeyStroke>?, var offset: Int?, var isLineEnd: Boolean = false) { | ||||
|     fun restoreRegister() { | ||||
|       setRegisterForCaret(REGISTER, caret, oldRegisterContent) | ||||
|     } | ||||
|  | ||||
|     fun moveCaret() { | ||||
|       if (innerText != null && offset != null) { | ||||
|         caret.moveToOffset(offset!! + if (isLineEnd) 1 else 0) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private class DSurroundHandler : ExtensionHandler { | ||||
|     override val isRepeatable = true | ||||
|  | ||||
| @@ -180,7 +215,7 @@ class VimSurroundExtension : VimExtension { | ||||
|       val charFrom = getChar(editor.ij) | ||||
|       if (charFrom.code == 0) return | ||||
|  | ||||
|       runWriteAction { CSurroundHandler.change(editor.ij, charFrom, null) } | ||||
|       runWriteAction { CSurroundHandler.change(editor, context, charFrom, null) } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -675,7 +675,7 @@ public class ChangeGroup extends VimChangeGroupBase { | ||||
|               } | ||||
|             } | ||||
|             if (pos > wsoff) { | ||||
|               deleteText(editor, new TextRange(wsoff, pos), null); | ||||
|               deleteText(editor, new TextRange(wsoff, pos), null, caret); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|   | ||||
| @@ -38,8 +38,7 @@ import com.maddyhome.idea.vim.action.ComplicatedKeysAction; | ||||
| import com.maddyhome.idea.vim.action.VimShortcutKeyAction; | ||||
| import com.maddyhome.idea.vim.api.*; | ||||
| import com.maddyhome.idea.vim.command.MappingMode; | ||||
| import com.maddyhome.idea.vim.common.Node; | ||||
| import com.maddyhome.idea.vim.common.NodesKt; | ||||
| import com.maddyhome.idea.vim.key.Node; | ||||
| import com.maddyhome.idea.vim.ex.ExOutputModel; | ||||
| import com.maddyhome.idea.vim.handler.EditorActionHandlerBase; | ||||
| import com.maddyhome.idea.vim.helper.HelperKt; | ||||
|   | ||||
| @@ -34,8 +34,8 @@ import com.maddyhome.idea.vim.api.ExecutionContext | ||||
| import com.maddyhome.idea.vim.api.VimCaret | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.isBlock | ||||
| import com.maddyhome.idea.vim.command.isChar | ||||
| import com.maddyhome.idea.vim.command.isLine | ||||
| @@ -60,10 +60,14 @@ import java.awt.datatransfer.DataFlavor | ||||
| import kotlin.math.min | ||||
|  | ||||
| class PutGroup : VimPutBase() { | ||||
|   override fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData): Boolean { | ||||
|   override fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData, updateVisualMarks: Boolean): Boolean { | ||||
|     val additionalData = collectPreModificationData(editor, data) | ||||
|     data.visualSelection?.let { deleteSelectedText(editor, data) } | ||||
|     val processedText = processText(editor, data) ?: return false | ||||
|     putForCaret(editor, caret, data, additionalData, context, processedText) | ||||
|     if (editor.primaryCaret() == caret && updateVisualMarks) { | ||||
|       wrapInsertedTextWithVisualMarks(editor, data, processedText) | ||||
|     } | ||||
|     return true | ||||
|   } | ||||
|  | ||||
| @@ -118,7 +122,9 @@ class PutGroup : VimPutBase() { | ||||
|         editor, caret, context, text.text, text.typeInRegister, subMode, | ||||
|         startOffset, data.count, data.indent, data.caretAfterInsertedText | ||||
|       ) | ||||
|       VimPlugin.getMark().setChangeMarks(editor, TextRange(startOffset, endOffset)) | ||||
|       if (caret == editor.primaryCaret()) { | ||||
|         VimPlugin.getMark().setChangeMarks(editor, TextRange(startOffset, endOffset)) | ||||
|       } | ||||
|       moveCaretToEndPosition( | ||||
|         editor, | ||||
|         caret, | ||||
| @@ -229,13 +235,13 @@ class PutGroup : VimPutBase() { | ||||
|   } | ||||
|  | ||||
|   private fun putTextViaIde( | ||||
|       pasteProvider: PasteProvider, | ||||
|       vimEditor: VimEditor, | ||||
|       vimContext: ExecutionContext, | ||||
|       text: ProcessedTextData, | ||||
|       subMode: VimStateMachine.SubMode, | ||||
|       data: PutData, | ||||
|       additionalData: Map<String, Any>, | ||||
|     pasteProvider: PasteProvider, | ||||
|     vimEditor: VimEditor, | ||||
|     vimContext: ExecutionContext, | ||||
|     text: ProcessedTextData, | ||||
|     subMode: VimStateMachine.SubMode, | ||||
|     data: PutData, | ||||
|     additionalData: Map<String, Any>, | ||||
|   ) { | ||||
|     val editor = (vimEditor as IjVimEditor).editor | ||||
|     val context = vimContext.context as DataContext | ||||
|   | ||||
| @@ -18,18 +18,16 @@ | ||||
|  | ||||
| package com.maddyhome.idea.vim.group.copy | ||||
|  | ||||
| import com.intellij.openapi.editor.Caret | ||||
| import com.intellij.openapi.editor.Editor | ||||
| import com.intellij.util.containers.ContainerUtil | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.action.motion.updown.MotionDownLess1FirstNonSpaceAction | ||||
| import com.maddyhome.idea.vim.api.ExecutionContext | ||||
| import com.maddyhome.idea.vim.api.VimCaret | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.Argument | ||||
| import com.maddyhome.idea.vim.command.OperatorArguments | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import com.maddyhome.idea.vim.group.MotionGroup | ||||
| import com.maddyhome.idea.vim.helper.EditorHelper | ||||
| import com.maddyhome.idea.vim.helper.fileSize | ||||
| import com.maddyhome.idea.vim.listener.VimYankListener | ||||
| @@ -46,8 +44,8 @@ class YankGroup : YankGroupBase() { | ||||
|  | ||||
|   fun removeListener(listener: VimYankListener) = yankListeners.remove(listener) | ||||
|  | ||||
|   private fun notifyListeners(editor: Editor, textRange: TextRange) = yankListeners.forEach { | ||||
|     it.yankPerformed(editor, textRange) | ||||
|   private fun notifyListeners(editor: VimEditor, textRange: TextRange) = yankListeners.forEach { | ||||
|     it.yankPerformed(editor.ij, textRange) | ||||
|   } | ||||
|  | ||||
|   /** | ||||
| @@ -67,32 +65,38 @@ class YankGroup : YankGroupBase() { | ||||
|     operatorArguments: OperatorArguments | ||||
|   ): Boolean { | ||||
|     val motion = argument.motion | ||||
|     val type = if (motion.isLinewiseMotion()) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE | ||||
|  | ||||
|     val caretModel = editor.ij.caretModel | ||||
|     if (caretModel.caretCount <= 0) return false | ||||
|     val nativeCaretCount = editor.nativeCarets().size | ||||
|     if (nativeCaretCount <= 0) return false | ||||
|  | ||||
|     val ranges = ArrayList<Pair<Int, Int>>(caretModel.caretCount) | ||||
|     val carretToRange = HashMap<VimCaret, TextRange>(nativeCaretCount) | ||||
|     val ranges = ArrayList<Pair<Int, Int>>(nativeCaretCount) | ||||
|  | ||||
|     // This logic is from original vim | ||||
|     val startOffsets = | ||||
|       if (argument.motion.action is MotionDownLess1FirstNonSpaceAction) null else HashMap<Caret, Int>(caretModel.caretCount) | ||||
|     val startOffsets = if (argument.motion.action is MotionDownLess1FirstNonSpaceAction) null else HashMap<VimCaret, Int>(nativeCaretCount) | ||||
|  | ||||
|     for (caret in caretModel.allCarets) { | ||||
|       val motionRange = MotionGroup.getMotionRange(editor.ij, caret, context.ij, argument, operatorArguments) | ||||
|     for (caret in editor.nativeCarets()) { | ||||
|       val motionRange = injector.motion.getMotionRange(editor, caret, context, argument, operatorArguments) | ||||
|         ?: continue | ||||
|  | ||||
|       assert(motionRange.size() == 1) | ||||
|       ranges.add(motionRange.startOffset to motionRange.endOffset) | ||||
|       startOffsets?.put(caret, motionRange.normalize().startOffset) | ||||
|       carretToRange[caret] = TextRange(motionRange.startOffset, motionRange.endOffset) | ||||
|     } | ||||
|  | ||||
|     val type = if (motion.isLinewiseMotion()) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE | ||||
|     val range = getTextRange(ranges, type) ?: return false | ||||
|  | ||||
|     if (range.size() == 0) return false | ||||
|  | ||||
|     val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type | ||||
|     return yankRange(editor.ij, range, selectionType, startOffsets) | ||||
|     return yankRange( | ||||
|       editor, | ||||
|       carretToRange, | ||||
|       range, | ||||
|       type, | ||||
|       startOffsets | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   /** | ||||
| @@ -103,19 +107,21 @@ class YankGroup : YankGroupBase() { | ||||
|    * @return true if able to yank the lines, false if not | ||||
|    */ | ||||
|   override fun yankLine(editor: VimEditor, count: Int): Boolean { | ||||
|     val caretModel = editor.ij.caretModel | ||||
|     val ranges = ArrayList<Pair<Int, Int>>(caretModel.caretCount) | ||||
|     for (caret in caretModel.allCarets) { | ||||
|       val start = VimPlugin.getMotion().moveCaretToLineStart(editor, caret.vim) | ||||
|       val end = min(VimPlugin.getMotion().moveCaretToLineEndOffset(editor, caret.vim, count - 1, true) + 1, editor.fileSize().toInt()) | ||||
|     val caretCount = editor.nativeCarets().size | ||||
|     val ranges = ArrayList<Pair<Int, Int>>(caretCount) | ||||
|     val caretToRange = HashMap<VimCaret, TextRange>(caretCount) | ||||
|     for (caret in editor.nativeCarets()) { | ||||
|       val start = injector.motion.moveCaretToLineStart(editor, caret) | ||||
|       val end = min(injector.motion.moveCaretToLineEndOffset(editor, caret, count - 1, true) + 1, editor.fileSize().toInt()) | ||||
|  | ||||
|       if (end == -1) continue | ||||
|  | ||||
|       ranges.add(start to end) | ||||
|       caretToRange[caret] = TextRange(start, end) | ||||
|     } | ||||
|  | ||||
|     val range = getTextRange(ranges, SelectionType.LINE_WISE) ?: return false | ||||
|     return yankRange(editor.ij, range, SelectionType.LINE_WISE, null) | ||||
|     return yankRange(editor, caretToRange, range, SelectionType.LINE_WISE, null) | ||||
|   } | ||||
|  | ||||
|   /** | ||||
| @@ -129,6 +135,7 @@ class YankGroup : YankGroupBase() { | ||||
|   override fun yankRange(editor: VimEditor, range: TextRange?, type: SelectionType, moveCursor: Boolean): Boolean { | ||||
|     range ?: return false | ||||
|  | ||||
|     val caretToRange = HashMap<VimCaret, TextRange>() | ||||
|     val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type | ||||
|  | ||||
|     if (type == SelectionType.LINE_WISE) { | ||||
| @@ -143,24 +150,25 @@ class YankGroup : YankGroupBase() { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     val caretModel = editor.ij.caretModel | ||||
|     val rangeStartOffsets = range.startOffsets | ||||
|     val rangeEndOffsets = range.endOffsets | ||||
|  | ||||
|     return if (moveCursor) { | ||||
|       val startOffsets = HashMap<Caret, Int>(caretModel.caretCount) | ||||
|       if (type == SelectionType.BLOCK_WISE) { | ||||
|         startOffsets[caretModel.primaryCaret] = range.normalize().startOffset | ||||
|       } else { | ||||
|         val carets = caretModel.allCarets | ||||
|         for (i in carets.indices) { | ||||
|           startOffsets[carets[i]] = TextRange(rangeStartOffsets[i], rangeEndOffsets[i]).normalize().startOffset | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       yankRange(editor.ij, range, selectionType, startOffsets) | ||||
|     val startOffsets = HashMap<VimCaret, Int>(editor.nativeCarets().size) | ||||
|     if (type == SelectionType.BLOCK_WISE) { | ||||
|       startOffsets[editor.primaryCaret()] = range.normalize().startOffset | ||||
|       caretToRange[editor.primaryCaret()] = range | ||||
|     } else { | ||||
|       yankRange(editor.ij, range, selectionType, null) | ||||
|       for ((i, caret) in editor.nativeCarets().withIndex()) { | ||||
|         val textRange = TextRange(rangeStartOffsets[i], rangeEndOffsets[i]) | ||||
|         startOffsets[caret] = textRange.normalize().startOffset | ||||
|         caretToRange[caret] = textRange | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return if (moveCursor) { | ||||
|       yankRange(editor, caretToRange, range, selectionType, startOffsets) | ||||
|     } else { | ||||
|       yankRange(editor, caretToRange, range, selectionType, null) | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -192,15 +200,20 @@ class YankGroup : YankGroupBase() { | ||||
|   } | ||||
|  | ||||
|   private fun yankRange( | ||||
|     editor: Editor, | ||||
|     editor: VimEditor, | ||||
|     caretToRange: Map<VimCaret, TextRange>, | ||||
|     range: TextRange, | ||||
|     type: SelectionType, | ||||
|     startOffsets: Map<Caret, Int>?, | ||||
|     startOffsets: Map<VimCaret, Int>?, | ||||
|   ): Boolean { | ||||
|     startOffsets?.forEach { (caret, offset) -> MotionGroup.moveCaret(editor, caret, offset) } | ||||
|     startOffsets?.forEach { (caret, offset) -> injector.motion.moveCaret(editor, caret, offset) } | ||||
|  | ||||
|     notifyListeners(editor, range) | ||||
|  | ||||
|     return VimPlugin.getRegister().storeText(editor.vim, range, type, false) | ||||
|     var result = true | ||||
|     for ((caret, range) in caretToRange) { | ||||
|       result = caret.registerStorage.storeText(editor, range, type, false) && result | ||||
|     } | ||||
|     return result | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -25,7 +25,7 @@ import com.maddyhome.idea.vim.KeyHandler | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.EditorDataContext | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.helper.exitSelectMode | ||||
| import com.maddyhome.idea.vim.helper.exitVisualMode | ||||
| import com.maddyhome.idea.vim.helper.hasVisualSelection | ||||
| @@ -35,8 +35,8 @@ import com.maddyhome.idea.vim.helper.inSelectMode | ||||
| import com.maddyhome.idea.vim.helper.inVisualMode | ||||
| import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere | ||||
| import com.maddyhome.idea.vim.helper.isTemplateActive | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.helper.popAllModes | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.listener.VimListenerManager | ||||
| import com.maddyhome.idea.vim.newapi.IjVimEditor | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
|   | ||||
| @@ -25,11 +25,11 @@ import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.VimMotionGroupBase | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.EditorHelper | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.helper.inBlockSubMode | ||||
| import com.maddyhome.idea.vim.helper.inSelectMode | ||||
| import com.maddyhome.idea.vim.helper.inVisualMode | ||||
| import com.maddyhome.idea.vim.helper.isEndAllowed | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset | ||||
| import com.maddyhome.idea.vim.helper.subMode | ||||
| import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes | ||||
|   | ||||
| @@ -25,9 +25,9 @@ import com.intellij.openapi.editor.Caret | ||||
| import com.intellij.openapi.editor.Editor | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.OperatorArguments | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | ||||
| import com.maddyhome.idea.vim.newapi.IjExecutionContext | ||||
|   | ||||
| @@ -15,25 +15,30 @@ | ||||
|  * 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.helper | ||||
| 
 | ||||
| package com.maddyhome.idea.vim.helper; | ||||
| 
 | ||||
| import javax.swing.*; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import static com.maddyhome.idea.vim.api.VimInjectorKt.injector; | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import java.util.* | ||||
| import java.util.stream.Collectors | ||||
| import javax.swing.KeyStroke | ||||
| 
 | ||||
| /** | ||||
|  * COMPATIBILITY-LAYER: Created a helper class | ||||
|  */ | ||||
| public class StringHelper { | ||||
|   public static List<KeyStroke> parseKeys(String string) { | ||||
|     return injector.getParser().parseKeys(string); | ||||
| object StringHelper { | ||||
|   @JvmStatic | ||||
|   fun parseKeys(string: String): List<KeyStroke> { | ||||
|     return injector.parser.parseKeys(string) | ||||
|   } | ||||
| 
 | ||||
|   public static List<KeyStroke> parseKeys(String... string) { | ||||
|     return Arrays.stream(string).flatMap(o -> injector.getParser().parseKeys(o).stream()).collect(Collectors.toList()); | ||||
|   @JvmStatic | ||||
|   fun parseKeys(vararg string: String): List<KeyStroke> { | ||||
|     return Arrays.stream(string).flatMap { o: String -> injector.parser.parseKeys(o).stream() } | ||||
|       .collect(Collectors.toList()) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|   @JvmStatic | ||||
|   fun isCloseKeyStroke(stroke: KeyStroke): Boolean { | ||||
|     return stroke.isCloseKeyStroke() | ||||
|   } | ||||
| } | ||||
| @@ -27,8 +27,9 @@ import com.intellij.openapi.editor.RangeMarker | ||||
| import com.intellij.openapi.editor.markup.RangeHighlighter | ||||
| import com.intellij.openapi.util.Key | ||||
| import com.intellij.openapi.util.UserDataHolder | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.api.CaretRegisterStorageBase | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.ex.ExOutputModel | ||||
| import com.maddyhome.idea.vim.group.visual.VisualChange | ||||
| import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset | ||||
| @@ -73,6 +74,7 @@ var Caret.vimInsertStart: RangeMarker by userDataOr { | ||||
|     this.offset | ||||
|   ) | ||||
| } | ||||
| var Caret.registerStorage: CaretRegisterStorageBase? by userDataCaretToEditor() | ||||
|  | ||||
| // ------------------ Editor | ||||
| fun unInitializeEditor(editor: Editor) { | ||||
|   | ||||
| @@ -19,8 +19,6 @@ | ||||
| package com.maddyhome.idea.vim.key | ||||
|  | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.common.Node | ||||
| import com.maddyhome.idea.vim.common.addLeafs | ||||
|  | ||||
| fun <T> Node<T>.addLeafs(keys: String, actionHolder: T) { | ||||
|   addLeafs(injector.parser.parseKeys(keys), actionHolder) | ||||
|   | ||||
| @@ -40,9 +40,9 @@ import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.group.NotificationService | ||||
| import com.maddyhome.idea.vim.helper.EditorDataContext | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.inNormalMode | ||||
| import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
| import com.maddyhome.idea.vim.options.OptionConstants | ||||
| import com.maddyhome.idea.vim.options.OptionScope | ||||
|   | ||||
| @@ -32,8 +32,8 @@ import com.maddyhome.idea.vim.api.VimChangeGroupBase | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.VimMotionGroupBase | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.common.EditorLine | ||||
| import com.maddyhome.idea.vim.common.IndentConfig | ||||
| import com.maddyhome.idea.vim.common.OperatedRange | ||||
|   | ||||
| @@ -22,7 +22,10 @@ import com.intellij.openapi.editor.Caret | ||||
| import com.intellij.openapi.editor.LogicalPosition | ||||
| import com.intellij.openapi.editor.VisualPosition | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.CaretRegisterStorage | ||||
| import com.maddyhome.idea.vim.api.CaretRegisterStorageBase | ||||
| import com.maddyhome.idea.vim.api.VimCaret | ||||
| import com.maddyhome.idea.vim.api.VimCaretBase | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.VimLogicalPosition | ||||
| import com.maddyhome.idea.vim.api.VimVisualPosition | ||||
| @@ -38,13 +41,23 @@ import com.maddyhome.idea.vim.group.visual.vimSetSystemSelectionSilently | ||||
| import com.maddyhome.idea.vim.group.visual.vimUpdateEditorSelection | ||||
| import com.maddyhome.idea.vim.helper.inlayAwareVisualColumn | ||||
| import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset | ||||
| import com.maddyhome.idea.vim.helper.registerStorage | ||||
| import com.maddyhome.idea.vim.helper.vimInsertStart | ||||
| import com.maddyhome.idea.vim.helper.vimLastColumn | ||||
| import com.maddyhome.idea.vim.helper.vimLastVisualOperatorRange | ||||
| import com.maddyhome.idea.vim.helper.vimLine | ||||
| import com.maddyhome.idea.vim.helper.vimSelectionStart | ||||
|  | ||||
| class IjVimCaret(val caret: Caret) : VimCaret { | ||||
| class IjVimCaret(val caret: Caret) : VimCaretBase() { | ||||
|   override val registerStorage: CaretRegisterStorage | ||||
|     get() { | ||||
|       var storage = this.caret.registerStorage | ||||
|       if (storage == null) { | ||||
|         storage = CaretRegisterStorageBase(editor.primaryCaret().ij == caret) | ||||
|         this.caret.registerStorage = storage | ||||
|       } | ||||
|       return storage | ||||
|     } | ||||
|   override val editor: VimEditor | ||||
|     get() = IjVimEditor(caret.editor) | ||||
|   override val offset: Offset | ||||
|   | ||||
| @@ -38,9 +38,9 @@ import com.maddyhome.idea.vim.api.VimLogicalPosition | ||||
| import com.maddyhome.idea.vim.api.VimSelectionModel | ||||
| import com.maddyhome.idea.vim.api.VimVisualPosition | ||||
| import com.maddyhome.idea.vim.api.VirtualFile | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.OperatorArguments | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.common.EditorLine | ||||
| import com.maddyhome.idea.vim.common.LiveRange | ||||
| import com.maddyhome.idea.vim.common.Offset | ||||
|   | ||||
| @@ -68,7 +68,7 @@ import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.history.VimHistory | ||||
| import com.maddyhome.idea.vim.macro.VimMacro | ||||
| import com.maddyhome.idea.vim.mark.VimMarkGroup | ||||
| import com.maddyhome.idea.vim.options.OptionService | ||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService | ||||
| import com.maddyhome.idea.vim.put.VimPut | ||||
| import com.maddyhome.idea.vim.register.VimRegisterGroup | ||||
| import com.maddyhome.idea.vim.ui.VimRcFileState | ||||
| @@ -76,7 +76,7 @@ import com.maddyhome.idea.vim.undo.VimUndoRedo | ||||
| import com.maddyhome.idea.vim.vimscript.Executor | ||||
| import com.maddyhome.idea.vim.vimscript.services.FunctionStorage | ||||
| import com.maddyhome.idea.vim.vimscript.services.PatternService | ||||
| import com.maddyhome.idea.vim.vimscript.services.VimVariableService | ||||
| import com.maddyhome.idea.vim.vimscript.services.VariableService | ||||
| import com.maddyhome.idea.vim.yank.VimYankGroup | ||||
|  | ||||
| class IjVimInjector : VimInjectorBase() { | ||||
| @@ -161,7 +161,7 @@ class IjVimInjector : VimInjectorBase() { | ||||
|  | ||||
|   override val functionService: VimscriptFunctionService | ||||
|     get() = FunctionStorage | ||||
|   override val variableService: VimVariableService | ||||
|   override val variableService: VariableService | ||||
|     get() = service() | ||||
|   override val vimrcFileState: VimrcFileState | ||||
|     get() = VimRcFileState | ||||
|   | ||||
| @@ -22,6 +22,8 @@ import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.options.OptionConstants | ||||
| import com.maddyhome.idea.vim.options.OptionConstants.Companion.ignorecaseName | ||||
| import com.maddyhome.idea.vim.options.OptionConstants.Companion.smartcaseName | ||||
| import com.maddyhome.idea.vim.options.OptionConstants.Companion.timeoutName | ||||
| import com.maddyhome.idea.vim.options.OptionConstants.Companion.timeoutlenName | ||||
| import com.maddyhome.idea.vim.options.OptionScope | ||||
| import com.maddyhome.idea.vim.options.helpers.KeywordOptionHelper | ||||
| import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService | ||||
| @@ -34,6 +36,10 @@ object OptionsManager { | ||||
|     get() = (injector.optionService as IjVimOptionService).getRawOption(ignorecaseName) as ToggleOption | ||||
|   val smartcase: ToggleOption | ||||
|     get() = (injector.optionService as IjVimOptionService).getRawOption(smartcaseName) as ToggleOption | ||||
|   val timeout: ToggleOption | ||||
|     get() = (injector.optionService as IjVimOptionService).getRawOption(timeoutName) as ToggleOption | ||||
|   val timeoutlen: NumberOption | ||||
|     get() = (injector.optionService as IjVimOptionService).getRawOption(timeoutlenName) as NumberOption | ||||
|   val iskeyword: KeywordOption | ||||
|     get() = KeywordOption(KeywordOptionHelper) | ||||
| } | ||||
|   | ||||
| @@ -20,8 +20,8 @@ package com.maddyhome.idea.vim.ui | ||||
|  | ||||
| import com.maddyhome.idea.vim.KeyHandler | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.isCloseKeyStroke | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import java.awt.KeyEventDispatcher | ||||
| import java.awt.KeyboardFocusManager | ||||
| import java.awt.Toolkit | ||||
|   | ||||
| @@ -25,9 +25,9 @@ import com.intellij.codeInsight.lookup.impl.LookupImpl | ||||
| import com.intellij.codeInsight.template.impl.TemplateManagerImpl | ||||
| import com.intellij.openapi.editor.Editor | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.helper.hasBlockOrUnderscoreCaret | ||||
| import com.maddyhome.idea.vim.helper.hasVisualSelection | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.helper.subMode | ||||
| import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
|   | ||||
| @@ -33,7 +33,7 @@ import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString | ||||
| import com.maddyhome.idea.vim.vimscript.model.expressions.Scope | ||||
| import com.maddyhome.idea.vim.vimscript.model.expressions.Variable | ||||
| 
 | ||||
| internal class VimVariableServiceImpl : VimVariableServiceBase() { | ||||
| class IjVariableService : VimVariableServiceBase() { | ||||
|   override fun storeVariable(variable: Variable, value: VimDataType, editor: VimEditor, context: ExecutionContext, vimContext: VimLContext) { | ||||
|     super.storeVariable(variable, value, editor, context, vimContext) | ||||
| 
 | ||||
| @@ -20,9 +20,9 @@ package com.maddyhome.idea.vim.vimscript.services | ||||
|  | ||||
| import com.intellij.openapi.application.ApplicationNamesInfo | ||||
| import com.maddyhome.idea.vim.api.VimOptionServiceBase | ||||
| import com.maddyhome.idea.vim.option.ToggleOption | ||||
| import com.maddyhome.idea.vim.options.OptionConstants | ||||
| import com.maddyhome.idea.vim.options.StringOption | ||||
| import com.maddyhome.idea.vim.option.ToggleOption | ||||
|  | ||||
| internal class IjVimOptionService : VimOptionServiceBase() { | ||||
|  | ||||
|   | ||||
| @@ -26,13 +26,13 @@ | ||||
|                         serviceInterface="com.maddyhome.idea.vim.api.VimVisualMotionGroup"/> | ||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.copy.YankGroup"/> | ||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.copy.PutGroup"/> | ||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.vimscript.services.VimVariableServiceImpl" | ||||
|                         serviceInterface="com.maddyhome.idea.vim.vimscript.services.VimVariableService"/> | ||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.vimscript.services.IjVariableService" | ||||
|                         serviceInterface="com.maddyhome.idea.vim.vimscript.services.VariableService"/> | ||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjStatisticsService" | ||||
|                         serviceInterface="com.maddyhome.idea.vim.api.VimStatistics"/> | ||||
|  | ||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.vimscript.services.IjVimOptionService" | ||||
|                         serviceInterface="com.maddyhome.idea.vim.options.OptionService"/> | ||||
|                         serviceInterface="com.maddyhome.idea.vim.vimscript.services.OptionService"/> | ||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjVimStorageService" | ||||
|                         serviceInterface="com.maddyhome.idea.vim.api.VimStorageService"/> | ||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjVimSystemInfoService" | ||||
|   | ||||
| @@ -31,9 +31,8 @@ import com.maddyhome.idea.vim.helper.RunnableHelper; | ||||
| import com.maddyhome.idea.vim.helper.TestInputModel; | ||||
| import com.maddyhome.idea.vim.newapi.IjExecutionContext; | ||||
| import com.maddyhome.idea.vim.newapi.IjVimEditor; | ||||
| import com.maddyhome.idea.vim.ui.ex.ExEntryPanel; | ||||
| import com.maddyhome.idea.vim.options.OptionScope; | ||||
| import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceImpl; | ||||
| import com.maddyhome.idea.vim.ui.ex.ExEntryPanel; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
|  | ||||
| @@ -63,7 +62,7 @@ public abstract class JavaVimTestCase extends JavaCodeInsightFixtureTestCase { | ||||
|   @Override | ||||
|   protected void tearDown() throws Exception { | ||||
|     ExEntryPanel.getInstance().deactivate(false); | ||||
|     ((VimVariableServiceImpl) VimPlugin.getVariableService()).clear(); | ||||
|     VimPlugin.getVariableService().clear(); | ||||
|     Timer swingTimer = VimVisualTimer.INSTANCE.getSwingTimer(); | ||||
|     if (swingTimer != null) { | ||||
|       swingTimer.stop(); | ||||
|   | ||||
| @@ -21,10 +21,10 @@ package org.jetbrains.plugins.ideavim | ||||
| import com.maddyhome.idea.vim.RegisterActions.VIM_ACTIONS_EP | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.common.CommandNode | ||||
| import com.maddyhome.idea.vim.common.CommandPartNode | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.key.CommandNode | ||||
| import com.maddyhome.idea.vim.key.CommandPartNode | ||||
| import com.maddyhome.idea.vim.handler.ActionBeanClass | ||||
| import junit.framework.TestCase | ||||
| import javax.swing.KeyStroke | ||||
|   | ||||
| @@ -76,9 +76,9 @@ inline fun waitAndAssert(timeInMillis: Int = 1000, condition: () -> Boolean) { | ||||
| } | ||||
|  | ||||
| fun waitAndAssertMode( | ||||
|     fixture: CodeInsightTestFixture, | ||||
|     mode: VimStateMachine.Mode, | ||||
|     timeInMillis: Int = (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.visualdelayName) as VimInt).value + 1000, | ||||
|   fixture: CodeInsightTestFixture, | ||||
|   mode: VimStateMachine.Mode, | ||||
|   timeInMillis: Int = (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.visualdelayName) as VimInt).value + 1000, | ||||
| ) { | ||||
|   waitAndAssert(timeInMillis) { fixture.editor.editorMode == mode } | ||||
| } | ||||
|   | ||||
| @@ -50,9 +50,9 @@ import com.maddyhome.idea.vim.KeyHandler | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.action.VimShortcutKeyAction | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine.SubMode | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.ex.ExException | ||||
| import com.maddyhome.idea.vim.ex.ExOutputModel.Companion.getInstance | ||||
| import com.maddyhome.idea.vim.group.visual.VimVisualTimer.swingTimer | ||||
| @@ -61,9 +61,9 @@ import com.maddyhome.idea.vim.helper.EditorHelper | ||||
| import com.maddyhome.idea.vim.helper.GuicursorChangeListener | ||||
| import com.maddyhome.idea.vim.helper.RunnableHelper.runWriteCommand | ||||
| import com.maddyhome.idea.vim.helper.TestInputModel | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.helper.getGuiCursorMode | ||||
| import com.maddyhome.idea.vim.helper.inBlockSubMode | ||||
| import com.maddyhome.idea.vim.helper.editorMode | ||||
| import com.maddyhome.idea.vim.helper.subMode | ||||
| import com.maddyhome.idea.vim.key.MappingOwner | ||||
| import com.maddyhome.idea.vim.key.ToKeysMappingInfo | ||||
| @@ -77,7 +77,6 @@ import com.maddyhome.idea.vim.ui.ex.ExEntryPanel | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimFuncref | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt | ||||
| import com.maddyhome.idea.vim.vimscript.parser.errors.IdeavimErrorListener | ||||
| import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceImpl | ||||
| import org.assertj.core.api.Assertions | ||||
| import org.junit.Assert | ||||
| import java.awt.event.KeyEvent | ||||
| @@ -137,7 +136,7 @@ abstract class VimTestCase : UsefulTestCase() { | ||||
|     } | ||||
|     SelectionVimListenerSuppressor.lock().use { myFixture.tearDown() } | ||||
|     ExEntryPanel.getInstance().deactivate(false) | ||||
|     (VimPlugin.getVariableService() as VimVariableServiceImpl).clear() | ||||
|     VimPlugin.getVariableService().clear() | ||||
|     VimFuncref.lambdaCounter = 0 | ||||
|     VimFuncref.anonymousCounter = 0 | ||||
|     IdeavimErrorListener.testLogger.clear() | ||||
| @@ -509,21 +508,21 @@ abstract class VimTestCase : UsefulTestCase() { | ||||
|   } | ||||
|  | ||||
|   fun doTest( | ||||
|       keys: List<String>, | ||||
|       before: String, | ||||
|       after: String, | ||||
|       modeAfter: VimStateMachine.Mode, | ||||
|       subModeAfter: SubMode, | ||||
|     keys: List<String>, | ||||
|     before: String, | ||||
|     after: String, | ||||
|     modeAfter: VimStateMachine.Mode, | ||||
|     subModeAfter: SubMode, | ||||
|   ) { | ||||
|     doTest(keys.joinToString(separator = ""), before, after, modeAfter, subModeAfter) | ||||
|   } | ||||
|  | ||||
|   fun doTest( | ||||
|       keys: String, | ||||
|       before: String, | ||||
|       after: String, | ||||
|       modeAfter: VimStateMachine.Mode, | ||||
|       subModeAfter: SubMode, | ||||
|     keys: String, | ||||
|     before: String, | ||||
|     after: String, | ||||
|     modeAfter: VimStateMachine.Mode, | ||||
|     subModeAfter: SubMode, | ||||
|   ) { | ||||
|     configureByText(before) | ||||
|  | ||||
| @@ -533,12 +532,12 @@ abstract class VimTestCase : UsefulTestCase() { | ||||
|   } | ||||
|  | ||||
|   fun doTest( | ||||
|       keys: String, | ||||
|       before: String, | ||||
|       after: String, | ||||
|       modeAfter: VimStateMachine.Mode, | ||||
|       subModeAfter: SubMode, | ||||
|       fileType: FileType, | ||||
|     keys: String, | ||||
|     before: String, | ||||
|     after: String, | ||||
|     modeAfter: VimStateMachine.Mode, | ||||
|     subModeAfter: SubMode, | ||||
|     fileType: FileType, | ||||
|   ) { | ||||
|     configureByText(fileType, before) | ||||
|  | ||||
| @@ -551,12 +550,12 @@ abstract class VimTestCase : UsefulTestCase() { | ||||
|   } | ||||
|  | ||||
|   fun doTest( | ||||
|       keys: String, | ||||
|       before: String, | ||||
|       after: String, | ||||
|       modeAfter: VimStateMachine.Mode, | ||||
|       subModeAfter: SubMode, | ||||
|       fileName: String, | ||||
|     keys: String, | ||||
|     before: String, | ||||
|     after: String, | ||||
|     modeAfter: VimStateMachine.Mode, | ||||
|     subModeAfter: SubMode, | ||||
|     fileName: String, | ||||
|   ) { | ||||
|     configureByText(fileName, before) | ||||
|  | ||||
| @@ -577,12 +576,12 @@ abstract class VimTestCase : UsefulTestCase() { | ||||
|   } | ||||
|  | ||||
|   fun doTest( | ||||
|       keys: List<KeyStroke>, | ||||
|       before: String, | ||||
|       after: String?, | ||||
|       modeAfter: VimStateMachine.Mode, | ||||
|       subModeAfter: SubMode, | ||||
|       afterEditorInitialized: (Editor) -> Unit, | ||||
|     keys: List<KeyStroke>, | ||||
|     before: String, | ||||
|     after: String?, | ||||
|     modeAfter: VimStateMachine.Mode, | ||||
|     subModeAfter: SubMode, | ||||
|     afterEditorInitialized: (Editor) -> Unit, | ||||
|   ) { | ||||
|     configureByText(before) | ||||
|     afterEditorInitialized(myFixture.editor) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -20,8 +20,8 @@ package org.jetbrains.plugins.ideavim.action | ||||
|  | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.key.MappingOwner | ||||
| import junit.framework.TestCase | ||||
| import org.jetbrains.plugins.ideavim.SkipNeovimReason | ||||
|   | ||||
| @@ -20,8 +20,8 @@ package org.jetbrains.plugins.ideavim.action.copy | ||||
|  | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
| import org.jetbrains.plugins.ideavim.VimTestCase | ||||
|   | ||||
| @@ -56,8 +56,7 @@ class PutViaIdeaTest : VimTestCase() { | ||||
|     val before = "${c}I found it in a legendary land" | ||||
|     configureByText(before) | ||||
|  | ||||
|     VimPlugin.getRegister() | ||||
|       .storeText(myFixture.editor.vim, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false) | ||||
|     injector.registerGroup.storeText('"', "legendary", SelectionType.CHARACTER_WISE) | ||||
|  | ||||
|     typeText(injector.parser.parseKeys("ve" + "p")) | ||||
|     val after = "legendar${c}y it in a legendary land" | ||||
|   | ||||
| @@ -115,9 +115,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|   @TestWithoutNeovim(SkipNeovimReason.DIFFERENT) | ||||
|   fun `test put visual text multicaret`() { | ||||
|     val before = "${c}I found ${c}it in a ${c}legendary land" | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("ve" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "legendary", SelectionType.CHARACTER_WISE) | ||||
|     typeText(injector.parser.parseKeys("ve" + "\"*p")) | ||||
|     val after = "legendar${c}y legendar${c}y in a legendar${c}y land" | ||||
|     assertState(after) | ||||
|   } | ||||
| @@ -254,9 +254,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             where it was settled on some sodden sand | ||||
|             ${c}hard by the torrent of a mountain pass. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("ve" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) | ||||
|     typeText(injector.parser.parseKeys("ve" + "\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
| @@ -285,9 +285,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             where it was settled on some sodden sand | ||||
|             ${c}hard by the$c torrent of a mountain pass. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("ve" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) | ||||
|     typeText(injector.parser.parseKeys("ve" + "\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
| @@ -314,9 +314,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             where it was settled on some sodden sand | ||||
|             ${c}hard by the$c torrent of a mountain pass. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("ve" + "2p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) | ||||
|     typeText(injector.parser.parseKeys("ve" + "2\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
| @@ -461,9 +461,10 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             akin to moonlight, tempering its blue, | ||||
|             the dingy ${c}underside, the checquered fringe. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("ve" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE) | ||||
| //    VimPlugin.getRegister().storeText(editor.vim, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("ve" + "\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
| @@ -592,9 +593,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             where it was settled on some sodden sand | ||||
|             hard by the ${c}torrent of a mountain pass. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("V" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "Discovery", SelectionType.CHARACTER_WISE) | ||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
| @@ -628,9 +629,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             where it was settled on some sodden sand | ||||
|             hard by the ${c}torrent of a mountain pass. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("V" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "Discovery", SelectionType.CHARACTER_WISE) | ||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
| @@ -753,9 +754,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             where it was settled on some sodden sand | ||||
|             hard by the ${c}torrent of a mountain pass. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("V" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) | ||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
| @@ -789,9 +790,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             where it was settled on some sodden sand | ||||
|             hard by the ${c}torrent of a mountain pass. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("V" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) | ||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
| @@ -995,9 +996,9 @@ class PutVisualTextActionTest : VimTestCase() { | ||||
|             akin to moonlight, tempering its blue, | ||||
|             the dingy ${c}underside, the checquered fringe. | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("V" + "p")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "|found|\n|l roc|\n|ere i|", SelectionType.BLOCK_WISE) | ||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) | ||||
|     val after = """ | ||||
|             A Discovery | ||||
|  | ||||
|   | ||||
| @@ -202,9 +202,9 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() { | ||||
|             ${c}zxcvbn | ||||
|  | ||||
|     """.trimIndent() | ||||
|     val editor = configureByText(before) | ||||
|     VimPlugin.getRegister().storeText(editor.vim, TextRange(14, 21), SelectionType.LINE_WISE, false) | ||||
|     typeText(injector.parser.parseKeys("vl" + "gp")) | ||||
|     configureByText(before) | ||||
|     injector.registerGroup.storeText('*', "zxcvbn\n", SelectionType.LINE_WISE) | ||||
|     typeText(injector.parser.parseKeys("vl" + "\"*gp")) | ||||
|     val after = """ | ||||
|             q | ||||
|             zxcvbn | ||||
|   | ||||
| @@ -24,7 +24,7 @@ import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | ||||
| import junit.framework.TestCase | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
| import org.jetbrains.plugins.ideavim.SkipNeovimReason | ||||
| import org.jetbrains.plugins.ideavim.TestWithoutNeovim | ||||
| import org.jetbrains.plugins.ideavim.VimTestCase | ||||
| @@ -79,47 +79,48 @@ class YankVisualActionTest : VimTestCase() { | ||||
|   } | ||||
|  | ||||
|   fun `test yank multicaret`() { | ||||
|     doTest( | ||||
|       injector.parser.parseKeys("viw" + "y"), | ||||
|       """ | ||||
|     val text = """ | ||||
|                             A Discovery | ||||
|  | ||||
|                             I ${c}found it in a legendary land | ||||
|                             all rocks and lavender and tufted grass, | ||||
|                             where it ${c}was settled on some sodden sand | ||||
|                             hard by the torrent of a mountain pass. | ||||
|       """.trimIndent(), | ||||
|       "found\nwas", SelectionType.BLOCK_WISE | ||||
|     ) | ||||
|     """.trimIndent() | ||||
|     configureByText(text) | ||||
|     typeText(injector.parser.parseKeys("viw" + "y")) | ||||
|     val editor = myFixture.editor.vim | ||||
|     val lastRegister = injector.registerGroup.lastRegisterChar | ||||
|     val registers = editor.carets().map { it.registerStorage.getRegister(lastRegister)?.rawText } | ||||
|     assertEquals(listOf("found", "was"), registers) | ||||
|   } | ||||
|  | ||||
|   @TestWithoutNeovim(SkipNeovimReason.DIFFERENT) | ||||
|   fun testYankVisualRange() { | ||||
|     val before = """ | ||||
|             q${c}werty | ||||
|             asdf${c}gh | ||||
|             ${c}zxcvbn | ||||
|  | ||||
|     """.trimIndent() | ||||
|     configureByText(before) | ||||
|     typeText(injector.parser.parseKeys("vey")) | ||||
|  | ||||
|     val lastRegister = VimPlugin.getRegister().lastRegister | ||||
|     TestCase.assertNotNull(lastRegister) | ||||
|     val text = lastRegister!!.text | ||||
|     TestCase.assertNotNull(text) | ||||
|  | ||||
|     typeText(injector.parser.parseKeys("G" + "$" + "p")) | ||||
|     val after = """ | ||||
|       qwerty | ||||
|       asdfgh | ||||
|       zxcvbn | ||||
|       ${c}werty | ||||
|       gh | ||||
|       zxcvbn | ||||
|     """.trimIndent() | ||||
|     assertState(after) | ||||
|   } | ||||
|   // todo multicaret | ||||
| //  @TestWithoutNeovim(SkipNeovimReason.DIFFERENT) | ||||
| //  fun testYankVisualRange() { | ||||
| //    val before = """ | ||||
| //            q${c}werty | ||||
| //            asdf${c}gh | ||||
| //            ${c}zxcvbn | ||||
| // | ||||
| //    """.trimIndent() | ||||
| //    configureByText(before) | ||||
| //    typeText(injector.parser.parseKeys("vey")) | ||||
| // | ||||
| //    val lastRegister = VimPlugin.getRegister().lastRegister | ||||
| //    TestCase.assertNotNull(lastRegister) | ||||
| //    val text = lastRegister!!.text | ||||
| //    TestCase.assertNotNull(text) | ||||
| // | ||||
| //    typeText(injector.parser.parseKeys("G" + "$" + "p")) | ||||
| //    val after = """ | ||||
| //      qwerty | ||||
| //      asdfgh | ||||
| //      zxcvbn | ||||
| //      wert${c}yg${c}hzxcvb${c}n | ||||
| //    """.trimIndent() | ||||
| //    assertState(after) | ||||
| //  } | ||||
|  | ||||
|   fun `test yank line`() { | ||||
|     doTest( | ||||
| @@ -152,17 +153,22 @@ class YankVisualActionTest : VimTestCase() { | ||||
|   } | ||||
|  | ||||
|   fun `test yank multicaret line`() { | ||||
|     doTest( | ||||
|       injector.parser.parseKeys("V" + "y"), | ||||
|       """ | ||||
|     val text = """ | ||||
|                             A Discovery | ||||
|  | ||||
|                             I found it in a legendary land | ||||
|                             all ${c}rocks and lavender and tufted grass, | ||||
|                             where it was settled on some sodden sand | ||||
|                             hard by ${c}the torrent of a mountain pass. | ||||
|       """.trimIndent(), | ||||
|       "all rocks and lavender and tufted grass,\nhard by the torrent of a mountain pass.\n", SelectionType.LINE_WISE | ||||
|     """.trimIndent() | ||||
|     configureByText(text) | ||||
|     typeText(injector.parser.parseKeys("V" + "y")) | ||||
|     val editor = myFixture.editor.vim | ||||
|     val lastRegister = injector.registerGroup.lastRegisterChar | ||||
|     val registers = editor.carets().map { it.registerStorage.getRegister(lastRegister)?.rawText } | ||||
|     assertEquals( | ||||
|       listOf("all rocks and lavender and tufted grass,\n", "hard by the torrent of a mountain pass.\n"), | ||||
|       registers | ||||
|     ) | ||||
|   } | ||||
|  | ||||
| @@ -180,35 +186,15 @@ class YankVisualActionTest : VimTestCase() { | ||||
|     configureByText(before) | ||||
|     typeText(injector.parser.parseKeys("Vy")) | ||||
|  | ||||
|     val lastRegister = VimPlugin.getRegister().lastRegister | ||||
|     TestCase.assertNotNull(lastRegister) | ||||
|     val text = lastRegister!!.text | ||||
|     TestCase.assertNotNull(text) | ||||
|     TestCase.assertEquals( | ||||
|       """ | ||||
|     qwe | ||||
|     zxc | ||||
|     rty | ||||
|  | ||||
|       """.trimIndent(), | ||||
|       text | ||||
|     ) | ||||
|  | ||||
|     typeText(injector.parser.parseKeys("p")) | ||||
|     val after = """ | ||||
|             qwe | ||||
|             ${c}qwe | ||||
|             zxc | ||||
|             rty | ||||
|             asd | ||||
|             zxc | ||||
|             ${c}qwe | ||||
|             zxc | ||||
|             rty | ||||
|             rty | ||||
|             ${c}qwe | ||||
|             zxc | ||||
|             ${c}zxc | ||||
|             rty | ||||
|             ${c}rty | ||||
|             fgh | ||||
|             vbn | ||||
|              | ||||
|   | ||||
| @@ -221,11 +221,9 @@ class MultipleCaretsTest : VimTestCase() { | ||||
|     val after = """qwe | ||||
|       |rty | ||||
|       |${c}rty | ||||
|       |fgh | ||||
|       |asd | ||||
|       |fgh | ||||
|       |${c}rty | ||||
|       |fgh | ||||
|       |${c}fgh | ||||
|       |zxc | ||||
|       |vbn | ||||
|     """.trimMargin() | ||||
|   | ||||
| @@ -25,15 +25,15 @@ import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.ExecutionContext | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.extension.Alias | ||||
| import com.maddyhome.idea.vim.extension.ExtensionBeanClass | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.extension.VimExtension | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.extension.VimExtensionRegistrar | ||||
| import com.maddyhome.idea.vim.group.MotionGroup | ||||
| import com.maddyhome.idea.vim.helper.isEndAllowed | ||||
|   | ||||
| @@ -20,8 +20,8 @@ package org.jetbrains.plugins.ideavim.extension.replacewithregister | ||||
|  | ||||
| import com.maddyhome.idea.vim.VimPlugin | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
| import com.maddyhome.idea.vim.register.RegisterConstants.UNNAMED_REGISTER | ||||
| @@ -367,9 +367,7 @@ class ReplaceWithRegisterTest : VimTestCase() { | ||||
|             I found it in a legendary land | ||||
|             where it was settled on some sodden sand | ||||
|             where it was settled on some sodden sand | ||||
|             I found it in a legendary land | ||||
|             where it was settled on some sodden sand | ||||
|  | ||||
|              | ||||
|       """.trimIndent() | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -541,4 +541,32 @@ class VimSurroundExtensionTest : VimTestCase() { | ||||
|     val keys = ":map gw ds)<CR>" + "qqgwqj@q" | ||||
|     doTest(keys, before, after, VimStateMachine.Mode.COMMAND, VimStateMachine.SubMode.NONE) | ||||
|   } | ||||
|  | ||||
|   @TestWithoutNeovim(SkipNeovimReason.PLUGIN) | ||||
|   fun `test change surround with multicaret`() { | ||||
|     val before = """ | ||||
|                   (${c}abc) | ||||
|                   (${c}xyz) | ||||
|                     """ | ||||
|     val after = """ | ||||
|                   [abc] | ||||
|                   [xyz] | ||||
|                     """ | ||||
|  | ||||
|     doTest(listOf("cs(]"), before, after, VimStateMachine.Mode.COMMAND, VimStateMachine.SubMode.NONE) | ||||
|   } | ||||
|  | ||||
|   @TestWithoutNeovim(SkipNeovimReason.PLUGIN) | ||||
|   fun `test delete surround with multicaret`() { | ||||
|     val before = """ | ||||
|                   (${c}abc) | ||||
|                   (${c}xyz) | ||||
|                     """ | ||||
|     val after = """ | ||||
|                   abc | ||||
|                   xyz | ||||
|                     """ | ||||
|  | ||||
|     doTest(listOf("ds("), before, after, VimStateMachine.Mode.COMMAND, VimStateMachine.SubMode.NONE) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import com.intellij.ide.IdeEventQueue | ||||
| import com.intellij.openapi.editor.Editor | ||||
| import com.intellij.testFramework.PlatformTestUtil | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.common.CommandNode | ||||
| import com.maddyhome.idea.vim.key.CommandNode | ||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | ||||
| import com.maddyhome.idea.vim.newapi.ij | ||||
| import com.maddyhome.idea.vim.newapi.vim | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								verifier/verifier-cli-dev-all.jar
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								verifier/verifier-cli-dev-all.jar
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -29,12 +29,12 @@ import com.maddyhome.idea.vim.command.VimStateMachine | ||||
| import com.maddyhome.idea.vim.command.VimStateMachine.Companion.getInstance | ||||
| import com.maddyhome.idea.vim.command.MappingState | ||||
| import com.maddyhome.idea.vim.command.OperatorArguments | ||||
| import com.maddyhome.idea.vim.common.CommandNode | ||||
| import com.maddyhome.idea.vim.common.CommandPartNode | ||||
| import com.maddyhome.idea.vim.key.CommandNode | ||||
| import com.maddyhome.idea.vim.key.CommandPartNode | ||||
| import com.maddyhome.idea.vim.common.CurrentCommandState | ||||
| import com.maddyhome.idea.vim.common.DigraphResult | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.common.Node | ||||
| import com.maddyhome.idea.vim.key.Node | ||||
| import com.maddyhome.idea.vim.common.argumentCaptured | ||||
| import com.maddyhome.idea.vim.diagnostic.VimLogger | ||||
| import com.maddyhome.idea.vim.diagnostic.debug | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
| package com.maddyhome.idea.vim.action.copy | ||||
|  | ||||
| import com.maddyhome.idea.vim.api.ExecutionContext | ||||
| import com.maddyhome.idea.vim.api.VimCaret | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.command.Argument | ||||
| @@ -40,14 +41,28 @@ sealed class PutTextBaseAction( | ||||
|     argument: Argument?, | ||||
|     operatorArguments: OperatorArguments | ||||
|   ): Boolean { | ||||
|     val lastRegister = injector.registerGroup.lastRegister | ||||
|     val textData = if (lastRegister != null) TextData( | ||||
|       lastRegister.text ?: injector.parser.toPrintableString(lastRegister.keys), | ||||
|       lastRegister.type, | ||||
|       lastRegister.transferableData | ||||
|     ) else null | ||||
|     val putData = PutData(textData, null, operatorArguments.count1, insertTextBeforeCaret, indent, caretAfterInsertedText, -1) | ||||
|     return injector.put.putText(editor, context, putData) | ||||
|     val count = operatorArguments.count1 | ||||
|     val caretToPutData = editor.sortedCarets().associateWith { getPutDataForCaret(it, count) } | ||||
|     var result = true | ||||
|     injector.application.runWriteAction { | ||||
|       caretToPutData.forEach { | ||||
|         result = injector.put.putTextForCaret(editor, it.key, context, it.value) && result | ||||
|       } | ||||
|     } | ||||
|     return result | ||||
|   } | ||||
|  | ||||
|   private fun getPutDataForCaret(caret: VimCaret, count: Int): PutData { | ||||
|     val lastRegisterChar = injector.registerGroup.lastRegisterChar | ||||
|     val register = caret.registerStorage.getRegister(lastRegisterChar) | ||||
|     val textData = register?.let { | ||||
|       TextData( | ||||
|         register.text ?: injector.parser.toPrintableString(register.keys), | ||||
|         register.type, | ||||
|         register.transferableData | ||||
|       ) | ||||
|     } | ||||
|     return PutData(textData, null, count, insertTextBeforeCaret, indent, caretAfterInsertedText, -1) | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -52,16 +52,30 @@ sealed class PutVisualTextBaseAction( | ||||
|     operatorArguments: OperatorArguments, | ||||
|   ): Boolean { | ||||
|     if (caretsAndSelections.isEmpty()) return false | ||||
|     val textData = injector.registerGroup.lastRegister?.let { PutData.TextData(it.text, it.type, it.transferableData) } | ||||
|     val count = cmd.count | ||||
|     val caretToPutData = editor.sortedCarets().associateWith { getPutDataForCaret(it, caretsAndSelections[it], count) } | ||||
|     injector.registerGroup.resetRegister() | ||||
|     var result = true | ||||
|     injector.application.runWriteAction { | ||||
|       caretToPutData.forEach { | ||||
|         result = injector.put.putTextForCaret(editor, it.key, context, it.value, true) && result | ||||
|       } | ||||
|     } | ||||
|     return result | ||||
|   } | ||||
|  | ||||
|     val selection = PutData.VisualSelection( | ||||
|       caretsAndSelections, | ||||
|       caretsAndSelections.values.first().type | ||||
|     ) | ||||
|     val putData = PutData(textData, selection, cmd.count, insertTextBeforeCaret, indent, caretAfterInsertedText) | ||||
|  | ||||
|     return injector.put.putText(editor, context, putData, true) | ||||
|   private fun getPutDataForCaret(caret: VimCaret, selection: VimSelection?, count: Int): PutData { | ||||
|     val lastRegisterChar = injector.registerGroup.lastRegisterChar | ||||
|     val register = caret.registerStorage.getRegister(lastRegisterChar) | ||||
|     val textData = register?.let { | ||||
|       PutData.TextData( | ||||
|         register.text ?: injector.parser.toPrintableString(register.keys), | ||||
|         register.type, | ||||
|         register.transferableData | ||||
|       ) | ||||
|     } | ||||
|     val visualSelection = selection?.let { PutData.VisualSelection(mapOf(caret to it), it.type) } | ||||
|     return PutData(textData, visualSelection, count, insertTextBeforeCaret, indent, caretAfterInsertedText) | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,12 +1,17 @@ | ||||
| package com.maddyhome.idea.vim.api | ||||
|  | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.common.EditorLine | ||||
| import com.maddyhome.idea.vim.common.LiveRange | ||||
| import com.maddyhome.idea.vim.common.Offset | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import com.maddyhome.idea.vim.group.visual.VisualChange | ||||
| import com.maddyhome.idea.vim.register.Register | ||||
| import javax.swing.KeyStroke | ||||
|  | ||||
| // TODO: 29.12.2021 Split interface to mutable and immutable | ||||
| interface VimCaret { | ||||
|   val registerStorage: CaretRegisterStorage | ||||
|   val editor: VimEditor | ||||
|   val offset: Offset | ||||
|   var vimLastColumn: Int | ||||
| @@ -35,4 +40,20 @@ interface VimCaret { | ||||
|   fun moveToVisualPosition(position: VimVisualPosition) | ||||
|   fun setNativeSelection(start: Offset, end: Offset) | ||||
|   fun removeNativeSelection() | ||||
| } | ||||
|  | ||||
| interface CaretRegisterStorage { | ||||
|   /** | ||||
|    * Stores text to caret's recordable (named/numbered/unnamed) register | ||||
|    */ | ||||
|   fun storeText(editor: VimEditor, range: TextRange, type: SelectionType, isDelete: Boolean): Boolean | ||||
|  | ||||
|   /** | ||||
|    * Gets text from caret's recordable register | ||||
|    * If the register is not recordable - global text state will be returned | ||||
|    */ | ||||
|   fun getRegister(r: Char): Register? | ||||
|  | ||||
|   fun setKeys(register: Char, keys: List<KeyStroke>) | ||||
|   fun saveRegister(r: Char, register: Register) | ||||
| } | ||||
| @@ -0,0 +1,56 @@ | ||||
| package com.maddyhome.idea.vim.api | ||||
|  | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import com.maddyhome.idea.vim.register.Register | ||||
| import com.maddyhome.idea.vim.register.RegisterConstants | ||||
| import com.maddyhome.idea.vim.register.VimRegisterGroupBase | ||||
| import javax.swing.KeyStroke | ||||
|  | ||||
| abstract class VimCaretBase : VimCaret | ||||
|  | ||||
| open class CaretRegisterStorageBase(private val isCaretPrimary: Boolean) : CaretRegisterStorage, VimRegisterGroupBase() { | ||||
|   override var lastRegisterChar: Char | ||||
|     get() { | ||||
|       return injector.registerGroup.lastRegisterChar | ||||
|     } | ||||
|     set(value) {} | ||||
|  | ||||
|   override fun storeText(editor: VimEditor, range: TextRange, type: SelectionType, isDelete: Boolean): Boolean { | ||||
|     if (isCaretPrimary) { | ||||
|       return injector.registerGroup.storeText(editor, range, type, isDelete) | ||||
|     } | ||||
|     val register = lastRegisterChar | ||||
|     if (!RegisterConstants.RECORDABLE_REGISTERS.contains(register)) { | ||||
|       return false | ||||
|     } | ||||
|     return super.storeText(editor, range, type, isDelete) | ||||
|   } | ||||
|  | ||||
|   override fun getRegister(r: Char): Register? { | ||||
|     if (isCaretPrimary || !RegisterConstants.RECORDABLE_REGISTERS.contains(r)) { | ||||
|       return injector.registerGroup.getRegister(r) | ||||
|     } | ||||
|     return super.getRegister(r) | ||||
|   } | ||||
|  | ||||
|   override fun setKeys(register: Char, keys: List<KeyStroke>) { | ||||
|     if (isCaretPrimary) { | ||||
|       injector.registerGroup.setKeys(register, keys) | ||||
|     } | ||||
|     if (!RegisterConstants.RECORDABLE_REGISTERS.contains(register)) { | ||||
|       return | ||||
|     } | ||||
|     return super.setKeys(register, keys) | ||||
|   } | ||||
|  | ||||
|   override fun saveRegister(r: Char, register: Register) { | ||||
|     if (isCaretPrimary) { | ||||
|       injector.registerGroup.saveRegister(r, register) | ||||
|     } | ||||
|     if (!RegisterConstants.RECORDABLE_REGISTERS.contains(r)) { | ||||
|       return | ||||
|     } | ||||
|     return super.saveRegister(r, register) | ||||
|   } | ||||
| } | ||||
| @@ -83,7 +83,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | ||||
|   override fun deleteCharacter(editor: VimEditor, caret: VimCaret, count: Int, isChange: Boolean): Boolean { | ||||
|     val endOffset = injector.motion.getOffsetOfHorizontalMotion(editor, caret, count, true) | ||||
|     if (endOffset != -1) { | ||||
|       val res = deleteText(editor, TextRange(caret.offset.point, endOffset), SelectionType.CHARACTER_WISE) | ||||
|       val res = deleteText(editor, TextRange(caret.offset.point, endOffset), SelectionType.CHARACTER_WISE, caret) | ||||
|       val pos = caret.offset.point | ||||
|       val norm = injector.engineEditorHelper.normalizeOffset(editor, caret.getLogicalPosition().line, pos, isChange) | ||||
|       if (norm != pos || | ||||
| @@ -132,6 +132,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | ||||
|     editor: VimEditor, | ||||
|     range: TextRange, | ||||
|     type: SelectionType?, | ||||
|     caret: VimCaret, | ||||
|   ): Boolean { | ||||
|     var updatedRange = range | ||||
|     // Fix for https://youtrack.jetbrains.net/issue/VIM-35 | ||||
| @@ -145,7 +146,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | ||||
|       } | ||||
|     } | ||||
|     if (type == null || | ||||
|       editor.inInsertMode || injector.registerGroup.storeText(editor, updatedRange, type, true) | ||||
|       editor.inInsertMode || caret.registerStorage.storeText(editor, updatedRange, type, true) | ||||
|     ) { | ||||
|       val startOffsets = updatedRange.startOffsets | ||||
|       val endOffsets = updatedRange.endOffsets | ||||
| @@ -154,8 +155,10 @@ abstract class VimChangeGroupBase : VimChangeGroup { | ||||
|       } | ||||
|       if (type != null) { | ||||
|         val start = updatedRange.startOffset | ||||
|         injector.markGroup.setMark(editor, MARK_CHANGE_POS, start) | ||||
|         injector.markGroup.setChangeMarks(editor, TextRange(start, start + 1)) | ||||
|         if (editor.primaryCaret() == caret) { | ||||
|           injector.markGroup.setMark(editor, MARK_CHANGE_POS, start) | ||||
|           injector.markGroup.setChangeMarks(editor, TextRange(start, start + 1)) | ||||
|         } | ||||
|       } | ||||
|       return true | ||||
|     } | ||||
| @@ -631,7 +634,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | ||||
|       val rangeToDelete = TextRange(startOffset, offset) | ||||
|       editor.nativeCarets().filter { it != caret && rangeToDelete.contains(it.offset.point) } | ||||
|         .forEach { editor.removeCaret(it) } | ||||
|       val res = deleteText(editor, rangeToDelete, SelectionType.CHARACTER_WISE) | ||||
|       val res = deleteText(editor, rangeToDelete, SelectionType.CHARACTER_WISE, caret) | ||||
|       if (usesVirtualSpace) { | ||||
|         injector.motion.moveCaret(editor, caret, startOffset) | ||||
|       } else { | ||||
| @@ -726,7 +729,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | ||||
|       logger.debug("offset=$offset") | ||||
|     } | ||||
|     if (offset != -1) { | ||||
|       val res = deleteText(editor, TextRange(start, offset), SelectionType.LINE_WISE) | ||||
|       val res = deleteText(editor, TextRange(start, offset), SelectionType.LINE_WISE, caret) | ||||
|       if (res && caret.offset.point >= editor.fileSize() && caret.offset.point != 0) { | ||||
|         injector.motion.moveCaret( | ||||
|           editor, caret, injector.motion.moveCaretToLineStartSkipLeadingOffset( | ||||
| @@ -856,7 +859,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | ||||
|     // Update the last column before we delete, or we might be retrieving the data for a line that no longer exists | ||||
|     caret.vimLastColumn = caret.inlayAwareVisualColumn | ||||
|     val removeLastNewLine = removeLastNewLine(editor, range, type) | ||||
|     val res = deleteText(editor, range, type) | ||||
|     val res = deleteText(editor, range, type, caret) | ||||
|     if (removeLastNewLine) { | ||||
|       val textLength = editor.fileSize().toInt() | ||||
|       editor.deleteString(TextRange(textLength - 1, textLength)) | ||||
| @@ -975,7 +978,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | ||||
|       } else { | ||||
|         injector.motion.moveCaretToLineStart(editor, caret.getLogicalPosition().line + 1) | ||||
|       } | ||||
|       deleteText(editor, TextRange(caret.offset.point, offset), null) | ||||
|       deleteText(editor, TextRange(caret.offset.point, offset), null, caret) | ||||
|       if (spaces && !hasTrailingWhitespace) { | ||||
|         insertText(editor, caret, " ") | ||||
|         injector.motion.moveCaret( | ||||
|   | ||||
| @@ -9,11 +9,11 @@ import com.maddyhome.idea.vim.helper.VimCommandLineHelper | ||||
| import com.maddyhome.idea.vim.history.VimHistory | ||||
| import com.maddyhome.idea.vim.macro.VimMacro | ||||
| import com.maddyhome.idea.vim.mark.VimMarkGroup | ||||
| import com.maddyhome.idea.vim.options.OptionService | ||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService | ||||
| import com.maddyhome.idea.vim.put.VimPut | ||||
| import com.maddyhome.idea.vim.register.VimRegisterGroup | ||||
| import com.maddyhome.idea.vim.undo.VimUndoRedo | ||||
| import com.maddyhome.idea.vim.vimscript.services.VimVariableService | ||||
| import com.maddyhome.idea.vim.vimscript.services.VariableService | ||||
| import com.maddyhome.idea.vim.yank.VimYankGroup | ||||
|  | ||||
| interface VimInjector { | ||||
| @@ -117,7 +117,7 @@ interface VimInjector { | ||||
|   // Can't be fully moved to vim-engine. | ||||
|   val vimscriptParser: VimscriptParser | ||||
|   // !! in progress | ||||
|   val variableService: VimVariableService | ||||
|   val variableService: VariableService | ||||
|   // !! in progress | ||||
|   val functionService: VimscriptFunctionService | ||||
|   // Can't be fully moved to vim-engine. | ||||
|   | ||||
| @@ -8,10 +8,10 @@ import com.maddyhome.idea.vim.api.stubs.VimProcessGroupStub | ||||
| import com.maddyhome.idea.vim.common.VimMachine | ||||
| import com.maddyhome.idea.vim.common.VimMachineBase | ||||
| import com.maddyhome.idea.vim.diagnostic.vimLogger | ||||
| import com.maddyhome.idea.vim.options.OptionService | ||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService | ||||
| import com.maddyhome.idea.vim.register.VimRegisterGroup | ||||
| import com.maddyhome.idea.vim.register.VimRegisterGroupBase | ||||
| import com.maddyhome.idea.vim.vimscript.services.VimVariableService | ||||
| import com.maddyhome.idea.vim.vimscript.services.VariableService | ||||
| import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceBase | ||||
|  | ||||
| abstract class VimInjectorBase : VimInjector { | ||||
| @@ -23,7 +23,7 @@ abstract class VimInjectorBase : VimInjector { | ||||
|   override val parser: VimStringParser = object : VimStringParserBase() {} | ||||
|   override val vimMachine: VimMachine = object : VimMachineBase() {} | ||||
|   override val optionService: OptionService by lazy { object : VimOptionServiceBase(){} } | ||||
|   override val variableService: VimVariableService by lazy { object : VimVariableServiceBase(){} } | ||||
|   override val variableService: VariableService by lazy { object : VimVariableServiceBase(){} } | ||||
|  | ||||
|   override val registerGroup: VimRegisterGroup by lazy { registerGroupStub } | ||||
|   override val registerGroupIfCreated: VimRegisterGroup? by lazy { registerGroupStub } | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|  */ | ||||
| package com.maddyhome.idea.vim.api | ||||
|  | ||||
| import com.maddyhome.idea.vim.common.CommandPartNode | ||||
| import com.maddyhome.idea.vim.key.CommandPartNode | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.key.KeyMapping | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| package com.maddyhome.idea.vim.api | ||||
|  | ||||
| import com.maddyhome.idea.vim.common.CommandPartNode | ||||
| import com.maddyhome.idea.vim.key.CommandPartNode | ||||
| import com.maddyhome.idea.vim.command.MappingMode | ||||
| import com.maddyhome.idea.vim.common.RootNode | ||||
| import com.maddyhome.idea.vim.key.RootNode | ||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||
| import com.maddyhome.idea.vim.handler.EditorActionHandlerBase | ||||
| import com.maddyhome.idea.vim.key.KeyMapping | ||||
|   | ||||
| @@ -3,12 +3,11 @@ package com.maddyhome.idea.vim.api | ||||
| import com.maddyhome.idea.vim.diagnostic.vimLogger | ||||
| import com.maddyhome.idea.vim.ex.ExException | ||||
| import com.maddyhome.idea.vim.option.ToggleOption | ||||
| import com.maddyhome.idea.vim.options.NumberOption | ||||
| import com.maddyhome.idea.vim.option.NumberOption | ||||
| import com.maddyhome.idea.vim.options.Option | ||||
| import com.maddyhome.idea.vim.options.OptionChangeListener | ||||
| import com.maddyhome.idea.vim.options.OptionConstants | ||||
| import com.maddyhome.idea.vim.options.OptionScope | ||||
| import com.maddyhome.idea.vim.options.OptionService | ||||
| import com.maddyhome.idea.vim.options.StringOption | ||||
| import com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper | ||||
| import com.maddyhome.idea.vim.options.helpers.KeywordOptionHelper | ||||
| @@ -16,6 +15,7 @@ import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber | ||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService | ||||
|  | ||||
| abstract class VimOptionServiceBase : OptionService { | ||||
|   private val localOptionsKey = Key<MutableMap<String, VimDataType>>("localOptions") | ||||
| @@ -253,6 +253,14 @@ abstract class VimOptionServiceBase : OptionService { | ||||
|     setOptionValue(scope, optionName, VimInt.ONE, token) | ||||
|   } | ||||
|  | ||||
|   override fun setOption(scope: OptionService.Scope, optionName: String, token: String) { | ||||
|     val newScope = when (scope) { | ||||
|       is OptionService.Scope.GLOBAL -> OptionScope.GLOBAL | ||||
|       is OptionService.Scope.LOCAL -> OptionScope.LOCAL(scope.editor) | ||||
|     } | ||||
|     this.setOption(newScope, optionName, token) | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Unsets the option (false) | ||||
|    */ | ||||
|   | ||||
| @@ -19,10 +19,10 @@ | ||||
| package com.maddyhome.idea.vim.command | ||||
|  | ||||
| import com.maddyhome.idea.vim.api.VimActionsInitiator | ||||
| import com.maddyhome.idea.vim.common.CommandPartNode | ||||
| import com.maddyhome.idea.vim.key.CommandPartNode | ||||
| import com.maddyhome.idea.vim.common.CurrentCommandState | ||||
| import com.maddyhome.idea.vim.common.Node | ||||
| import com.maddyhome.idea.vim.common.RootNode | ||||
| import com.maddyhome.idea.vim.key.Node | ||||
| import com.maddyhome.idea.vim.key.RootNode | ||||
| import com.maddyhome.idea.vim.diagnostic.debug | ||||
| import com.maddyhome.idea.vim.diagnostic.vimLogger | ||||
| import com.maddyhome.idea.vim.handler.EditorActionHandlerBase | ||||
|   | ||||
| @@ -25,54 +25,58 @@ import java.util.* | ||||
|  * COMPATIBILITY-LAYER: Do not move this class to a different package | ||||
|  */ | ||||
| enum class MappingMode { | ||||
|     /** | ||||
|      * Indicates this key mapping applies to Normal mode | ||||
|      */ | ||||
|     NORMAL, | ||||
|   /** | ||||
|    * Indicates this key mapping applies to Normal mode | ||||
|    */ | ||||
|   NORMAL, | ||||
|  | ||||
|     /** | ||||
|      * Indicates this key mapping applies to Visual mode | ||||
|      */ | ||||
|     VISUAL, | ||||
|   /** | ||||
|    * Indicates this key mapping applies to Visual mode | ||||
|    */ | ||||
|   VISUAL, | ||||
|  | ||||
|     /** | ||||
|      * Indicates this key mapping applies to Select mode | ||||
|      */ | ||||
|     SELECT, | ||||
|   /** | ||||
|    * Indicates this key mapping applies to Select mode | ||||
|    */ | ||||
|   SELECT, | ||||
|  | ||||
|     /** | ||||
|      * Indicates this key mapping applies to Operator Pending mode | ||||
|      */ | ||||
|     OP_PENDING, | ||||
|   /** | ||||
|    * Indicates this key mapping applies to Operator Pending mode | ||||
|    */ | ||||
|   OP_PENDING, | ||||
|  | ||||
|     /** | ||||
|      * Indicates this key mapping applies to Insert mode | ||||
|      */ | ||||
|     INSERT, | ||||
|   /** | ||||
|    * Indicates this key mapping applies to Insert mode | ||||
|    */ | ||||
|   INSERT, | ||||
|  | ||||
|     /** | ||||
|      * Indicates this key mapping applies to Command Line mode | ||||
|      */ | ||||
|     CMD_LINE; | ||||
|   /** | ||||
|    * Indicates this key mapping applies to Command Line mode | ||||
|    */ | ||||
|   CMD_LINE; | ||||
|  | ||||
|     companion object { | ||||
|         @JvmField | ||||
|         val N: EnumSet<MappingMode> = EnumSet.of(NORMAL) | ||||
|         val X: EnumSet<MappingMode> = EnumSet.of(VISUAL) | ||||
|         val O: EnumSet<MappingMode> = EnumSet.of(OP_PENDING) | ||||
|         val I: EnumSet<MappingMode> = EnumSet.of(INSERT) | ||||
|         val C: EnumSet<MappingMode> = EnumSet.of(CMD_LINE) | ||||
|         val S: EnumSet<MappingMode> = EnumSet.of(SELECT) | ||||
|         val V: EnumSet<MappingMode> = EnumSet.of(VISUAL, SELECT) | ||||
|         val NO: EnumSet<MappingMode> = EnumSet.of(NORMAL, OP_PENDING) | ||||
|         @JvmField | ||||
|         val XO: EnumSet<MappingMode> = EnumSet.of(VISUAL, OP_PENDING) | ||||
|         val NX: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL) | ||||
|         val IC: EnumSet<MappingMode> = EnumSet.of(INSERT, CMD_LINE) | ||||
|         val NV: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, SELECT) | ||||
|         val NXO: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, OP_PENDING) | ||||
|         @JvmField | ||||
|         val NVO: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, OP_PENDING, SELECT) | ||||
|         val ALL: EnumSet<MappingMode> = EnumSet.allOf(MappingMode::class.java) | ||||
|     } | ||||
| } | ||||
|   companion object { | ||||
|     @JvmField | ||||
|     val N: EnumSet<MappingMode> = EnumSet.of(NORMAL) | ||||
|     val X: EnumSet<MappingMode> = EnumSet.of(VISUAL) | ||||
|     val O: EnumSet<MappingMode> = EnumSet.of(OP_PENDING) | ||||
|     val I: EnumSet<MappingMode> = EnumSet.of(INSERT) | ||||
|     val C: EnumSet<MappingMode> = EnumSet.of(CMD_LINE) | ||||
|     val S: EnumSet<MappingMode> = EnumSet.of(SELECT) | ||||
|     val V: EnumSet<MappingMode> = EnumSet.of(VISUAL, SELECT) | ||||
|     val NO: EnumSet<MappingMode> = EnumSet.of(NORMAL, OP_PENDING) | ||||
|  | ||||
|     @JvmField | ||||
|     val XO: EnumSet<MappingMode> = EnumSet.of(VISUAL, OP_PENDING) | ||||
|     val NX: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL) | ||||
|     val IC: EnumSet<MappingMode> = EnumSet.of(INSERT, CMD_LINE) | ||||
|     val NV: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, SELECT) | ||||
|  | ||||
|     @JvmField | ||||
|     val NXO: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, OP_PENDING) | ||||
|  | ||||
|     @JvmField | ||||
|     val NVO: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, OP_PENDING, SELECT) | ||||
|     val ALL: EnumSet<MappingMode> = EnumSet.allOf(MappingMode::class.java) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -20,7 +20,7 @@ package com.maddyhome.idea.vim.command | ||||
| import com.maddyhome.idea.vim.api.VimActionsInitiator | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.common.CommandPartNode | ||||
| import com.maddyhome.idea.vim.key.CommandPartNode | ||||
| import com.maddyhome.idea.vim.common.DigraphResult | ||||
| import com.maddyhome.idea.vim.common.DigraphSequence | ||||
| import com.maddyhome.idea.vim.diagnostic.debug | ||||
|   | ||||
| @@ -95,7 +95,7 @@ abstract class VimMachineBase : VimMachine { | ||||
|     val operatedText = editor.deleteDryRun(range) ?: return null | ||||
|  | ||||
|     val normalizedRange = operatedText.toNormalizedTextRange(editor) | ||||
|     injector.registerGroup.storeText(editor, normalizedRange, operatedText.toType(), true) | ||||
|     caret.registerStorage.storeText(editor, normalizedRange, operatedText.toType(), true) | ||||
|     (editor as MutableVimEditor).delete(range) | ||||
|  | ||||
|     val start = normalizedRange.startOffset | ||||
|   | ||||
| @@ -16,10 +16,14 @@ | ||||
|  * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| 
 | ||||
| package com.maddyhome.idea.vim.common | ||||
| package com.maddyhome.idea.vim.key | ||||
| 
 | ||||
| import javax.swing.KeyStroke | ||||
| 
 | ||||
| /** | ||||
|  * COMPATIBILITY-LAYER: Moved from common package to this one | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * All the commands are stored into the tree where the key is either a complete command (for `x`, `j`, `l`, etc.), | ||||
|  * or a part of a command (e.g. `g` for `gg`). | ||||
| @@ -0,0 +1,42 @@ | ||||
| package com.maddyhome.idea.vim.option | ||||
|  | ||||
| import com.maddyhome.idea.vim.api.injector | ||||
| import com.maddyhome.idea.vim.ex.ExException | ||||
| import com.maddyhome.idea.vim.options.Option | ||||
| import com.maddyhome.idea.vim.options.OptionScope | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber | ||||
|  | ||||
| /** | ||||
|  * COMPATIBILITY-LAYER: Moved out of class and to a different package | ||||
|  */ | ||||
| open class NumberOption(name: String, abbrev: String, defaultValue: VimInt) : | ||||
|   Option<VimInt>(name, abbrev, defaultValue) { | ||||
|   constructor(name: String, abbrev: String, defaultValue: Int) : this(name, abbrev, VimInt(defaultValue)) | ||||
|  | ||||
|   override fun checkIfValueValid(value: VimDataType, token: String) { | ||||
|     if (value !is VimInt) { | ||||
|       throw ExException("E521: Number required after =: $token") | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   override fun getValueIfAppend(currentValue: VimDataType, value: String, token: String): VimInt { | ||||
|     val valueToAdd = parseNumber(token) ?: throw ExException("E521: Number required after =: $token") | ||||
|     return VimInt((currentValue as VimInt).value + valueToAdd) | ||||
|   } | ||||
|  | ||||
|   override fun getValueIfPrepend(currentValue: VimDataType, value: String, token: String): VimInt { | ||||
|     val valueToAdd = parseNumber(token) ?: throw ExException("E521: Number required after =: $token") | ||||
|     return VimInt((currentValue as VimInt).value * valueToAdd) | ||||
|   } | ||||
|  | ||||
|   override fun getValueIfRemove(currentValue: VimDataType, value: String, token: String): VimInt { | ||||
|     val valueToAdd = parseNumber(token) ?: throw ExException("E521: Number required after =: $token") | ||||
|     return VimInt((currentValue as VimInt).value - valueToAdd) | ||||
|   } | ||||
|  | ||||
|   fun value(): Int { | ||||
|     return injector.optionService.getOptionValue(OptionScope.GLOBAL, name).asDouble().toInt() | ||||
|   } | ||||
| } | ||||
| @@ -37,4 +37,15 @@ class ToggleOption(name: String, abbrev: String, defaultValue: VimInt) : Option< | ||||
|   fun isSet(): Boolean { | ||||
|     return injector.optionService.getOptionValue(OptionScope.GLOBAL, name).asBoolean() | ||||
|   } | ||||
| } | ||||
|  | ||||
|   /** | ||||
|    * COMPATIBILITY-LAYER: Method added | ||||
|    */ | ||||
|   @Suppress("DEPRECATION", "PLATFORM_CLASS_MAPPED_TO_KOTLIN") | ||||
|   override val value: java.lang.Boolean | ||||
|     get() = if (injector.optionService.getOptionValue(OptionScope.GLOBAL, name).asBoolean()) { | ||||
|       java.lang.Boolean(true) | ||||
|     } else { | ||||
|       java.lang.Boolean(false) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -20,9 +20,7 @@ package com.maddyhome.idea.vim.options | ||||
|  | ||||
| import com.maddyhome.idea.vim.ex.ExException | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber | ||||
| import java.util.* | ||||
|  | ||||
| /** | ||||
| @@ -59,6 +57,13 @@ import java.util.* | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * COMPATIBILITY-LAYER: Method added | ||||
|    */ | ||||
|   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") | ||||
|   open val value: java.lang.Boolean | ||||
|     get() = TODO() | ||||
|  | ||||
|   // todo 1.9 should return Result with exceptions | ||||
|   abstract fun checkIfValueValid(value: VimDataType, token: String) | ||||
|  | ||||
| @@ -67,31 +72,6 @@ import java.util.* | ||||
|   abstract fun getValueIfRemove(currentValue: VimDataType, value: String, token: String): T | ||||
| } | ||||
|  | ||||
| open class NumberOption(name: String, abbrev: String, defaultValue: VimInt) : Option<VimInt>(name, abbrev, defaultValue) { | ||||
|   constructor(name: String, abbrev: String, defaultValue: Int) : this(name, abbrev, VimInt(defaultValue)) | ||||
|  | ||||
|   override fun checkIfValueValid(value: VimDataType, token: String) { | ||||
|     if (value !is VimInt) { | ||||
|       throw ExException("E521: Number required after =: $token") | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   override fun getValueIfAppend(currentValue: VimDataType, value: String, token: String): VimInt { | ||||
|     val valueToAdd = parseNumber(token) ?: throw ExException("E521: Number required after =: $token") | ||||
|     return VimInt((currentValue as VimInt).value + valueToAdd) | ||||
|   } | ||||
|  | ||||
|   override fun getValueIfPrepend(currentValue: VimDataType, value: String, token: String): VimInt { | ||||
|     val valueToAdd = parseNumber(token) ?: throw ExException("E521: Number required after =: $token") | ||||
|     return VimInt((currentValue as VimInt).value * valueToAdd) | ||||
|   } | ||||
|  | ||||
|   override fun getValueIfRemove(currentValue: VimDataType, value: String, token: String): VimInt { | ||||
|     val valueToAdd = parseNumber(token) ?: throw ExException("E521: Number required after =: $token") | ||||
|     return VimInt((currentValue as VimInt).value - valueToAdd) | ||||
|   } | ||||
| } | ||||
|  | ||||
| open class StringOption(name: String, abbrev: String, defaultValue: VimString, private val isList: Boolean = false, private val boundedValues: Collection<String>? = null) : Option<VimString>(name, abbrev, defaultValue) { | ||||
|   constructor(name: String, abbrev: String, defaultValue: String, isList: Boolean = false, boundedValues: Collection<String>? = null) : this(name, abbrev, VimString(defaultValue), isList, boundedValues) | ||||
|  | ||||
|   | ||||
| @@ -23,5 +23,5 @@ interface VimPut { | ||||
|     updateVisualMarks: Boolean = false, | ||||
|   ): Boolean | ||||
|  | ||||
|   fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData): Boolean | ||||
|   fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData, updateVisualMarks: Boolean = false): Boolean | ||||
| } | ||||
| @@ -20,6 +20,7 @@ package com.maddyhome.idea.vim.register | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.command.SelectionType | ||||
| import com.maddyhome.idea.vim.common.TextRange | ||||
| import org.jetbrains.annotations.TestOnly | ||||
| import javax.swing.KeyStroke | ||||
|  | ||||
| interface VimRegisterGroup { | ||||
| @@ -30,6 +31,7 @@ interface VimRegisterGroup { | ||||
|    * @return The register, null if no such register | ||||
|    */ | ||||
|   val lastRegister: Register? | ||||
|   val lastRegisterChar: Char | ||||
|   val currentRegister: Char | ||||
|   val defaultRegister: Char | ||||
|  | ||||
| @@ -53,6 +55,13 @@ interface VimRegisterGroup { | ||||
|    */ | ||||
|   fun storeText(register: Char, text: String): Boolean | ||||
|  | ||||
|   /** | ||||
|    * Stores text to any writable register (used for multicaret tests) | ||||
|    */ | ||||
|   @TestOnly | ||||
|   // todo better tests | ||||
|   fun storeText(register: Char, text: String, selectionType: SelectionType): Boolean | ||||
|  | ||||
|   /** | ||||
|    * Stores text, character wise, in the given special register | ||||
|    * | ||||
|   | ||||
| @@ -36,8 +36,7 @@ abstract class VimRegisterGroupBase : VimRegisterGroup { | ||||
|   @JvmField | ||||
|   protected var defaultRegisterChar = UNNAMED_REGISTER | ||||
|  | ||||
|   @JvmField | ||||
|   protected var lastRegisterChar = defaultRegisterChar | ||||
|   override var lastRegisterChar = defaultRegisterChar | ||||
|  | ||||
|   /** | ||||
|    * Gets the last register name selected by the user | ||||
| @@ -293,7 +292,7 @@ abstract class VimRegisterGroupBase : VimRegisterGroup { | ||||
|     return true | ||||
|   } | ||||
|  | ||||
|   override fun storeText(register: Char, text: String): Boolean { | ||||
|   override fun storeText(register: Char, text: String, selectionType: SelectionType): Boolean { | ||||
|     if (!WRITABLE_REGISTERS.contains(register)) { | ||||
|       return false | ||||
|     } | ||||
| @@ -303,7 +302,7 @@ abstract class VimRegisterGroupBase : VimRegisterGroup { | ||||
|     } else { | ||||
|       text | ||||
|     } | ||||
|     val reg = Register(register, SelectionType.CHARACTER_WISE, textToStore, ArrayList()) | ||||
|     val reg = Register(register, selectionType, textToStore, ArrayList()) | ||||
|     saveRegister(register, reg) | ||||
|     if (register == '/') { | ||||
|       injector.searchGroup.lastSearchPattern = text // todo we should not have this field if we have the "/" register | ||||
| @@ -311,6 +310,10 @@ abstract class VimRegisterGroupBase : VimRegisterGroup { | ||||
|     return true | ||||
|   } | ||||
|  | ||||
|   override fun storeText(register: Char, text: String): Boolean { | ||||
|     return storeText(register, text, SelectionType.CHARACTER_WISE) | ||||
|   } | ||||
|  | ||||
|   private fun guessSelectionType(text: String): SelectionType { | ||||
|     return if (text.endsWith("\n")) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE | ||||
|   } | ||||
|   | ||||
| @@ -16,11 +16,17 @@ | ||||
|  * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| 
 | ||||
| package com.maddyhome.idea.vim.options | ||||
| package com.maddyhome.idea.vim.vimscript.services | ||||
| 
 | ||||
| import com.maddyhome.idea.vim.api.VimEditor | ||||
| import com.maddyhome.idea.vim.ex.ExException | ||||
| import com.maddyhome.idea.vim.options.Option | ||||
| import com.maddyhome.idea.vim.options.OptionChangeListener | ||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | ||||
| 
 | ||||
| /** | ||||
|  * COMPATIBILITY-LAYER: Moved to a different package | ||||
|  */ | ||||
| interface OptionService { | ||||
| 
 | ||||
|   /** | ||||
| @@ -30,7 +36,7 @@ interface OptionService { | ||||
|    * @param token used in exception messages | ||||
|    * @throws ExException("E518: Unknown option: $token") | ||||
|    */ | ||||
|   fun getOptionValue(scope: OptionScope, optionName: String, token: String = optionName): VimDataType | ||||
|   fun getOptionValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName): VimDataType | ||||
| 
 | ||||
|   /** | ||||
|    * Sets option value. | ||||
| @@ -40,7 +46,7 @@ interface OptionService { | ||||
|    * @param token used in exception messages | ||||
|    * @throws ExException("E518: Unknown option: $token") | ||||
|    */ | ||||
|   fun setOptionValue(scope: OptionScope, optionName: String, value: VimDataType, token: String = optionName) | ||||
|   fun setOptionValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: VimDataType, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * Checks if the [value] is contained in string option. | ||||
| @@ -50,7 +56,7 @@ interface OptionService { | ||||
|    * @param optionName option name or alias | ||||
|    * @param value option value | ||||
|    */ | ||||
|   fun contains(scope: OptionScope, optionName: String, value: String): Boolean | ||||
|   fun contains(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String): Boolean | ||||
| 
 | ||||
|   /** | ||||
|    * Splits a string option into flags | ||||
| @@ -61,7 +67,7 @@ interface OptionService { | ||||
|    * @param scope global/local option scope | ||||
|    * @param optionName option name or alias | ||||
|    */ | ||||
|   fun getValues(scope: OptionScope, optionName: String): List<String>? | ||||
|   fun getValues(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String): List<String>? | ||||
| 
 | ||||
|   /** | ||||
|    * Same as [setOptionValue], but automatically casts [value] to the required [VimDataType] | ||||
| @@ -72,7 +78,7 @@ interface OptionService { | ||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||
|    * @throws ExException("E474: Invalid argument: $token") in case the cast to VimDataType is impossible | ||||
|    */ | ||||
|   fun setOptionValue(scope: OptionScope, optionName: String, value: String, token: String = optionName) | ||||
|   fun setOptionValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * Same as `set {option}+={value}` in Vim documentation. | ||||
| @@ -85,7 +91,7 @@ interface OptionService { | ||||
|    * @throws ExException("E474: Invalid argument: $token") in case the method was called for the [StringOption] and the argument is invalid (does not satisfy the option bounded values) | ||||
|    * @throws ExException("E521: Number required after =: $token") in case the cast to VimInt is impossible | ||||
|    */ | ||||
|   fun appendValue(scope: OptionScope, optionName: String, value: String, token: String = optionName) | ||||
|   fun appendValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * Same as `set {option}^={value}` in Vim documentation. | ||||
| @@ -98,7 +104,7 @@ interface OptionService { | ||||
|    * @throws ExException("E474: Invalid argument: $token") in case the method was called for the [StringOption] and the argument is invalid (does not satisfy the option bounded values) | ||||
|    * @throws ExException("E521: Number required after =: $token") in case the cast to VimInt is impossible | ||||
|    */ | ||||
|   fun prependValue(scope: OptionScope, optionName: String, value: String, token: String = optionName) | ||||
|   fun prependValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * Same as `set {option}-={value}` in Vim documentation. | ||||
| @@ -111,7 +117,7 @@ interface OptionService { | ||||
|    * @throws ExException("E474: Invalid argument: $token") in case the method was called for the [StringOption] and the argument is invalid (does not satisfy the option bounded values) | ||||
|    * @throws ExException("E521: Number required after =: $token") in case the cast to VimInt is impossible | ||||
|    */ | ||||
|   fun removeValue(scope: OptionScope, optionName: String, value: String, token: String = optionName) | ||||
|   fun removeValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * Checks if the toggle option on. | ||||
| @@ -122,7 +128,7 @@ interface OptionService { | ||||
|    * @param token used in exception messages | ||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||
|    */ | ||||
|   fun isSet(scope: OptionScope, optionName: String, token: String = optionName): Boolean | ||||
|   fun isSet(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName): Boolean | ||||
| 
 | ||||
|   /** | ||||
|    * Checks if the option's value set to default. | ||||
| @@ -132,7 +138,7 @@ interface OptionService { | ||||
|    * @param token used in exception messages | ||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||
|    */ | ||||
|   fun isDefault(scope: OptionScope, optionName: String, token: String = optionName): Boolean | ||||
|   fun isDefault(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName): Boolean | ||||
| 
 | ||||
|   /** | ||||
|    * Resets option's value to default. | ||||
| @@ -142,7 +148,7 @@ interface OptionService { | ||||
|    * @param token used in exception messages | ||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||
|    */ | ||||
|   fun resetDefault(scope: OptionScope, optionName: String, token: String = optionName) | ||||
|   fun resetDefault(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * Resets all options back to default values. | ||||
| @@ -163,7 +169,12 @@ interface OptionService { | ||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||
|    * @throws ExException("E474: Invalid argument: $token") in case the option is not a [ToggleOption] | ||||
|    */ | ||||
|   fun setOption(scope: OptionScope, optionName: String, token: String = optionName) | ||||
|   fun setOption(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * COMPATIBILITY-LAYER: New method added | ||||
|    */ | ||||
|   fun setOption(scope: Scope, optionName: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * Unsets the option (false). | ||||
| @@ -173,7 +184,7 @@ interface OptionService { | ||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||
|    * @throws ExException("E474: Invalid argument: $token") in case the option is not a [ToggleOption] | ||||
|    */ | ||||
|   fun unsetOption(scope: OptionScope, optionName: String, token: String = optionName) | ||||
|   fun unsetOption(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * Inverts boolean option value true -> false / false -> true. | ||||
| @@ -183,7 +194,7 @@ interface OptionService { | ||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||
|    * @throws ExException("E474: Invalid argument: $token") in case the option is not a [ToggleOption] | ||||
|    */ | ||||
|   fun toggleOption(scope: OptionScope, optionName: String, token: String = optionName) | ||||
|   fun toggleOption(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName) | ||||
| 
 | ||||
|   /** | ||||
|    * @return list of all option names | ||||
| @@ -221,4 +232,12 @@ interface OptionService { | ||||
|    * @param listener option listener | ||||
|    */ | ||||
|   fun removeListener(optionName: String, listener: OptionChangeListener<VimDataType>) | ||||
| 
 | ||||
|   /** | ||||
|    * COMPATIBILITY-LAYER: Added this class | ||||
|    */ | ||||
|   sealed class Scope { | ||||
|     object GLOBAL : Scope() | ||||
|     class LOCAL(val editor: VimEditor) : Scope() | ||||
|   } | ||||
| } | ||||
| @@ -26,7 +26,11 @@ import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | ||||
| import com.maddyhome.idea.vim.vimscript.model.expressions.Variable | ||||
| import org.jetbrains.annotations.TestOnly | ||||
| 
 | ||||
| interface VimVariableService { | ||||
| 
 | ||||
| /** | ||||
|  * COMPATIBILITY-LAYER: Renamed from VimVariableService | ||||
|  */ | ||||
| interface VariableService { | ||||
|   /** | ||||
|    * Stores variable. | ||||
|    * | ||||
| @@ -13,7 +13,7 @@ import com.maddyhome.idea.vim.vimscript.model.expressions.Variable | ||||
| import com.maddyhome.idea.vim.vimscript.model.statements.FunctionDeclaration | ||||
| import com.maddyhome.idea.vim.vimscript.model.statements.FunctionFlag | ||||
|  | ||||
| abstract class VimVariableServiceBase : VimVariableService { | ||||
| abstract class VimVariableServiceBase : VariableService { | ||||
|   private var globalVariables: MutableMap<String, VimDataType> = mutableMapOf() | ||||
|   private val windowVariablesKey = Key<MutableMap<String, VimDataType>>("TabVariables") | ||||
|   private val bufferVariablesKey = Key<MutableMap<String, VimDataType>>("BufferVariables") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user