Skip to content

Commit 18544d4

Browse files
committed
Implement standalone deriving indentation
1 parent cff017b commit 18544d4

File tree

2 files changed

+72
-15
lines changed

2 files changed

+72
-15
lines changed

haskell-indentation.el

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,8 @@ fixes up only indentation."
496496
("newtype" . haskell-indentation-data)
497497
("import" . haskell-indentation-import)
498498
("class" . haskell-indentation-class-declaration)
499-
("instance" . haskell-indentation-class-declaration))
499+
("instance" . haskell-indentation-class-declaration)
500+
("deriving" . haskell-indentation-deriving))
500501
"Alist of toplevel keywords with associated parsers.")
501502

502503
(defconst haskell-indentation-type-list
@@ -635,6 +636,25 @@ After a lambda (backslash) there are two possible cases:
635636
(throw 'return nil)
636637
(funcall (cdr parser))))))))))
637638

639+
(defun haskell-indentation-type-1 ()
640+
"Parse a single type declaration."
641+
(let ((current-indent (current-column)))
642+
(catch 'return
643+
(cond
644+
((member current-token '(value operator "->"))
645+
(haskell-indentation-read-next-token))
646+
647+
((eq current-token 'end-tokens)
648+
(when (member following-token
649+
'(value operator no-following-token
650+
"->" "(" "[" "{" "::"))
651+
(haskell-indentation-add-indentation current-indent))
652+
(throw 'return nil))
653+
(t (let ((parser (assoc current-token haskell-indentation-type-list)))
654+
(if (not parser)
655+
(throw 'return nil)
656+
(funcall (cdr parser)))))))))
657+
638658
(defun haskell-indentation-scoped-type ()
639659
"Parse scoped type declaration.
640660
@@ -657,13 +677,30 @@ For example
657677
(haskell-indentation-add-indentation current-indent)
658678
(throw 'parse-end nil)))
659679
((string= current-token "=")
660-
(haskell-indentation-with-starter
661-
(lambda ()
662-
(haskell-indentation-separated
663-
#'haskell-indentation-expression "|" "deriving"))))
680+
(let ((starter-indent-inside (current-column)))
681+
(haskell-indentation-with-starter
682+
(lambda ()
683+
(haskell-indentation-separated
684+
#'haskell-indentation-expression "|")))
685+
(cond
686+
((equal current-token 'end-tokens)
687+
(when (string= following-token "deriving")
688+
(haskell-indentation-push-indentation starter-indent-inside)
689+
(haskell-indentation-add-left-indent)))
690+
((equal current-token "deriving")
691+
(haskell-indentation-with-starter
692+
#'haskell-indentation-type-1)))))
664693
((string= current-token "where")
665-
(haskell-indentation-with-starter
666-
#'haskell-indentation-expression-layout nil))))
694+
(let ((starter-indent-inside (current-column)))
695+
(haskell-indentation-with-starter
696+
#'haskell-indentation-expression-layout nil)
697+
(cond
698+
((equal current-token 'end-tokens)
699+
(when (string= following-token "deriving")
700+
(haskell-indentation-add-left-indent)))
701+
((equal current-token "deriving")
702+
(haskell-indentation-with-starter
703+
#'haskell-indentation-type-1)))))))
667704

668705
(defun haskell-indentation-import ()
669706
"Parse import declaration."
@@ -680,6 +717,19 @@ For example
680717
(haskell-indentation-with-starter
681718
#'haskell-indentation-declaration-layout nil)))))
682719

720+
(defun haskell-indentation-deriving ()
721+
"Parse standalone declaration."
722+
(haskell-indentation-with-starter
723+
(lambda ()
724+
(when (string= "instance" current-token)
725+
(haskell-indentation-read-next-token))
726+
(when (equal current-token 'end-tokens)
727+
(haskell-indentation-add-left-indent)
728+
(throw 'parse-end nil))
729+
(haskell-indentation-type)
730+
(when (string= current-token "|")
731+
(haskell-indentation-fundep)))))
732+
683733
(defun haskell-indentation-module ()
684734
"Parse module declaration."
685735
(haskell-indentation-with-starter

tests/haskell-indentation-tests.el

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -320,19 +320,26 @@ fun = do { putStrLn \"X\";
320320
(2 9 11)
321321
(3 0))
322322

323-
(hindent-test "13a* Deriving on new line""
323+
(hindent-test "13a Deriving on new line""
324324
data X = X | Y
325325
deriving (Eq, Ord, Show)"
326326
(1 0)
327-
(2 2))
327+
(2 0 2 7))
328328

329-
(hindent-test "13b* Don't indent after deriving""
329+
(hindent-test "13b Don't indent after deriving""
330330
data X = X
331331
deriving (Eq, Ord, Show)"
332332
(1 0)
333-
(2 2)
333+
(2 0 2 7)
334334
(3 0))
335335

336+
(hindent-test "13bb Don't indent after deriving""
337+
data X = X
338+
deriving"
339+
(1 0)
340+
(2 0 2 7)
341+
(3 4))
342+
336343
(hindent-test "13c honour = on a separate line in data declaration" "
337344
data X a b
338345
= X"
@@ -869,22 +876,22 @@ data Term a where
869876
(3 0 2 9)
870877
(4 0 2 10))
871878

872-
(hindent-test "49b* data with GADT syntax and a deriving clause" "
879+
(hindent-test "49b data with GADT syntax and a deriving clause" "
873880
data G [a] b where
874881
G1 :: c -> G [Int] b
875882
deriving (Eq)"
876883
(1 0)
877884
(2 2)
878885
(3 0 2))
879886

880-
(hindent-test "50* standalone deriving" "
887+
(hindent-test "50 standalone deriving" "
881888
data Name = Name String
882889
deriving instance Eq Name"
883890
(1 0)
884891
;; We accept position 2 here because we have just one
885892
;; look-ahead token so we do not see 'instance'
886893
;; following 'deriving'.
887-
(2 0 2))
894+
(2 0 2 10))
888895

889896
(hindent-test "51 standalone deriving" "
890897
data family T a
@@ -950,7 +957,7 @@ data Foo = Bar
950957
deriving (Show)"
951958
(1 0)
952959
(2 9)
953-
(3 9))
960+
(3 0 2 9))
954961

955962
(ert-deftest haskell-indentation-ret-indents ()
956963
(with-temp-switch-to-buffer

0 commit comments

Comments
 (0)