VSpaceCode / VSpaceCode

Spacemacs like keybindings for Visual Studio Code

Home Page:https://vspacecode.github.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Weird behavior when using snippets from visual mode

david-morris opened this issue · comments

Bug description

Snippets' "blank spaces" fight with modal editing and result in unpredictable edits when used from a visual mode.

To Reproduce

  1. Make a snippet which uses ${TM_SELECTED_TEXT} to give you a reason to use snippets from visual mode

  2. Go into visual mode, select that text, and use <[space]><i><s> to insert it

  3. start typing the text you want to insert in $1. Congratulations, you were in a strange non-insert mode and just performed commands in weird locations.

Expected behavior

It should be possible to have a workflow where you:

  1. select a region
  2. insert a snippet
  3. get dropped in $1 and hitting tab cycles you through the blanks as expected.

I think this behavior is just a bug, but if I'm wrong, then this should be configurable.

The thing that makes this tricky is that the snippet mechanism isn't aware of our mode.

Screenshots

Ok, so I started by writing this snippet:

  "Story interaction step block": {
    "prefix": "-step-block",
    "body": ["await step('$1', async () =>{", "  ${TM_SELECTED_TEXT}$2", "})"]
  },

grafik
Normal so far.
grafik
Hmm, what's that weird black mark? Is that supposed to be a cursor? Well, there's a vertical line cursor so let's start typing.
grafik
Weird, it thinks it's in visual mode?
grafik
grafik
using j/k shows that the origin of the visual mode remains the origin of this visual mode. But if we didn't notice...
grafik
After typing "some text" it's clear that something unexpected happened.

Additional context

Keybindings

Click to toggle contents of `keybindings.json`

// Place your key bindings in this file to override the defaults
[
  { "key": "ctrl+l", "command": "recenterTopBottom" },
  {
    "key": "space",
    "command": "vspacecode.space",
    "when": "activeEditorGroupEmpty && focusedView == '' && !whichkeyActive && !inputFocus"
  },
  {
    "key": "space",
    "command": "vspacecode.space",
    "when": "sideBarFocus && !inputFocus && !whichkeyActive"
  },
  {
    "key": "tab",
    "command": "extension.vim_tab",
    "when": "editorFocus && vim.active && !inDebugRepl && vim.mode != 'Insert' && editorLangId != 'magit'"
  },
  {
    "key": "tab",
    "command": "-extension.vim_tab",
    "when": "editorFocus && vim.active && !inDebugRepl && vim.mode != 'Insert'"
  },
  {
    "key": "x",
    "command": "magit.discard-at-point",
    "when": "editorTextFocus && editorLangId == 'magit' && vim.mode =~ /^(?!SearchInProgressMode|CommandlineInProgress).*$/"
  },
  {
    "key": "k",
    "command": "-magit.discard-at-point"
  },
  {
    "key": "-",
    "command": "magit.reverse-at-point",
    "when": "editorTextFocus && editorLangId == 'magit' && vim.mode =~ /^(?!SearchInProgressMode|CommandlineInProgress).*$/"
  },
  {
    "key": "v",
    "command": "-magit.reverse-at-point"
  },
  {
    "key": "shift+-",
    "command": "magit.reverting",
    "when": "editorTextFocus && editorLangId == 'magit' && vim.mode =~ /^(?!SearchInProgressMode|CommandlineInProgress).*$/"
  },
  {
    "key": "shift+v",
    "command": "-magit.reverting"
  },
  {
    "key": "shift+o",
    "command": "magit.resetting",
    "when": "editorTextFocus && editorLangId == 'magit' && vim.mode =~ /^(?!SearchInProgressMode|CommandlineInProgress).*$/"
  },
  {
    "key": "shift+x",
    "command": "-magit.resetting"
  },
  {
    "key": "x",
    "command": "-magit.reset-mixed"
  },
  {
    "key": "ctrl+u x",
    "command": "-magit.reset-hard"
  },
  {
    "key": "y",
    "command": "-magit.show-refs"
  },
  {
    "key": "y",
    "command": "vspacecode.showMagitRefMenu",
    "when": "editorTextFocus && editorLangId == 'magit' && vim.mode == 'Normal'"
  },
  {
    "key": "ctrl+j",
    "command": "workbench.action.quickOpenSelectNext",
    "when": "inQuickOpen"
  },
  {
    "key": "ctrl+k",
    "command": "workbench.action.quickOpenSelectPrevious",
    "when": "inQuickOpen"
  },
  {
    "key": "ctrl+j",
    "command": "selectNextSuggestion",
    "when": "suggestWidgetMultipleSuggestions && suggestWidgetVisible && textInputFocus"
  },
  {
    "key": "ctrl+k",
    "command": "selectPrevSuggestion",
    "when": "suggestWidgetMultipleSuggestions && suggestWidgetVisible && textInputFocus"
  },
  {
    "key": "ctrl+l",
    "command": "acceptSelectedSuggestion",
    "when": "suggestWidgetMultipleSuggestions && suggestWidgetVisible && textInputFocus"
  },
  {
    "key": "ctrl+j",
    "command": "showNextParameterHint",
    "when": "editorFocus && parameterHintsMultipleSignatures && parameterHintsVisible"
  },
  {
    "key": "ctrl+k",
    "command": "showPrevParameterHint",
    "when": "editorFocus && parameterHintsMultipleSignatures && parameterHintsVisible"
  },
  {
    "key": "ctrl+h",
    "command": "file-browser.stepOut",
    "when": "inFileBrowser"
  },
  {
    "key": "ctrl+l",
    "command": "file-browser.stepIn",
    "when": "inFileBrowser"
  },
  {
    "key": "ctrl+/",
    "command": "-emacs.C-/",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "ctrl+x ctrl+o",
    "command": "-emacs.C-x_C-o",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "ctrl+x u",
    "command": "-emacs.C-x_u",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "backspace",
    "command": "-emacs.deleteLeft",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "delete",
    "command": "-emacs.deleteRight",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "ctrl+space",
    "command": "-emacs.enterMarkMode",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+g",
    "command": "-emacs.exitMarkMode",
    "when": "editorHasSelection && editorTextFocus"
  },
  {
    "key": "ctrl+g",
    "command": "-emacs.C-g",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+m",
    "command": "-emacs.C-j",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "ctrl+j",
    "command": "-emacs.C-j",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "ctrl+k",
    "command": "-emacs.C-k",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "ctrl+shift+backspace",
    "command": "-emacs.C-S_bs",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+w",
    "command": "-emacs.C-w",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "ctrl+y",
    "command": "-emacs.C-y",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "shift+alt+.",
    "command": "-emacs.cursorBottom",
    "when": "editorTextFocus"
  },
  {
    "key": "down",
    "command": "-emacs.cursorDown",
    "when": "editorTextFocus && !suggestWidgetVisible"
  },
  {
    "key": "ctrl+n",
    "command": "-emacs.cursorDown",
    "when": "editorTextFocus && !suggestWidgetVisible"
  },
  {
    "key": "end",
    "command": "-emacs.cursorEnd",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+e",
    "command": "-emacs.cursorEnd",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+e",
    "command": "-emacs.cursorEnd",
    "when": "terminalFocus"
  },
  {
    "key": "home",
    "command": "-emacs.cursorHome",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+a",
    "command": "-emacs.cursorHome",
    "when": "editorTextFocus"
  },
  {
    "key": "left",
    "command": "-emacs.cursorLeft",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+b",
    "command": "-emacs.cursorLeft",
    "when": "editorTextFocus"
  },
  {
    "key": "pagedown",
    "command": "-emacs.cursorPageDown",
    "when": "editorTextFocus && !suggestWidgetVisible"
  },
  {
    "key": "ctrl+v",
    "command": "-emacs.cursorPageDown",
    "when": "editorTextFocus && !suggestWidgetVisible"
  },
  {
    "key": "pageup",
    "command": "-emacs.cursorPageUp",
    "when": "editorTextFocus && !suggestWidgetVisible"
  },
  {
    "key": "alt+v",
    "command": "-emacs.cursorPageUp",
    "when": "editorTextFocus && !suggestWidgetVisible"
  },
  {
    "key": "right",
    "command": "-emacs.cursorRight",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+f",
    "command": "-emacs.cursorRight",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+f",
    "command": "-emacs.cursorRight",
    "when": "terminalFocus"
  },
  {
    "key": "shift+alt+,",
    "command": "-emacs.cursorTop",
    "when": "editorTextFocus"
  },
  {
    "key": "up",
    "command": "-emacs.cursorUp",
    "when": "editorTextFocus && !suggestWidgetVisible"
  },
  {
    "key": "ctrl+p",
    "command": "-emacs.cursorUp",
    "when": "editorTextFocus && !suggestWidgetVisible"
  },
  {
    "key": "ctrl+p",
    "command": "-emacs.cursorUp",
    "when": "terminalFocus"
  },
  {
    "key": "alt+b",
    "command": "-emacs.cursorWordLeft",
    "when": "editorTextFocus"
  },
  {
    "key": "alt+f",
    "command": "-emacs.cursorWordRight",
    "when": "editorTextFocus"
  },
  {
    "key": "alt+w",
    "command": "-emacs.M-w",
    "when": "editorTextFocus"
  },
  {
    "key": "shift+alt+1",
    "command": "-emacs.shellCommand"
  },
  {
    "key": "ctrl+j",
    "command": "selectNextCodeAction",
    "when": "codeActionMenuVisible"
  },
  {
    "key": "ctrl+k",
    "command": "selectPrevCodeAction",
    "when": "codeActionMenuVisible"
  },
  {
    "key": "ctrl+l",
    "command": "acceptSelectedCodeAction",
    "when": "codeActionMenuVisible"
  }
]

Settings

Click to toggle contents of `settings.json`

{
  "vim.easymotion": true,
  "vim.useSystemClipboard": true,
  "vim.normalModeKeyBindingsNonRecursive": [
    {
      "before": ["<space>"],
      "commands": ["vspacecode.space"]
    },
    {
      "before": [","],
      "commands": [
        "vspacecode.space",
        {
          "command": "whichkey.triggerKey",
          "args": "m"
        }
      ]
    }
  ],
  "vim.visualModeKeyBindingsNonRecursive": [
    {
      "before": ["<space>"],
      "commands": ["vspacecode.space"]
    },
    {
      "before": [","],
      "commands": [
        "vspacecode.space",
        {
          "command": "whichkey.triggerKey",
          "args": "m"
        }
      ]
    }
  ],
  "vim.insertModeKeyBindingsNonRecursive": [
    {
      "before": ["j", "k"],
      "after": ["<esc>"]
    }
  ],
  "yaml.schemas": {
    "file:///c%3A/Users/DavidMorris/.vscode/extensions/atlassian.atlascode-3.0.2/resources/schemas/pipelines-schema.json": "bitbucket-pipelines.yml"
  },
  "redhat.telemetry.enabled": false,
  "atlascode.jira.jqlList": [
    {
      "id": "3fb89c7b-ac54-4ed2-a52a-72d71b9ca21d",
      "enabled": true,
      "name": "My jira.nefino.eu Issues",
      "query": "assignee = currentUser() AND resolution = Unresolved ORDER BY lastViewed DESC",
      "siteId": "jira.nefino.eu",
      "monitor": true
    }
  ],
  "terminal.integrated.profiles.linux": {
    "zsh": {
      "path": "zsh",
      "args": ["-l"]
    },
    "bash": {
      "path": "bash",
      "args": ["-l"]
    }
  },
  "tabnine.inlineCompletions": false,
  "tabnine.experimentalInlineCompletions": false,
  "tabnine.experimentalAutoImports": true,
  "python.defaultInterpreterPath": "/var/lang/bin/python",
  "editor.suggestSelection": "first",
  "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
  "workbench.editorAssociations": {
    "*.ipynb": "jupyter-notebook"
  },
  "notebook.cellToolbarLocation": {
    "default": "right",
    "jupyter-notebook": "left"
  },
  "git.autofetch": true,
  "explorer.confirmDragAndDrop": false,
  "terminal.integrated.scrollback": 100000000,
  "terminal.integrated.defaultProfile.linux": "zsh",
  "yaml.customTags": [
    "!And",
    "!And sequence",
    "!If",
    "!If sequence",
    "!Not",
    "!Not sequence",
    "!Equals",
    "!Equals sequence",
    "!Or",
    "!Or sequence",
    "!FindInMap",
    "!FindInMap sequence",
    "!Base64",
    "!Join",
    "!Join sequence",
    "!Cidr",
    "!Ref",
    "!Sub",
    "!Sub sequence",
    "!GetAtt",
    "!GetAZs",
    "!ImportValue",
    "!ImportValue sequence",
    "!Select",
    "!Select sequence",
    "!Split",
    "!Split sequence"
  ],
  "atlascode.jira.explorer.fetchAllQueryResults": false,
  "atlascode.jira.statusbar.showProduct": true,
  "git.supportCancellation": true,
  "editor.lineNumbers": "relative",
  "atlascode.bitbucket.explorer.relatedBitbucketIssues.enabled": true,
  "atlascode.bitbucket.explorer.notifications.pullRequestCreated": true,
  "atlascode.bitbucket.explorer.enabled": true,
  "workbench.colorTheme": "Default Light+ Experimental",

vspacecode bindings omitted because the message body was too long.

System information

grafik
grafik

This is unfortunately a bug in how Vscode Vim unable to handle snippet insertion. VSCodeVim/Vim#7068

I believe the reason is as follows, when inserting snippet during visual mode, vscode will automatically select $1 outside the knowledge of the VsCode Vim. When they you starting to type, VscodeVim assumes vscode has the old selection.


Developing notes:

One way to workaround this is to perform additional c vim key in visual mode before calling the actual insert snippet command. Although, we can't directly ask vim to know if it is visual mode, we may able to pass that information when when calling whichkey.show in the vim remap configuration.

Wouldn't c wipe out the selection? That would defeat the purpose of ${TM_SELECTED_TEXT} snippets.

From the vantage point of vscode, maybe there's something we could do at the level of the insert snippet command from visual mode? Like maybe switch to insert mode with "click selected" text before calling the insert snippet function?