VSCodeVim / Vim

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

`S`/`cc` doesn't auto indent on empty line #1017

Open alnorris opened 7 years ago

alnorris commented 7 years ago

When your in Normal mode and your on an empty line and the cursor is at the very left, pressing 'S' in normal Vim auto indents the line and goes into insert mode, but VS Vim doesn't seem to indent at all.

Technical details:

What happened:

Here all of those scenarios in a GIF (with tab width of 3 instead of 2) cc

Contributed by @lumio at https://github.com/VSCodeVim/Vim/issues/1828.

What did you expect to happen: Typing cc will always clear the line, indents it and cursor jumps to end of line.

How to reproduce it: See above, but typically typing cc on different col positions.

rebornix commented 7 years ago

Nice catch, if the cursor is at somewhere between first char or last char, S works as expected but doesn't work if it's at the beginning of the file.

rebornix commented 7 years ago

Not sure for what reason cursor updating in commands which invoke delete no longer works, I saw this commit change https://github.com/VSCodeVim/Vim/commit/3dad7cab1d09704c85824b726d9769a71be12817#diff-7addcd1a8a241060a73b1fe4abb39960R1269 so @johnfn might have an idea about that.

I take a quick look but now I'm confused, take S for example, if we want to control the cursor position after running delete operator, how can we do that? delete operator is now a postponed action.

johnfn commented 7 years ago

@rebornix we use PositionDiffs now. We have a "beginning of line" position diff that just tells the cursor to go to the beginning of the line after the transformation is applied. We use that a few times...

Chillee commented 7 years ago

This problem is fixable once the "reindent a selection" command is added, per https://github.com/Microsoft/vscode/issues/19847#issuecomment-277348907

xiluo58 commented 7 years ago

Seems dd O works perfectly for me. Is it possible to remap cc to dd O?

Chillee commented 7 years ago

@xiluo58 That's an interesting idea actually. To be clear to anybody who was confused as me, he's suggesting ddO.

knpwrs commented 6 years ago

That works for me!

    "vim.insertModeKeyBindings": [{
        "before": ["j", "k"],
        "after": ["<Esc>"]
    }, {
        "before": ["c", "c"],
        "after": ["d", "d", "O"]
    }],

It would still definitely be nice to see the default behavior fixed.

EDIT: Actually it seems like this doesn't work, seeing as though it's an insert mode key binding. I tried otherModesKeyBindings and it doesn't seem to work there.

alexozer commented 6 years ago

Any progress on this?

ddO sadly isn't a universal workaround either. For example, it won't work on the last line of a file.

ddO on c:

a
  b
  c

Produces

a
  _
  b

Also doesn't work when single line is indented:

ddO on b:

a
  b
c

Produces:

a
_
c
asethwright commented 6 years ago

I agree a proper indentation should be performed of the lines. This temporary fix seems to work for me. But the previous problems by @alexozer still apply.

    "vim.otherModesKeyBindings": [
      {
        "before": ["c", "c"],
        "after": ["d", "d", "d", "O"]
      }
    ],

Not sure why the third "d" is necessary.

shaunlebron commented 6 years ago

Hitting Tab after cc seems to do the right thing every time.

Is there a way to automate this?

Chillee commented 6 years ago

@shaunlebron It doesn't if your cursor starts after the tab position.

shaunlebron commented 6 years ago

@Chillee do you have an example? would like to reproduce

Chillee commented 6 years ago

@shaunlebron Take something like

  asd|f

where there's 2 spaces before the asdf. Presing cc takes you to

  |

and a tab adds 2 more spaces, which is not the right thing.

asilvadesigns commented 6 years ago

any updates on this?

rben01 commented 6 years ago

Another problem with remapping to ddO is that for isolated lines (single lines with whitespace immediately above and below), there is no preceding line to base indentation off of, and so O creates the new line above with no indentation. For instance consider the following Python code:

def f():  # next line intentionally left blank

    ret|urn  # | represents the cursor

In vim, cc would clear the line and place the cursor at the correct indentation (four space from the left margin, in this example). But in VSCode Vim, since there's no line above return to base indentation off of, it clears the line and places the cursor at the beginning of the line (outside the function body).

Python isn't the easiest language to infer desired indentation, but when the desired indentation is already given, it should be respected when using cc -- independent of any VSCode capabilities or settings.

That said, I think a better temporary keybinding for a single cc would be ^C. However that's not easily repeatable -- 5cc is not achievable by repeating ^C

aldanor commented 5 years ago

Has anyone here managed to figure it out?.. Seems to be an issue still.

casio commented 4 years ago

Sorry to revive such an old thread - but is this really not solved yet? In python it's really annoying and given the love python gets elsewhere in vscode, this appears a bit strange.

@rben01 s workaround of using ^ C works best for me. So much that I'd like to remap it actually, but that doesnt work either:

  "vim.normalModeKeyBindings": [
    {
      "before": [
        "c",
        "c"
      ],
      "after": [
        "^",
        "C"
      ]
    }
  ]

Somebody got a better idea?

J-Fields commented 4 years ago

There's nothing we can do about this - it's an upstream problem. After a command like cc, we run editor.action.reindentselectedlines, which requires indentation rules to be specified for the current language to work correctly.

Seems like these are relevant issues. Go upvote them please! Python: https://github.com/microsoft/vscode-python/issues/8996 C++: https://github.com/microsoft/vscode-cpptools/issues/883

Raikiri commented 4 years ago

How about using some kind of workaround until it's fixed properly upstream? It's a very annoying problem and I don't think it's good for the end user to just shove it under the rug waiting for it to potentially be fixed someday somewhere else. Like, O action for example could be implemented just by doing end+enter macro or something like that.

zeroxia commented 4 years ago

Hi I have Visual Studio Code 1.43.2, vim extension 1.13.1. I cannot remap cc, is it also a known bug? I've included the following chunk in my settings.json, "leader, m" works, but the cc remap does not.

    "vim.normalModeKeyBindings": [
      {
        "before": [ "c", "c" ],
        "after": [ "^", "C" ],
      },
      {
        "before": [ "<leader>", "m" ],
        "commands": [ "bookmarks.toggle" ]
      },
      {
        "before": [ "<leader>", "b" ],
        "commands": [ "bookmarks.list" ]
      }
    ]

This is frustrating, especially when I see this issue was raised in the year of 2016, and now it's 2020.

Spirarel commented 4 years ago

@zeroxia see https://github.com/VSCodeVim/Vim/issues/4464#issuecomment-577246612

I agree, it's frustrating, but then this is open source...

ColdSpirit0 commented 4 years ago

Have that problem with C#. "Reindent selected lines" does not work for it, but indent adds when use "o". So I made that workaround. But it only works if upper line not empty too.

    "vim.normalModeKeyBindingsNonRecursive": [
        {
            "before": ["S"],
            "after": ["d", "d", "g", "k", "o"],
        },
    ],
MrHate commented 4 years ago

Such kind of key binding works well indeed. However, it now makes u confuse me. It considers the combination as the combination itself, so I need to undo for 3 times. I think an update to implement a real S should be better indeed.

gaoshan0621 commented 4 years ago

offer a workaround for "o", which I use frequently:

    "vim.normalModeKeyBindingsNonRecursive": [
        {
            "before": [
                "o"
            ],
            "after": [
                "o", "_",
            ],
            "commands":[
                "editor.action.formatSelection",
                "deleteLeft",
            ]
        },
sql-koala commented 4 years ago

I have noticed something. "cc" does not automatically indent, while "o" and "O" do, at least most of the time. Therefore, a fix should be possible without upstream/vscode, or not?

berknam commented 3 years ago

@sql-koala Is this still an issue? Because I can't reproduce this. Both cc and S auto indent for me, even on empty lines.

J-Fields commented 3 years ago

Indentation after both o (editor.action.insertLineAfter) and cc (editor.action.reindentselectedlines) is determined by the language support, but they're specified differently, so some language plugins support the former better than the latter. Maybe some supports the latter better than the former, but none that I've found.

I write C++ and python for my job and o works great while cc doesn't in both of these. Typescript and rust, however, both work as expected.

fwcd commented 2 years ago

@J-Fields Which part of the language support handles this indentation? Is it the TextMate grammar, the formatter, the language-configuration.json or even something else?

There are many languages (like Swift) which currently aren't supported very well by S/cc either and I would like to help improve support for those.

Clev7 commented 2 years ago

remapping cc to ddko seems to work. It seems that o formats differently from O. There might be exceptions though.

CalebMDMI commented 11 months ago

I've been looking for answers to this for a while, and it's still broken. There are workarounds that get close, but no perfect solutions yet. The main thing I want is for cc<escape> to remove any indentation as it does in Vim, and none of the workarounds I've found achieve this.

rben01 commented 11 months ago

I've been looking for answers to this for a while, and it's still broken. There are workarounds that get close, but no perfect solutions yet. The main thing I want is for cc<escape> to remove any indentation as it does in Vim, and none of the workarounds I've found achieve this.

There is always https://github.com/vscode-neovim/vscode-neovim

J-Fields commented 11 months ago

@fwcd If I remember correctly, it's indentation rules documented here.