VSCodeVim / Vim

:star: Vim for Visual Studio Code
http://aka.ms/vscodevim
MIT License
13.95k stars 1.32k forks source link

Feature: vim smart semicolon? #5179

Open sql-koala opened 4 years ago

sql-koala commented 4 years ago

Is your feature request related to a problem? Please describe. I have worked with semicolon languages (C#, Typescript) more lately... this often requires the input of a line ending semicolon from inside brackets and strings. vims source is full of examples. Lets take:

  keys = ['A'];
  keys = ['A|']

which looks like so before, | = cursor. Now you need to move 2 right/EOL and enter ";". I don't know a really good way to automate this "chore", see alternatives.

Describe the solution you'd like A smart semicolon, built inside vim (meaning: working with repeat), where we can press ";" in the setting above and have it entered at EOL. A basic solution could be a setting: vim.smartSemicolonFiletypes = ".cs,.ts" which would always enter ";" at EOL for a given filetype (with some option to put it back to the orig place).

Describe alternatives you've considered You can do a mapping like so, but that screws up repeat. inoremap ; <c-o>$; Since we can't map <c-;> (#5152 ), I don't see an intuitive way to have a normal ; and an EOL ; in insert mode.

There are extensions for smart semicolon, I tried two and did not get them to work. And if, I am sure they don't cooperate with repeat.

berknam commented 4 years ago

You can do this:

    {
        "key": "ctrl+oem_comma",
        "command": "vim.remap",
        "when": "editorTextFocus && vim.active && vim.mode == 'Insert' && !inDebugRepl",
        "args": {
            "after": ["<Esc>", "m", "m", "A", ";", "<Esc>", "`", "m", "a"]
        }
    },

What this does is it goes to normal mode, sets mark 'm' (I usually reserve this mark for this sort of remaps, you can use whatever you want), appends ';' to the end of the line, goes to normal mode again, jumps to mark 'm' and lastly enters insert mode, leaving you exactly where you were when you pressed \<C-,>.

I'm using \<C-,> because the key ';' on my keyboard is "shift+,"

berknam commented 4 years ago

Also if you want to limit that remap just for C# and Typescript, you can do so by changing the "when" clause to this:

"when": "editorTextFocus && vim.active && vim.mode == 'Insert' && !inDebugRepl && editorLangId == 'typescript' || editorTextFocus && vim.active && vim.mode == 'Insert' && !inDebugRepl && editorLangId == 'csharp'",
sql-koala commented 4 years ago

@berknam , thanks for the idea. I have build myself what I described here. It's a setting "vim.smartSemicolonLanguages" : "typescript,csharp", together with an excludeLinePattern, which you basically need to catch for-loops. This is recent, so I have not done longer coding sessions with it, but I am positive it does the right thing 9 out of 10 times for me. test

berknam commented 4 years ago

Why don't you just use some mapping like this?

"vim.insertModeKeyBindings": [
    {
        "before": [";", ";"],
        "after": ["<Esc>", "m", "m", "A", ";", "<Esc>", "`", "m", "a"]
    }
]

I've tried this and it works great. And if you don't want it to stay in insert mode just leave out the last "a".