Skip to content

Commit 84cc626

Browse files
committed
Merge pull request #1276 from gracjan/pr-standalone-deriving-indentation
Implement standalone deriving indentation
2 parents 40b1df7 + 18544d4 commit 84cc626

File tree

2 files changed

+72
-15
lines changed

2 files changed

+72
-15
lines changed

haskell-indentation.el

+57-7
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,8 @@ fixes up only indentation."
494494
("newtype" . haskell-indentation-data)
495495
("import" . haskell-indentation-import)
496496
("class" . haskell-indentation-class-declaration)
497-
("instance" . haskell-indentation-class-declaration))
497+
("instance" . haskell-indentation-class-declaration)
498+
("deriving" . haskell-indentation-deriving))
498499
"Alist of toplevel keywords with associated parsers.")
499500

500501
(defconst haskell-indentation-type-list
@@ -633,6 +634,25 @@ After a lambda (backslash) there are two possible cases:
633634
(throw 'return nil)
634635
(funcall (cdr parser))))))))))
635636

637+
(defun haskell-indentation-type-1 ()
638+
"Parse a single type declaration."
639+
(let ((current-indent (current-column)))
640+
(catch 'return
641+
(cond
642+
((member current-token '(value operator "->"))
643+
(haskell-indentation-read-next-token))
644+
645+
((eq current-token 'end-tokens)
646+
(when (member following-token
647+
'(value operator no-following-token
648+
"->" "(" "[" "{" "::"))
649+
(haskell-indentation-add-indentation current-indent))
650+
(throw 'return nil))
651+
(t (let ((parser (assoc current-token haskell-indentation-type-list)))
652+
(if (not parser)
653+
(throw 'return nil)
654+
(funcall (cdr parser)))))))))
655+
636656
(defun haskell-indentation-scoped-type ()
637657
"Parse scoped type declaration.
638658
@@ -655,13 +675,30 @@ For example
655675
(haskell-indentation-add-indentation current-indent)
656676
(throw 'parse-end nil)))
657677
((string= current-token "=")
658-
(haskell-indentation-with-starter
659-
(lambda ()
660-
(haskell-indentation-separated
661-
#'haskell-indentation-expression "|" "deriving"))))
678+
(let ((starter-indent-inside (current-column)))
679+
(haskell-indentation-with-starter
680+
(lambda ()
681+
(haskell-indentation-separated
682+
#'haskell-indentation-expression "|")))
683+
(cond
684+
((equal current-token 'end-tokens)
685+
(when (string= following-token "deriving")
686+
(haskell-indentation-push-indentation starter-indent-inside)
687+
(haskell-indentation-add-left-indent)))
688+
((equal current-token "deriving")
689+
(haskell-indentation-with-starter
690+
#'haskell-indentation-type-1)))))
662691
((string= current-token "where")
663-
(haskell-indentation-with-starter
664-
#'haskell-indentation-expression-layout nil))))
692+
(let ((starter-indent-inside (current-column)))
693+
(haskell-indentation-with-starter
694+
#'haskell-indentation-expression-layout nil)
695+
(cond
696+
((equal current-token 'end-tokens)
697+
(when (string= following-token "deriving")
698+
(haskell-indentation-add-left-indent)))
699+
((equal current-token "deriving")
700+
(haskell-indentation-with-starter
701+
#'haskell-indentation-type-1)))))))
665702

666703
(defun haskell-indentation-import ()
667704
"Parse import declaration."
@@ -678,6 +715,19 @@ For example
678715
(haskell-indentation-with-starter
679716
#'haskell-indentation-declaration-layout nil)))))
680717

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

tests/haskell-indentation-tests.el

+15-8
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)