-
Notifications
You must be signed in to change notification settings - Fork 347
Redefining evil-open-above for Haskell (spacemacs) #896
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is super annoying, any ideas on how to fix? It would be less annoying if you didn't have to press TAB twice... |
The 'twice' part is a misarchitecture in https://github.com/haskell/haskell-mode/blob/master/haskell-indentation.el#L236 . Can be fixed, just somebody needs to sit down and write a specification how this is supposed to work. |
It annoys me too (: |
I also have similar issues with |
I did some research on the Spacemacs issue concerning As far as I understood, the function responsible to indent the line after Calling foo :: a
| will indent it "wrongly" to: foo :: a
| I think it's where issues with I don't know haskell very well, but I suppose you can improve it to do like python, deducing the information from context. For instance in a signature line end with foo :: a
|
bar :: a ->
| Not sure if it's valid Haskell at all 😄, but you get the idea I hope. FYI Python is doing something like this to have a smarter indentation, by looking at block ender ( I hope it's helpful. |
It's valid Haskell, but so is: foo :: Int
-> Int
foo = succ
bar :: Either String
Int -> Either String Int
bar = fmap (+2) So even without a |
Ok, but there may be some better approaches though, like using the statistically most probable indentation to diminish the need of using I don't have special opinion on this, as I said I'm not doing Haskell, so I let you discuss this inbetween interested people 😃 |
Normally it does just indent to the 0th column. Evil is an exception as it uses Changing the indentation function when using Evil to something similar to what the above does to: (defun haskell-indentation-indent-line ()
"Indent current line, cycle though indentation positions.
Do nothing inside multiline comments and multiline strings.
Start enumerating the indentation points to the right. The user
can continue by repeatedly pressing TAB. When there is no more
indentation points to the right, we switch going to the left."
(interactive)
;; try to repeat
(when (not (haskell-indentation-indent-line-repeat))
(setq haskell-indentation-dyn-last-direction nil)
;; parse error is intentionally not caught here, it may come from
;; `haskell-indentation-find-indentations', but escapes the scope
;; and aborts the operation before any moving happens
(let* ((cc (current-column))
(ci (haskell-indentation-current-indentation))
(inds (save-excursion
(move-to-column ci)
(or (haskell-indentation-find-indentations)
'(0))))
(valid (memq ci inds))
(cursor-in-whitespace (< cc ci))
(evil-special-command? (and (bound-and-true-p evil-mode)
(memq this-command '(evil-open-above
evil-open-below
evil-replace))))
(on-last-indent (eq ci (car (last inds)))))
(if (and valid cursor-in-whitespace)
(move-to-column ci)
(haskell-indentation-reindent-to
(funcall
(if on-last-indent
#'haskell-indentation-previous-indentation
#'haskell-indentation-next-indentation)
(if evil-special-command?
(save-excursion
(end-of-line 0)
(1- (haskell-indentation-current-indentation)))
ci)
inds
'nofail)
cursor-in-whitespace))
(setq haskell-indentation-dyn-last-direction (if on-last-indent 'left 'right)
haskell-indentation-dyn-last-indentations inds)))) should work though. A few Evil users should test this out and see if it works for them.
|
emacs noob here. Would just dumping this code into my |
You can just paste it into any buffer (scratch is usually for these things), and press C-x C-e at the end of the function(s) if you just want the effects temporarily for one Emacs session. |
Yeah, just dumped into scratch. Thanks! My initial impression is that this is much better. Something sorta interesting in just testing right now, when I'm in the middle of a |
Yeah, that would make sense. I updated the first function. Hopefully it should work this time. |
Oh wow! This is fantastic. Just noticed while playing around:
If you do open below on the line with
Having the weird hanging import thing confuses it. |
That seems to be an unrelated bug. Did you find any other issues? Also, I found a way to make it so that Evil guys don't have to press TAB twice anymore. You don't have to use/change the 2nd function now. You can find that version above. |
@fice-t, Nice! Can you create a test suite for this cycle function? |
I don't know, it might be best if someone with more knowledge in the area than myself would do that. I'm just doing a hack job on top of what's already there. In other news, I updated the above function with one does away with pressing TAB twice on the last indent position. There's a side effect of the function looking a lot worse, but hey. Both Evil/non-Evil people should test it out. Oh, and what should main = do
something
where -- cursor is here
something = putStrLn "Hello" Should it indent lining up to the |
|
I don't think either case would make it empty. I just changed it to indent to |
@fice-t: Can you create a pull request out of this, with unit tests and whatnot? |
Maybe it is possible to change the implementation of In fact, modes with significant whitespace like haskell and python usually make the trouble. That said, it might be possible (and maybe it's a good idea) to make Of course, we could tweak haskell-mode, but I would prefer that Evil "just works" without special adaptions. There are no guarantees that Evil's implementation remains as it is now ;) (I'm the current main developer of Evil) |
That sounds nice. I edited I can imagine this may cause issues elsewhere, but at least it means that it can be done somehow. Using |
@Lyro thanks for your quick response! (: |
(defun evil-open-above (count)
"Insert a new line above point and switch to Insert state.
The insertion will be repeated COUNT times."
(interactive "p")
(evil-insert-newline-above)
(setq evil-insert-count count
evil-insert-lines t
evil-insert-vcount nil)
(evil-insert-state 1)
(add-hook 'post-command-hook #'evil-maybe-remove-spaces)
(when evil-auto-indent
(indent-according-to-mode)))
(defun evil-open-below (count)
"Insert a new line below point and switch to Insert state.
The insertion will be repeated COUNT times."
(interactive "p")
(push (point) buffer-undo-list)
(evil-insert-newline-below)
(setq evil-insert-count count
evil-insert-lines t
evil-insert-vcount nil)
(evil-insert-state 1)
(add-hook 'post-command-hook #'evil-maybe-remove-spaces)
(when evil-auto-indent
(indent-according-to-mode))) So it seems that |
Closing in favor of #1265 where we will track the real solution. |
Yet another electric-indent problem:
syl20bnr/spacemacs#3162
The text was updated successfully, but these errors were encountered: