Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remap refactor get leader key original action and handle plugins through mappings #1

Open
wants to merge 25 commits into
base: remapRefactor_PoC
Choose a base branch
from

Conversation

berknam
Copy link
Owner

@berknam berknam commented Jun 30, 2020

What this PR does / why we need it:
It creates a new way of handling plugins. Now the plugin's main actions are registered through the new @RegisterPluginAction(pluginName) which takes the new BasePluginAction with the new property pluginActionDefaultKeys: string[] which holds the keys that will be used to create the default remappings. The keys property now needs to have the plugin action name (the same as used by that plugin in Vim) as the first key, but can have more keys.

Examples:
Plugin: CamelCaseMotion
Action: Move "word"
In Vim you would do map <leader>w <Plug>CamelCaseMotion_w, here we have:

@RegisterPluginAction('camelcasemotion')
class MoveCamelCaseWordBegin extends CamelCaseBaseMovement {
  pluginActionDefaultKeys = ['<leader>', 'w'];
  keys = ['<Plug>CamelCaseMotion_w'];

  public async execAction(position: Position, vimState: VimState): Promise<Position> {

Which when registering will create the default remapping <leader>w -> <Plug>CamelCaseMotion_w, here we handle <Plug>CamelCaseMotion_w as a single key.

Plugin: Sneak
Action: find 2 chars
In Vim you would do nmap s <Plug>Sneak_s, here we have:

@RegisterPluginAction('sneak')
class SneakForwardNormalAndVisualMode extends SneakForward {
  keys = ['<Plug>Sneak_s', '<character>', '<character>'];
  pluginActionDefaultKeys = ['s'];
  modes = [Mode.Normal, Mode.Visual, Mode.VisualLine, Mode.VisualBlock];
}

Here even though we have 3 keys for the action we only map the pluginActionDefaultKeys to the first key of keys, so we get a remap of s -> <Plug>Sneak_s which when it gets to the action handler waits for two more keys of type <character>.

This was implemented on all plugins and since I was changing them I also added some features to them (this method actually makes it easier to add more features from these plugins) like the <Plug>Sneak_t, <Plug>Sneak_T from sneak and the keys 'cS', 'yS' (operator), 'ySs', 'ySS' (same as 'ySs') and 'gS' (visual mode) from surround plugin.

On register we create the default mappings but we add them to the mappings Maps when loading config depending on whether the plugin is active or not, we also don't add the plugin default mapping if the user already has a map for that key. Example: if the user has this map: w -> <Plug>CamelCaseMotion_w we don't create the mapping for <leader>w. This is a behavior that a lot of plugins do in Vim as well.

The result of all this is not only do we have a better implementation of plugins, we also get the original action of the <leader> key back. Now if you press the leader key it waits for timeout when it has potential mappings, but after timeout finishes it executes its original action. If you don't want to wait, you can now create a different NonRecursive mapping to the leader key. For example if you set your leader to ,, you can do:

"vim.normalModeKeyBindingsNonRecursive": [
    {
        "before": ["\\"],
        "after": [","]
    }
]

And this way you get the original action of , with the \ key.

The next step with this is to be able to read the mappings from .vimrc that use <Plug>. I intend to do this by storing all the <Plug>name that we implement on the RegisterPluginAction, then the vimrc builder can use those stored implemented plugin actions to regex the vimrc for compatible plugin actions. This would mean that we would be able to read the following remaps from vimrc:

map w <Plug>CamelCaseMotion_w
omap iw <Plug>CamelCaseMotion_iw
nnoremap <leader>s" v<Plug>CamelCaseMotion_iw<Plug>VSurround"

Which issue(s) this PR fixes
fixes VSCodeVim#4916
fixes VSCodeVim#2027
fixes VSCodeVim#4909
fixes VSCodeVim#4973

Special notes for your reviewer:
This PR is based off of the PR VSCodeVim#4735

@berknam berknam force-pushed the remapRefactor_LeaderKeyOpt3 branch 2 times, most recently from 3048485 to 5cdb7ae Compare July 7, 2020 10:49
@berknam berknam force-pushed the remapRefactor_LeaderKeyOpt3 branch 3 times, most recently from 0966303 to 768db4b Compare July 11, 2020 09:10
@berknam berknam force-pushed the remapRefactor_LeaderKeyOpt3 branch from 768db4b to 143ef4d Compare July 16, 2020 21:09
@berknam berknam force-pushed the remapRefactor_LeaderKeyOpt3 branch from 143ef4d to 79094cd Compare July 25, 2020 21:59
@berknam berknam force-pushed the remapRefactor_LeaderKeyOpt3 branch from 79094cd to 68d7e57 Compare August 14, 2020 14:09
berknam and others added 19 commits August 16, 2020 14:22
This is a pretty massive change; see pull request VSCodeVim#4735 for full details

Most notably:
- Support for operator-pending mode, including remaps and a half-cursor decoration
- Correct handling of ambiguous remaps with timeout
- Correct handling of recursive special case when the RHS starts with the LHS
- Correct handling of multi-key remaps in insert mode
- Failed movements that occur partway through a remap stop & discard the rest of the remap
- Implement `unmap` and `mapclear` in .vimrc

Refs VSCodeVim#463, refs VSCodeVim#4908
Fixes VSCodeVim#1261, fixes VSCodeVim#1398, fixes VSCodeVim#1579, fixes VSCodeVim#1821, fixes VSCodeVim#1835
Fixes VSCodeVim#1870, fixes VSCodeVim#1883, fixes VSCodeVim#2041, fixes VSCodeVim#2234, fixes VSCodeVim#2466
Fixes VSCodeVim#2897, fixes VSCodeVim#2955, fixes VSCodeVim#2975, fixes VSCodeVim#3082, fixes VSCodeVim#3086
Fixes VSCodeVim#3171, fixes VSCodeVim#3373, fixes VSCodeVim#3413, fixes VSCodeVim#3742, fixes VSCodeVim#3768
Fixes VSCodeVim#3988, fixes VSCodeVim#4057, fixes VSCodeVim#4118, fixes VSCodeVim#4236, fixes VSCodeVim#4353
Fixes VSCodeVim#4464, fixes VSCodeVim#4530, fixes VSCodeVim#4532, fixes VSCodeVim#4563, fixes VSCodeVim#4674
Fixes VSCodeVim#4756, fixes VSCodeVim#4883, fixes VSCodeVim#4928, fixes VSCodeVim#4991, fixes VSCodeVim#5016
Fixes VSCodeVim#5057, fixes VSCodeVim#5067, fixes VSCodeVim#5084, fixes VSCodeVim#5125
- Implements the 'BasePluginAction' to be registered with
'@RegisterPluginAction' by every plugin action
- Create default keybindings when registering plugin actions
- Add this default keybindings to the user keybindings when validating
while also filtering out the default mappings that already have a map to
made by the user
- Make the NormalizeKey return the original key when there is no change
so that keys like '<CamelCaseMotion_w>' aren't changed to '<camelcasemotion_w>
- Implement '@RegisterPluginActions' on camel case motion actions
- Remove logic from 'CompareKeypressSequence' that handled the leader
key to allow the leader key to be compared normally to itself
- Make the action handler get the relevant action by looking for actions
the 'vimState.currentModeIncludingPseudoModes'
- Change the 'doesActionApply' and 'couldActionApply' to look get the
current mode with pseudo modes as well
- Add OperatorPendingMode to all actions where it applies
- Add OperatorPendingMode to all operators that can run repeated,
like 'dd', 'cc', 'gUU'
- Add OperatorPendingMode to all textObjects and remove NormalMode as
textObjects only apply on OperatorPending, Visual or VisualBlock modes
- Should have whichwrap with 'b'
- 'RegisterPluginAction' now takes the plugin name as a parameter
- 'RegisterPluginAction' adds plugin name to the default keybindings it
creates so that the remappingValidator can check if that plugin is
active before adding the keybinding to the map of bindings
- When registering the plugin actions it will now also store the default
mappings on the var 'Globals.mockConfigurationDefaultBindings' and
when creating a new testConfiguration on the Tests it loads this defaults
- This made it necessary to clone the default mappings before validating
otherwise they would be changed by the tests messing it up for the next
tests to come.
- Fix surround 'yss' not working
- Add check for '<leader>' key on 'handleKeyEvent' because the plugin
tests might send this key and it needs to be swapped by its
representation before actually handling it.
- Fix the Notation.NormalizeKey missing '>' character
- Fix the Notation.NormalizeKey regex replacing some characters on the
new plugin keys by mistake. Like the key '<(easymotion-bd-t)>' was being
changed to '<(easymotion-bD-t)>'
- Fix bug on camelCaseMotion test with the plugin disable that now
handles the leader key while before it didn't
- Changed the plugin keys to be the same as used by its corresponding
Vim plugin, like '<Plug>(easymoption-s)' or '<Plug>Sneak_s'
- Create the default mappings only to the plugin key but allow the
actions to accept more keys. For example: The sneak plugin 's' key is
mapped to '<Plug>Sneak_s' but the action it self has the keys
`['<Plug>Sneak_s', '<character>, '<character>']`, meaning that after the
<Plug> key it still needs two characters.
- Fix remappingValidator still creating remaps for default remappings
when the user already had remaps to that same remap.
(Example: if the user remaps '<leader>sw <Plug>CamelCaseMotion_w' the
remappingValidator should not create the default remap
'<leader>w <Plug>CamelCaseMotion_w'
- Add default mappings for 'f','F','t','T' when config.sneakReplacesF is
set to true and remove them when it is false
- Add '<Plug>Sneak_t' and  '<Plug>Sneak_T' when config.sneakReplacesF
is set
- Add tests for this new 'till' movements
- Create 'StartSurroundMode' function similar to the previous
'CommandSurroundModeStart' action exec
- Create 'BaseSurroundCommand' used by 'cs', 'ds' and 'S' in visual mode
- Implements 'ys' has an operator
- Make all surround actions only apply if surround is set in
configuration
- Add 'surround' plugin name to the 'isPluginActive'' from
remappingValidator
- Implement the following keys from the surround plugin:
'cS', 'yS' (operator), 'ySs', 'ySS' (same as 'ySs') and 'gS' (visual mode)
- Now the only missing parts of surround plugin is the insert mode
mappings, but those aren't that important anyway.
- Still missing tests for these new actions
- There should be no need to implement a full OperatorPendingMode, even
Vim doesn't do it, in vim operator pending mode is considered
'no' or 'nov', 'noV', 'no^V' mode which is normal mode with operator
pending mode with optinally forced parameters
operatorPending or visual modes
@berknam berknam force-pushed the remapRefactor_LeaderKeyOpt3 branch from 68d7e57 to e513902 Compare August 16, 2020 22:37
J-Fields and others added 2 commits August 16, 2020 18:46
Register.get() will now return undefined when the given register has no value, which lets us throw E353, etc.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants