nim-mode
nim-mode copied to clipboard
Indent problems
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
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.
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)
Well since I don't use spacemacs, I guess I don't have indent on paste enabled.
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.
@vegansk I don't understand your problem yet. what is the expected result?
@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.
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.
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.
@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.
@krux02 @vegansk
I think you guys should use "C-x C-i" (indent-rigidly
) instead of indent-region
in your cases.
that is an interesting function indeed. Emacs has so many hidden features ...
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 I tested your example, and I can't reproduce it. The else branch is not affectey by the newline.
Looks like it can be reproduced in spacemacs only
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:
@krux02, one more comment, else
branch reindents after inserting ':' symbol, not the newline
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.
@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)