Open gracjan opened 8 years ago
I thought this was going to be solved upstream in Evil?
The issue there, from what I can remember, is that in haskell-mode haskell-indentation-newline-and-indent
uses haskell-indentation-find-indentations
on the end of the line before entering the newline.
This gives different results compared to the evil-open-
case where it does (newline)
then (indent-according-to-mode)
.
So if this was to be fixed here, then I believe changing the behaviour of haskell-indentation-find-indentations
such that haskell-indentation-newline-and-indent
is unnecessary would work.
The point is to change the behaviour of haskell-indentation-find-indentations such that haskell-indentation-newline-and-indent is unnecessary would work.
So newline-and-indent
takes previous line indentation and indents at least that amount or more.
Hi, do you remember if there is an easy workaround for this issue (while waiting for a full resolution ?)
@PierreR Does the following patch work for you? I haven't touched it since February, but it worked then:
diff --git a/haskell-indentation.el b/haskell-indentation.el
index 03c5348..b174006 100644
--- a/haskell-indentation.el
+++ b/haskell-indentation.el
@@ -253,14 +253,30 @@ indentation points to the right, we switch going to the left."
(or (haskell-indentation-find-indentations)
'(0))))
(valid (memq ci inds))
- (cursor-in-whitespace (< cc ci)))
-
+ (cursor-in-whitespace (< cc ci))
+ ;; certain evil commands need the behaviour seen in
+ ;; `haskell-indentation-newline-and-indent'
+ (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
- (haskell-indentation-next-indentation ci inds 'nofail)
+ (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 'right
+ (setq haskell-indentation-dyn-last-direction (if on-last-indent 'left 'right)
haskell-indentation-dyn-last-indentations inds))))
(defun haskell-indentation-indent-line-repeat ()
The code below works at least for my use cases. I'm quite new at Emacs and Emacs Lisp, so there could be something ridiculous in the code. Hope it can help somebody though :)
(defun haskell-evil-open-above ()
(interactive)
(evil-digit-argument-or-evil-beginning-of-line)
(haskell-indentation-newline-and-indent)
(evil-previous-line)
(haskell-indentation-indent-line)
(evil-append-line nil))
(defun haskell-evil-open-below ()
(interactive)
(evil-append-line nil)
(haskell-indentation-newline-and-indent))
(evil-define-key 'normal haskell-mode-map "o" 'haskell-evil-open-below
"O" 'haskell-evil-open-above)
@noraesae I tried your code and it's much better, but there is one small problem. When opening line above ('O') at a top-level statements the indent is 2 not 0. Take this example:
partitionM :: (Applicative m) => (a -> m Bool) -> [a] -> m ([a], [a])
partitionM p = foldr f $ pure ([],[]) ...
If you go to line 2 (partitionM p = ...
), then press 'O', then the cursor is indented two spaces:
partitionM :: (Applicative m) => (a -> m Bool) -> [a] -> m ([a], [a])
|<- cursor is here
partitionM p = foldr f $ pure ([],[]) ...
The same applies for opening line above ('O') at line 1 (function signature). Opening line below seem to work correctly.
I created a question on the emacs stack exchange asking about indentation in haskell-mode. It appears that this is the bug in question:
Is @utatti's suggested solution still the best way to work-around this bug?
(defun haskell-evil-open-above ()
(interactive)
(evil-digit-argument-or-evil-beginning-of-line)
(haskell-indentation-newline-and-indent)
(evil-previous-line)
(haskell-indentation-indent-line)
(evil-append-line nil))
(defun haskell-evil-open-below ()
(interactive)
(evil-append-line nil)
(haskell-indentation-newline-and-indent))
(evil-define-key 'normal haskell-mode-map "o" 'haskell-evil-open-below
"O" 'haskell-evil-open-above)
haskell-indentation-newline-and-indent works nice here with the example given. Maybe close this?
Why does evil-open-below
!=
A<RET>
? As a dumb user, this is annoying and it would be great if it was fixed properly so it just worked :D
Anyone have any idea on how to fix this for org-babel source blocks? Getting weird behaviors there.
The same problem occurs with typescript-mode.
I got so sick of this I've rebound o
to A RET
:
(defun hly/evil-open-below (count)
"Simulate evil’s o using ‘A RET’.
Evil’s native \\[evil-open-below] is too unreliable in the face of various
major
modes messing with indenting. This bruteforces it by relying on (the more
reliable) RET, instead.
See:
- https://github.com/haskell/haskell-mode/issues/1265
- https://emacs.stackexchange.com/a/2471
"
(interactive "p")
(setq unread-command-events (listify-key-sequence (kbd "RET")))
(evil-append-line count))
(defun hly/evil-open-above (count)
"Simulate evil’s O using ‘UP A RET’.
Evil’s native \\[evil-open-above] is too unreliable in the face of various major
modes messing with indenting. This bruteforces it by relying on (the more
reliable) RET, instead.
Doesn’t work on the first line of a file.
"
(interactive "p")
(forward-line -1)
(hly/evil-open-below count))
(define-key evil-normal-state-map "o" 'hly/evil-open-below)
(define-key evil-normal-state-map "O" 'hly/evil-open-above)
Besides what @hraban wrote I also needed:
(with-eval-after-load "haskell-mode"
(evil-define-key 'normal haskell-mode-map "o" 'hly/evil-open-below)
(evil-define-key 'normal haskell-mode-map "O" 'hly/evil-open-above))
indent-according-to-mode
is called in:newline-and-indent
.electric-indent-mode
after\n
has been inserted.evil-open-above
.evil-open-below
.Each of these cases is same: it is to semantically continue previous line. So we need:
Note that
haskell-indentation
already hashaskell-indentation-newline-and-indent
that touches this problem but hard to say how good it is.Reference: https://github.com/syl20bnr/spacemacs/issues/5010, https://github.com/syl20bnr/spacemacs/issues/621, https://github.com/syl20bnr/spacemacs/issues/3162, https://github.com/haskell/haskell-mode/issues/896