nim-mode icon indicating copy to clipboard operation
nim-mode copied to clipboard

Indent problems

Open vegansk opened this issue 7 years ago • 18 comments

Why nim-mode doesn't save indent of the expressions? For example, select this code:

proc test(xs: seq[int]) =
  for x in xs:
    echo x
  echo x.len

then call indent-region and you will get:

proc test(xs: seq[int]) =
  for x in xs:
    echo x
    echo x.len

vegansk avatar Mar 02 '17 02:03 vegansk

Yes, I have this problem, too. I just never opened an issue, because reasons. Do you know how to fix it in emacs? Seems like you know more about this problem than I do.

krux02 avatar Mar 02 '17 14:03 krux02

The only thing I did is turned off autoindent on paste. For spacemacs this can be done via:

  (add-to-list 'spacemacs-indent-sensitive-modes 'nim-mode)

vegansk avatar Mar 03 '17 02:03 vegansk

Well since I don't use spacemacs, I guess I don't have indent on paste enabled.

krux02 avatar Mar 03 '17 14:03 krux02

I also noticed this problem. It's strange because indent-region works correctly in python-mode, which nim-mode is based off of.

electric-indent-inhibit is set to t, which should prevent this, but it seems like there is a problem with the configuration of electric-indent-mode as I'm about to write up another issue about it.

mrcnski avatar Mar 03 '17 17:03 mrcnski

@vegansk I don't understand your problem yet. what is the expected result?

yuutayamada avatar Mar 05 '17 05:03 yuutayamada

@yuutayamada Well I think he pointed it out quite nicely, even though there is a typo (echo x.len should be echo xs.len). Indent region on a region destroys the logical blocks, and that is not what should happen, when indent-region is triggered on a pasted block of code. It should indent that block of code, so that is actually working on that indentation level, where it is pasted into. I guess the this was initially designed for curly braced languages, where the indentation level can be inferred, and then it was hacked, to also work in python mode.

krux02 avatar Mar 05 '17 18:03 krux02

Sorry, I was wondering if you don't want to indent that region, why you use indent-region function. I assume you guys encountered nasty indentation by using nim-mode, but this example didn't get me the picture.

@m-cat

I also noticed this problem. It's strange because indent-region works correctly in python-mode, which nim-mode is based off of.

nim-mode inherited some code, but by the time, the indentation logic was replaced by nim-smie.el. (some features were still remaining though)

Indent region on a region destroys the logical blocks, and that is not what should happen, when indent-region is triggered on a pasted block of code.

FYI, I saw python-mode.el little bit, and it seems skipping indentation when the line starts specific identifiers like def, class, if, etc., but I'm not sure we could use same logic to nim-mode. Because of smie.el library, nim-mode has advanced indentation compared to python-mode. For example:

let x = if true:
          echo "foo"
        elif true:
          echo "bar"
        else:
          echo "buzz"

In above code, nim-mode can auto-indent correctly.

yuutayamada avatar Mar 05 '17 19:03 yuutayamada

I think the only thing, that really needs to be addressed is, that pastes should be indeted somehow, and I think that should not be too smart. I don't really know the internals of emacs, and how indentation works, but when I cut a block of code that starts on indentation level X, and then I move my cursor to a position with indentation level Y, the code block should be shifted vertically by Y-X to the right, so that newly inserted code blocks are indented correctly.

krux02 avatar Mar 05 '17 20:03 krux02

@yuutayamada, maybe indent-region must only fix explicit indent errors and must not touch the existing structure, as it was shown in the first message? For example, if I use 2 spaces for indent and paste some code with 4 spaces indent, I can select that block and use indent-region to fix it.

vegansk avatar Mar 06 '17 03:03 vegansk

@krux02 @vegansk

I think you guys should use "C-x C-i" (indent-rigidly) instead of indent-region in your cases.

yuutayamada avatar Mar 06 '17 08:03 yuutayamada

that is an interesting function indeed. Emacs has so many hidden features ...

krux02 avatar Mar 06 '17 14:03 krux02

Ok, here is another problem. The code:

  if url =~ parser:
    let params = @matches.filterIt(not it.isNil)
    case params.len
    of 1:# Cursor is here
  else:
    result = ("Malformed jdbc url: " & url).left(type(result.get))

The comment shows the position of cursor. And when I press enter, the code becomes:

  if url =~ parser:
    let params = @matches.filterIt(not it.isNil)
    case params.len
    of 1:
    # Cursor is here
    else:
    result = ("Malformed jdbc url: " & url).left(type(result.get))

Look at the else branch. It was reindented. But It shouldn't.

vegansk avatar Mar 07 '17 03:03 vegansk

@vegansk I tested your example, and I can't reproduce it. The else branch is not affectey by the newline.

krux02 avatar Mar 07 '17 15:03 krux02

Looks like it can be reproduced in spacemacs only

vegansk avatar Mar 08 '17 05:03 vegansk

After some investigations, I found the solution here:

(when (fboundp 'electric-indent-mode) (electric-indent-mode -1))

But now case branches stopped indenting and looks like:

case params.len
     of 1:

vegansk avatar Mar 09 '17 02:03 vegansk

@krux02, one more comment, else branch reindents after inserting ':' symbol, not the newline

vegansk avatar Mar 09 '17 03:03 vegansk

Well the else branch actually should indent to the same level as the case of branch, because the else brach is mandatory in almost all case of statements. While in your case it might be not what you want, I guess it's not that wrong. And to talk about spacemacs, I have no idea what it actually chages, so I can't really help with your problem.

krux02 avatar Mar 10 '17 00:03 krux02

@vegansk this may help about indenting previous line: link though nim-mode pre-configure that electric-indent-inhibit to set it to t.

regarding the ":", you may avoid the behavior following config:

(add-hook 'nim-mode-hook
          '(lambda () (setq-local electric-indent-chars '(?\s))))

but I'm not sure it really works for you because the ":"s behavior was implemented only for electric-indent-mode. (and you turned off it)

yuutayamada avatar Apr 01 '17 16:04 yuutayamada