mirror of
				https://github.com/chylex/IntelliJ-IdeaVim.git
				synced 2025-10-31 11:17:13 +01:00 
			
		
		
		
	Compare commits
	
		
			10 Commits
		
	
	
		
			1791692d92
			...
			customized
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| edb9b194bb | |||
|   | eae7ed95e2 | ||
| a1e2ae0eb9 | |||
| eae2e3b6b8 | |||
| c2d997a520 | |||
| e2a8a3c21a | |||
| 9b7fee6163 | |||
| d0f9d3dc70 | |||
| 8d3a69b338 | |||
| 3c530474a1 | 
							
								
								
									
										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.BuildType | ||||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.golang | 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.buildSteps.script | ||||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.schedule | import jetbrains.buildServer.configs.kotlin.v2019_2.triggers.vcs | ||||||
| import jetbrains.buildServer.configs.kotlin.v2019_2.ui.* | import jetbrains.buildServer.configs.kotlin.v2019_2.ui.* | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -17,33 +17,17 @@ create(DslContext.projectId, BuildType({ | |||||||
|     name = "IdeaVim compatibility with external plugins" |     name = "IdeaVim compatibility with external plugins" | ||||||
|  |  | ||||||
|     vcs { |     vcs { | ||||||
|         root(DslContext.settingsRoot) |         root(RelativeId("HttpsGithubComAlexPl292IdeaVimCompatibilityRefsHeadsMaster")) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     steps { |     steps { | ||||||
|         script { |         script { | ||||||
|             name = "Check" |             scriptContent = "go run test.go" | ||||||
|             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 { |     triggers { | ||||||
|         schedule { |         vcs { | ||||||
|             schedulingPolicy = daily { |  | ||||||
|                 hour = 4 |  | ||||||
|             } |  | ||||||
|             branchFilter = "" |  | ||||||
|             triggerBuild = always() |  | ||||||
|             withPendingChangesOnly = false |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| # suppress inspection "UnusedProperty" for whole file | # suppress inspection "UnusedProperty" for whole file | ||||||
|  |  | ||||||
| ideaVersion=LATEST-EAP-SNAPSHOT | ideaVersion=2022.1.2 | ||||||
| downloadIdeaSources=true | downloadIdeaSources=true | ||||||
| instrumentPluginCode=true | instrumentPluginCode=true | ||||||
| version=SNAPSHOT | version=chylex-12 | ||||||
| javaVersion=11 | javaVersion=11 | ||||||
| remoteRobotVersion=0.11.10 | remoteRobotVersion=0.11.10 | ||||||
| antlrVersion=4.10.1 | antlrVersion=4.10.1 | ||||||
|   | |||||||
| @@ -48,13 +48,13 @@ import com.maddyhome.idea.vim.group.visual.VisualMotionGroup; | |||||||
| import com.maddyhome.idea.vim.helper.MacKeyRepeat; | import com.maddyhome.idea.vim.helper.MacKeyRepeat; | ||||||
| import com.maddyhome.idea.vim.listener.VimListenerManager; | import com.maddyhome.idea.vim.listener.VimListenerManager; | ||||||
| import com.maddyhome.idea.vim.newapi.IjVimInjector; | 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.StatusBarIconFactory; | ||||||
| import com.maddyhome.idea.vim.ui.VimEmulationConfigurable; | import com.maddyhome.idea.vim.ui.VimEmulationConfigurable; | ||||||
| import com.maddyhome.idea.vim.ui.ex.ExEntryPanel; | import com.maddyhome.idea.vim.ui.ex.ExEntryPanel; | ||||||
| import com.maddyhome.idea.vim.vimscript.services.FunctionStorage; | import com.maddyhome.idea.vim.vimscript.services.FunctionStorage; | ||||||
| import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService; | import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService; | ||||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService; | import com.maddyhome.idea.vim.vimscript.services.VimVariableService; | ||||||
| import com.maddyhome.idea.vim.vimscript.services.VariableService; |  | ||||||
| import org.jdom.Element; | import org.jdom.Element; | ||||||
| import org.jetbrains.annotations.Nls; | import org.jetbrains.annotations.Nls; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| @@ -226,8 +226,8 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable | |||||||
|     return (PutGroup)VimInjectorKt.getInjector().getPut(); |     return (PutGroup)VimInjectorKt.getInjector().getPut(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public static @NotNull VariableService getVariableService() { |   public static @NotNull VimVariableService getVariableService() { | ||||||
|     return ApplicationManager.getApplication().getService(VariableService.class); |     return ApplicationManager.getApplication().getService(VimVariableService.class); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public static @NotNull OptionService getOptionService() { |   public static @NotNull OptionService getOptionService() { | ||||||
|   | |||||||
| @@ -148,6 +148,10 @@ class VimShortcutKeyAction : AnAction(), DumbAware/*, LightEditCompatible*/ { | |||||||
|       if (keyCode == KeyEvent.VK_TAB && editor.isTemplateActive()) return false |       if (keyCode == KeyEvent.VK_TAB && editor.isTemplateActive()) return false | ||||||
|  |  | ||||||
|       if ((keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_ENTER) && editor.appCodeTemplateCaptured()) return false |       if ((keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_ENTER) && editor.appCodeTemplateCaptured()) return false | ||||||
|  |        | ||||||
|  |       if (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT) return false | ||||||
|  |       if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN) return false | ||||||
|  |       if (keyCode == KeyEvent.VK_HOME || keyCode == KeyEvent.VK_END) return false | ||||||
|  |  | ||||||
|       if (editor.inInsertMode) { |       if (editor.inInsertMode) { | ||||||
|         if (keyCode == KeyEvent.VK_TAB) { |         if (keyCode == KeyEvent.VK_TAB) { | ||||||
|   | |||||||
| @@ -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.VimActionHandler | ||||||
| import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler | import com.maddyhome.idea.vim.handler.VisualOperatorActionHandler | ||||||
| import com.maddyhome.idea.vim.helper.MessageHelper | import com.maddyhome.idea.vim.helper.MessageHelper | ||||||
| import com.maddyhome.idea.vim.helper.enumSetOf |  | ||||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | import com.maddyhome.idea.vim.helper.vimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.helper.enumSetOf | ||||||
| import com.maddyhome.idea.vim.newapi.ij | import com.maddyhome.idea.vim.newapi.ij | ||||||
| import java.util.* | import java.util.* | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,15 +30,6 @@ class CommandState(private val machine: VimStateMachine) { | |||||||
|   val isOperatorPending: Boolean |   val isOperatorPending: Boolean | ||||||
|     get() = machine.isOperatorPending |     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 { |   enum class Mode { | ||||||
|     // Basic modes |     // Basic modes | ||||||
|     COMMAND, VISUAL, SELECT, INSERT, CMD_LINE, /*EX*/ |     COMMAND, VISUAL, SELECT, INSERT, CMD_LINE, /*EX*/ | ||||||
| @@ -59,6 +50,7 @@ class CommandState(private val machine: VimStateMachine) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| val CommandState.SubMode.engine: VimStateMachine.SubMode | val CommandState.SubMode.engine: VimStateMachine.SubMode | ||||||
|   get() = when (this) { |   get() = when (this) { | ||||||
|     CommandState.SubMode.NONE -> VimStateMachine.SubMode.NONE |     CommandState.SubMode.NONE -> VimStateMachine.SubMode.NONE | ||||||
| @@ -81,6 +73,7 @@ val CommandState.Mode.engine: VimStateMachine.Mode | |||||||
|     CommandState.Mode.INSERT_SELECT -> VimStateMachine.Mode.INSERT_SELECT |     CommandState.Mode.INSERT_SELECT -> VimStateMachine.Mode.INSERT_SELECT | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
| val VimStateMachine.Mode.ij: CommandState.Mode | val VimStateMachine.Mode.ij: CommandState.Mode | ||||||
|   get() = when (this) { |   get() = when (this) { | ||||||
|     VimStateMachine.Mode.COMMAND -> CommandState.Mode.COMMAND |     VimStateMachine.Mode.COMMAND -> CommandState.Mode.COMMAND | ||||||
|   | |||||||
| @@ -23,7 +23,6 @@ import com.intellij.openapi.editor.Editor | |||||||
| import com.maddyhome.idea.vim.KeyHandler | import com.maddyhome.idea.vim.KeyHandler | ||||||
| import com.maddyhome.idea.vim.VimPlugin | import com.maddyhome.idea.vim.VimPlugin | ||||||
| import com.maddyhome.idea.vim.action.change.Extension | 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.MappingMode | ||||||
| import com.maddyhome.idea.vim.command.SelectionType | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.common.CommandAlias | import com.maddyhome.idea.vim.common.CommandAlias | ||||||
| @@ -60,8 +59,8 @@ object VimExtensionFacade { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * COMPATIBILITY-LAYER: Additional method |   * COMPATIBILITY-LAYER: Additional method | ||||||
|    */ |   */ | ||||||
|   /** The 'map' command for mapping keys to handlers defined in extensions. */ |   /** The 'map' command for mapping keys to handlers defined in extensions. */ | ||||||
|   @JvmStatic |   @JvmStatic | ||||||
|   fun putExtensionHandlerMapping( |   fun putExtensionHandlerMapping( | ||||||
| @@ -183,24 +182,12 @@ object VimExtensionFacade { | |||||||
|     return reg.keys |     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 */ |   /** Set the current contents of the given register */ | ||||||
|   @JvmStatic |   @JvmStatic | ||||||
|   fun setRegister(register: Char, keys: List<KeyStroke?>?) { |   fun setRegister(register: Char, keys: List<KeyStroke?>?) { | ||||||
|     VimPlugin.getRegister().setKeys(register, keys?.filterNotNull() ?: emptyList()) |     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 */ |   /** Set the current contents of the given register */ | ||||||
|   @JvmStatic |   @JvmStatic | ||||||
|   fun setRegister(register: Char, keys: List<KeyStroke?>?, type: SelectionType) { |   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.api.injector | ||||||
| import com.maddyhome.idea.vim.ex.ExException | import com.maddyhome.idea.vim.ex.ExException | ||||||
| import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove | 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.OptionChangeListener | ||||||
| import com.maddyhome.idea.vim.options.OptionScope | 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.statistic.PluginState | ||||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | ||||||
|  |  | ||||||
|   | |||||||
| @@ -34,14 +34,13 @@ import com.maddyhome.idea.vim.api.injector | |||||||
| import com.maddyhome.idea.vim.command.Argument | import com.maddyhome.idea.vim.command.Argument | ||||||
| import com.maddyhome.idea.vim.command.Command | import com.maddyhome.idea.vim.command.Command | ||||||
| import com.maddyhome.idea.vim.command.CommandFlags | import com.maddyhome.idea.vim.command.CommandFlags | ||||||
| import com.maddyhome.idea.vim.command.MappingMode | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
| import com.maddyhome.idea.vim.command.SelectionType | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.command.TextObjectVisualType | 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.common.CommandAliasHandler | ||||||
|  | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.common.TextRange | import com.maddyhome.idea.vim.common.TextRange | ||||||
| import com.maddyhome.idea.vim.ex.ranges.Ranges | 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.VimExtension | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.addCommand | import com.maddyhome.idea.vim.extension.VimExtensionFacade.addCommand | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | ||||||
| @@ -49,6 +48,7 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMa | |||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping | import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | ||||||
|  | import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||||
| import com.maddyhome.idea.vim.handler.TextObjectActionHandler | import com.maddyhome.idea.vim.handler.TextObjectActionHandler | ||||||
| import com.maddyhome.idea.vim.helper.EditorHelper | import com.maddyhome.idea.vim.helper.EditorHelper | ||||||
| import com.maddyhome.idea.vim.helper.PsiHelper | import com.maddyhome.idea.vim.helper.PsiHelper | ||||||
|   | |||||||
| @@ -31,11 +31,10 @@ import com.maddyhome.idea.vim.VimPlugin | |||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| 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.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.SelectionType | ||||||
|  | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.common.TextRange | 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.VimExtension | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister | import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister | ||||||
| @@ -43,6 +42,7 @@ import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMa | |||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegister | 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.EditorHelper | ||||||
| import com.maddyhome.idea.vim.helper.fileSize | import com.maddyhome.idea.vim.helper.fileSize | ||||||
| import com.maddyhome.idea.vim.helper.moveToInlayAwareLogicalPosition | 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.Argument | ||||||
| import com.maddyhome.idea.vim.command.Command | import com.maddyhome.idea.vim.command.Command | ||||||
| import com.maddyhome.idea.vim.command.CommandFlags | 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.MotionType | ||||||
| import com.maddyhome.idea.vim.command.OperatorArguments | import com.maddyhome.idea.vim.command.OperatorArguments | ||||||
| import com.maddyhome.idea.vim.common.Direction | import com.maddyhome.idea.vim.common.Direction | ||||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.extension.VimExtension | import com.maddyhome.idea.vim.extension.VimExtension | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade | import com.maddyhome.idea.vim.extension.VimExtensionFacade | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | 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.Motion | ||||||
| import com.maddyhome.idea.vim.handler.MotionActionHandler | import com.maddyhome.idea.vim.handler.MotionActionHandler | ||||||
| import com.maddyhome.idea.vim.handler.toMotionOrError | import com.maddyhome.idea.vim.handler.toMotionOrError | ||||||
| import com.maddyhome.idea.vim.helper.EditorHelper | import com.maddyhome.idea.vim.helper.EditorHelper | ||||||
| import com.maddyhome.idea.vim.helper.PsiHelper | import com.maddyhome.idea.vim.helper.PsiHelper | ||||||
| import com.maddyhome.idea.vim.helper.enumSetOf |  | ||||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | import com.maddyhome.idea.vim.helper.vimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.helper.enumSetOf | ||||||
| import com.maddyhome.idea.vim.newapi.ij | import com.maddyhome.idea.vim.newapi.ij | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
| import java.util.* | import java.util.* | ||||||
| @@ -233,7 +233,7 @@ private object FileTypePatterns { | |||||||
|     } else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") { |     } else if (fileTypeName == "CMakeLists.txt" || fileName == "CMakeLists") { | ||||||
|       this.cMakePatterns |       this.cMakePatterns | ||||||
|     } else { |     } else { | ||||||
|       return null |       this.htmlPatterns | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,8 +29,8 @@ import com.maddyhome.idea.vim.VimPlugin | |||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.MappingMode |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.common.TextRange | import com.maddyhome.idea.vim.common.TextRange | ||||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||||
| import com.maddyhome.idea.vim.extension.VimExtension | 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.api.injector | ||||||
| import com.maddyhome.idea.vim.common.CommandAlias | import com.maddyhome.idea.vim.common.CommandAlias | ||||||
| import com.maddyhome.idea.vim.common.CommandAliasHandler | import com.maddyhome.idea.vim.common.CommandAliasHandler | ||||||
| import com.maddyhome.idea.vim.key.CommandNode | import com.maddyhome.idea.vim.common.CommandNode | ||||||
| import com.maddyhome.idea.vim.key.CommandPartNode | import com.maddyhome.idea.vim.common.CommandPartNode | ||||||
| import com.maddyhome.idea.vim.key.Node | import com.maddyhome.idea.vim.common.Node | ||||||
| import com.maddyhome.idea.vim.key.RootNode | import com.maddyhome.idea.vim.common.RootNode | ||||||
| import com.maddyhome.idea.vim.key.addLeafs | import com.maddyhome.idea.vim.common.addLeafs | ||||||
| import com.maddyhome.idea.vim.ex.ranges.Ranges | import com.maddyhome.idea.vim.ex.ranges.Ranges | ||||||
| import com.maddyhome.idea.vim.extension.VimExtension | import com.maddyhome.idea.vim.extension.VimExtension | ||||||
| import com.maddyhome.idea.vim.group.KeyGroup | 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.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.MappingMode | 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.VimExtension | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade | import com.maddyhome.idea.vim.extension.VimExtensionFacade | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | 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.group.MotionGroup | ||||||
| import com.maddyhome.idea.vim.helper.EditorHelper | import com.maddyhome.idea.vim.helper.EditorHelper | ||||||
| import com.maddyhome.idea.vim.helper.SearchHelper | import com.maddyhome.idea.vim.helper.SearchHelper | ||||||
|   | |||||||
| @@ -65,14 +65,15 @@ class ReplaceWithRegister : VimExtension { | |||||||
|  |  | ||||||
|   private class RwrVisual : ExtensionHandler { |   private class RwrVisual : ExtensionHandler { | ||||||
|     override fun execute(editor: VimEditor, context: ExecutionContext) { |     override fun execute(editor: VimEditor, context: ExecutionContext) { | ||||||
|  |       val caretsAndSelections = mutableMapOf<VimCaret, VimSelection>() | ||||||
|       val typeInEditor = SelectionType.fromSubMode(editor.subMode) |       val typeInEditor = SelectionType.fromSubMode(editor.subMode) | ||||||
|       editor.forEachCaret { caret -> |       editor.forEachCaret { caret -> | ||||||
|         val selectionStart = caret.selectionStart |         val selectionStart = caret.selectionStart | ||||||
|         val selectionEnd = caret.selectionEnd |         val selectionEnd = caret.selectionEnd | ||||||
|  |  | ||||||
|         val visualSelection = caret to VimSelection.create(selectionStart, selectionEnd - 1, typeInEditor, editor) |         caretsAndSelections += 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() |       editor.exitVisualModeNative() | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -96,12 +97,12 @@ class ReplaceWithRegister : VimExtension { | |||||||
|         val lineStart = editor.getLineStartOffset(logicalLine) |         val lineStart = editor.getLineStartOffset(logicalLine) | ||||||
|         val lineEnd = editor.getLineEndOffset(logicalLine, true) |         val lineEnd = editor.getLineEndOffset(logicalLine, true) | ||||||
|  |  | ||||||
|         val visualSelection = caret to VimSelection.create(lineStart, lineEnd, SelectionType.LINE_WISE, editor) |         caretsAndSelections += caret to VimSelection.create(lineStart, lineEnd, SelectionType.LINE_WISE, editor) | ||||||
|         caretsAndSelections += visualSelection |  | ||||||
|  |  | ||||||
|         doReplace(editor.ij, caret, PutData.VisualSelection(mapOf(visualSelection), SelectionType.LINE_WISE)) |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       val visualSelection = PutData.VisualSelection(caretsAndSelections, SelectionType.LINE_WISE) | ||||||
|  |       doReplace(editor.ij, visualSelection) | ||||||
|  |  | ||||||
|       editor.forEachCaret { caret -> |       editor.forEachCaret { caret -> | ||||||
|         val vimStart = caretsAndSelections[caret]?.vimStart |         val vimStart = caretsAndSelections[caret]?.vimStart | ||||||
|         if (vimStart != null) { |         if (vimStart != null) { | ||||||
| @@ -125,8 +126,7 @@ class ReplaceWithRegister : VimExtension { | |||||||
|         ), |         ), | ||||||
|         selectionType |         selectionType | ||||||
|       ) |       ) | ||||||
|       // todo multicaret |       doReplace(editor, visualSelection) | ||||||
|       doReplace(editor, editor.vim.primaryCaret(), visualSelection) |  | ||||||
|       return true |       return true | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -147,9 +147,8 @@ class ReplaceWithRegister : VimExtension { | |||||||
|     @NonNls |     @NonNls | ||||||
|     private const val RWR_VISUAL = "<Plug>ReplaceWithRegisterVisual" |     private const val RWR_VISUAL = "<Plug>ReplaceWithRegisterVisual" | ||||||
|  |  | ||||||
|     private fun doReplace(editor: Editor, caret: VimCaret, visualSelection: PutData.VisualSelection) { |     private fun doReplace(editor: Editor, visualSelection: PutData.VisualSelection) { | ||||||
|       val lastRegisterChar = injector.registerGroup.lastRegisterChar |       val savedRegister = VimPlugin.getRegister().lastRegister ?: return | ||||||
|       val savedRegister = caret.registerStorage.getRegister(lastRegisterChar) ?: return |  | ||||||
|  |  | ||||||
|       var usedType = savedRegister.type |       var usedType = savedRegister.type | ||||||
|       var usedText = savedRegister.text |       var usedText = savedRegister.text | ||||||
| @@ -174,8 +173,8 @@ class ReplaceWithRegister : VimExtension { | |||||||
|         VimPlugin.getPut().putText(IjVimEditor(editor), IjExecutionContext(EditorDataContext.init(editor)), putData) |         VimPlugin.getPut().putText(IjVimEditor(editor), IjExecutionContext(EditorDataContext.init(editor)), putData) | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       caret.registerStorage.saveRegister(savedRegister.name, savedRegister) |       VimPlugin.getRegister().saveRegister(savedRegister.name, savedRegister) | ||||||
|       caret.registerStorage.saveRegister(VimPlugin.getRegister().defaultRegister, savedRegister) |       VimPlugin.getRegister().saveRegister(VimPlugin.getRegister().defaultRegister, savedRegister) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ import com.intellij.openapi.application.runWriteAction | |||||||
| import com.intellij.openapi.editor.Editor | import com.intellij.openapi.editor.Editor | ||||||
| import com.maddyhome.idea.vim.VimPlugin | import com.maddyhome.idea.vim.VimPlugin | ||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimCaret | import com.maddyhome.idea.vim.api.VimChangeGroup | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.MappingMode | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| @@ -32,21 +32,22 @@ import com.maddyhome.idea.vim.common.TextRange | |||||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||||
| import com.maddyhome.idea.vim.extension.VimExtension | import com.maddyhome.idea.vim.extension.VimExtension | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | import com.maddyhome.idea.vim.extension.VimExtensionFacade.executeNormalWithoutMapping | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegisterForCaret | import com.maddyhome.idea.vim.extension.VimExtensionFacade.getRegister | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputKeyStroke | import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputKeyStroke | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputString | import com.maddyhome.idea.vim.extension.VimExtensionFacade.inputString | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping | import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | import com.maddyhome.idea.vim.extension.VimExtensionFacade.setOperatorFunction | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegisterForCaret | import com.maddyhome.idea.vim.extension.VimExtensionFacade.setRegister | ||||||
|  | import com.maddyhome.idea.vim.helper.EditorHelper | ||||||
| import com.maddyhome.idea.vim.helper.editorMode | import com.maddyhome.idea.vim.helper.editorMode | ||||||
|  | import com.maddyhome.idea.vim.helper.runWithEveryCaretAndRestore | ||||||
| import com.maddyhome.idea.vim.key.OperatorFunction | import com.maddyhome.idea.vim.key.OperatorFunction | ||||||
| import com.maddyhome.idea.vim.newapi.IjVimCaret | import com.maddyhome.idea.vim.newapi.IjVimCaret | ||||||
| import com.maddyhome.idea.vim.newapi.IjVimEditor | import com.maddyhome.idea.vim.newapi.IjVimEditor | ||||||
| import com.maddyhome.idea.vim.newapi.ij | import com.maddyhome.idea.vim.newapi.ij | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
| import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper | import com.maddyhome.idea.vim.options.helpers.ClipboardOptionHelper | ||||||
| import com.maddyhome.idea.vim.put.PutData |  | ||||||
| import org.jetbrains.annotations.NonNls | import org.jetbrains.annotations.NonNls | ||||||
| import java.awt.event.KeyEvent | import java.awt.event.KeyEvent | ||||||
| import javax.swing.KeyStroke | import javax.swing.KeyStroke | ||||||
| @@ -85,22 +86,20 @@ class VimSurroundExtension : VimExtension { | |||||||
|     override val isRepeatable = true |     override val isRepeatable = true | ||||||
|  |  | ||||||
|     override fun execute(editor: VimEditor, context: ExecutionContext) { |     override fun execute(editor: VimEditor, context: ExecutionContext) { | ||||||
|       setOperatorFunction(Operator()) |       setOperatorFunction(Operator(supportsMultipleCursors = false)) // TODO | ||||||
|       executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij) |       executeNormalWithoutMapping(injector.parser.parseKeys("g@"), editor.ij) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private class VSurroundHandler : ExtensionHandler { |   private class VSurroundHandler : ExtensionHandler { | ||||||
|     override fun execute(editor: VimEditor, context: ExecutionContext) { |     override fun execute(editor: VimEditor, context: ExecutionContext) { | ||||||
|       val selectionStart = editor.ij.caretModel.primaryCaret.selectionStart |  | ||||||
|       // NB: Operator ignores SelectionType anyway |       // NB: Operator ignores SelectionType anyway | ||||||
|       if (!Operator().apply(editor.ij, context.ij, SelectionType.CHARACTER_WISE)) { |       if (!Operator(supportsMultipleCursors = true).apply(editor.ij, context.ij, SelectionType.CHARACTER_WISE)) { | ||||||
|         return |         return | ||||||
|       } |       } | ||||||
|       runWriteAction { |       runWriteAction { | ||||||
|         // Leave visual mode |         // Leave visual mode | ||||||
|         executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij) |         executeNormalWithoutMapping(injector.parser.parseKeys("<Esc>"), editor.ij) | ||||||
|         editor.ij.caretModel.moveToOffset(selectionStart) |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -116,70 +115,37 @@ class VimSurroundExtension : VimExtension { | |||||||
|       if (charTo.code == 0) return |       if (charTo.code == 0) return | ||||||
|  |  | ||||||
|       val newSurround = getOrInputPair(charTo, editor.ij) ?: return |       val newSurround = getOrInputPair(charTo, editor.ij) ?: return | ||||||
|       runWriteAction { change(editor, context, charFrom, newSurround) } |       runWriteAction { change(editor.ij, charFrom, newSurround) } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     companion object { |     companion object { | ||||||
|       fun change(editor: VimEditor, context: ExecutionContext, charFrom: Char, newSurround: Pair<String, String>?) { |       fun change(editor: Editor, charFrom: Char, newSurround: Pair<String, String>?) { | ||||||
|         // Save old register values for carets |         editor.runWithEveryCaretAndRestore { changeAtCaret(editor, charFrom, newSurround) } | ||||||
|         val surroundings = editor.sortedCarets() |       } | ||||||
|           .map { |        | ||||||
|             val oldValue: List<KeyStroke>? = getRegisterForCaret(REGISTER, it) |       fun changeAtCaret(editor: Editor, charFrom: Char, newSurround: Pair<String, String>?) { | ||||||
|             setRegisterForCaret(REGISTER, it, null) |         // We take over the " register, so preserve it | ||||||
|             SurroundingInfo(it, null, oldValue, null) |         val oldValue: List<KeyStroke>? = getRegister(REGISTER) | ||||||
|           } |         // Empty the " register | ||||||
|  |         setRegister(REGISTER, null) | ||||||
|         // Delete surrounding's content |         // Extract the inner value | ||||||
|         perform("di" + pick(charFrom), editor.ij) |         perform("di" + pick(charFrom), editor) | ||||||
|  |         val innerValue: MutableList<KeyStroke> = getRegister(REGISTER)?.toMutableList() ?: mutableListOf() | ||||||
|         // Add info about surrounding's inner text and location |         // If the surrounding characters were not found, the register will be empty | ||||||
|         surroundings.forEach { |         if (innerValue.isNotEmpty()) { | ||||||
|           val registerValue = getRegisterForCaret(REGISTER, it.caret) |           // Delete the surrounding | ||||||
|           val innerValue = if (registerValue.isNullOrEmpty()) null else registerValue |           perform("da" + pick(charFrom), editor) | ||||||
|           it.innerText = innerValue |           // Insert the surrounding characters and paste | ||||||
|  |           if (newSurround != null) { | ||||||
|           val lineEndOffset = injector.engineEditorHelper.getLineEndOffset(editor, it.caret.getLine().line, false) |             innerValue.addAll(0, injector.parser.parseKeys(newSurround.first)) | ||||||
|           if (lineEndOffset == it.caret.offset.point) { |             innerValue.addAll(injector.parser.parseKeys(newSurround.second)) | ||||||
|             it.isLineEnd = true |  | ||||||
|           } |           } | ||||||
|  |           pasteSurround(innerValue, editor) | ||||||
|  |           // Jump back to start | ||||||
|  |           executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor) | ||||||
|         } |         } | ||||||
|  |         // Restore the old value | ||||||
|         // Remove surrounding |         setRegister(REGISTER, oldValue) | ||||||
|         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) { |       private fun perform(sequence: String, editor: Editor) { | ||||||
| @@ -187,6 +153,21 @@ class VimSurroundExtension : VimExtension { | |||||||
|           .use { executeNormalWithoutMapping(injector.parser.parseKeys("\"" + REGISTER + sequence), editor) } |           .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) { |       private fun pick(charFrom: Char) = when (charFrom) { | ||||||
|         'a' -> '>' |         'a' -> '>' | ||||||
|         'r' -> ']' |         'r' -> ']' | ||||||
| @@ -195,18 +176,6 @@ 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 { |   private class DSurroundHandler : ExtensionHandler { | ||||||
|     override val isRepeatable = true |     override val isRepeatable = true | ||||||
|  |  | ||||||
| @@ -215,29 +184,47 @@ class VimSurroundExtension : VimExtension { | |||||||
|       val charFrom = getChar(editor.ij) |       val charFrom = getChar(editor.ij) | ||||||
|       if (charFrom.code == 0) return |       if (charFrom.code == 0) return | ||||||
|  |  | ||||||
|       runWriteAction { CSurroundHandler.change(editor, context, charFrom, null) } |       runWriteAction { CSurroundHandler.change(editor.ij, charFrom, null) } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private class Operator : OperatorFunction { |   private class Operator(private val supportsMultipleCursors: Boolean) : OperatorFunction { | ||||||
|     override fun apply(editor: Editor, context: DataContext, selectionType: SelectionType): Boolean { |     override fun apply(editor: Editor, context: DataContext, selectionType: SelectionType): Boolean { | ||||||
|       val c = getChar(editor) |       val c = getChar(editor) | ||||||
|       if (c.code == 0) return true |       if (c.code == 0) return true | ||||||
|  |  | ||||||
|       val pair = getOrInputPair(c, editor) ?: return false |       val pair = getOrInputPair(c, editor) ?: return false | ||||||
|       // XXX: Will it work with line-wise or block-wise selections? |  | ||||||
|       val range = getSurroundRange(editor) ?: return false |  | ||||||
|       runWriteAction { |       runWriteAction { | ||||||
|         val change = VimPlugin.getChange() |         val change = VimPlugin.getChange() | ||||||
|         val leftSurround = pair.first |         if (supportsMultipleCursors) { | ||||||
|         val primaryCaret = editor.caretModel.primaryCaret |           editor.runWithEveryCaretAndRestore { | ||||||
|         change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, leftSurround) |             applyOnce(editor, change, pair) | ||||||
|         change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.endOffset + leftSurround.length, pair.second) |           } | ||||||
|         // Jump back to start |         } | ||||||
|         executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor) |         else { | ||||||
|  |           applyOnce(editor, change, pair) | ||||||
|  |           // Jump back to start | ||||||
|  |           executeNormalWithoutMapping(injector.parser.parseKeys("`["), editor) | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|       return true |       return true | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     private fun applyOnce(editor: Editor, change: VimChangeGroup, pair: Pair<String, String>) { | ||||||
|  |       // XXX: Will it work with line-wise or block-wise selections? | ||||||
|  |       val range = getSurroundRange(editor) | ||||||
|  |       if (range != null) { | ||||||
|  |         val primaryCaret = editor.caretModel.primaryCaret | ||||||
|  |         change.insertText(IjVimEditor(editor), IjVimCaret(primaryCaret), range.startOffset, pair.first) | ||||||
|  |         change.insertText( | ||||||
|  |           IjVimEditor(editor), | ||||||
|  |           IjVimCaret(primaryCaret), | ||||||
|  |           range.endOffset + pair.first.length, | ||||||
|  |           pair.second | ||||||
|  |         ) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private fun getSurroundRange(editor: Editor): TextRange? = when (editor.editorMode) { |     private fun getSurroundRange(editor: Editor): TextRange? = when (editor.editorMode) { | ||||||
|       VimStateMachine.Mode.COMMAND -> VimPlugin.getMark().getChangeMarks(editor.vim) |       VimStateMachine.Mode.COMMAND -> VimPlugin.getMark().getChangeMarks(editor.vim) | ||||||
|   | |||||||
| @@ -50,7 +50,10 @@ import com.maddyhome.idea.vim.group.visual.VisualModeHelperKt; | |||||||
| import com.maddyhome.idea.vim.helper.*; | import com.maddyhome.idea.vim.helper.*; | ||||||
| import com.maddyhome.idea.vim.key.KeyHandlerKeeper; | import com.maddyhome.idea.vim.key.KeyHandlerKeeper; | ||||||
| import com.maddyhome.idea.vim.listener.VimInsertListener; | import com.maddyhome.idea.vim.listener.VimInsertListener; | ||||||
| import com.maddyhome.idea.vim.newapi.*; | import com.maddyhome.idea.vim.newapi.IjExecutionContext; | ||||||
|  | import com.maddyhome.idea.vim.newapi.IjExecutionContextKt; | ||||||
|  | import com.maddyhome.idea.vim.newapi.IjVimCaret; | ||||||
|  | import com.maddyhome.idea.vim.newapi.IjVimEditor; | ||||||
| import com.maddyhome.idea.vim.options.OptionConstants; | import com.maddyhome.idea.vim.options.OptionConstants; | ||||||
| import com.maddyhome.idea.vim.options.OptionScope; | import com.maddyhome.idea.vim.options.OptionScope; | ||||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString; | import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString; | ||||||
| @@ -200,6 +203,61 @@ public class ChangeGroup extends VimChangeGroupBase { | |||||||
|     return new Pair<>(range, type); |     return new Pair<>(range, type); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Delete the range of text. | ||||||
|  |    * | ||||||
|  |    * @param editor   The editor to delete the text from | ||||||
|  |    * @param caret    The caret to be moved after deletion | ||||||
|  |    * @param range    The range to delete | ||||||
|  |    * @param type     The type of deletion | ||||||
|  |    * @param isChange Is from a change action | ||||||
|  |    * @return true if able to delete the text, false if not | ||||||
|  |    */ | ||||||
|  |   @Override | ||||||
|  |   public boolean deleteRange(@NotNull VimEditor editor, | ||||||
|  |                              @NotNull VimCaret caret, | ||||||
|  |                              @NotNull TextRange range, | ||||||
|  |                              @Nullable SelectionType type, | ||||||
|  |                              boolean isChange, | ||||||
|  |                              boolean noYank) { | ||||||
|  |  | ||||||
|  |     // Update the last column before we delete, or we might be retrieving the data for a line that no longer exists | ||||||
|  |     UserDataManager.setVimLastColumn(((IjVimCaret) caret).getCaret(), InlayHelperKt.getInlayAwareVisualColumn(((IjVimCaret) caret).getCaret())); | ||||||
|  |  | ||||||
|  |     boolean removeLastNewLine = removeLastNewLine(editor, range, type); | ||||||
|  |     final boolean res = deleteText(editor, range, type, noYank); | ||||||
|  |     if (removeLastNewLine) { | ||||||
|  |       int textLength = ((IjVimEditor) editor).getEditor().getDocument().getTextLength(); | ||||||
|  |       ((IjVimEditor) editor).getEditor().getDocument().deleteString(textLength - 1, textLength); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (res) { | ||||||
|  |       int pos = EditorHelper.normalizeOffset(((IjVimEditor) editor).getEditor(), range.getStartOffset(), isChange); | ||||||
|  |       if (type == SelectionType.LINE_WISE) { | ||||||
|  |         pos = VimPlugin.getMotion() | ||||||
|  |           .moveCaretToLineWithStartOfLineOption(editor, editor.offsetToLogicalPosition(pos).getLine(), | ||||||
|  |                                                 caret); | ||||||
|  |       } | ||||||
|  |       injector.getMotion().moveCaret(editor, caret, pos); | ||||||
|  |     } | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private boolean removeLastNewLine(@NotNull VimEditor editor, @NotNull TextRange range, @Nullable SelectionType type) { | ||||||
|  |     int endOffset = range.getEndOffset(); | ||||||
|  |     int fileSize = EditorHelperRt.getFileSize(((IjVimEditor) editor).getEditor()); | ||||||
|  |     if (endOffset > fileSize) { | ||||||
|  |       if (injector.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, OptionConstants.ideastrictmodeName, OptionConstants.ideastrictmodeName)) { | ||||||
|  |         throw new IllegalStateException("Incorrect offset. File size: " + fileSize + ", offset: " + endOffset); | ||||||
|  |       } | ||||||
|  |       endOffset = fileSize; | ||||||
|  |     } | ||||||
|  |     return type == SelectionType.LINE_WISE && | ||||||
|  |            range.getStartOffset() != 0 && | ||||||
|  |            ((IjVimEditor) editor).getEditor().getDocument().getCharsSequence().charAt(endOffset - 1) != '\n' && | ||||||
|  |            endOffset == fileSize; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @Override |   @Override | ||||||
|   public void insertLineAround(@NotNull VimEditor editor, @NotNull ExecutionContext context, int shift) { |   public void insertLineAround(@NotNull VimEditor editor, @NotNull ExecutionContext context, int shift) { | ||||||
|     com.maddyhome.idea.vim.newapi.ChangeGroupKt.insertLineAround(editor, context, shift); |     com.maddyhome.idea.vim.newapi.ChangeGroupKt.insertLineAround(editor, context, shift); | ||||||
| @@ -228,7 +286,8 @@ public class ChangeGroup extends VimChangeGroupBase { | |||||||
|                               @NotNull VimCaret caret, |                               @NotNull VimCaret caret, | ||||||
|                               @NotNull ExecutionContext context, |                               @NotNull ExecutionContext context, | ||||||
|                               @NotNull Argument argument, |                               @NotNull Argument argument, | ||||||
|                               @NotNull OperatorArguments operatorArguments) { |                               @NotNull OperatorArguments operatorArguments, | ||||||
|  |                               boolean noYank) { | ||||||
|     int count0 = operatorArguments.getCount0(); |     int count0 = operatorArguments.getCount0(); | ||||||
|     // Vim treats cw as ce and cW as cE if cursor is on a non-blank character |     // Vim treats cw as ce and cW as cE if cursor is on a non-blank character | ||||||
|     final Command motion = argument.getMotion(); |     final Command motion = argument.getMotion(); | ||||||
| @@ -306,7 +365,7 @@ public class ChangeGroup extends VimChangeGroupBase { | |||||||
|       Pair<TextRange, SelectionType> deleteRangeAndType = |       Pair<TextRange, SelectionType> deleteRangeAndType = | ||||||
|         getDeleteRangeAndType(editor, caret, context, argument, true, operatorArguments.withCount0(count0)); |         getDeleteRangeAndType(editor, caret, context, argument, true, operatorArguments.withCount0(count0)); | ||||||
|       if (deleteRangeAndType == null) return false; |       if (deleteRangeAndType == null) return false; | ||||||
|       return changeRange(editor, caret, deleteRangeAndType.getFirst(), deleteRangeAndType.getSecond(), context); |       return changeRange(editor, caret, deleteRangeAndType.getFirst(), deleteRangeAndType.getSecond(), context, noYank); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -436,7 +495,8 @@ public class ChangeGroup extends VimChangeGroupBase { | |||||||
|                              @NotNull VimCaret caret, |                              @NotNull VimCaret caret, | ||||||
|                              @NotNull TextRange range, |                              @NotNull TextRange range, | ||||||
|                              @NotNull SelectionType type, |                              @NotNull SelectionType type, | ||||||
|                              ExecutionContext context) { |                              @Nullable ExecutionContext context, | ||||||
|  |                              boolean noYank) { | ||||||
|     int col = 0; |     int col = 0; | ||||||
|     int lines = 0; |     int lines = 0; | ||||||
|     if (type == SelectionType.BLOCK_WISE) { |     if (type == SelectionType.BLOCK_WISE) { | ||||||
| @@ -450,7 +510,7 @@ public class ChangeGroup extends VimChangeGroupBase { | |||||||
|  |  | ||||||
|     final VimLogicalPosition lp = editor.offsetToLogicalPosition(injector.getMotion().moveCaretToLineStartSkipLeading(editor, caret)); |     final VimLogicalPosition lp = editor.offsetToLogicalPosition(injector.getMotion().moveCaretToLineStartSkipLeading(editor, caret)); | ||||||
|  |  | ||||||
|     boolean res = deleteRange(editor, caret, range, type, true); |     boolean res = deleteRange(editor, caret, range, type, true, noYank); | ||||||
|     if (res) { |     if (res) { | ||||||
|       if (type == SelectionType.LINE_WISE) { |       if (type == SelectionType.LINE_WISE) { | ||||||
|         // Please don't use `getDocument().getText().isEmpty()` because it converts CharSequence into String |         // Please don't use `getDocument().getText().isEmpty()` because it converts CharSequence into String | ||||||
| @@ -675,7 +735,7 @@ public class ChangeGroup extends VimChangeGroupBase { | |||||||
|               } |               } | ||||||
|             } |             } | ||||||
|             if (pos > wsoff) { |             if (pos > wsoff) { | ||||||
|               deleteText(editor, new TextRange(wsoff, pos), null, caret); |               deleteText(editor, new TextRange(wsoff, pos), null, false); | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -38,7 +38,8 @@ import com.maddyhome.idea.vim.action.ComplicatedKeysAction; | |||||||
| import com.maddyhome.idea.vim.action.VimShortcutKeyAction; | import com.maddyhome.idea.vim.action.VimShortcutKeyAction; | ||||||
| import com.maddyhome.idea.vim.api.*; | import com.maddyhome.idea.vim.api.*; | ||||||
| import com.maddyhome.idea.vim.command.MappingMode; | import com.maddyhome.idea.vim.command.MappingMode; | ||||||
| import com.maddyhome.idea.vim.key.Node; | import com.maddyhome.idea.vim.common.Node; | ||||||
|  | import com.maddyhome.idea.vim.common.NodesKt; | ||||||
| import com.maddyhome.idea.vim.ex.ExOutputModel; | import com.maddyhome.idea.vim.ex.ExOutputModel; | ||||||
| import com.maddyhome.idea.vim.handler.EditorActionHandlerBase; | import com.maddyhome.idea.vim.handler.EditorActionHandlerBase; | ||||||
| import com.maddyhome.idea.vim.helper.HelperKt; | import com.maddyhome.idea.vim.helper.HelperKt; | ||||||
|   | |||||||
| @@ -92,7 +92,7 @@ public class ProcessGroup extends VimProcessGroupBase { | |||||||
|     String initText = getRange(((IjVimEditor) editor).getEditor(), cmd); |     String initText = getRange(((IjVimEditor) editor).getEditor(), cmd); | ||||||
|     VimStateMachine.getInstance(editor).pushModes(VimStateMachine.Mode.CMD_LINE, VimStateMachine.SubMode.NONE); |     VimStateMachine.getInstance(editor).pushModes(VimStateMachine.Mode.CMD_LINE, VimStateMachine.SubMode.NONE); | ||||||
|     ExEntryPanel panel = ExEntryPanel.getInstance(); |     ExEntryPanel panel = ExEntryPanel.getInstance(); | ||||||
|     panel.activate(((IjVimEditor) editor).getEditor(), ((IjExecutionContext) context).getContext(), ":", initText, 1); |     panel.activate(((IjVimEditor) editor).getEditor(), ((IjExecutionContext) context).getContext(), ":", initText, cmd.getCount()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @Override |   @Override | ||||||
| @@ -123,7 +123,7 @@ public class ProcessGroup extends VimProcessGroupBase { | |||||||
|  |  | ||||||
|       logger.debug("processing command"); |       logger.debug("processing command"); | ||||||
|  |  | ||||||
|       final String text = panel.getText(); |       String text = panel.getText(); | ||||||
|  |  | ||||||
|       if (!panel.getLabel().equals(":")) { |       if (!panel.getLabel().equals(":")) { | ||||||
|         // Search is handled via Argument.Type.EX_STRING. Although ProcessExEntryAction is registered as the handler for |         // Search is handled via Argument.Type.EX_STRING. Although ProcessExEntryAction is registered as the handler for | ||||||
| @@ -134,7 +134,15 @@ public class ProcessGroup extends VimProcessGroupBase { | |||||||
|  |  | ||||||
|       if (logger.isDebugEnabled()) logger.debug("swing=" + SwingUtilities.isEventDispatchThread()); |       if (logger.isDebugEnabled()) logger.debug("swing=" + SwingUtilities.isEventDispatchThread()); | ||||||
|  |  | ||||||
|       VimInjectorKt.getInjector().getVimscriptExecutor().execute(text, editor, context, skipHistory(editor), true, CommandLineVimLContext.INSTANCE); |       int repeat = 1; | ||||||
|  |       if (text.contains("raction ")) { | ||||||
|  |         text = text.replace("raction ", "action "); | ||||||
|  |         repeat = panel.getCount(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       for (int i = 0; i < repeat; i++) { | ||||||
|  |         VimInjectorKt.getInjector().getVimscriptExecutor().execute(text, editor, context, skipHistory(editor), true, CommandLineVimLContext.INSTANCE); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     catch (ExException e) { |     catch (ExException e) { | ||||||
|       VimPlugin.showMessage(e.getMessage()); |       VimPlugin.showMessage(e.getMessage()); | ||||||
|   | |||||||
| @@ -34,8 +34,8 @@ import com.maddyhome.idea.vim.api.ExecutionContext | |||||||
| import com.maddyhome.idea.vim.api.VimCaret | import com.maddyhome.idea.vim.api.VimCaret | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.SelectionType |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.command.isBlock | import com.maddyhome.idea.vim.command.isBlock | ||||||
| import com.maddyhome.idea.vim.command.isChar | import com.maddyhome.idea.vim.command.isChar | ||||||
| import com.maddyhome.idea.vim.command.isLine | import com.maddyhome.idea.vim.command.isLine | ||||||
| @@ -60,14 +60,10 @@ import java.awt.datatransfer.DataFlavor | |||||||
| import kotlin.math.min | import kotlin.math.min | ||||||
|  |  | ||||||
| class PutGroup : VimPutBase() { | class PutGroup : VimPutBase() { | ||||||
|   override fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData, updateVisualMarks: Boolean): Boolean { |   override fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData): Boolean { | ||||||
|     val additionalData = collectPreModificationData(editor, data) |     val additionalData = collectPreModificationData(editor, data) | ||||||
|     data.visualSelection?.let { deleteSelectedText(editor, data) } |  | ||||||
|     val processedText = processText(editor, data) ?: return false |     val processedText = processText(editor, data) ?: return false | ||||||
|     putForCaret(editor, caret, data, additionalData, context, processedText) |     putForCaret(editor, caret, data, additionalData, context, processedText) | ||||||
|     if (editor.primaryCaret() == caret && updateVisualMarks) { |  | ||||||
|       wrapInsertedTextWithVisualMarks(editor, data, processedText) |  | ||||||
|     } |  | ||||||
|     return true |     return true | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -101,7 +97,22 @@ class PutGroup : VimPutBase() { | |||||||
|       EditorHelper.getOrderedCaretsList(editor.ij).map { IjVimCaret(it) } |       EditorHelper.getOrderedCaretsList(editor.ij).map { IjVimCaret(it) } | ||||||
|     } |     } | ||||||
|     injector.application.runWriteAction { |     injector.application.runWriteAction { | ||||||
|       myCarets.forEach { caret -> putForCaret(editor, caret, data, additionalData, context, text) } |       val singleCaret = myCarets.singleOrNull() | ||||||
|  |       if (singleCaret != null) { | ||||||
|  |         putForCaret(editor, singleCaret, data, additionalData, context, text) | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         val lines = text.text.split('\n') | ||||||
|  |         if (lines.size != myCarets.size) { | ||||||
|  |           myCarets.forEach { caret -> putForCaret(editor, caret, data, additionalData, context, text) } | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |           myCarets.asReversed().forEachIndexed { index, caret -> | ||||||
|  |             val line = ProcessedTextData(lines[index], text.typeInRegister, text.transferableData) | ||||||
|  |             putForCaret(editor, caret, data, additionalData, context, line) | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -122,9 +133,7 @@ class PutGroup : VimPutBase() { | |||||||
|         editor, caret, context, text.text, text.typeInRegister, subMode, |         editor, caret, context, text.text, text.typeInRegister, subMode, | ||||||
|         startOffset, data.count, data.indent, data.caretAfterInsertedText |         startOffset, data.count, data.indent, data.caretAfterInsertedText | ||||||
|       ) |       ) | ||||||
|       if (caret == editor.primaryCaret()) { |       VimPlugin.getMark().setChangeMarks(editor, TextRange(startOffset, endOffset)) | ||||||
|         VimPlugin.getMark().setChangeMarks(editor, TextRange(startOffset, endOffset)) |  | ||||||
|       } |  | ||||||
|       moveCaretToEndPosition( |       moveCaretToEndPosition( | ||||||
|         editor, |         editor, | ||||||
|         caret, |         caret, | ||||||
| @@ -235,13 +244,13 @@ class PutGroup : VimPutBase() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   private fun putTextViaIde( |   private fun putTextViaIde( | ||||||
|     pasteProvider: PasteProvider, |       pasteProvider: PasteProvider, | ||||||
|     vimEditor: VimEditor, |       vimEditor: VimEditor, | ||||||
|     vimContext: ExecutionContext, |       vimContext: ExecutionContext, | ||||||
|     text: ProcessedTextData, |       text: ProcessedTextData, | ||||||
|     subMode: VimStateMachine.SubMode, |       subMode: VimStateMachine.SubMode, | ||||||
|     data: PutData, |       data: PutData, | ||||||
|     additionalData: Map<String, Any>, |       additionalData: Map<String, Any>, | ||||||
|   ) { |   ) { | ||||||
|     val editor = (vimEditor as IjVimEditor).editor |     val editor = (vimEditor as IjVimEditor).editor | ||||||
|     val context = vimContext.context as DataContext |     val context = vimContext.context as DataContext | ||||||
|   | |||||||
| @@ -18,16 +18,18 @@ | |||||||
|  |  | ||||||
| package com.maddyhome.idea.vim.group.copy | 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.intellij.util.containers.ContainerUtil | ||||||
|  | import com.maddyhome.idea.vim.VimPlugin | ||||||
| import com.maddyhome.idea.vim.action.motion.updown.MotionDownLess1FirstNonSpaceAction | import com.maddyhome.idea.vim.action.motion.updown.MotionDownLess1FirstNonSpaceAction | ||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimCaret |  | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | 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.Argument | ||||||
| import com.maddyhome.idea.vim.command.OperatorArguments | import com.maddyhome.idea.vim.command.OperatorArguments | ||||||
| import com.maddyhome.idea.vim.command.SelectionType | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.common.TextRange | 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.EditorHelper | ||||||
| import com.maddyhome.idea.vim.helper.fileSize | import com.maddyhome.idea.vim.helper.fileSize | ||||||
| import com.maddyhome.idea.vim.listener.VimYankListener | import com.maddyhome.idea.vim.listener.VimYankListener | ||||||
| @@ -44,8 +46,8 @@ class YankGroup : YankGroupBase() { | |||||||
|  |  | ||||||
|   fun removeListener(listener: VimYankListener) = yankListeners.remove(listener) |   fun removeListener(listener: VimYankListener) = yankListeners.remove(listener) | ||||||
|  |  | ||||||
|   private fun notifyListeners(editor: VimEditor, textRange: TextRange) = yankListeners.forEach { |   private fun notifyListeners(editor: Editor, textRange: TextRange) = yankListeners.forEach { | ||||||
|     it.yankPerformed(editor.ij, textRange) |     it.yankPerformed(editor, textRange) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @@ -65,38 +67,32 @@ class YankGroup : YankGroupBase() { | |||||||
|     operatorArguments: OperatorArguments |     operatorArguments: OperatorArguments | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|     val motion = argument.motion |     val motion = argument.motion | ||||||
|     val type = if (motion.isLinewiseMotion()) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE |  | ||||||
|  |  | ||||||
|     val nativeCaretCount = editor.nativeCarets().size |     val caretModel = editor.ij.caretModel | ||||||
|     if (nativeCaretCount <= 0) return false |     if (caretModel.caretCount <= 0) return false | ||||||
|  |  | ||||||
|     val carretToRange = HashMap<VimCaret, TextRange>(nativeCaretCount) |     val ranges = ArrayList<Pair<Int, Int>>(caretModel.caretCount) | ||||||
|     val ranges = ArrayList<Pair<Int, Int>>(nativeCaretCount) |  | ||||||
|  |  | ||||||
|     // This logic is from original vim |     // This logic is from original vim | ||||||
|     val startOffsets = if (argument.motion.action is MotionDownLess1FirstNonSpaceAction) null else HashMap<VimCaret, Int>(nativeCaretCount) |     val startOffsets = | ||||||
|  |       if (argument.motion.action is MotionDownLess1FirstNonSpaceAction) null else HashMap<Caret, Int>(caretModel.caretCount) | ||||||
|  |  | ||||||
|     for (caret in editor.nativeCarets()) { |     for (caret in caretModel.allCarets) { | ||||||
|       val motionRange = injector.motion.getMotionRange(editor, caret, context, argument, operatorArguments) |       val motionRange = MotionGroup.getMotionRange(editor.ij, caret, context.ij, argument, operatorArguments) | ||||||
|         ?: continue |         ?: continue | ||||||
|  |  | ||||||
|       assert(motionRange.size() == 1) |       assert(motionRange.size() == 1) | ||||||
|       ranges.add(motionRange.startOffset to motionRange.endOffset) |       ranges.add(motionRange.startOffset to motionRange.endOffset) | ||||||
|       startOffsets?.put(caret, motionRange.normalize().startOffset) |       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 |     val range = getTextRange(ranges, type) ?: return false | ||||||
|  |  | ||||||
|     if (range.size() == 0) return false |     if (range.size() == 0) return false | ||||||
|  |  | ||||||
|     return yankRange( |     val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type | ||||||
|       editor, |     return yankRange(editor.ij, range, selectionType, startOffsets) | ||||||
|       carretToRange, |  | ||||||
|       range, |  | ||||||
|       type, |  | ||||||
|       startOffsets |  | ||||||
|     ) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @@ -107,21 +103,19 @@ class YankGroup : YankGroupBase() { | |||||||
|    * @return true if able to yank the lines, false if not |    * @return true if able to yank the lines, false if not | ||||||
|    */ |    */ | ||||||
|   override fun yankLine(editor: VimEditor, count: Int): Boolean { |   override fun yankLine(editor: VimEditor, count: Int): Boolean { | ||||||
|     val caretCount = editor.nativeCarets().size |     val caretModel = editor.ij.caretModel | ||||||
|     val ranges = ArrayList<Pair<Int, Int>>(caretCount) |     val ranges = ArrayList<Pair<Int, Int>>(caretModel.caretCount) | ||||||
|     val caretToRange = HashMap<VimCaret, TextRange>(caretCount) |     for (caret in caretModel.allCarets) { | ||||||
|     for (caret in editor.nativeCarets()) { |       val start = VimPlugin.getMotion().moveCaretToLineStart(editor, caret.vim) | ||||||
|       val start = injector.motion.moveCaretToLineStart(editor, caret) |       val end = min(VimPlugin.getMotion().moveCaretToLineEndOffset(editor, caret.vim, count - 1, true) + 1, editor.fileSize().toInt()) | ||||||
|       val end = min(injector.motion.moveCaretToLineEndOffset(editor, caret, count - 1, true) + 1, editor.fileSize().toInt()) |  | ||||||
|  |  | ||||||
|       if (end == -1) continue |       if (end == -1) continue | ||||||
|  |  | ||||||
|       ranges.add(start to end) |       ranges.add(start to end) | ||||||
|       caretToRange[caret] = TextRange(start, end) |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     val range = getTextRange(ranges, SelectionType.LINE_WISE) ?: return false |     val range = getTextRange(ranges, SelectionType.LINE_WISE) ?: return false | ||||||
|     return yankRange(editor, caretToRange, range, SelectionType.LINE_WISE, null) |     return yankRange(editor.ij, range, SelectionType.LINE_WISE, null) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @@ -135,7 +129,6 @@ class YankGroup : YankGroupBase() { | |||||||
|   override fun yankRange(editor: VimEditor, range: TextRange?, type: SelectionType, moveCursor: Boolean): Boolean { |   override fun yankRange(editor: VimEditor, range: TextRange?, type: SelectionType, moveCursor: Boolean): Boolean { | ||||||
|     range ?: return false |     range ?: return false | ||||||
|  |  | ||||||
|     val caretToRange = HashMap<VimCaret, TextRange>() |  | ||||||
|     val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type |     val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type | ||||||
|  |  | ||||||
|     if (type == SelectionType.LINE_WISE) { |     if (type == SelectionType.LINE_WISE) { | ||||||
| @@ -150,25 +143,24 @@ class YankGroup : YankGroupBase() { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     val caretModel = editor.ij.caretModel | ||||||
|     val rangeStartOffsets = range.startOffsets |     val rangeStartOffsets = range.startOffsets | ||||||
|     val rangeEndOffsets = range.endOffsets |     val rangeEndOffsets = range.endOffsets | ||||||
|  |  | ||||||
|     val startOffsets = HashMap<VimCaret, Int>(editor.nativeCarets().size) |  | ||||||
|     if (type == SelectionType.BLOCK_WISE) { |  | ||||||
|       startOffsets[editor.primaryCaret()] = range.normalize().startOffset |  | ||||||
|       caretToRange[editor.primaryCaret()] = range |  | ||||||
|     } else { |  | ||||||
|       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) { |     return if (moveCursor) { | ||||||
|       yankRange(editor, caretToRange, range, selectionType, startOffsets) |       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) | ||||||
|     } else { |     } else { | ||||||
|       yankRange(editor, caretToRange, range, selectionType, null) |       yankRange(editor.ij, range, selectionType, null) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -200,20 +192,15 @@ class YankGroup : YankGroupBase() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   private fun yankRange( |   private fun yankRange( | ||||||
|     editor: VimEditor, |     editor: Editor, | ||||||
|     caretToRange: Map<VimCaret, TextRange>, |  | ||||||
|     range: TextRange, |     range: TextRange, | ||||||
|     type: SelectionType, |     type: SelectionType, | ||||||
|     startOffsets: Map<VimCaret, Int>?, |     startOffsets: Map<Caret, Int>?, | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|     startOffsets?.forEach { (caret, offset) -> injector.motion.moveCaret(editor, caret, offset) } |     startOffsets?.forEach { (caret, offset) -> MotionGroup.moveCaret(editor, caret, offset) } | ||||||
|  |  | ||||||
|     notifyListeners(editor, range) |     notifyListeners(editor, range) | ||||||
|  |  | ||||||
|     var result = true |     return VimPlugin.getRegister().storeText(editor.vim, range, type, false) | ||||||
|     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.VimPlugin | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
| import com.maddyhome.idea.vim.helper.EditorDataContext | import com.maddyhome.idea.vim.helper.EditorDataContext | ||||||
| import com.maddyhome.idea.vim.helper.editorMode | import com.maddyhome.idea.vim.helper.vimStateMachine | ||||||
| import com.maddyhome.idea.vim.helper.exitSelectMode | import com.maddyhome.idea.vim.helper.exitSelectMode | ||||||
| import com.maddyhome.idea.vim.helper.exitVisualMode | import com.maddyhome.idea.vim.helper.exitVisualMode | ||||||
| import com.maddyhome.idea.vim.helper.hasVisualSelection | 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.inVisualMode | ||||||
| import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere | import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere | ||||||
| import com.maddyhome.idea.vim.helper.isTemplateActive | 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.popAllModes | ||||||
| import com.maddyhome.idea.vim.helper.vimStateMachine |  | ||||||
| import com.maddyhome.idea.vim.listener.VimListenerManager | import com.maddyhome.idea.vim.listener.VimListenerManager | ||||||
| import com.maddyhome.idea.vim.newapi.IjVimEditor | import com.maddyhome.idea.vim.newapi.IjVimEditor | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
|   | |||||||
| @@ -25,11 +25,11 @@ import com.maddyhome.idea.vim.VimPlugin | |||||||
| import com.maddyhome.idea.vim.api.VimMotionGroupBase | import com.maddyhome.idea.vim.api.VimMotionGroupBase | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
| import com.maddyhome.idea.vim.helper.EditorHelper | 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.inBlockSubMode | ||||||
| import com.maddyhome.idea.vim.helper.inSelectMode | import com.maddyhome.idea.vim.helper.inSelectMode | ||||||
| import com.maddyhome.idea.vim.helper.inVisualMode | import com.maddyhome.idea.vim.helper.inVisualMode | ||||||
| import com.maddyhome.idea.vim.helper.isEndAllowed | 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.moveToInlayAwareOffset | ||||||
| import com.maddyhome.idea.vim.helper.subMode | import com.maddyhome.idea.vim.helper.subMode | ||||||
| import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes | import com.maddyhome.idea.vim.helper.updateCaretsVisualAttributes | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ package com.maddyhome.idea.vim.helper | |||||||
|  |  | ||||||
| import com.intellij.codeWithMe.ClientId | import com.intellij.codeWithMe.ClientId | ||||||
| import com.intellij.openapi.editor.Caret | import com.intellij.openapi.editor.Caret | ||||||
|  | import com.intellij.openapi.editor.CaretState | ||||||
| import com.intellij.openapi.editor.Editor | import com.intellij.openapi.editor.Editor | ||||||
| import com.intellij.openapi.editor.ex.util.EditorUtil | import com.intellij.openapi.editor.ex.util.EditorUtil | ||||||
| import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx | import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx | ||||||
| @@ -106,3 +107,41 @@ val Caret.vimLine: Int | |||||||
|  */ |  */ | ||||||
| val Editor.vimLine: Int | val Editor.vimLine: Int | ||||||
|   get() = this.caretModel.currentCaret.vimLine |   get() = this.caretModel.currentCaret.vimLine | ||||||
|  |  | ||||||
|  | inline fun Editor.runWithEveryCaretAndRestore(action: () -> Unit) { | ||||||
|  |   val caretModel = this.caretModel | ||||||
|  |   val carets = if (this.inBlockSubMode) null else caretModel.allCarets | ||||||
|  |   if (carets == null || carets.size == 1) { | ||||||
|  |     action() | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     var initialDocumentSize = this.document.textLength | ||||||
|  |     var documentSizeDifference = 0 | ||||||
|  |  | ||||||
|  |     val caretOffsets = carets.map { it.selectionStart to it.selectionEnd } | ||||||
|  |     val restoredCarets = mutableListOf<CaretState>() | ||||||
|  |  | ||||||
|  |     caretModel.removeSecondaryCarets() | ||||||
|  |      | ||||||
|  |     for ((selectionStart, selectionEnd) in caretOffsets) { | ||||||
|  |       if (selectionStart == selectionEnd) { | ||||||
|  |         caretModel.primaryCaret.moveToOffset(selectionStart + documentSizeDifference) | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  |         caretModel.primaryCaret.setSelection( | ||||||
|  |           selectionStart + documentSizeDifference, | ||||||
|  |           selectionEnd + documentSizeDifference | ||||||
|  |         ) | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       action() | ||||||
|  |       restoredCarets.add(caretModel.caretsAndSelections.single()) | ||||||
|  |  | ||||||
|  |       val documentLength = this.document.textLength | ||||||
|  |       documentSizeDifference += documentLength - initialDocumentSize | ||||||
|  |       initialDocumentSize = documentLength | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     caretModel.caretsAndSelections = restoredCarets | ||||||
|  |   }  | ||||||
|  | } | ||||||
|   | |||||||
| @@ -25,9 +25,9 @@ import com.intellij.openapi.editor.Caret | |||||||
| import com.intellij.openapi.editor.Editor | import com.intellij.openapi.editor.Editor | ||||||
| import com.maddyhome.idea.vim.VimPlugin | import com.maddyhome.idea.vim.VimPlugin | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | 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.OperatorArguments | ||||||
| import com.maddyhome.idea.vim.command.SelectionType | 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.common.TextRange | ||||||
| import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | ||||||
| import com.maddyhome.idea.vim.newapi.IjExecutionContext | import com.maddyhome.idea.vim.newapi.IjExecutionContext | ||||||
|   | |||||||
| @@ -15,30 +15,25 @@ | |||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program. If not, see <https://www.gnu.org/licenses/>. |  * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
|  */ |  */ | ||||||
| package com.maddyhome.idea.vim.helper |  | ||||||
| 
 | 
 | ||||||
| import com.maddyhome.idea.vim.api.injector | package com.maddyhome.idea.vim.helper; | ||||||
| import java.util.* | 
 | ||||||
| import java.util.stream.Collectors | import javax.swing.*; | ||||||
| import javax.swing.KeyStroke | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static com.maddyhome.idea.vim.api.VimInjectorKt.injector; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * COMPATIBILITY-LAYER: Created a helper class |  * COMPATIBILITY-LAYER: Created a helper class | ||||||
|  */ |  */ | ||||||
| object StringHelper { | public class StringHelper { | ||||||
|   @JvmStatic |   public static List<KeyStroke> parseKeys(String string) { | ||||||
|   fun parseKeys(string: String): List<KeyStroke> { |     return injector.getParser().parseKeys(string); | ||||||
|     return injector.parser.parseKeys(string) |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @JvmStatic |   public static List<KeyStroke> parseKeys(String... string) { | ||||||
|   fun parseKeys(vararg string: String): List<KeyStroke> { |     return Arrays.stream(string).flatMap(o -> injector.getParser().parseKeys(o).stream()).collect(Collectors.toList()); | ||||||
|     return Arrays.stream(string).flatMap { o: String -> injector.parser.parseKeys(o).stream() } |  | ||||||
|       .collect(Collectors.toList()) |  | ||||||
|   } |   } | ||||||
| 
 | } | ||||||
|   @JvmStatic |  | ||||||
|   fun isCloseKeyStroke(stroke: KeyStroke): Boolean { |  | ||||||
|     return stroke.isCloseKeyStroke() |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -25,9 +25,7 @@ import com.intellij.openapi.command.undo.UndoManager | |||||||
| import com.intellij.openapi.components.Service | import com.intellij.openapi.components.Service | ||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.common.ChangesListener |  | ||||||
| import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | ||||||
| import com.maddyhome.idea.vim.newapi.IjVimEditor |  | ||||||
| import com.maddyhome.idea.vim.newapi.ij | import com.maddyhome.idea.vim.newapi.ij | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
| import com.maddyhome.idea.vim.options.OptionScope | import com.maddyhome.idea.vim.options.OptionScope | ||||||
| @@ -49,7 +47,7 @@ class UndoRedoHelper : UndoRedoBase() { | |||||||
|         SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) } |         SelectionVimListenerSuppressor.lock().use { undoManager.undo(fileEditor) } | ||||||
|       } else { |       } else { | ||||||
|         val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim |         val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim | ||||||
|         performUntilFileChanges(editor, { undoManager.isUndoAvailable(fileEditor) }, { undoManager.undo(fileEditor) }) |         undoManager.undo(fileEditor) | ||||||
|         editor?.carets()?.forEach { |         editor?.carets()?.forEach { | ||||||
|           val ijCaret = it.ij |           val ijCaret = it.ij | ||||||
|           val hasSelection = ijCaret.hasSelection() |           val hasSelection = ijCaret.hasSelection() | ||||||
| @@ -75,30 +73,14 @@ class UndoRedoHelper : UndoRedoBase() { | |||||||
|         SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) } |         SelectionVimListenerSuppressor.lock().use { undoManager.redo(fileEditor) } | ||||||
|       } else { |       } else { | ||||||
|         val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim |         val editor = CommonDataKeys.EDITOR.getData(context.ij)?.vim | ||||||
|         performUntilFileChanges(editor, { undoManager.isRedoAvailable(fileEditor) }, { undoManager.redo(fileEditor) }) |         undoManager.redo(fileEditor) | ||||||
|  |         if (editor?.primaryCaret()?.ij?.hasSelection() == true) { | ||||||
|  |           undoManager.redo(fileEditor) | ||||||
|  |         } | ||||||
|         editor?.carets()?.forEach { it.ij.removeSelection() } |         editor?.carets()?.forEach { it.ij.removeSelection() } | ||||||
|       } |       } | ||||||
|       return true |       return true | ||||||
|     } |     } | ||||||
|     return false |     return false | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private fun performUntilFileChanges(editor: IjVimEditor?, check: () -> Boolean, action: Runnable) { |  | ||||||
|     if (editor == null) return |  | ||||||
|     val vimDocument = editor.document |  | ||||||
|  |  | ||||||
|     val changeListener = object : ChangesListener { |  | ||||||
|       var hasChanged = false |  | ||||||
|  |  | ||||||
|       override fun documentChanged(change: ChangesListener.Change) { |  | ||||||
|         hasChanged = true |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     vimDocument.addChangeListener(changeListener) |  | ||||||
|     while (check() && !changeListener.hasChanged) { |  | ||||||
|       action.run() |  | ||||||
|     } |  | ||||||
|     vimDocument.removeChangeListener(changeListener) |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -27,9 +27,8 @@ import com.intellij.openapi.editor.RangeMarker | |||||||
| import com.intellij.openapi.editor.markup.RangeHighlighter | import com.intellij.openapi.editor.markup.RangeHighlighter | ||||||
| import com.intellij.openapi.util.Key | import com.intellij.openapi.util.Key | ||||||
| import com.intellij.openapi.util.UserDataHolder | import com.intellij.openapi.util.UserDataHolder | ||||||
| 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.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.ex.ExOutputModel | import com.maddyhome.idea.vim.ex.ExOutputModel | ||||||
| import com.maddyhome.idea.vim.group.visual.VisualChange | import com.maddyhome.idea.vim.group.visual.VisualChange | ||||||
| import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset | import com.maddyhome.idea.vim.group.visual.vimLeadSelectionOffset | ||||||
| @@ -74,7 +73,6 @@ var Caret.vimInsertStart: RangeMarker by userDataOr { | |||||||
|     this.offset |     this.offset | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
| var Caret.registerStorage: CaretRegisterStorageBase? by userDataCaretToEditor() |  | ||||||
|  |  | ||||||
| // ------------------ Editor | // ------------------ Editor | ||||||
| fun unInitializeEditor(editor: Editor) { | fun unInitializeEditor(editor: Editor) { | ||||||
|   | |||||||
| @@ -19,6 +19,8 @@ | |||||||
| package com.maddyhome.idea.vim.key | package com.maddyhome.idea.vim.key | ||||||
|  |  | ||||||
| import com.maddyhome.idea.vim.api.injector | 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) { | fun <T> Node<T>.addLeafs(keys: String, actionHolder: T) { | ||||||
|   addLeafs(injector.parser.parseKeys(keys), actionHolder) |   addLeafs(injector.parser.parseKeys(keys), actionHolder) | ||||||
|   | |||||||
| @@ -19,8 +19,10 @@ | |||||||
| package com.maddyhome.idea.vim.listener | package com.maddyhome.idea.vim.listener | ||||||
|  |  | ||||||
| import com.intellij.codeInsight.lookup.Lookup | import com.intellij.codeInsight.lookup.Lookup | ||||||
|  | import com.intellij.codeInsight.lookup.LookupManager | ||||||
| import com.intellij.codeInsight.lookup.LookupManagerListener | import com.intellij.codeInsight.lookup.LookupManagerListener | ||||||
| import com.intellij.codeInsight.lookup.impl.LookupImpl | import com.intellij.codeInsight.lookup.impl.LookupImpl | ||||||
|  | import com.intellij.codeInsight.lookup.impl.actions.ChooseItemAction | ||||||
| import com.intellij.codeInsight.template.Template | import com.intellij.codeInsight.template.Template | ||||||
| import com.intellij.codeInsight.template.TemplateEditingAdapter | import com.intellij.codeInsight.template.TemplateEditingAdapter | ||||||
| import com.intellij.codeInsight.template.TemplateManagerListener | import com.intellij.codeInsight.template.TemplateManagerListener | ||||||
| @@ -35,20 +37,22 @@ import com.intellij.openapi.actionSystem.ex.AnActionListener | |||||||
| import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet | import com.intellij.openapi.actionSystem.impl.ProxyShortcutSet | ||||||
| import com.intellij.openapi.editor.Editor | import com.intellij.openapi.editor.Editor | ||||||
| import com.intellij.openapi.project.DumbAwareToggleAction | import com.intellij.openapi.project.DumbAwareToggleAction | ||||||
|  | import com.intellij.openapi.util.TextRange | ||||||
| import com.maddyhome.idea.vim.KeyHandler | import com.maddyhome.idea.vim.KeyHandler | ||||||
| import com.maddyhome.idea.vim.VimPlugin | import com.maddyhome.idea.vim.VimPlugin | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | 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.EditorDataContext | ||||||
|  | import com.maddyhome.idea.vim.helper.vimStateMachine | ||||||
| import com.maddyhome.idea.vim.helper.inNormalMode | import com.maddyhome.idea.vim.helper.inNormalMode | ||||||
| import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere | import com.maddyhome.idea.vim.helper.isIdeaVimDisabledHere | ||||||
| import com.maddyhome.idea.vim.helper.vimStateMachine |  | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
| import com.maddyhome.idea.vim.options.OptionConstants | import com.maddyhome.idea.vim.options.OptionConstants | ||||||
| import com.maddyhome.idea.vim.options.OptionScope | import com.maddyhome.idea.vim.options.OptionScope | ||||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt | import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt | ||||||
| import com.maddyhome.idea.vim.vimscript.model.options.helpers.IdeaRefactorModeHelper | import com.maddyhome.idea.vim.vimscript.model.options.helpers.IdeaRefactorModeHelper | ||||||
| import org.jetbrains.annotations.NonNls | import org.jetbrains.annotations.NonNls | ||||||
|  | import java.awt.event.KeyEvent | ||||||
|  | import javax.swing.KeyStroke | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @author Alex Plate |  * @author Alex Plate | ||||||
| @@ -60,6 +64,8 @@ object IdeaSpecifics { | |||||||
|     private val surrounderAction = |     private val surrounderAction = | ||||||
|       "com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler\$InvokeSurrounderAction" |       "com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler\$InvokeSurrounderAction" | ||||||
|     private var editor: Editor? = null |     private var editor: Editor? = null | ||||||
|  |     private var completionPrevDocumentLength: Int? = null | ||||||
|  |     private var completionPrevDocumentOffset: Int? = null | ||||||
|     override fun beforeActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) { |     override fun beforeActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) { | ||||||
|       if (!VimPlugin.isEnabled()) return |       if (!VimPlugin.isEnabled()) return | ||||||
|  |  | ||||||
| @@ -68,19 +74,52 @@ object IdeaSpecifics { | |||||||
|         editor = hostEditor |         editor = hostEditor | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       //region Track action id |  | ||||||
|       if (VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.trackactionidsName)) { |       if (VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.trackactionidsName)) { | ||||||
|         if (action !is NotificationService.ActionIdNotifier.CopyActionId && action !is NotificationService.ActionIdNotifier.StopTracking) { |         val id: String? = ActionManager.getInstance().getId(action) ?: (action.shortcutSet as? ProxyShortcutSet)?.actionId | ||||||
|           val id: String? = ActionManager.getInstance().getId(action) ?: (action.shortcutSet as? ProxyShortcutSet)?.actionId |         VimPlugin.getNotifications(dataContext.getData(CommonDataKeys.PROJECT)).notifyActionId(id) | ||||||
|           VimPlugin.getNotifications(dataContext.getData(CommonDataKeys.PROJECT)).notifyActionId(id) |       } | ||||||
|  |  | ||||||
|  |       if (hostEditor != null && action is ChooseItemAction && hostEditor.vimStateMachine?.isRecording == true) { | ||||||
|  |         val lookup = LookupManager.getActiveLookup(hostEditor) | ||||||
|  |         if (lookup != null) { | ||||||
|  |           val charsToRemove = hostEditor.caretModel.primaryCaret.offset - lookup.lookupStart | ||||||
|  |  | ||||||
|  |           val register = VimPlugin.getRegister() | ||||||
|  |           val backSpace = KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0) | ||||||
|  |           repeat(charsToRemove) { | ||||||
|  |             register.recordKeyStroke(backSpace) | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           completionPrevDocumentLength = hostEditor.document.textLength - charsToRemove | ||||||
|  |           completionPrevDocumentOffset = lookup.lookupStart | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       //endregion |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun afterActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) { |     override fun afterActionPerformed(action: AnAction, dataContext: DataContext, event: AnActionEvent) { | ||||||
|       if (!VimPlugin.isEnabled()) return |       if (!VimPlugin.isEnabled()) return | ||||||
|  |  | ||||||
|  |       val editor = editor | ||||||
|  |       if (editor != null && action is ChooseItemAction && editor.vimStateMachine?.isRecording == true) { | ||||||
|  |         val prevDocumentLength = completionPrevDocumentLength | ||||||
|  |         val prevDocumentOffset = completionPrevDocumentOffset | ||||||
|  |  | ||||||
|  |         if (prevDocumentLength != null && prevDocumentOffset != null) { | ||||||
|  |           val register = VimPlugin.getRegister() | ||||||
|  |           val addedTextLength = editor.document.textLength - prevDocumentLength | ||||||
|  |           val caretShift = addedTextLength - (editor.caretModel.primaryCaret.offset - prevDocumentOffset) | ||||||
|  |           val leftArrow = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0) | ||||||
|  |  | ||||||
|  |           register.recordText(editor.document.getText(TextRange(prevDocumentOffset, prevDocumentOffset + addedTextLength))) | ||||||
|  |           repeat(caretShift.coerceAtLeast(0)) { | ||||||
|  |             register.recordKeyStroke(leftArrow) | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.completionPrevDocumentLength = null | ||||||
|  |         this.completionPrevDocumentOffset = null | ||||||
|  |       } | ||||||
|  |  | ||||||
|       //region Enter insert mode after surround with if |       //region Enter insert mode after surround with if | ||||||
|       if (surrounderAction == action.javaClass.name && surrounderItems.any { |       if (surrounderAction == action.javaClass.name && surrounderItems.any { | ||||||
|         action.templatePresentation.text.endsWith( |         action.templatePresentation.text.endsWith( | ||||||
| @@ -99,7 +138,7 @@ object IdeaSpecifics { | |||||||
|       } |       } | ||||||
|       //endregion |       //endregion | ||||||
|  |  | ||||||
|       editor = null |       this.editor = null | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,8 +32,8 @@ import com.maddyhome.idea.vim.api.VimChangeGroupBase | |||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.VimMotionGroupBase | import com.maddyhome.idea.vim.api.VimMotionGroupBase | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.SelectionType |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.common.EditorLine | import com.maddyhome.idea.vim.common.EditorLine | ||||||
| import com.maddyhome.idea.vim.common.IndentConfig | import com.maddyhome.idea.vim.common.IndentConfig | ||||||
| import com.maddyhome.idea.vim.common.OperatedRange | import com.maddyhome.idea.vim.common.OperatedRange | ||||||
|   | |||||||
| @@ -22,10 +22,7 @@ import com.intellij.openapi.editor.Caret | |||||||
| import com.intellij.openapi.editor.LogicalPosition | import com.intellij.openapi.editor.LogicalPosition | ||||||
| import com.intellij.openapi.editor.VisualPosition | import com.intellij.openapi.editor.VisualPosition | ||||||
| import com.maddyhome.idea.vim.VimPlugin | 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.VimCaret | ||||||
| import com.maddyhome.idea.vim.api.VimCaretBase |  | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.VimLogicalPosition | import com.maddyhome.idea.vim.api.VimLogicalPosition | ||||||
| import com.maddyhome.idea.vim.api.VimVisualPosition | import com.maddyhome.idea.vim.api.VimVisualPosition | ||||||
| @@ -41,23 +38,13 @@ import com.maddyhome.idea.vim.group.visual.vimSetSystemSelectionSilently | |||||||
| import com.maddyhome.idea.vim.group.visual.vimUpdateEditorSelection | import com.maddyhome.idea.vim.group.visual.vimUpdateEditorSelection | ||||||
| import com.maddyhome.idea.vim.helper.inlayAwareVisualColumn | import com.maddyhome.idea.vim.helper.inlayAwareVisualColumn | ||||||
| import com.maddyhome.idea.vim.helper.moveToInlayAwareOffset | 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.vimInsertStart | ||||||
| import com.maddyhome.idea.vim.helper.vimLastColumn | import com.maddyhome.idea.vim.helper.vimLastColumn | ||||||
| import com.maddyhome.idea.vim.helper.vimLastVisualOperatorRange | import com.maddyhome.idea.vim.helper.vimLastVisualOperatorRange | ||||||
| import com.maddyhome.idea.vim.helper.vimLine | import com.maddyhome.idea.vim.helper.vimLine | ||||||
| import com.maddyhome.idea.vim.helper.vimSelectionStart | import com.maddyhome.idea.vim.helper.vimSelectionStart | ||||||
|  |  | ||||||
| class IjVimCaret(val caret: Caret) : VimCaretBase() { | class IjVimCaret(val caret: Caret) : VimCaret { | ||||||
|   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 |   override val editor: VimEditor | ||||||
|     get() = IjVimEditor(caret.editor) |     get() = IjVimEditor(caret.editor) | ||||||
|   override val offset: Offset |   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.VimSelectionModel | ||||||
| import com.maddyhome.idea.vim.api.VimVisualPosition | import com.maddyhome.idea.vim.api.VimVisualPosition | ||||||
| import com.maddyhome.idea.vim.api.VirtualFile | 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.OperatorArguments | ||||||
| import com.maddyhome.idea.vim.command.SelectionType | 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.EditorLine | ||||||
| import com.maddyhome.idea.vim.common.LiveRange | import com.maddyhome.idea.vim.common.LiveRange | ||||||
| import com.maddyhome.idea.vim.common.Offset | 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.history.VimHistory | ||||||
| import com.maddyhome.idea.vim.macro.VimMacro | import com.maddyhome.idea.vim.macro.VimMacro | ||||||
| import com.maddyhome.idea.vim.mark.VimMarkGroup | import com.maddyhome.idea.vim.mark.VimMarkGroup | ||||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService | import com.maddyhome.idea.vim.options.OptionService | ||||||
| import com.maddyhome.idea.vim.put.VimPut | import com.maddyhome.idea.vim.put.VimPut | ||||||
| import com.maddyhome.idea.vim.register.VimRegisterGroup | import com.maddyhome.idea.vim.register.VimRegisterGroup | ||||||
| import com.maddyhome.idea.vim.ui.VimRcFileState | 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.Executor | ||||||
| import com.maddyhome.idea.vim.vimscript.services.FunctionStorage | import com.maddyhome.idea.vim.vimscript.services.FunctionStorage | ||||||
| import com.maddyhome.idea.vim.vimscript.services.PatternService | import com.maddyhome.idea.vim.vimscript.services.PatternService | ||||||
| import com.maddyhome.idea.vim.vimscript.services.VariableService | import com.maddyhome.idea.vim.vimscript.services.VimVariableService | ||||||
| import com.maddyhome.idea.vim.yank.VimYankGroup | import com.maddyhome.idea.vim.yank.VimYankGroup | ||||||
|  |  | ||||||
| class IjVimInjector : VimInjectorBase() { | class IjVimInjector : VimInjectorBase() { | ||||||
| @@ -161,7 +161,7 @@ class IjVimInjector : VimInjectorBase() { | |||||||
|  |  | ||||||
|   override val functionService: VimscriptFunctionService |   override val functionService: VimscriptFunctionService | ||||||
|     get() = FunctionStorage |     get() = FunctionStorage | ||||||
|   override val variableService: VariableService |   override val variableService: VimVariableService | ||||||
|     get() = service() |     get() = service() | ||||||
|   override val vimrcFileState: VimrcFileState |   override val vimrcFileState: VimrcFileState | ||||||
|     get() = VimRcFileState |     get() = VimRcFileState | ||||||
|   | |||||||
| @@ -22,8 +22,6 @@ import com.maddyhome.idea.vim.api.injector | |||||||
| import com.maddyhome.idea.vim.options.OptionConstants | import com.maddyhome.idea.vim.options.OptionConstants | ||||||
| import com.maddyhome.idea.vim.options.OptionConstants.Companion.ignorecaseName | 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.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.OptionScope | ||||||
| import com.maddyhome.idea.vim.options.helpers.KeywordOptionHelper | import com.maddyhome.idea.vim.options.helpers.KeywordOptionHelper | ||||||
| import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService | import com.maddyhome.idea.vim.vimscript.services.IjVimOptionService | ||||||
| @@ -36,10 +34,6 @@ object OptionsManager { | |||||||
|     get() = (injector.optionService as IjVimOptionService).getRawOption(ignorecaseName) as ToggleOption |     get() = (injector.optionService as IjVimOptionService).getRawOption(ignorecaseName) as ToggleOption | ||||||
|   val smartcase: ToggleOption |   val smartcase: ToggleOption | ||||||
|     get() = (injector.optionService as IjVimOptionService).getRawOption(smartcaseName) as 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 |   val iskeyword: KeywordOption | ||||||
|     get() = KeywordOption(KeywordOptionHelper) |     get() = KeywordOption(KeywordOptionHelper) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,8 +20,8 @@ package com.maddyhome.idea.vim.ui | |||||||
|  |  | ||||||
| import com.maddyhome.idea.vim.KeyHandler | import com.maddyhome.idea.vim.KeyHandler | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.helper.isCloseKeyStroke |  | ||||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | import com.maddyhome.idea.vim.helper.vimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.helper.isCloseKeyStroke | ||||||
| import java.awt.KeyEventDispatcher | import java.awt.KeyEventDispatcher | ||||||
| import java.awt.KeyboardFocusManager | import java.awt.KeyboardFocusManager | ||||||
| import java.awt.Toolkit | import java.awt.Toolkit | ||||||
|   | |||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | /* | ||||||
|  |  * IdeaVim - Vim emulator for IDEs based on the IntelliJ platform | ||||||
|  |  * Copyright (C) 2003-2021 The IdeaVim authors | ||||||
|  |  * | ||||||
|  |  * This program is free software: you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation, either version 2 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package com.maddyhome.idea.vim.vimscript.model.functions.handlers | ||||||
|  |  | ||||||
|  | import com.intellij.refactoring.rename.inplace.InplaceRefactoring | ||||||
|  | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
|  | import com.maddyhome.idea.vim.api.VimEditor | ||||||
|  | import com.maddyhome.idea.vim.newapi.ij | ||||||
|  | import com.maddyhome.idea.vim.vimscript.model.VimLContext | ||||||
|  | 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.expressions.Expression | ||||||
|  | import com.maddyhome.idea.vim.vimscript.model.functions.FunctionHandler | ||||||
|  |  | ||||||
|  | object RenamingFunctionHandler : FunctionHandler() { | ||||||
|  |  | ||||||
|  |   override val name = "renaming" | ||||||
|  |   override val minimumNumberOfArguments = 0 | ||||||
|  |   override val maximumNumberOfArguments = 0 | ||||||
|  |    | ||||||
|  |   override fun doFunction( | ||||||
|  |     argumentValues: List<Expression>, | ||||||
|  |     editor: VimEditor, | ||||||
|  |     context: ExecutionContext, | ||||||
|  |     vimContext: VimLContext, | ||||||
|  |   ): VimDataType { | ||||||
|  |     return if (InplaceRefactoring.getActiveInplaceRenamer(editor.ij) == null) | ||||||
|  |       VimInt.ZERO | ||||||
|  |     else | ||||||
|  |       VimInt.ONE | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -25,9 +25,9 @@ import com.intellij.codeInsight.lookup.impl.LookupImpl | |||||||
| import com.intellij.codeInsight.template.impl.TemplateManagerImpl | import com.intellij.codeInsight.template.impl.TemplateManagerImpl | ||||||
| import com.intellij.openapi.editor.Editor | import com.intellij.openapi.editor.Editor | ||||||
| import com.maddyhome.idea.vim.VimPlugin | 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.hasBlockOrUnderscoreCaret | ||||||
| import com.maddyhome.idea.vim.helper.hasVisualSelection | 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.helper.subMode | ||||||
| import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
|   | |||||||
| @@ -20,9 +20,9 @@ package com.maddyhome.idea.vim.vimscript.services | |||||||
|  |  | ||||||
| import com.intellij.openapi.application.ApplicationNamesInfo | import com.intellij.openapi.application.ApplicationNamesInfo | ||||||
| import com.maddyhome.idea.vim.api.VimOptionServiceBase | 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.OptionConstants | ||||||
| import com.maddyhome.idea.vim.options.StringOption | import com.maddyhome.idea.vim.options.StringOption | ||||||
|  | import com.maddyhome.idea.vim.option.ToggleOption | ||||||
|  |  | ||||||
| internal class IjVimOptionService : VimOptionServiceBase() { | internal class IjVimOptionService : VimOptionServiceBase() { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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.Scope | ||||||
| import com.maddyhome.idea.vim.vimscript.model.expressions.Variable | import com.maddyhome.idea.vim.vimscript.model.expressions.Variable | ||||||
| 
 | 
 | ||||||
| class IjVariableService : VimVariableServiceBase() { | internal class VimVariableServiceImpl : VimVariableServiceBase() { | ||||||
|   override fun storeVariable(variable: Variable, value: VimDataType, editor: VimEditor, context: ExecutionContext, vimContext: VimLContext) { |   override fun storeVariable(variable: Variable, value: VimDataType, editor: VimEditor, context: ExecutionContext, vimContext: VimLContext) { | ||||||
|     super.storeVariable(variable, value, editor, context, vimContext) |     super.storeVariable(variable, value, editor, context, vimContext) | ||||||
| 
 | 
 | ||||||
| @@ -26,13 +26,13 @@ | |||||||
|                         serviceInterface="com.maddyhome.idea.vim.api.VimVisualMotionGroup"/> |                         serviceInterface="com.maddyhome.idea.vim.api.VimVisualMotionGroup"/> | ||||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.copy.YankGroup"/> |     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.copy.YankGroup"/> | ||||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.copy.PutGroup"/> |     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.copy.PutGroup"/> | ||||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.vimscript.services.IjVariableService" |     <applicationService serviceImplementation="com.maddyhome.idea.vim.vimscript.services.VimVariableServiceImpl" | ||||||
|                         serviceInterface="com.maddyhome.idea.vim.vimscript.services.VariableService"/> |                         serviceInterface="com.maddyhome.idea.vim.vimscript.services.VimVariableService"/> | ||||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjStatisticsService" |     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjStatisticsService" | ||||||
|                         serviceInterface="com.maddyhome.idea.vim.api.VimStatistics"/> |                         serviceInterface="com.maddyhome.idea.vim.api.VimStatistics"/> | ||||||
|  |  | ||||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.vimscript.services.IjVimOptionService" |     <applicationService serviceImplementation="com.maddyhome.idea.vim.vimscript.services.IjVimOptionService" | ||||||
|                         serviceInterface="com.maddyhome.idea.vim.vimscript.services.OptionService"/> |                         serviceInterface="com.maddyhome.idea.vim.options.OptionService"/> | ||||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjVimStorageService" |     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjVimStorageService" | ||||||
|                         serviceInterface="com.maddyhome.idea.vim.api.VimStorageService"/> |                         serviceInterface="com.maddyhome.idea.vim.api.VimStorageService"/> | ||||||
|     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjVimSystemInfoService" |     <applicationService serviceImplementation="com.maddyhome.idea.vim.group.IjVimSystemInfoService" | ||||||
|   | |||||||
| @@ -14,5 +14,6 @@ | |||||||
|     <vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.TolowerFunctionHandler" name="tolower"/> |     <vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.TolowerFunctionHandler" name="tolower"/> | ||||||
|     <vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.ToupperFunctionHandler" name="toupper"/> |     <vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.ToupperFunctionHandler" name="toupper"/> | ||||||
|     <vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.JoinFunctionHandler" name="join"/> |     <vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.JoinFunctionHandler" name="join"/> | ||||||
|  |     <vimLibraryFunction implementation="com.maddyhome.idea.vim.vimscript.model.functions.handlers.RenamingFunctionHandler" name="renaming"/> | ||||||
|   </extensions> |   </extensions> | ||||||
| </idea-plugin> | </idea-plugin> | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| <idea-plugin url="https://plugins.jetbrains.com/plugin/164" xmlns:xi="http://www.w3.org/2001/XInclude"> | <idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude"> | ||||||
|   <name>IdeaVim</name> |   <name>IdeaVim</name> | ||||||
|   <id>IdeaVIM</id> |   <id>IdeaVIM</id> | ||||||
|   <change-notes><![CDATA[ |   <change-notes><![CDATA[ | ||||||
| @@ -65,7 +65,7 @@ | |||||||
|         <li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li> |         <li><a href="https://youtrack.jetbrains.com/issues/VIM">Issue tracker</a>: feature requests and bug reports</li> | ||||||
|       </ul> |       </ul> | ||||||
|     ]]></description> |     ]]></description> | ||||||
|   <version>SNAPSHOT</version> |   <version>chylex</version> | ||||||
|   <vendor>JetBrains</vendor> |   <vendor>JetBrains</vendor> | ||||||
|  |  | ||||||
|   <!-- Please search for "[VERSION UPDATE]" in project in case you update the since-build version --> |   <!-- Please search for "[VERSION UPDATE]" in project in case you update the since-build version --> | ||||||
|   | |||||||
| @@ -31,8 +31,9 @@ import com.maddyhome.idea.vim.helper.RunnableHelper; | |||||||
| import com.maddyhome.idea.vim.helper.TestInputModel; | import com.maddyhome.idea.vim.helper.TestInputModel; | ||||||
| import com.maddyhome.idea.vim.newapi.IjExecutionContext; | import com.maddyhome.idea.vim.newapi.IjExecutionContext; | ||||||
| import com.maddyhome.idea.vim.newapi.IjVimEditor; | import com.maddyhome.idea.vim.newapi.IjVimEditor; | ||||||
| import com.maddyhome.idea.vim.options.OptionScope; |  | ||||||
| import com.maddyhome.idea.vim.ui.ex.ExEntryPanel; | import com.maddyhome.idea.vim.ui.ex.ExEntryPanel; | ||||||
|  | import com.maddyhome.idea.vim.options.OptionScope; | ||||||
|  | import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceImpl; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| import org.jetbrains.annotations.Nullable; | import org.jetbrains.annotations.Nullable; | ||||||
|  |  | ||||||
| @@ -62,7 +63,7 @@ public abstract class JavaVimTestCase extends JavaCodeInsightFixtureTestCase { | |||||||
|   @Override |   @Override | ||||||
|   protected void tearDown() throws Exception { |   protected void tearDown() throws Exception { | ||||||
|     ExEntryPanel.getInstance().deactivate(false); |     ExEntryPanel.getInstance().deactivate(false); | ||||||
|     VimPlugin.getVariableService().clear(); |     ((VimVariableServiceImpl) VimPlugin.getVariableService()).clear(); | ||||||
|     Timer swingTimer = VimVisualTimer.INSTANCE.getSwingTimer(); |     Timer swingTimer = VimVisualTimer.INSTANCE.getSwingTimer(); | ||||||
|     if (swingTimer != null) { |     if (swingTimer != null) { | ||||||
|       swingTimer.stop(); |       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.RegisterActions.VIM_ACTIONS_EP | ||||||
| import com.maddyhome.idea.vim.VimPlugin | import com.maddyhome.idea.vim.VimPlugin | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.MappingMode |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
| import com.maddyhome.idea.vim.key.CommandNode | import com.maddyhome.idea.vim.common.CommandNode | ||||||
| import com.maddyhome.idea.vim.key.CommandPartNode | import com.maddyhome.idea.vim.common.CommandPartNode | ||||||
|  | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.handler.ActionBeanClass | import com.maddyhome.idea.vim.handler.ActionBeanClass | ||||||
| import junit.framework.TestCase | import junit.framework.TestCase | ||||||
| import javax.swing.KeyStroke | import javax.swing.KeyStroke | ||||||
|   | |||||||
| @@ -76,9 +76,9 @@ inline fun waitAndAssert(timeInMillis: Int = 1000, condition: () -> Boolean) { | |||||||
| } | } | ||||||
|  |  | ||||||
| fun waitAndAssertMode( | fun waitAndAssertMode( | ||||||
|   fixture: CodeInsightTestFixture, |     fixture: CodeInsightTestFixture, | ||||||
|   mode: VimStateMachine.Mode, |     mode: VimStateMachine.Mode, | ||||||
|   timeInMillis: Int = (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.visualdelayName) as VimInt).value + 1000, |     timeInMillis: Int = (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.visualdelayName) as VimInt).value + 1000, | ||||||
| ) { | ) { | ||||||
|   waitAndAssert(timeInMillis) { fixture.editor.editorMode == mode } |   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.VimPlugin | ||||||
| import com.maddyhome.idea.vim.action.VimShortcutKeyAction | import com.maddyhome.idea.vim.action.VimShortcutKeyAction | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.MappingMode |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine.SubMode | 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.ExException | ||||||
| import com.maddyhome.idea.vim.ex.ExOutputModel.Companion.getInstance | import com.maddyhome.idea.vim.ex.ExOutputModel.Companion.getInstance | ||||||
| import com.maddyhome.idea.vim.group.visual.VimVisualTimer.swingTimer | 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.GuicursorChangeListener | ||||||
| import com.maddyhome.idea.vim.helper.RunnableHelper.runWriteCommand | import com.maddyhome.idea.vim.helper.RunnableHelper.runWriteCommand | ||||||
| import com.maddyhome.idea.vim.helper.TestInputModel | 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.getGuiCursorMode | ||||||
| import com.maddyhome.idea.vim.helper.inBlockSubMode | 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.helper.subMode | ||||||
| import com.maddyhome.idea.vim.key.MappingOwner | import com.maddyhome.idea.vim.key.MappingOwner | ||||||
| import com.maddyhome.idea.vim.key.ToKeysMappingInfo | import com.maddyhome.idea.vim.key.ToKeysMappingInfo | ||||||
| @@ -77,6 +77,7 @@ 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.VimFuncref | ||||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt | import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt | ||||||
| import com.maddyhome.idea.vim.vimscript.parser.errors.IdeavimErrorListener | 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.assertj.core.api.Assertions | ||||||
| import org.junit.Assert | import org.junit.Assert | ||||||
| import java.awt.event.KeyEvent | import java.awt.event.KeyEvent | ||||||
| @@ -136,7 +137,7 @@ abstract class VimTestCase : UsefulTestCase() { | |||||||
|     } |     } | ||||||
|     SelectionVimListenerSuppressor.lock().use { myFixture.tearDown() } |     SelectionVimListenerSuppressor.lock().use { myFixture.tearDown() } | ||||||
|     ExEntryPanel.getInstance().deactivate(false) |     ExEntryPanel.getInstance().deactivate(false) | ||||||
|     VimPlugin.getVariableService().clear() |     (VimPlugin.getVariableService() as VimVariableServiceImpl).clear() | ||||||
|     VimFuncref.lambdaCounter = 0 |     VimFuncref.lambdaCounter = 0 | ||||||
|     VimFuncref.anonymousCounter = 0 |     VimFuncref.anonymousCounter = 0 | ||||||
|     IdeavimErrorListener.testLogger.clear() |     IdeavimErrorListener.testLogger.clear() | ||||||
| @@ -508,21 +509,21 @@ abstract class VimTestCase : UsefulTestCase() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   fun doTest( |   fun doTest( | ||||||
|     keys: List<String>, |       keys: List<String>, | ||||||
|     before: String, |       before: String, | ||||||
|     after: String, |       after: String, | ||||||
|     modeAfter: VimStateMachine.Mode, |       modeAfter: VimStateMachine.Mode, | ||||||
|     subModeAfter: SubMode, |       subModeAfter: SubMode, | ||||||
|   ) { |   ) { | ||||||
|     doTest(keys.joinToString(separator = ""), before, after, modeAfter, subModeAfter) |     doTest(keys.joinToString(separator = ""), before, after, modeAfter, subModeAfter) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   fun doTest( |   fun doTest( | ||||||
|     keys: String, |       keys: String, | ||||||
|     before: String, |       before: String, | ||||||
|     after: String, |       after: String, | ||||||
|     modeAfter: VimStateMachine.Mode, |       modeAfter: VimStateMachine.Mode, | ||||||
|     subModeAfter: SubMode, |       subModeAfter: SubMode, | ||||||
|   ) { |   ) { | ||||||
|     configureByText(before) |     configureByText(before) | ||||||
|  |  | ||||||
| @@ -532,12 +533,12 @@ abstract class VimTestCase : UsefulTestCase() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   fun doTest( |   fun doTest( | ||||||
|     keys: String, |       keys: String, | ||||||
|     before: String, |       before: String, | ||||||
|     after: String, |       after: String, | ||||||
|     modeAfter: VimStateMachine.Mode, |       modeAfter: VimStateMachine.Mode, | ||||||
|     subModeAfter: SubMode, |       subModeAfter: SubMode, | ||||||
|     fileType: FileType, |       fileType: FileType, | ||||||
|   ) { |   ) { | ||||||
|     configureByText(fileType, before) |     configureByText(fileType, before) | ||||||
|  |  | ||||||
| @@ -550,12 +551,12 @@ abstract class VimTestCase : UsefulTestCase() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   fun doTest( |   fun doTest( | ||||||
|     keys: String, |       keys: String, | ||||||
|     before: String, |       before: String, | ||||||
|     after: String, |       after: String, | ||||||
|     modeAfter: VimStateMachine.Mode, |       modeAfter: VimStateMachine.Mode, | ||||||
|     subModeAfter: SubMode, |       subModeAfter: SubMode, | ||||||
|     fileName: String, |       fileName: String, | ||||||
|   ) { |   ) { | ||||||
|     configureByText(fileName, before) |     configureByText(fileName, before) | ||||||
|  |  | ||||||
| @@ -576,12 +577,12 @@ abstract class VimTestCase : UsefulTestCase() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   fun doTest( |   fun doTest( | ||||||
|     keys: List<KeyStroke>, |       keys: List<KeyStroke>, | ||||||
|     before: String, |       before: String, | ||||||
|     after: String?, |       after: String?, | ||||||
|     modeAfter: VimStateMachine.Mode, |       modeAfter: VimStateMachine.Mode, | ||||||
|     subModeAfter: SubMode, |       subModeAfter: SubMode, | ||||||
|     afterEditorInitialized: (Editor) -> Unit, |       afterEditorInitialized: (Editor) -> Unit, | ||||||
|   ) { |   ) { | ||||||
|     configureByText(before) |     configureByText(before) | ||||||
|     afterEditorInitialized(myFixture.editor) |     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.VimPlugin | ||||||
| import com.maddyhome.idea.vim.api.injector | 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 | ||||||
|  | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.key.MappingOwner | import com.maddyhome.idea.vim.key.MappingOwner | ||||||
| import junit.framework.TestCase | import junit.framework.TestCase | ||||||
| import org.jetbrains.plugins.ideavim.SkipNeovimReason | import org.jetbrains.plugins.ideavim.SkipNeovimReason | ||||||
|   | |||||||
| @@ -75,28 +75,6 @@ class UndoActionTest : VimTestCase() { | |||||||
|     assertFalse(hasSelection()) |     assertFalse(hasSelection()) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   fun `test cursor movements do not require additional undo`() { |  | ||||||
|     val keys = listOf("a1<Esc>ea2<Esc>ea3<Esc>", "uu") |  | ||||||
|     val before = """ |  | ||||||
|                 A Discovery |  | ||||||
|  |  | ||||||
|                 ${c}I found it in a legendary land |  | ||||||
|                 all rocks and lavender and tufted grass, |  | ||||||
|                 where it was settled on some sodden sand |  | ||||||
|                 hard by the torrent of a mountain pass. |  | ||||||
|     """.trimIndent() |  | ||||||
|     val after = """ |  | ||||||
|                 A Discovery |  | ||||||
|  |  | ||||||
|                 I1 found$c it in a legendary land |  | ||||||
|                 all rocks and lavender and tufted grass, |  | ||||||
|                 where it was settled on some sodden sand |  | ||||||
|                 hard by the torrent of a mountain pass. |  | ||||||
|     """.trimIndent() |  | ||||||
|     doTest(keys, before, after, VimStateMachine.Mode.COMMAND, VimStateMachine.SubMode.NONE) |  | ||||||
|     assertFalse(hasSelection()) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private fun hasSelection(): Boolean { |   private fun hasSelection(): Boolean { | ||||||
|     val editor = myFixture.editor |     val editor = myFixture.editor | ||||||
|     return editor.caretModel.primaryCaret.hasSelection() |     return editor.caretModel.primaryCaret.hasSelection() | ||||||
|   | |||||||
| @@ -20,8 +20,8 @@ package org.jetbrains.plugins.ideavim.action.copy | |||||||
|  |  | ||||||
| import com.maddyhome.idea.vim.VimPlugin | import com.maddyhome.idea.vim.VimPlugin | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.SelectionType |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
| import org.jetbrains.plugins.ideavim.VimTestCase | import org.jetbrains.plugins.ideavim.VimTestCase | ||||||
|   | |||||||
| @@ -56,7 +56,8 @@ class PutViaIdeaTest : VimTestCase() { | |||||||
|     val before = "${c}I found it in a legendary land" |     val before = "${c}I found it in a legendary land" | ||||||
|     configureByText(before) |     configureByText(before) | ||||||
|  |  | ||||||
|     injector.registerGroup.storeText('"', "legendary", SelectionType.CHARACTER_WISE) |     VimPlugin.getRegister() | ||||||
|  |       .storeText(myFixture.editor.vim, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false) | ||||||
|  |  | ||||||
|     typeText(injector.parser.parseKeys("ve" + "p")) |     typeText(injector.parser.parseKeys("ve" + "p")) | ||||||
|     val after = "legendar${c}y it in a legendary land" |     val after = "legendar${c}y it in a legendary land" | ||||||
|   | |||||||
| @@ -115,9 +115,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|   @TestWithoutNeovim(SkipNeovimReason.DIFFERENT) |   @TestWithoutNeovim(SkipNeovimReason.DIFFERENT) | ||||||
|   fun `test put visual text multicaret`() { |   fun `test put visual text multicaret`() { | ||||||
|     val before = "${c}I found ${c}it in a ${c}legendary land" |     val before = "${c}I found ${c}it in a ${c}legendary land" | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "legendary", SelectionType.CHARACTER_WISE) |     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "legendary", SelectionType.CHARACTER_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("ve" + "\"*p")) |     typeText(injector.parser.parseKeys("ve" + "p")) | ||||||
|     val after = "legendar${c}y legendar${c}y in a legendar${c}y land" |     val after = "legendar${c}y legendar${c}y in a legendar${c}y land" | ||||||
|     assertState(after) |     assertState(after) | ||||||
|   } |   } | ||||||
| @@ -254,9 +254,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             where it was settled on some sodden sand |             where it was settled on some sodden sand | ||||||
|             ${c}hard by the torrent of a mountain pass. |             ${c}hard by the torrent of a mountain pass. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) |     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("ve" + "\"*p")) |     typeText(injector.parser.parseKeys("ve" + "p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
| @@ -285,9 +285,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             where it was settled on some sodden sand |             where it was settled on some sodden sand | ||||||
|             ${c}hard by the$c torrent of a mountain pass. |             ${c}hard by the$c torrent of a mountain pass. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) |     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("ve" + "\"*p")) |     typeText(injector.parser.parseKeys("ve" + "p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
| @@ -314,9 +314,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             where it was settled on some sodden sand |             where it was settled on some sodden sand | ||||||
|             ${c}hard by the$c torrent of a mountain pass. |             ${c}hard by the$c torrent of a mountain pass. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) |     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("ve" + "2\"*p")) |     typeText(injector.parser.parseKeys("ve" + "2p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
| @@ -461,10 +461,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             akin to moonlight, tempering its blue, |             akin to moonlight, tempering its blue, | ||||||
|             the dingy ${c}underside, the checquered fringe. |             the dingy ${c}underside, the checquered fringe. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = 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) | ||||||
| //    VimPlugin.getRegister().storeText(editor.vim, editor.rangeOf("|found|", 2), SelectionType.BLOCK_WISE, false) |     typeText(injector.parser.parseKeys("ve" + "p")) | ||||||
|     typeText(injector.parser.parseKeys("ve" + "\"*p")) |  | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
| @@ -593,9 +592,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             where it was settled on some sodden sand |             where it was settled on some sodden sand | ||||||
|             hard by the ${c}torrent of a mountain pass. |             hard by the ${c}torrent of a mountain pass. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "Discovery", SelectionType.CHARACTER_WISE) |     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) |     typeText(injector.parser.parseKeys("V" + "p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
| @@ -629,9 +628,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             where it was settled on some sodden sand |             where it was settled on some sodden sand | ||||||
|             hard by the ${c}torrent of a mountain pass. |             hard by the ${c}torrent of a mountain pass. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "Discovery", SelectionType.CHARACTER_WISE) |     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "Discovery", SelectionType.CHARACTER_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) |     typeText(injector.parser.parseKeys("V" + "p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
| @@ -754,9 +753,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             where it was settled on some sodden sand |             where it was settled on some sodden sand | ||||||
|             hard by the ${c}torrent of a mountain pass. |             hard by the ${c}torrent of a mountain pass. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) |     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) |     typeText(injector.parser.parseKeys("V" + "p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
| @@ -790,9 +789,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             where it was settled on some sodden sand |             where it was settled on some sodden sand | ||||||
|             hard by the ${c}torrent of a mountain pass. |             hard by the ${c}torrent of a mountain pass. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "A Discovery\n", SelectionType.LINE_WISE) |     VimPlugin.getRegister().storeText(editor.vim, before rangeOf "A Discovery\n", SelectionType.LINE_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("V" + "\"*p")) |     typeText(injector.parser.parseKeys("V" + "p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
| @@ -996,9 +995,9 @@ class PutVisualTextActionTest : VimTestCase() { | |||||||
|             akin to moonlight, tempering its blue, |             akin to moonlight, tempering its blue, | ||||||
|             the dingy ${c}underside, the checquered fringe. |             the dingy ${c}underside, the checquered fringe. | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = 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("V" + "\"*p")) |     typeText(injector.parser.parseKeys("V" + "p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             A Discovery |             A Discovery | ||||||
|  |  | ||||||
|   | |||||||
| @@ -202,9 +202,9 @@ class PutVisualTextMoveCursorActionTest : VimTestCase() { | |||||||
|             ${c}zxcvbn |             ${c}zxcvbn | ||||||
|  |  | ||||||
|     """.trimIndent() |     """.trimIndent() | ||||||
|     configureByText(before) |     val editor = configureByText(before) | ||||||
|     injector.registerGroup.storeText('*', "zxcvbn\n", SelectionType.LINE_WISE) |     VimPlugin.getRegister().storeText(editor.vim, TextRange(14, 21), SelectionType.LINE_WISE, false) | ||||||
|     typeText(injector.parser.parseKeys("vl" + "\"*gp")) |     typeText(injector.parser.parseKeys("vl" + "gp")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             q |             q | ||||||
|             zxcvbn |             zxcvbn | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ import com.maddyhome.idea.vim.VimPlugin | |||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.SelectionType | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import junit.framework.TestCase | ||||||
| import org.jetbrains.plugins.ideavim.SkipNeovimReason | import org.jetbrains.plugins.ideavim.SkipNeovimReason | ||||||
| import org.jetbrains.plugins.ideavim.TestWithoutNeovim | import org.jetbrains.plugins.ideavim.TestWithoutNeovim | ||||||
| import org.jetbrains.plugins.ideavim.VimTestCase | import org.jetbrains.plugins.ideavim.VimTestCase | ||||||
| @@ -79,48 +79,47 @@ class YankVisualActionTest : VimTestCase() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   fun `test yank multicaret`() { |   fun `test yank multicaret`() { | ||||||
|     val text = """ |     doTest( | ||||||
|  |       injector.parser.parseKeys("viw" + "y"), | ||||||
|  |       """ | ||||||
|                             A Discovery |                             A Discovery | ||||||
|  |  | ||||||
|                             I ${c}found it in a legendary land |                             I ${c}found it in a legendary land | ||||||
|                             all rocks and lavender and tufted grass, |                             all rocks and lavender and tufted grass, | ||||||
|                             where it ${c}was settled on some sodden sand |                             where it ${c}was settled on some sodden sand | ||||||
|                             hard by the torrent of a mountain pass. |                             hard by the torrent of a mountain pass. | ||||||
|     """.trimIndent() |       """.trimIndent(), | ||||||
|     configureByText(text) |       "found\nwas", SelectionType.BLOCK_WISE | ||||||
|     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) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // todo multicaret |   @TestWithoutNeovim(SkipNeovimReason.DIFFERENT) | ||||||
| //  @TestWithoutNeovim(SkipNeovimReason.DIFFERENT) |   fun testYankVisualRange() { | ||||||
| //  fun testYankVisualRange() { |     val before = """ | ||||||
| //    val before = """ |             q${c}werty | ||||||
| //            q${c}werty |             asdf${c}gh | ||||||
| //            asdf${c}gh |             ${c}zxcvbn | ||||||
| //            ${c}zxcvbn |  | ||||||
| // |     """.trimIndent() | ||||||
| //    """.trimIndent() |     configureByText(before) | ||||||
| //    configureByText(before) |     typeText(injector.parser.parseKeys("vey")) | ||||||
| //    typeText(injector.parser.parseKeys("vey")) |  | ||||||
| // |     val lastRegister = VimPlugin.getRegister().lastRegister | ||||||
| //    val lastRegister = VimPlugin.getRegister().lastRegister |     TestCase.assertNotNull(lastRegister) | ||||||
| //    TestCase.assertNotNull(lastRegister) |     val text = lastRegister!!.text | ||||||
| //    val text = lastRegister!!.text |     TestCase.assertNotNull(text) | ||||||
| //    TestCase.assertNotNull(text) |  | ||||||
| // |     typeText(injector.parser.parseKeys("G" + "$" + "p")) | ||||||
| //    typeText(injector.parser.parseKeys("G" + "$" + "p")) |     val after = """ | ||||||
| //    val after = """ |       qwerty | ||||||
| //      qwerty |       asdfgh | ||||||
| //      asdfgh |       zxcvbn | ||||||
| //      zxcvbn |       ${c}werty | ||||||
| //      wert${c}yg${c}hzxcvb${c}n |       gh | ||||||
| //    """.trimIndent() |       zxcvbn | ||||||
| //    assertState(after) |     """.trimIndent() | ||||||
| //  } |     assertState(after) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   fun `test yank line`() { |   fun `test yank line`() { | ||||||
|     doTest( |     doTest( | ||||||
| @@ -153,22 +152,17 @@ class YankVisualActionTest : VimTestCase() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   fun `test yank multicaret line`() { |   fun `test yank multicaret line`() { | ||||||
|     val text = """ |     doTest( | ||||||
|  |       injector.parser.parseKeys("V" + "y"), | ||||||
|  |       """ | ||||||
|                             A Discovery |                             A Discovery | ||||||
|  |  | ||||||
|                             I found it in a legendary land |                             I found it in a legendary land | ||||||
|                             all ${c}rocks and lavender and tufted grass, |                             all ${c}rocks and lavender and tufted grass, | ||||||
|                             where it was settled on some sodden sand |                             where it was settled on some sodden sand | ||||||
|                             hard by ${c}the torrent of a mountain pass. |                             hard by ${c}the torrent of a mountain pass. | ||||||
|     """.trimIndent() |       """.trimIndent(), | ||||||
|     configureByText(text) |       "all rocks and lavender and tufted grass,\nhard by the torrent of a mountain pass.\n", SelectionType.LINE_WISE | ||||||
|     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 |  | ||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -186,15 +180,35 @@ class YankVisualActionTest : VimTestCase() { | |||||||
|     configureByText(before) |     configureByText(before) | ||||||
|     typeText(injector.parser.parseKeys("Vy")) |     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")) |     typeText(injector.parser.parseKeys("p")) | ||||||
|     val after = """ |     val after = """ | ||||||
|             qwe |             qwe | ||||||
|             ${c}qwe |             ${c}qwe | ||||||
|  |             zxc | ||||||
|  |             rty | ||||||
|             asd |             asd | ||||||
|             zxc |             zxc | ||||||
|             ${c}zxc |             ${c}qwe | ||||||
|  |             zxc | ||||||
|  |             rty | ||||||
|  |             rty | ||||||
|  |             ${c}qwe | ||||||
|  |             zxc | ||||||
|             rty |             rty | ||||||
|             ${c}rty |  | ||||||
|             fgh |             fgh | ||||||
|             vbn |             vbn | ||||||
|              |              | ||||||
|   | |||||||
| @@ -221,9 +221,11 @@ class MultipleCaretsTest : VimTestCase() { | |||||||
|     val after = """qwe |     val after = """qwe | ||||||
|       |rty |       |rty | ||||||
|       |${c}rty |       |${c}rty | ||||||
|  |       |fgh | ||||||
|       |asd |       |asd | ||||||
|       |fgh |       |fgh | ||||||
|       |${c}fgh |       |${c}rty | ||||||
|  |       |fgh | ||||||
|       |zxc |       |zxc | ||||||
|       |vbn |       |vbn | ||||||
|     """.trimMargin() |     """.trimMargin() | ||||||
|   | |||||||
| @@ -25,15 +25,15 @@ import com.maddyhome.idea.vim.VimPlugin | |||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.MappingMode |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.extension.Alias | import com.maddyhome.idea.vim.extension.Alias | ||||||
| import com.maddyhome.idea.vim.extension.ExtensionBeanClass | 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.VimExtension | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping | import com.maddyhome.idea.vim.extension.VimExtensionFacade.putExtensionHandlerMapping | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping | import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMapping | ||||||
| import com.maddyhome.idea.vim.extension.VimExtensionFacade.putKeyMappingIfMissing | 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.extension.VimExtensionRegistrar | ||||||
| import com.maddyhome.idea.vim.group.MotionGroup | import com.maddyhome.idea.vim.group.MotionGroup | ||||||
| import com.maddyhome.idea.vim.helper.isEndAllowed | 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.VimPlugin | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.SelectionType |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | import com.maddyhome.idea.vim.helper.VimBehaviorDiffers | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
| import com.maddyhome.idea.vim.register.RegisterConstants.UNNAMED_REGISTER | import com.maddyhome.idea.vim.register.RegisterConstants.UNNAMED_REGISTER | ||||||
| @@ -367,7 +367,9 @@ class ReplaceWithRegisterTest : VimTestCase() { | |||||||
|             I found it in a legendary land |             I found it in a legendary land | ||||||
|             where it was settled on some sodden sand |             where it was settled on some sodden sand | ||||||
|             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() |       """.trimIndent() | ||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -541,32 +541,4 @@ class VimSurroundExtensionTest : VimTestCase() { | |||||||
|     val keys = ":map gw ds)<CR>" + "qqgwqj@q" |     val keys = ":map gw ds)<CR>" + "qqgwqj@q" | ||||||
|     doTest(keys, before, after, VimStateMachine.Mode.COMMAND, VimStateMachine.SubMode.NONE) |     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.openapi.editor.Editor | ||||||
| import com.intellij.testFramework.PlatformTestUtil | import com.intellij.testFramework.PlatformTestUtil | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.key.CommandNode | import com.maddyhome.idea.vim.common.CommandNode | ||||||
| import com.maddyhome.idea.vim.helper.vimStateMachine | import com.maddyhome.idea.vim.helper.vimStateMachine | ||||||
| import com.maddyhome.idea.vim.newapi.ij | import com.maddyhome.idea.vim.newapi.ij | ||||||
| import com.maddyhome.idea.vim.newapi.vim | import com.maddyhome.idea.vim.newapi.vim | ||||||
|   | |||||||
										
											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.VimStateMachine.Companion.getInstance | ||||||
| import com.maddyhome.idea.vim.command.MappingState | import com.maddyhome.idea.vim.command.MappingState | ||||||
| import com.maddyhome.idea.vim.command.OperatorArguments | import com.maddyhome.idea.vim.command.OperatorArguments | ||||||
| import com.maddyhome.idea.vim.key.CommandNode | import com.maddyhome.idea.vim.common.CommandNode | ||||||
| import com.maddyhome.idea.vim.key.CommandPartNode | import com.maddyhome.idea.vim.common.CommandPartNode | ||||||
| import com.maddyhome.idea.vim.common.CurrentCommandState | import com.maddyhome.idea.vim.common.CurrentCommandState | ||||||
| import com.maddyhome.idea.vim.common.DigraphResult | import com.maddyhome.idea.vim.common.DigraphResult | ||||||
| import com.maddyhome.idea.vim.command.MappingMode | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.key.Node | import com.maddyhome.idea.vim.common.Node | ||||||
| import com.maddyhome.idea.vim.common.argumentCaptured | import com.maddyhome.idea.vim.common.argumentCaptured | ||||||
| import com.maddyhome.idea.vim.diagnostic.VimLogger | import com.maddyhome.idea.vim.diagnostic.VimLogger | ||||||
| import com.maddyhome.idea.vim.diagnostic.debug | import com.maddyhome.idea.vim.diagnostic.debug | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ | |||||||
|  */ |  */ | ||||||
| package com.maddyhome.idea.vim.action.change.change | package com.maddyhome.idea.vim.action.change.change | ||||||
|  |  | ||||||
|  | import com.maddyhome.idea.vim.action.copy.YankMotionAction | ||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimCaret | import com.maddyhome.idea.vim.api.VimCaret | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| @@ -34,6 +35,19 @@ class ChangeMotionAction : ChangeEditorActionHandler.ForEachCaret(), DuplicableO | |||||||
|  |  | ||||||
|   override val duplicateWith: Char = 'c' |   override val duplicateWith: Char = 'c' | ||||||
|  |  | ||||||
|  |   private var isMultiCaret = false | ||||||
|  |  | ||||||
|  |   override fun baseExecute( | ||||||
|  |     editor: VimEditor, | ||||||
|  |     caret: VimCaret, | ||||||
|  |     context: ExecutionContext, | ||||||
|  |     cmd: Command, | ||||||
|  |     operatorArguments: OperatorArguments | ||||||
|  |   ): Boolean { | ||||||
|  |     isMultiCaret = YankMotionAction().yankIfMultiCaret(cmd, editor, context, operatorArguments) | ||||||
|  |     return super.baseExecute(editor, caret, context, cmd, operatorArguments) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   override fun execute( |   override fun execute( | ||||||
|     editor: VimEditor, |     editor: VimEditor, | ||||||
|     caret: VimCaret, |     caret: VimCaret, | ||||||
| @@ -46,7 +60,8 @@ class ChangeMotionAction : ChangeEditorActionHandler.ForEachCaret(), DuplicableO | |||||||
|       caret, |       caret, | ||||||
|       context, |       context, | ||||||
|       argument, |       argument, | ||||||
|       operatorArguments |       operatorArguments, | ||||||
|  |       noYank = isMultiCaret | ||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ | |||||||
|  */ |  */ | ||||||
| package com.maddyhome.idea.vim.action.change.change | package com.maddyhome.idea.vim.action.change.change | ||||||
|  |  | ||||||
|  | import com.maddyhome.idea.vim.action.copy.YankVisualAction | ||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimCaret | import com.maddyhome.idea.vim.api.VimCaret | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| @@ -37,6 +38,18 @@ class ChangeVisualAction : VisualOperatorActionHandler.ForEachCaret() { | |||||||
|  |  | ||||||
|   override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_MULTIKEY_UNDO, CommandFlags.FLAG_EXIT_VISUAL) |   override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_MULTIKEY_UNDO, CommandFlags.FLAG_EXIT_VISUAL) | ||||||
|  |  | ||||||
|  |   private var isMultiCaret = false | ||||||
|  |  | ||||||
|  |   override fun beforeExecution( | ||||||
|  |     editor: VimEditor, | ||||||
|  |     context: ExecutionContext, | ||||||
|  |     cmd: Command, | ||||||
|  |     caretsAndSelections: Map<VimCaret, VimSelection> | ||||||
|  |   ): Boolean { | ||||||
|  |     isMultiCaret = YankVisualAction().yankIfMultiCaret(editor, caretsAndSelections) | ||||||
|  |     return super.beforeExecution(editor, context, cmd, caretsAndSelections) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   override fun executeAction( |   override fun executeAction( | ||||||
|     editor: VimEditor, |     editor: VimEditor, | ||||||
|     caret: VimCaret, |     caret: VimCaret, | ||||||
| @@ -50,7 +63,8 @@ class ChangeVisualAction : VisualOperatorActionHandler.ForEachCaret() { | |||||||
|       caret, |       caret, | ||||||
|       range.toVimTextRange(false), |       range.toVimTextRange(false), | ||||||
|       range.type, |       range.type, | ||||||
|       context |       context, | ||||||
|  |       noYank = isMultiCaret | ||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ | |||||||
|  */ |  */ | ||||||
| package com.maddyhome.idea.vim.action.change.delete | package com.maddyhome.idea.vim.action.change.delete | ||||||
|  |  | ||||||
|  | import com.maddyhome.idea.vim.action.copy.YankMotionAction | ||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimCaret | import com.maddyhome.idea.vim.api.VimCaret | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| @@ -36,6 +37,19 @@ class DeleteMotionAction : ChangeEditorActionHandler.ForEachCaret(), DuplicableO | |||||||
|  |  | ||||||
|   override val duplicateWith: Char = 'd' |   override val duplicateWith: Char = 'd' | ||||||
|  |  | ||||||
|  |   private var isMultiCaret = false | ||||||
|  |  | ||||||
|  |   override fun baseExecute( | ||||||
|  |     editor: VimEditor, | ||||||
|  |     caret: VimCaret, | ||||||
|  |     context: ExecutionContext, | ||||||
|  |     cmd: Command, | ||||||
|  |     operatorArguments: OperatorArguments | ||||||
|  |   ): Boolean { | ||||||
|  |     isMultiCaret = YankMotionAction().yankIfMultiCaret(cmd, editor, context, operatorArguments) | ||||||
|  |     return super.baseExecute(editor, caret, context, cmd, operatorArguments) | ||||||
|  |   } | ||||||
|  |    | ||||||
|   override fun execute( |   override fun execute( | ||||||
|     editor: VimEditor, |     editor: VimEditor, | ||||||
|     caret: VimCaret, |     caret: VimCaret, | ||||||
| @@ -53,7 +67,7 @@ class DeleteMotionAction : ChangeEditorActionHandler.ForEachCaret(), DuplicableO | |||||||
|       val (first, second) = injector.changeGroup |       val (first, second) = injector.changeGroup | ||||||
|         .getDeleteRangeAndType(editor, caret, context, argument, false, operatorArguments) |         .getDeleteRangeAndType(editor, caret, context, argument, false, operatorArguments) | ||||||
|         ?: return false |         ?: return false | ||||||
|       return injector.changeGroup.deleteRange(editor, caret, first, second, false) |       return injector.changeGroup.deleteRange(editor, caret, first, second, false, noYank = isMultiCaret) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ | |||||||
|  */ |  */ | ||||||
| package com.maddyhome.idea.vim.action.change.delete | package com.maddyhome.idea.vim.action.change.delete | ||||||
|  |  | ||||||
|  | import com.maddyhome.idea.vim.action.copy.YankVisualAction | ||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimCaret | import com.maddyhome.idea.vim.api.VimCaret | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| @@ -37,6 +38,18 @@ class DeleteVisualAction : VisualOperatorActionHandler.ForEachCaret() { | |||||||
|  |  | ||||||
|   override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_EXIT_VISUAL) |   override val flags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_EXIT_VISUAL) | ||||||
|  |  | ||||||
|  |   private var isMultiCaret = false | ||||||
|  |  | ||||||
|  |   override fun beforeExecution( | ||||||
|  |     editor: VimEditor, | ||||||
|  |     context: ExecutionContext, | ||||||
|  |     cmd: Command, | ||||||
|  |     caretsAndSelections: Map<VimCaret, VimSelection>, | ||||||
|  |   ): Boolean { | ||||||
|  |     isMultiCaret = YankVisualAction().yankIfMultiCaret(editor, caretsAndSelections) | ||||||
|  |     return super.beforeExecution(editor, context, cmd, caretsAndSelections) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   override fun executeAction( |   override fun executeAction( | ||||||
|     editor: VimEditor, |     editor: VimEditor, | ||||||
|     caret: VimCaret, |     caret: VimCaret, | ||||||
| @@ -45,7 +58,13 @@ class DeleteVisualAction : VisualOperatorActionHandler.ForEachCaret() { | |||||||
|     range: VimSelection, |     range: VimSelection, | ||||||
|     operatorArguments: OperatorArguments, |     operatorArguments: OperatorArguments, | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|     val selectionType = range.type |     return injector.changeGroup.deleteRange( | ||||||
|     return injector.changeGroup.deleteRange(editor, caret, range.toVimTextRange(false), selectionType, false) |       editor, | ||||||
|  |       caret, | ||||||
|  |       range.toVimTextRange(false), | ||||||
|  |       range.type, | ||||||
|  |       false, | ||||||
|  |       noYank = isMultiCaret | ||||||
|  |     ) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,7 +18,6 @@ | |||||||
| package com.maddyhome.idea.vim.action.copy | package com.maddyhome.idea.vim.action.copy | ||||||
|  |  | ||||||
| import com.maddyhome.idea.vim.api.ExecutionContext | import com.maddyhome.idea.vim.api.ExecutionContext | ||||||
| import com.maddyhome.idea.vim.api.VimCaret |  | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.command.Argument | import com.maddyhome.idea.vim.command.Argument | ||||||
| @@ -41,28 +40,14 @@ sealed class PutTextBaseAction( | |||||||
|     argument: Argument?, |     argument: Argument?, | ||||||
|     operatorArguments: OperatorArguments |     operatorArguments: OperatorArguments | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|     val count = operatorArguments.count1 |     val lastRegister = injector.registerGroup.lastRegister | ||||||
|     val caretToPutData = editor.sortedCarets().associateWith { getPutDataForCaret(it, count) } |     val textData = if (lastRegister != null) TextData( | ||||||
|     var result = true |       lastRegister.text ?: injector.parser.toPrintableString(lastRegister.keys), | ||||||
|     injector.application.runWriteAction { |       lastRegister.type, | ||||||
|       caretToPutData.forEach { |       lastRegister.transferableData | ||||||
|         result = injector.put.putTextForCaret(editor, it.key, context, it.value) && result |     ) else null | ||||||
|       } |     val putData = PutData(textData, null, operatorArguments.count1, insertTextBeforeCaret, indent, caretAfterInsertedText, -1) | ||||||
|     } |     return injector.put.putText(editor, context, putData) | ||||||
|     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,30 +52,16 @@ sealed class PutVisualTextBaseAction( | |||||||
|     operatorArguments: OperatorArguments, |     operatorArguments: OperatorArguments, | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|     if (caretsAndSelections.isEmpty()) return false |     if (caretsAndSelections.isEmpty()) return false | ||||||
|     val count = cmd.count |     val textData = injector.registerGroup.lastRegister?.let { PutData.TextData(it.text, it.type, it.transferableData) } | ||||||
|     val caretToPutData = editor.sortedCarets().associateWith { getPutDataForCaret(it, caretsAndSelections[it], count) } |  | ||||||
|     injector.registerGroup.resetRegister() |     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 |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private fun getPutDataForCaret(caret: VimCaret, selection: VimSelection?, count: Int): PutData { |     val selection = PutData.VisualSelection( | ||||||
|     val lastRegisterChar = injector.registerGroup.lastRegisterChar |       caretsAndSelections, | ||||||
|     val register = caret.registerStorage.getRegister(lastRegisterChar) |       caretsAndSelections.values.first().type | ||||||
|     val textData = register?.let { |     ) | ||||||
|       PutData.TextData( |     val putData = PutData(textData, selection, cmd.count, insertTextBeforeCaret, indent, caretAfterInsertedText) | ||||||
|         register.text ?: injector.parser.toPrintableString(register.keys), |  | ||||||
|         register.type, |     return injector.put.putText(editor, context, putData, true) | ||||||
|         register.transferableData |  | ||||||
|       ) |  | ||||||
|     } |  | ||||||
|     val visualSelection = selection?.let { PutData.VisualSelection(mapOf(caret to it), it.type) } |  | ||||||
|     return PutData(textData, visualSelection, count, insertTextBeforeCaret, indent, caretAfterInsertedText) |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -38,8 +38,27 @@ class YankMotionAction : VimActionHandler.SingleExecution(), DuplicableOperatorA | |||||||
|     context: ExecutionContext, |     context: ExecutionContext, | ||||||
|     cmd: Command, |     cmd: Command, | ||||||
|     operatorArguments: OperatorArguments, |     operatorArguments: OperatorArguments, | ||||||
|  |   ): Boolean { | ||||||
|  |     return executeYank(cmd, editor, context, operatorArguments) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private fun executeYank( | ||||||
|  |     cmd: Command, | ||||||
|  |     editor: VimEditor, | ||||||
|  |     context: ExecutionContext, | ||||||
|  |     operatorArguments: OperatorArguments, | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|     val argument = cmd.argument ?: return false |     val argument = cmd.argument ?: return false | ||||||
|     return injector.yank.yankMotion(editor, context, argument, operatorArguments) |     return injector.yank.yankMotion(editor, context, argument, operatorArguments) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   fun yankIfMultiCaret(cmd: Command, editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): Boolean { | ||||||
|  |     if (editor.nativeCarets().size > 1) { | ||||||
|  |       executeYank(cmd, editor, context, operatorArguments) | ||||||
|  |       return true | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       return false | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -44,6 +44,13 @@ class YankVisualAction : VisualOperatorActionHandler.SingleExecution() { | |||||||
|     cmd: Command, |     cmd: Command, | ||||||
|     caretsAndSelections: Map<VimCaret, VimSelection>, |     caretsAndSelections: Map<VimCaret, VimSelection>, | ||||||
|     operatorArguments: OperatorArguments, |     operatorArguments: OperatorArguments, | ||||||
|  |   ): Boolean { | ||||||
|  |     return executeYank(editor, caretsAndSelections) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private fun executeYank( | ||||||
|  |     editor: VimEditor, | ||||||
|  |     caretsAndSelections: Map<VimCaret, VimSelection>, | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|     val selections = caretsAndSelections.values |     val selections = caretsAndSelections.values | ||||||
|     val starts: MutableList<Int> = ArrayList() |     val starts: MutableList<Int> = ArrayList() | ||||||
| @@ -58,4 +65,14 @@ class YankVisualAction : VisualOperatorActionHandler.SingleExecution() { | |||||||
|     val endsArray = ends.toIntArray() |     val endsArray = ends.toIntArray() | ||||||
|     return injector.yank.yankRange(editor, TextRange(startsArray, endsArray), vimSelection.type, true) |     return injector.yank.yankRange(editor, TextRange(startsArray, endsArray), vimSelection.type, true) | ||||||
|   } |   } | ||||||
|  |    | ||||||
|  |   fun yankIfMultiCaret(editor: VimEditor, caretsAndSelections: Map<VimCaret, VimSelection>): Boolean { | ||||||
|  |     if (caretsAndSelections.size > 1) { | ||||||
|  |       executeYank(editor, caretsAndSelections) | ||||||
|  |       return true | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       return false | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,17 +1,12 @@ | |||||||
| package com.maddyhome.idea.vim.api | 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.EditorLine | ||||||
| import com.maddyhome.idea.vim.common.LiveRange | import com.maddyhome.idea.vim.common.LiveRange | ||||||
| import com.maddyhome.idea.vim.common.Offset | 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.group.visual.VisualChange | ||||||
| import com.maddyhome.idea.vim.register.Register |  | ||||||
| import javax.swing.KeyStroke |  | ||||||
|  |  | ||||||
| // TODO: 29.12.2021 Split interface to mutable and immutable | // TODO: 29.12.2021 Split interface to mutable and immutable | ||||||
| interface VimCaret { | interface VimCaret { | ||||||
|   val registerStorage: CaretRegisterStorage |  | ||||||
|   val editor: VimEditor |   val editor: VimEditor | ||||||
|   val offset: Offset |   val offset: Offset | ||||||
|   var vimLastColumn: Int |   var vimLastColumn: Int | ||||||
| @@ -40,20 +35,4 @@ interface VimCaret { | |||||||
|   fun moveToVisualPosition(position: VimVisualPosition) |   fun moveToVisualPosition(position: VimVisualPosition) | ||||||
|   fun setNativeSelection(start: Offset, end: Offset) |   fun setNativeSelection(start: Offset, end: Offset) | ||||||
|   fun removeNativeSelection() |   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) |  | ||||||
| } | } | ||||||
| @@ -1,56 +0,0 @@ | |||||||
| 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,14 +83,14 @@ interface VimChangeGroup { | |||||||
|  |  | ||||||
|   fun getDeleteRangeAndType2(editor: VimEditor, caret: VimCaret, context: ExecutionContext, argument: Argument, isChange: Boolean, operatorArguments: OperatorArguments): Pair<TextRange, SelectionType>? |   fun getDeleteRangeAndType2(editor: VimEditor, caret: VimCaret, context: ExecutionContext, argument: Argument, isChange: Boolean, operatorArguments: OperatorArguments): Pair<TextRange, SelectionType>? | ||||||
|  |  | ||||||
|   fun deleteRange(editor: VimEditor, caret: VimCaret, range: TextRange, type: SelectionType?, isChange: Boolean): Boolean |   fun deleteRange(editor: VimEditor, caret: VimCaret, range: TextRange, type: SelectionType?, isChange: Boolean, noYank: Boolean = false): Boolean | ||||||
|   fun deleteRange2(editor: VimEditor, caret: VimCaret, range: TextRange, type: SelectionType): Boolean |   fun deleteRange2(editor: VimEditor, caret: VimCaret, range: TextRange, type: SelectionType): Boolean | ||||||
|  |  | ||||||
|   fun changeCharacters(editor: VimEditor, caret: VimCaret, count: Int): Boolean |   fun changeCharacters(editor: VimEditor, caret: VimCaret, count: Int): Boolean | ||||||
|  |  | ||||||
|   fun changeEndOfLine(editor: VimEditor, caret: VimCaret, count: Int): Boolean |   fun changeEndOfLine(editor: VimEditor, caret: VimCaret, count: Int): Boolean | ||||||
|  |  | ||||||
|   fun changeMotion(editor: VimEditor, caret: VimCaret, context: ExecutionContext, argument: Argument, operatorArguments: OperatorArguments): Boolean |   fun changeMotion(editor: VimEditor, caret: VimCaret, context: ExecutionContext, argument: Argument, operatorArguments: OperatorArguments, noYank: Boolean = false): Boolean | ||||||
|  |  | ||||||
|   fun changeCaseToggleCharacter(editor: VimEditor, caret: VimCaret, count: Int): Boolean |   fun changeCaseToggleCharacter(editor: VimEditor, caret: VimCaret, count: Int): Boolean | ||||||
|  |  | ||||||
| @@ -98,7 +98,7 @@ interface VimChangeGroup { | |||||||
|  |  | ||||||
|   fun changeCaseRange(editor: VimEditor, caret: VimCaret, range: TextRange, type: Char): Boolean |   fun changeCaseRange(editor: VimEditor, caret: VimCaret, range: TextRange, type: Char): Boolean | ||||||
|  |  | ||||||
|   fun changeRange(editor: VimEditor, caret: VimCaret, range: TextRange, type: SelectionType, context: ExecutionContext?): Boolean |   fun changeRange(editor: VimEditor, caret: VimCaret, range: TextRange, type: SelectionType, context: ExecutionContext?, noYank: Boolean = false): Boolean | ||||||
|  |  | ||||||
|   fun changeCaseMotion(editor: VimEditor, caret: VimCaret, context: ExecutionContext?, type: Char, argument: Argument, operatorArguments: OperatorArguments): Boolean |   fun changeCaseMotion(editor: VimEditor, caret: VimCaret, context: ExecutionContext?, type: Char, argument: Argument, operatorArguments: OperatorArguments): Boolean | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,10 +4,10 @@ import com.maddyhome.idea.vim.KeyHandler | |||||||
| import com.maddyhome.idea.vim.command.Argument | import com.maddyhome.idea.vim.command.Argument | ||||||
| import com.maddyhome.idea.vim.command.Command | import com.maddyhome.idea.vim.command.Command | ||||||
| import com.maddyhome.idea.vim.command.CommandFlags | import com.maddyhome.idea.vim.command.CommandFlags | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine |  | ||||||
| import com.maddyhome.idea.vim.command.VimStateMachine.Companion.getInstance |  | ||||||
| import com.maddyhome.idea.vim.command.OperatorArguments | import com.maddyhome.idea.vim.command.OperatorArguments | ||||||
| import com.maddyhome.idea.vim.command.SelectionType | import com.maddyhome.idea.vim.command.SelectionType | ||||||
|  | import com.maddyhome.idea.vim.command.VimStateMachine | ||||||
|  | import com.maddyhome.idea.vim.command.VimStateMachine.Companion.getInstance | ||||||
| import com.maddyhome.idea.vim.common.ChangesListener | import com.maddyhome.idea.vim.common.ChangesListener | ||||||
| import com.maddyhome.idea.vim.common.Offset | import com.maddyhome.idea.vim.common.Offset | ||||||
| import com.maddyhome.idea.vim.common.OperatedRange | import com.maddyhome.idea.vim.common.OperatedRange | ||||||
| @@ -17,10 +17,10 @@ import com.maddyhome.idea.vim.diagnostic.debug | |||||||
| import com.maddyhome.idea.vim.diagnostic.vimLogger | import com.maddyhome.idea.vim.diagnostic.vimLogger | ||||||
| import com.maddyhome.idea.vim.group.visual.VimSelection | import com.maddyhome.idea.vim.group.visual.VimSelection | ||||||
| import com.maddyhome.idea.vim.handler.EditorActionHandlerBase | import com.maddyhome.idea.vim.handler.EditorActionHandlerBase | ||||||
| import com.maddyhome.idea.vim.helper.vimStateMachine |  | ||||||
| import com.maddyhome.idea.vim.helper.inInsertMode | import com.maddyhome.idea.vim.helper.inInsertMode | ||||||
| import com.maddyhome.idea.vim.helper.inSingleCommandMode | import com.maddyhome.idea.vim.helper.inSingleCommandMode | ||||||
| import com.maddyhome.idea.vim.helper.usesVirtualSpace | import com.maddyhome.idea.vim.helper.usesVirtualSpace | ||||||
|  | import com.maddyhome.idea.vim.helper.vimStateMachine | ||||||
| import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor | ||||||
| import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_END | import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_END | ||||||
| import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_POS | import com.maddyhome.idea.vim.mark.VimMarkConstants.MARK_CHANGE_POS | ||||||
| @@ -83,7 +83,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | |||||||
|   override fun deleteCharacter(editor: VimEditor, caret: VimCaret, count: Int, isChange: Boolean): Boolean { |   override fun deleteCharacter(editor: VimEditor, caret: VimCaret, count: Int, isChange: Boolean): Boolean { | ||||||
|     val endOffset = injector.motion.getOffsetOfHorizontalMotion(editor, caret, count, true) |     val endOffset = injector.motion.getOffsetOfHorizontalMotion(editor, caret, count, true) | ||||||
|     if (endOffset != -1) { |     if (endOffset != -1) { | ||||||
|       val res = deleteText(editor, TextRange(caret.offset.point, endOffset), SelectionType.CHARACTER_WISE, caret) |       val res = deleteText(editor, TextRange(caret.offset.point, endOffset), SelectionType.CHARACTER_WISE) | ||||||
|       val pos = caret.offset.point |       val pos = caret.offset.point | ||||||
|       val norm = injector.engineEditorHelper.normalizeOffset(editor, caret.getLogicalPosition().line, pos, isChange) |       val norm = injector.engineEditorHelper.normalizeOffset(editor, caret.getLogicalPosition().line, pos, isChange) | ||||||
|       if (norm != pos || |       if (norm != pos || | ||||||
| @@ -132,7 +132,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | |||||||
|     editor: VimEditor, |     editor: VimEditor, | ||||||
|     range: TextRange, |     range: TextRange, | ||||||
|     type: SelectionType?, |     type: SelectionType?, | ||||||
|     caret: VimCaret, |     noYank: Boolean = false | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|     var updatedRange = range |     var updatedRange = range | ||||||
|     // Fix for https://youtrack.jetbrains.net/issue/VIM-35 |     // Fix for https://youtrack.jetbrains.net/issue/VIM-35 | ||||||
| @@ -146,7 +146,8 @@ abstract class VimChangeGroupBase : VimChangeGroup { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     if (type == null || |     if (type == null || | ||||||
|       editor.inInsertMode || caret.registerStorage.storeText(editor, updatedRange, type, true) |       noYank || | ||||||
|  |       editor.inInsertMode || injector.registerGroup.storeText(editor, updatedRange, type, true) | ||||||
|     ) { |     ) { | ||||||
|       val startOffsets = updatedRange.startOffsets |       val startOffsets = updatedRange.startOffsets | ||||||
|       val endOffsets = updatedRange.endOffsets |       val endOffsets = updatedRange.endOffsets | ||||||
| @@ -155,10 +156,8 @@ abstract class VimChangeGroupBase : VimChangeGroup { | |||||||
|       } |       } | ||||||
|       if (type != null) { |       if (type != null) { | ||||||
|         val start = updatedRange.startOffset |         val start = updatedRange.startOffset | ||||||
|         if (editor.primaryCaret() == caret) { |         injector.markGroup.setMark(editor, MARK_CHANGE_POS, start) | ||||||
|           injector.markGroup.setMark(editor, MARK_CHANGE_POS, start) |         injector.markGroup.setChangeMarks(editor, TextRange(start, start + 1)) | ||||||
|           injector.markGroup.setChangeMarks(editor, TextRange(start, start + 1)) |  | ||||||
|         } |  | ||||||
|       } |       } | ||||||
|       return true |       return true | ||||||
|     } |     } | ||||||
| @@ -634,7 +633,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | |||||||
|       val rangeToDelete = TextRange(startOffset, offset) |       val rangeToDelete = TextRange(startOffset, offset) | ||||||
|       editor.nativeCarets().filter { it != caret && rangeToDelete.contains(it.offset.point) } |       editor.nativeCarets().filter { it != caret && rangeToDelete.contains(it.offset.point) } | ||||||
|         .forEach { editor.removeCaret(it) } |         .forEach { editor.removeCaret(it) } | ||||||
|       val res = deleteText(editor, rangeToDelete, SelectionType.CHARACTER_WISE, caret) |       val res = deleteText(editor, rangeToDelete, SelectionType.CHARACTER_WISE) | ||||||
|       if (usesVirtualSpace) { |       if (usesVirtualSpace) { | ||||||
|         injector.motion.moveCaret(editor, caret, startOffset) |         injector.motion.moveCaret(editor, caret, startOffset) | ||||||
|       } else { |       } else { | ||||||
| @@ -729,7 +728,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | |||||||
|       logger.debug("offset=$offset") |       logger.debug("offset=$offset") | ||||||
|     } |     } | ||||||
|     if (offset != -1) { |     if (offset != -1) { | ||||||
|       val res = deleteText(editor, TextRange(start, offset), SelectionType.LINE_WISE, caret) |       val res = deleteText(editor, TextRange(start, offset), SelectionType.LINE_WISE) | ||||||
|       if (res && caret.offset.point >= editor.fileSize() && caret.offset.point != 0) { |       if (res && caret.offset.point >= editor.fileSize() && caret.offset.point != 0) { | ||||||
|         injector.motion.moveCaret( |         injector.motion.moveCaret( | ||||||
|           editor, caret, injector.motion.moveCaretToLineStartSkipLeadingOffset( |           editor, caret, injector.motion.moveCaretToLineStartSkipLeadingOffset( | ||||||
| @@ -854,12 +853,13 @@ abstract class VimChangeGroupBase : VimChangeGroup { | |||||||
|     range: TextRange, |     range: TextRange, | ||||||
|     type: SelectionType?, |     type: SelectionType?, | ||||||
|     isChange: Boolean, |     isChange: Boolean, | ||||||
|  |     noYank: Boolean | ||||||
|   ): Boolean { |   ): Boolean { | ||||||
|  |  | ||||||
|     // Update the last column before we delete, or we might be retrieving the data for a line that no longer exists |     // 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 |     caret.vimLastColumn = caret.inlayAwareVisualColumn | ||||||
|     val removeLastNewLine = removeLastNewLine(editor, range, type) |     val removeLastNewLine = removeLastNewLine(editor, range, type) | ||||||
|     val res = deleteText(editor, range, type, caret) |     val res = deleteText(editor, range, type) | ||||||
|     if (removeLastNewLine) { |     if (removeLastNewLine) { | ||||||
|       val textLength = editor.fileSize().toInt() |       val textLength = editor.fileSize().toInt() | ||||||
|       editor.deleteString(TextRange(textLength - 1, textLength)) |       editor.deleteString(TextRange(textLength - 1, textLength)) | ||||||
| @@ -978,7 +978,7 @@ abstract class VimChangeGroupBase : VimChangeGroup { | |||||||
|       } else { |       } else { | ||||||
|         injector.motion.moveCaretToLineStart(editor, caret.getLogicalPosition().line + 1) |         injector.motion.moveCaretToLineStart(editor, caret.getLogicalPosition().line + 1) | ||||||
|       } |       } | ||||||
|       deleteText(editor, TextRange(caret.offset.point, offset), null, caret) |       deleteText(editor, TextRange(caret.offset.point, offset), null) | ||||||
|       if (spaces && !hasTrailingWhitespace) { |       if (spaces && !hasTrailingWhitespace) { | ||||||
|         insertText(editor, caret, " ") |         insertText(editor, caret, " ") | ||||||
|         injector.motion.moveCaret( |         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.history.VimHistory | ||||||
| import com.maddyhome.idea.vim.macro.VimMacro | import com.maddyhome.idea.vim.macro.VimMacro | ||||||
| import com.maddyhome.idea.vim.mark.VimMarkGroup | import com.maddyhome.idea.vim.mark.VimMarkGroup | ||||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService | import com.maddyhome.idea.vim.options.OptionService | ||||||
| import com.maddyhome.idea.vim.put.VimPut | import com.maddyhome.idea.vim.put.VimPut | ||||||
| import com.maddyhome.idea.vim.register.VimRegisterGroup | import com.maddyhome.idea.vim.register.VimRegisterGroup | ||||||
| import com.maddyhome.idea.vim.undo.VimUndoRedo | import com.maddyhome.idea.vim.undo.VimUndoRedo | ||||||
| import com.maddyhome.idea.vim.vimscript.services.VariableService | import com.maddyhome.idea.vim.vimscript.services.VimVariableService | ||||||
| import com.maddyhome.idea.vim.yank.VimYankGroup | import com.maddyhome.idea.vim.yank.VimYankGroup | ||||||
|  |  | ||||||
| interface VimInjector { | interface VimInjector { | ||||||
| @@ -117,7 +117,7 @@ interface VimInjector { | |||||||
|   // Can't be fully moved to vim-engine. |   // Can't be fully moved to vim-engine. | ||||||
|   val vimscriptParser: VimscriptParser |   val vimscriptParser: VimscriptParser | ||||||
|   // !! in progress |   // !! in progress | ||||||
|   val variableService: VariableService |   val variableService: VimVariableService | ||||||
|   // !! in progress |   // !! in progress | ||||||
|   val functionService: VimscriptFunctionService |   val functionService: VimscriptFunctionService | ||||||
|   // Can't be fully moved to vim-engine. |   // 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.VimMachine | ||||||
| import com.maddyhome.idea.vim.common.VimMachineBase | import com.maddyhome.idea.vim.common.VimMachineBase | ||||||
| import com.maddyhome.idea.vim.diagnostic.vimLogger | import com.maddyhome.idea.vim.diagnostic.vimLogger | ||||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService | import com.maddyhome.idea.vim.options.OptionService | ||||||
| import com.maddyhome.idea.vim.register.VimRegisterGroup | import com.maddyhome.idea.vim.register.VimRegisterGroup | ||||||
| import com.maddyhome.idea.vim.register.VimRegisterGroupBase | import com.maddyhome.idea.vim.register.VimRegisterGroupBase | ||||||
| import com.maddyhome.idea.vim.vimscript.services.VariableService | import com.maddyhome.idea.vim.vimscript.services.VimVariableService | ||||||
| import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceBase | import com.maddyhome.idea.vim.vimscript.services.VimVariableServiceBase | ||||||
|  |  | ||||||
| abstract class VimInjectorBase : VimInjector { | abstract class VimInjectorBase : VimInjector { | ||||||
| @@ -23,7 +23,7 @@ abstract class VimInjectorBase : VimInjector { | |||||||
|   override val parser: VimStringParser = object : VimStringParserBase() {} |   override val parser: VimStringParser = object : VimStringParserBase() {} | ||||||
|   override val vimMachine: VimMachine = object : VimMachineBase() {} |   override val vimMachine: VimMachine = object : VimMachineBase() {} | ||||||
|   override val optionService: OptionService by lazy { object : VimOptionServiceBase(){} } |   override val optionService: OptionService by lazy { object : VimOptionServiceBase(){} } | ||||||
|   override val variableService: VariableService by lazy { object : VimVariableServiceBase(){} } |   override val variableService: VimVariableService by lazy { object : VimVariableServiceBase(){} } | ||||||
|  |  | ||||||
|   override val registerGroup: VimRegisterGroup by lazy { registerGroupStub } |   override val registerGroup: VimRegisterGroup by lazy { registerGroupStub } | ||||||
|   override val registerGroupIfCreated: VimRegisterGroup? by lazy { registerGroupStub } |   override val registerGroupIfCreated: VimRegisterGroup? by lazy { registerGroupStub } | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ | |||||||
|  */ |  */ | ||||||
| package com.maddyhome.idea.vim.api | package com.maddyhome.idea.vim.api | ||||||
|  |  | ||||||
| import com.maddyhome.idea.vim.key.CommandPartNode | import com.maddyhome.idea.vim.common.CommandPartNode | ||||||
| import com.maddyhome.idea.vim.command.MappingMode | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||||
| import com.maddyhome.idea.vim.key.KeyMapping | import com.maddyhome.idea.vim.key.KeyMapping | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| package com.maddyhome.idea.vim.api | package com.maddyhome.idea.vim.api | ||||||
|  |  | ||||||
| import com.maddyhome.idea.vim.key.CommandPartNode | import com.maddyhome.idea.vim.common.CommandPartNode | ||||||
| import com.maddyhome.idea.vim.command.MappingMode | import com.maddyhome.idea.vim.command.MappingMode | ||||||
| import com.maddyhome.idea.vim.key.RootNode | import com.maddyhome.idea.vim.common.RootNode | ||||||
| import com.maddyhome.idea.vim.extension.ExtensionHandler | import com.maddyhome.idea.vim.extension.ExtensionHandler | ||||||
| import com.maddyhome.idea.vim.handler.EditorActionHandlerBase | import com.maddyhome.idea.vim.handler.EditorActionHandlerBase | ||||||
| import com.maddyhome.idea.vim.key.KeyMapping | import com.maddyhome.idea.vim.key.KeyMapping | ||||||
|   | |||||||
| @@ -3,11 +3,12 @@ package com.maddyhome.idea.vim.api | |||||||
| import com.maddyhome.idea.vim.diagnostic.vimLogger | import com.maddyhome.idea.vim.diagnostic.vimLogger | ||||||
| import com.maddyhome.idea.vim.ex.ExException | import com.maddyhome.idea.vim.ex.ExException | ||||||
| import com.maddyhome.idea.vim.option.ToggleOption | import com.maddyhome.idea.vim.option.ToggleOption | ||||||
| import com.maddyhome.idea.vim.option.NumberOption | import com.maddyhome.idea.vim.options.NumberOption | ||||||
| import com.maddyhome.idea.vim.options.Option | import com.maddyhome.idea.vim.options.Option | ||||||
| import com.maddyhome.idea.vim.options.OptionChangeListener | import com.maddyhome.idea.vim.options.OptionChangeListener | ||||||
| import com.maddyhome.idea.vim.options.OptionConstants | import com.maddyhome.idea.vim.options.OptionConstants | ||||||
| import com.maddyhome.idea.vim.options.OptionScope | 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.StringOption | ||||||
| import com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper | import com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper | ||||||
| import com.maddyhome.idea.vim.options.helpers.KeywordOptionHelper | import com.maddyhome.idea.vim.options.helpers.KeywordOptionHelper | ||||||
| @@ -15,7 +16,6 @@ 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.VimInt | ||||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString | import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString | ||||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber | import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber | ||||||
| import com.maddyhome.idea.vim.vimscript.services.OptionService |  | ||||||
|  |  | ||||||
| abstract class VimOptionServiceBase : OptionService { | abstract class VimOptionServiceBase : OptionService { | ||||||
|   private val localOptionsKey = Key<MutableMap<String, VimDataType>>("localOptions") |   private val localOptionsKey = Key<MutableMap<String, VimDataType>>("localOptions") | ||||||
| @@ -253,14 +253,6 @@ abstract class VimOptionServiceBase : OptionService { | |||||||
|     setOptionValue(scope, optionName, VimInt.ONE, token) |     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) |    * Unsets the option (false) | ||||||
|    */ |    */ | ||||||
|   | |||||||
| @@ -19,10 +19,10 @@ | |||||||
| package com.maddyhome.idea.vim.command | package com.maddyhome.idea.vim.command | ||||||
|  |  | ||||||
| import com.maddyhome.idea.vim.api.VimActionsInitiator | import com.maddyhome.idea.vim.api.VimActionsInitiator | ||||||
| import com.maddyhome.idea.vim.key.CommandPartNode | import com.maddyhome.idea.vim.common.CommandPartNode | ||||||
| import com.maddyhome.idea.vim.common.CurrentCommandState | import com.maddyhome.idea.vim.common.CurrentCommandState | ||||||
| import com.maddyhome.idea.vim.key.Node | import com.maddyhome.idea.vim.common.Node | ||||||
| import com.maddyhome.idea.vim.key.RootNode | import com.maddyhome.idea.vim.common.RootNode | ||||||
| import com.maddyhome.idea.vim.diagnostic.debug | import com.maddyhome.idea.vim.diagnostic.debug | ||||||
| import com.maddyhome.idea.vim.diagnostic.vimLogger | import com.maddyhome.idea.vim.diagnostic.vimLogger | ||||||
| import com.maddyhome.idea.vim.handler.EditorActionHandlerBase | import com.maddyhome.idea.vim.handler.EditorActionHandlerBase | ||||||
|   | |||||||
| @@ -25,58 +25,54 @@ import java.util.* | |||||||
|  * COMPATIBILITY-LAYER: Do not move this class to a different package |  * COMPATIBILITY-LAYER: Do not move this class to a different package | ||||||
|  */ |  */ | ||||||
| enum class MappingMode { | enum class MappingMode { | ||||||
|   /** |     /** | ||||||
|    * Indicates this key mapping applies to Normal mode |      * Indicates this key mapping applies to Normal mode | ||||||
|    */ |      */ | ||||||
|   NORMAL, |     NORMAL, | ||||||
|  |  | ||||||
|   /** |     /** | ||||||
|    * Indicates this key mapping applies to Visual mode |      * Indicates this key mapping applies to Visual mode | ||||||
|    */ |      */ | ||||||
|   VISUAL, |     VISUAL, | ||||||
|  |  | ||||||
|   /** |     /** | ||||||
|    * Indicates this key mapping applies to Select mode |      * Indicates this key mapping applies to Select mode | ||||||
|    */ |      */ | ||||||
|   SELECT, |     SELECT, | ||||||
|  |  | ||||||
|   /** |     /** | ||||||
|    * Indicates this key mapping applies to Operator Pending mode |      * Indicates this key mapping applies to Operator Pending mode | ||||||
|    */ |      */ | ||||||
|   OP_PENDING, |     OP_PENDING, | ||||||
|  |  | ||||||
|   /** |     /** | ||||||
|    * Indicates this key mapping applies to Insert mode |      * Indicates this key mapping applies to Insert mode | ||||||
|    */ |      */ | ||||||
|   INSERT, |     INSERT, | ||||||
|  |  | ||||||
|   /** |     /** | ||||||
|    * Indicates this key mapping applies to Command Line mode |      * Indicates this key mapping applies to Command Line mode | ||||||
|    */ |      */ | ||||||
|   CMD_LINE; |     CMD_LINE; | ||||||
|  |  | ||||||
|   companion object { |     companion object { | ||||||
|     @JvmField |         @JvmField | ||||||
|     val N: EnumSet<MappingMode> = EnumSet.of(NORMAL) |         val N: EnumSet<MappingMode> = EnumSet.of(NORMAL) | ||||||
|     val X: EnumSet<MappingMode> = EnumSet.of(VISUAL) |         val X: EnumSet<MappingMode> = EnumSet.of(VISUAL) | ||||||
|     val O: EnumSet<MappingMode> = EnumSet.of(OP_PENDING) |         val O: EnumSet<MappingMode> = EnumSet.of(OP_PENDING) | ||||||
|     val I: EnumSet<MappingMode> = EnumSet.of(INSERT) |         val I: EnumSet<MappingMode> = EnumSet.of(INSERT) | ||||||
|     val C: EnumSet<MappingMode> = EnumSet.of(CMD_LINE) |         val C: EnumSet<MappingMode> = EnumSet.of(CMD_LINE) | ||||||
|     val S: EnumSet<MappingMode> = EnumSet.of(SELECT) |         val S: EnumSet<MappingMode> = EnumSet.of(SELECT) | ||||||
|     val V: EnumSet<MappingMode> = EnumSet.of(VISUAL, SELECT) |         val V: EnumSet<MappingMode> = EnumSet.of(VISUAL, SELECT) | ||||||
|     val NO: EnumSet<MappingMode> = EnumSet.of(NORMAL, OP_PENDING) |         val NO: EnumSet<MappingMode> = EnumSet.of(NORMAL, OP_PENDING) | ||||||
|  |         @JvmField | ||||||
|     @JvmField |         val XO: EnumSet<MappingMode> = EnumSet.of(VISUAL, OP_PENDING) | ||||||
|     val XO: EnumSet<MappingMode> = EnumSet.of(VISUAL, OP_PENDING) |         val NX: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL) | ||||||
|     val NX: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL) |         val IC: EnumSet<MappingMode> = EnumSet.of(INSERT, CMD_LINE) | ||||||
|     val IC: EnumSet<MappingMode> = EnumSet.of(INSERT, CMD_LINE) |         val NV: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, SELECT) | ||||||
|     val NV: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, SELECT) |         val NXO: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, OP_PENDING) | ||||||
|  |         @JvmField | ||||||
|     @JvmField |         val NVO: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, OP_PENDING, SELECT) | ||||||
|     val NXO: EnumSet<MappingMode> = EnumSet.of(NORMAL, VISUAL, OP_PENDING) |         val ALL: EnumSet<MappingMode> = EnumSet.allOf(MappingMode::class.java) | ||||||
|  |     } | ||||||
|     @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.VimActionsInitiator | ||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.api.injector | import com.maddyhome.idea.vim.api.injector | ||||||
| import com.maddyhome.idea.vim.key.CommandPartNode | import com.maddyhome.idea.vim.common.CommandPartNode | ||||||
| import com.maddyhome.idea.vim.common.DigraphResult | import com.maddyhome.idea.vim.common.DigraphResult | ||||||
| import com.maddyhome.idea.vim.common.DigraphSequence | import com.maddyhome.idea.vim.common.DigraphSequence | ||||||
| import com.maddyhome.idea.vim.diagnostic.debug | import com.maddyhome.idea.vim.diagnostic.debug | ||||||
|   | |||||||
| @@ -16,14 +16,10 @@ | |||||||
|  * along with this program. If not, see <https://www.gnu.org/licenses/>. |  * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package com.maddyhome.idea.vim.key | package com.maddyhome.idea.vim.common | ||||||
| 
 | 
 | ||||||
| import javax.swing.KeyStroke | 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.), |  * 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`). |  * or a part of a command (e.g. `g` for `gg`). | ||||||
| @@ -95,7 +95,7 @@ abstract class VimMachineBase : VimMachine { | |||||||
|     val operatedText = editor.deleteDryRun(range) ?: return null |     val operatedText = editor.deleteDryRun(range) ?: return null | ||||||
|  |  | ||||||
|     val normalizedRange = operatedText.toNormalizedTextRange(editor) |     val normalizedRange = operatedText.toNormalizedTextRange(editor) | ||||||
|     caret.registerStorage.storeText(editor, normalizedRange, operatedText.toType(), true) |     injector.registerGroup.storeText(editor, normalizedRange, operatedText.toType(), true) | ||||||
|     (editor as MutableVimEditor).delete(range) |     (editor as MutableVimEditor).delete(range) | ||||||
|  |  | ||||||
|     val start = normalizedRange.startOffset |     val start = normalizedRange.startOffset | ||||||
|   | |||||||
| @@ -66,7 +66,7 @@ sealed class ChangeEditorActionHandler : EditorActionHandlerBase(false) { | |||||||
|     ): Boolean |     ): Boolean | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   final override fun baseExecute( |   override fun baseExecute( | ||||||
|     editor: VimEditor, |     editor: VimEditor, | ||||||
|     caret: VimCaret, |     caret: VimCaret, | ||||||
|     context: ExecutionContext, |     context: ExecutionContext, | ||||||
|   | |||||||
| @@ -1,42 +0,0 @@ | |||||||
| 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,15 +37,4 @@ class ToggleOption(name: String, abbrev: String, defaultValue: VimInt) : Option< | |||||||
|   fun isSet(): Boolean { |   fun isSet(): Boolean { | ||||||
|     return injector.optionService.getOptionValue(OptionScope.GLOBAL, name).asBoolean() |     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,7 +20,9 @@ package com.maddyhome.idea.vim.options | |||||||
|  |  | ||||||
| import com.maddyhome.idea.vim.ex.ExException | import com.maddyhome.idea.vim.ex.ExException | ||||||
| import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | 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.VimString | ||||||
|  | import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber | ||||||
| import java.util.* | import java.util.* | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -57,13 +59,6 @@ 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 |   // todo 1.9 should return Result with exceptions | ||||||
|   abstract fun checkIfValueValid(value: VimDataType, token: String) |   abstract fun checkIfValueValid(value: VimDataType, token: String) | ||||||
|  |  | ||||||
| @@ -72,6 +67,31 @@ import java.util.* | |||||||
|   abstract fun getValueIfRemove(currentValue: VimDataType, value: String, token: String): T |   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) { | 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) |   constructor(name: String, abbrev: String, defaultValue: String, isList: Boolean = false, boundedValues: Collection<String>? = null) : this(name, abbrev, VimString(defaultValue), isList, boundedValues) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,17 +16,11 @@ | |||||||
|  * along with this program. If not, see <https://www.gnu.org/licenses/>. |  * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package com.maddyhome.idea.vim.vimscript.services | package com.maddyhome.idea.vim.options | ||||||
| 
 | 
 | ||||||
| import com.maddyhome.idea.vim.api.VimEditor |  | ||||||
| import com.maddyhome.idea.vim.ex.ExException | 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 | import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | ||||||
| 
 | 
 | ||||||
| /** |  | ||||||
|  * COMPATIBILITY-LAYER: Moved to a different package |  | ||||||
|  */ |  | ||||||
| interface OptionService { | interface OptionService { | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @@ -36,7 +30,7 @@ interface OptionService { | |||||||
|    * @param token used in exception messages |    * @param token used in exception messages | ||||||
|    * @throws ExException("E518: Unknown option: $token") |    * @throws ExException("E518: Unknown option: $token") | ||||||
|    */ |    */ | ||||||
|   fun getOptionValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName): VimDataType |   fun getOptionValue(scope: OptionScope, optionName: String, token: String = optionName): VimDataType | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Sets option value. |    * Sets option value. | ||||||
| @@ -46,7 +40,7 @@ interface OptionService { | |||||||
|    * @param token used in exception messages |    * @param token used in exception messages | ||||||
|    * @throws ExException("E518: Unknown option: $token") |    * @throws ExException("E518: Unknown option: $token") | ||||||
|    */ |    */ | ||||||
|   fun setOptionValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: VimDataType, token: String = optionName) |   fun setOptionValue(scope: OptionScope, optionName: String, value: VimDataType, token: String = optionName) | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Checks if the [value] is contained in string option. |    * Checks if the [value] is contained in string option. | ||||||
| @@ -56,7 +50,7 @@ interface OptionService { | |||||||
|    * @param optionName option name or alias |    * @param optionName option name or alias | ||||||
|    * @param value option value |    * @param value option value | ||||||
|    */ |    */ | ||||||
|   fun contains(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String): Boolean |   fun contains(scope: OptionScope, optionName: String, value: String): Boolean | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Splits a string option into flags |    * Splits a string option into flags | ||||||
| @@ -67,7 +61,7 @@ interface OptionService { | |||||||
|    * @param scope global/local option scope |    * @param scope global/local option scope | ||||||
|    * @param optionName option name or alias |    * @param optionName option name or alias | ||||||
|    */ |    */ | ||||||
|   fun getValues(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String): List<String>? |   fun getValues(scope: OptionScope, optionName: String): List<String>? | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Same as [setOptionValue], but automatically casts [value] to the required [VimDataType] |    * Same as [setOptionValue], but automatically casts [value] to the required [VimDataType] | ||||||
| @@ -78,7 +72,7 @@ interface OptionService { | |||||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found |    * @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 |    * @throws ExException("E474: Invalid argument: $token") in case the cast to VimDataType is impossible | ||||||
|    */ |    */ | ||||||
|   fun setOptionValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String, token: String = optionName) |   fun setOptionValue(scope: OptionScope, optionName: String, value: String, token: String = optionName) | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Same as `set {option}+={value}` in Vim documentation. |    * Same as `set {option}+={value}` in Vim documentation. | ||||||
| @@ -91,7 +85,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("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 |    * @throws ExException("E521: Number required after =: $token") in case the cast to VimInt is impossible | ||||||
|    */ |    */ | ||||||
|   fun appendValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String, token: String = optionName) |   fun appendValue(scope: OptionScope, optionName: String, value: String, token: String = optionName) | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Same as `set {option}^={value}` in Vim documentation. |    * Same as `set {option}^={value}` in Vim documentation. | ||||||
| @@ -104,7 +98,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("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 |    * @throws ExException("E521: Number required after =: $token") in case the cast to VimInt is impossible | ||||||
|    */ |    */ | ||||||
|   fun prependValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String, token: String = optionName) |   fun prependValue(scope: OptionScope, optionName: String, value: String, token: String = optionName) | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Same as `set {option}-={value}` in Vim documentation. |    * Same as `set {option}-={value}` in Vim documentation. | ||||||
| @@ -117,7 +111,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("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 |    * @throws ExException("E521: Number required after =: $token") in case the cast to VimInt is impossible | ||||||
|    */ |    */ | ||||||
|   fun removeValue(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, value: String, token: String = optionName) |   fun removeValue(scope: OptionScope, optionName: String, value: String, token: String = optionName) | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Checks if the toggle option on. |    * Checks if the toggle option on. | ||||||
| @@ -128,7 +122,7 @@ interface OptionService { | |||||||
|    * @param token used in exception messages |    * @param token used in exception messages | ||||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found |    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||||
|    */ |    */ | ||||||
|   fun isSet(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName): Boolean |   fun isSet(scope: OptionScope, optionName: String, token: String = optionName): Boolean | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Checks if the option's value set to default. |    * Checks if the option's value set to default. | ||||||
| @@ -138,7 +132,7 @@ interface OptionService { | |||||||
|    * @param token used in exception messages |    * @param token used in exception messages | ||||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found |    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||||
|    */ |    */ | ||||||
|   fun isDefault(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName): Boolean |   fun isDefault(scope: OptionScope, optionName: String, token: String = optionName): Boolean | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Resets option's value to default. |    * Resets option's value to default. | ||||||
| @@ -148,7 +142,7 @@ interface OptionService { | |||||||
|    * @param token used in exception messages |    * @param token used in exception messages | ||||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found |    * @throws ExException("E518: Unknown option: $token") in case the option is not found | ||||||
|    */ |    */ | ||||||
|   fun resetDefault(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName) |   fun resetDefault(scope: OptionScope, optionName: String, token: String = optionName) | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Resets all options back to default values. |    * Resets all options back to default values. | ||||||
| @@ -169,12 +163,7 @@ interface OptionService { | |||||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found |    * @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] |    * @throws ExException("E474: Invalid argument: $token") in case the option is not a [ToggleOption] | ||||||
|    */ |    */ | ||||||
|   fun setOption(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName) |   fun setOption(scope: OptionScope, optionName: String, token: String = optionName) | ||||||
| 
 |  | ||||||
|   /** |  | ||||||
|    * COMPATIBILITY-LAYER: New method added |  | ||||||
|    */ |  | ||||||
|   fun setOption(scope: Scope, optionName: String, token: String = optionName) |  | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Unsets the option (false). |    * Unsets the option (false). | ||||||
| @@ -184,7 +173,7 @@ interface OptionService { | |||||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found |    * @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] |    * @throws ExException("E474: Invalid argument: $token") in case the option is not a [ToggleOption] | ||||||
|    */ |    */ | ||||||
|   fun unsetOption(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName) |   fun unsetOption(scope: OptionScope, optionName: String, token: String = optionName) | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Inverts boolean option value true -> false / false -> true. |    * Inverts boolean option value true -> false / false -> true. | ||||||
| @@ -194,7 +183,7 @@ interface OptionService { | |||||||
|    * @throws ExException("E518: Unknown option: $token") in case the option is not found |    * @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] |    * @throws ExException("E474: Invalid argument: $token") in case the option is not a [ToggleOption] | ||||||
|    */ |    */ | ||||||
|   fun toggleOption(scope: com.maddyhome.idea.vim.options.OptionScope, optionName: String, token: String = optionName) |   fun toggleOption(scope: OptionScope, optionName: String, token: String = optionName) | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * @return list of all option names |    * @return list of all option names | ||||||
| @@ -232,12 +221,4 @@ interface OptionService { | |||||||
|    * @param listener option listener |    * @param listener option listener | ||||||
|    */ |    */ | ||||||
|   fun removeListener(optionName: String, listener: OptionChangeListener<VimDataType>) |   fun removeListener(optionName: String, listener: OptionChangeListener<VimDataType>) | ||||||
| 
 |  | ||||||
|   /** |  | ||||||
|    * COMPATIBILITY-LAYER: Added this class |  | ||||||
|    */ |  | ||||||
|   sealed class Scope { |  | ||||||
|     object GLOBAL : Scope() |  | ||||||
|     class LOCAL(val editor: VimEditor) : Scope() |  | ||||||
|   } |  | ||||||
| } | } | ||||||
| @@ -23,5 +23,5 @@ interface VimPut { | |||||||
|     updateVisualMarks: Boolean = false, |     updateVisualMarks: Boolean = false, | ||||||
|   ): Boolean |   ): Boolean | ||||||
|  |  | ||||||
|   fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData, updateVisualMarks: Boolean = false): Boolean |   fun putTextForCaret(editor: VimEditor, caret: VimCaret, context: ExecutionContext, data: PutData): Boolean | ||||||
| } | } | ||||||
| @@ -20,7 +20,6 @@ package com.maddyhome.idea.vim.register | |||||||
| import com.maddyhome.idea.vim.api.VimEditor | import com.maddyhome.idea.vim.api.VimEditor | ||||||
| import com.maddyhome.idea.vim.command.SelectionType | import com.maddyhome.idea.vim.command.SelectionType | ||||||
| import com.maddyhome.idea.vim.common.TextRange | import com.maddyhome.idea.vim.common.TextRange | ||||||
| import org.jetbrains.annotations.TestOnly |  | ||||||
| import javax.swing.KeyStroke | import javax.swing.KeyStroke | ||||||
|  |  | ||||||
| interface VimRegisterGroup { | interface VimRegisterGroup { | ||||||
| @@ -31,7 +30,6 @@ interface VimRegisterGroup { | |||||||
|    * @return The register, null if no such register |    * @return The register, null if no such register | ||||||
|    */ |    */ | ||||||
|   val lastRegister: Register? |   val lastRegister: Register? | ||||||
|   val lastRegisterChar: Char |  | ||||||
|   val currentRegister: Char |   val currentRegister: Char | ||||||
|   val defaultRegister: Char |   val defaultRegister: Char | ||||||
|  |  | ||||||
| @@ -55,13 +53,6 @@ interface VimRegisterGroup { | |||||||
|    */ |    */ | ||||||
|   fun storeText(register: Char, text: String): Boolean |   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 |    * Stores text, character wise, in the given special register | ||||||
|    * |    * | ||||||
|   | |||||||
| @@ -36,7 +36,8 @@ abstract class VimRegisterGroupBase : VimRegisterGroup { | |||||||
|   @JvmField |   @JvmField | ||||||
|   protected var defaultRegisterChar = UNNAMED_REGISTER |   protected var defaultRegisterChar = UNNAMED_REGISTER | ||||||
|  |  | ||||||
|   override var lastRegisterChar = defaultRegisterChar |   @JvmField | ||||||
|  |   protected var lastRegisterChar = defaultRegisterChar | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Gets the last register name selected by the user |    * Gets the last register name selected by the user | ||||||
| @@ -292,7 +293,7 @@ abstract class VimRegisterGroupBase : VimRegisterGroup { | |||||||
|     return true |     return true | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   override fun storeText(register: Char, text: String, selectionType: SelectionType): Boolean { |   override fun storeText(register: Char, text: String): Boolean { | ||||||
|     if (!WRITABLE_REGISTERS.contains(register)) { |     if (!WRITABLE_REGISTERS.contains(register)) { | ||||||
|       return false |       return false | ||||||
|     } |     } | ||||||
| @@ -302,7 +303,7 @@ abstract class VimRegisterGroupBase : VimRegisterGroup { | |||||||
|     } else { |     } else { | ||||||
|       text |       text | ||||||
|     } |     } | ||||||
|     val reg = Register(register, selectionType, textToStore, ArrayList()) |     val reg = Register(register, SelectionType.CHARACTER_WISE, textToStore, ArrayList()) | ||||||
|     saveRegister(register, reg) |     saveRegister(register, reg) | ||||||
|     if (register == '/') { |     if (register == '/') { | ||||||
|       injector.searchGroup.lastSearchPattern = text // todo we should not have this field if we have the "/" register |       injector.searchGroup.lastSearchPattern = text // todo we should not have this field if we have the "/" register | ||||||
| @@ -310,10 +311,6 @@ abstract class VimRegisterGroupBase : VimRegisterGroup { | |||||||
|     return true |     return true | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   override fun storeText(register: Char, text: String): Boolean { |  | ||||||
|     return storeText(register, text, SelectionType.CHARACTER_WISE) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private fun guessSelectionType(text: String): SelectionType { |   private fun guessSelectionType(text: String): SelectionType { | ||||||
|     return if (text.endsWith("\n")) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE |     return if (text.endsWith("\n")) SelectionType.LINE_WISE else SelectionType.CHARACTER_WISE | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -26,11 +26,7 @@ import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType | |||||||
| import com.maddyhome.idea.vim.vimscript.model.expressions.Variable | import com.maddyhome.idea.vim.vimscript.model.expressions.Variable | ||||||
| import org.jetbrains.annotations.TestOnly | import org.jetbrains.annotations.TestOnly | ||||||
| 
 | 
 | ||||||
| 
 | interface VimVariableService { | ||||||
| /** |  | ||||||
|  * COMPATIBILITY-LAYER: Renamed from VimVariableService |  | ||||||
|  */ |  | ||||||
| interface VariableService { |  | ||||||
|   /** |   /** | ||||||
|    * Stores variable. |    * 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.FunctionDeclaration | ||||||
| import com.maddyhome.idea.vim.vimscript.model.statements.FunctionFlag | import com.maddyhome.idea.vim.vimscript.model.statements.FunctionFlag | ||||||
|  |  | ||||||
| abstract class VimVariableServiceBase : VariableService { | abstract class VimVariableServiceBase : VimVariableService { | ||||||
|   private var globalVariables: MutableMap<String, VimDataType> = mutableMapOf() |   private var globalVariables: MutableMap<String, VimDataType> = mutableMapOf() | ||||||
|   private val windowVariablesKey = Key<MutableMap<String, VimDataType>>("TabVariables") |   private val windowVariablesKey = Key<MutableMap<String, VimDataType>>("TabVariables") | ||||||
|   private val bufferVariablesKey = Key<MutableMap<String, VimDataType>>("BufferVariables") |   private val bufferVariablesKey = Key<MutableMap<String, VimDataType>>("BufferVariables") | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user