Vsvim: cc doesn't put the cursor at indent if on empty line

Created on 8 May 2012  ·  10Comments  ·  Source: VsVim/VsVim

cc deletes the current line and places the cursor in insert mode (the 'autoindent' option determines its position).

VsVim doesn't always put the cursor in the right position. The one case I consistently managed to reproduce it is if you cc on an empty line it will place the cursor at the first column rather than at the indent.
Consider the following starting C# code ([ ] is the ncursor, | the icursor):

class Foo {
    public void Bar()
    [{]
    }
}

Press o to open line below:

class Foo {
    public void Bar()
    {
        |
    }
}

Now press Esc:

class Foo {
    public void Bar()
    {
[ ]
    }
}

Now press cc. This is where Vim and VsVim differ: Vim will place the cursor indented within the Bar:

class Foo {
    public void Bar()
    {
        |
    }
}

while VsVim will place it at line 0:

class Foo {
    public void Bar()
    {
|
    }
}

Alternatively, use this code:

class Foo {
    public void Bar()
    {
        throw new NotImplementedException()[;]
    }
}

In both Vim and VsVim a single cc will place the cursor in the indented position, but cc<Esc>cc will place the cursor at column 0 in VsVim (while Vim puts it at the right indent).

bug

Most helpful comment

This simple workaround gives me the behaviour I expect from vim:

nmap S ddO
nmap cc S

All 10 comments

The behavior I see in VsVim mirrors what I see in gVim.

I think we have a different setting toggled. I actually see a behavior difference after the 'o' step at the top. My cursor will appear on the same column as the { and not indented as yours was.

Can you run :set and paste the output?

autoindent seems to be one of those options I have set in my vimrc, which I then source in vsvimrc.

hlsearch
ignorecase
incsearch
scrolloff=5
smartcase
vimrc="C:\Users\pmateescu\_vsvimrc"
vimrcpaths="C:\Users\pmateescu;C:\Users\pmateescu"
autoindent
number
tabstop=4

Does VsVim account for indentation settings in VS? If so, here are mine (under Options -> Text Editor -> C# -> Formatting):

  1. Indentation (indent block contents, case, labels, do not indent open/close braces)
class MyClass
{
    public void Method()
    {
        goto MyLabel;
MyLabel:
        return;
    }
}
  1. Under New Lines I have everything checked
  2. Spacing: everything unchecked except for "Set other spacing options" - Insert space after keywords in control flow statements; "Set spacing for delimiters" - : after colon for base, after comma, after semicolon in for, before colon for base; "Set spacing for operators": before and after.

I don't know if this matters either, but I have indenting set to Smart, size 4, Keep tabs.

HTH

Yeah autoindent does appear to be the difference. Once I set that + saved it as a .c file I could get the behavior you were seeing.

Took a quick glance at the code and it does appear to be an issue with empty lines. The code doesn't respect autoindent when the deleted line was empty which it apparently should.

In general VsVim prefers Visual Studio indent over Vim indent. This can be overriden by disabling the option vsvim_useeditorindent.

This mostly works out. Unfortunately in 2010 though not all languages provide good APIs for indenting services. C# has the best, VB has practically none and C++ is a roll of the dice. I believe it gets better in VS11 but haven't played around enough yet to see how much.

Will try to squeeze this fix into 1.3

Played around a bit more and this behavior is actually keyed off of cindent and not autoindent. This is one of the reasons it took me so long to repro the problem. I was experimenting in text files where I had autoindent enabled. This only repros in C files with cindent on.

You're right, I managed to reproduce it too after you mentioned it with vim -U NONE -u NONE -cmd 'set cindent' index.cs

In normal settings, Vim seems to be automatically setting cindent on when in C-like files (shows up in :setl in both C# and JS).
However, the same behavior - remove indent on <Esc>, re-indent on cc - seem to happen in non cindent files: showed up for me in both CSS and HTML, but in those cases it might have been the effect of specific indentexpr.

@philipmat
@jaredpar

Hi guys,I met with the same issue.
Is it fixed in the latest release?
Output after :set

backspace="indent,eol,start"
hlsearch
ignorecase
incsearch
autoindent

@lookforit at the moment no. This behavior is actually a part of cindent which is not supported by VsVim at this time.

This simple workaround gives me the behaviour I expect from vim:

nmap S ddO
nmap cc S

This would still be a nice-to-have. My intuitive sense is that the 'cc' to clear a line and begin editing should begin at the same indent level as creating a newline. Is there an internal Vim/VS reasoning that this shouldn't be so? I may tackle it as an inroad into working with the project.

The solution to this problem was superficially nothing more than "do for cc whatever o was already doing" (which is why @shkm's workaround works), but the surgery necessary made it quite a bit more work.

VsVim was already doing the correct thing for so-called "vim indent," the kind of indent VsVim uses when there is no language service available. In order to add tests for this issue, I had to add infrastructure to the tests to simulate a language service. So the disconnect was that all the existing tests use "vim indent" but 99% of users are using "host indent", i.e., are editing files where Visual Studio provides an indent service.

To further complicate the problem, there was a bug that nobody ever reported with "vim indent" where it didn't work correctly when tabs were not being expanded (see issue #2302). Again, from a practical point of view nobody uses "vim indent" so upon reflection this isn't that surprising.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

elrob picture elrob  ·  6Comments

ArnisL picture ArnisL  ·  5Comments

thelamb picture thelamb  ·  5Comments

ogirginc picture ogirginc  ·  6Comments

jaredpar picture jaredpar  ·  5Comments