Skip to content

Commit 773540c

Browse files
committed
Merge pull request #1290 from gracjan/or-indentation-fixes
Allow more indentation positions in haskell-indentation
2 parents 235b19b + b94cbc6 commit 773540c

File tree

2 files changed

+182
-139
lines changed

2 files changed

+182
-139
lines changed

haskell-indentation.el

+68-49
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,6 @@ fixes up only indentation."
355355
(defvar starter-indent) ;; column at a keyword
356356
(defvar current-indent) ;; the most right indentation
357357
(defvar layout-indent) ;; the column of the layout list
358-
(defvar parse-line-number) ;; the number of lines parsed
359358
(defvar possible-indentations) ;; the return value of the indentations
360359
(defvar indentation-point) ;; where to stop parsing
361360
(defvar implicit-layout-active) ;; is "off-side" rule active?
@@ -409,7 +408,6 @@ fixes up only indentation."
409408
(skip-syntax-forward "-")
410409
(let ((indentation-point (point))
411410
(layout-indent 0)
412-
(parse-line-number 0)
413411
(current-indent haskell-indentation-layout-offset)
414412
(starter-indent haskell-indentation-layout-offset)
415413
(left-indent haskell-indentation-layout-offset)
@@ -616,8 +614,9 @@ After a lambda (backslash) there are two possible cases:
616614
((eq current-token 'end-tokens)
617615
(when (member following-token
618616
'(value operator no-following-token
619-
"->" "(" "[" "{" "::"))
620-
(haskell-indentation-add-indentation current-indent))
617+
"(" "[" "{" "::"))
618+
(haskell-indentation-add-indentation current-indent)
619+
(haskell-indentation-add-indentation left-indent))
621620
(throw 'return nil))
622621
(t (let ((parser (assoc current-token haskell-indentation-type-list)))
623622
(if (not parser)
@@ -884,41 +883,46 @@ parser. If parsing ends here, set indentation to left-indent."
884883
(defun haskell-indentation-expression ()
885884
"Parse an expression until an unknown token is encountered."
886885
(catch 'return
887-
(while t
888-
(cond
889-
((memq current-token '(value operator))
890-
(haskell-indentation-read-next-token))
891-
((eq current-token 'end-tokens)
892-
(cond ((string= following-token "where")
893-
(haskell-indentation-add-where-pre-indent)) ; before a where
894-
((haskell-indentation-expression-token-p following-token)
895-
(haskell-indentation-add-indentation
896-
current-indent))) ; a normal expression
897-
(throw 'return nil))
898-
(t (let ((parser (assoc current-token
899-
haskell-indentation-expression-list)))
900-
(when (null parser)
901-
(throw 'return nil)) ; not expression token, so exit
902-
(funcall (cdr parser)) ; run parser
903-
(when (and (eq current-token 'end-tokens)
904-
(string= (car parser) "let")
905-
(= haskell-indentation-layout-offset current-indent)
906-
(haskell-indentation-expression-token-p following-token))
907-
;; inside a layout, after a let construct
908-
;; for example: "do let a = 20"
909-
(haskell-indentation-add-layout-indent)
910-
(throw 'parse-end nil))
911-
;; after an 'open' expression such as 'if', exit
912-
(unless (member (car parser) '("(" "[" "{" "case"))
913-
(throw 'return nil))))))))
886+
(let ((current-indent (current-column)))
887+
(while t
888+
(cond
889+
((memq current-token '(value operator))
890+
(haskell-indentation-read-next-token))
891+
((eq current-token 'end-tokens)
892+
(cond ((string= following-token "where")
893+
(haskell-indentation-add-where-pre-indent)) ; before a where
894+
((haskell-indentation-expression-token-p following-token)
895+
;; a normal expression can be either continued or have
896+
;; left indent
897+
(haskell-indentation-add-indentation
898+
current-indent)
899+
(haskell-indentation-add-indentation
900+
left-indent)))
901+
(throw 'return nil))
902+
(t (let ((parser (assoc current-token
903+
haskell-indentation-expression-list)))
904+
(when (null parser)
905+
(throw 'return nil)) ; not expression token, so exit
906+
(funcall (cdr parser)) ; run parser
907+
(when (and (eq current-token 'end-tokens)
908+
(string= (car parser) "let")
909+
(= haskell-indentation-layout-offset current-indent)
910+
(haskell-indentation-expression-token-p following-token))
911+
;; inside a layout, after a let construct
912+
;; for example: "do let a = 20"
913+
(haskell-indentation-add-layout-indent)
914+
(throw 'parse-end nil))
915+
;; after an 'open' expression such as 'if', exit
916+
(unless (member (car parser) '("(" "[" "{" "case"))
917+
(throw 'return nil)))))))))
914918

915919
(defun haskell-indentation-separated (parser separator &optional stmt-separator)
916920
"Evaluate PARSER separated by SEPARATOR and STMT-SEPARATOR.
917921
If STMT-SEPARATOR is not NIL, it will be used to set a new starter-indent.
918922
919923
For example:
920924
921-
[ i | i <- [1..10]
925+
[ i | i <- [1..10]
922926
,"
923927
(catch 'return
924928
(unless (listp separator)
@@ -935,13 +939,21 @@ For example:
935939
(haskell-indentation-at-separator))
936940

937941
((eq current-token 'end-tokens)
938-
(cond ((or (member following-token separator)
939-
(member following-token stmt-separator))
940-
;; Set an indentation before a separator, for example:
941-
;; [ 1 or [ 1 | a
942-
;; , 2 , 20
943-
(haskell-indentation-add-indentation starter-indent)
944-
(throw 'parse-end nil)))
942+
(when (or (member following-token separator)
943+
(member following-token stmt-separator))
944+
;; Set an indentation before a separator, for example:
945+
;; [ 1 or [ 1 | a
946+
;; , 2 , 20
947+
(haskell-indentation-add-indentation starter-indent)
948+
(when (< left-indent starter-indent)
949+
(haskell-indentation-add-indentation left-indent))
950+
(throw 'parse-end nil))
951+
(when (equal following-token 'no-following-token)
952+
;; Set an indentation before a separator, for example:
953+
;; [ 1 or [ 1 | a
954+
;; , 2 , 20
955+
(haskell-indentation-add-indentation starter-indent)
956+
(haskell-indentation-add-indentation left-indent))
945957
(throw 'return nil))
946958
(t (throw 'return nil))))))
947959

@@ -960,6 +972,7 @@ l = [ 1
960972
(haskell-indentation-read-next-token)
961973
(cond ((eq current-token 'end-tokens)
962974
(haskell-indentation-add-indentation current-indent)
975+
(haskell-indentation-add-indentation left-indent)
963976
(throw 'return nil))
964977
(separator-column ; on the beginning of the line
965978
(setq current-indent (current-column))
@@ -1024,16 +1037,20 @@ layout starts."
10241037
(defun haskell-indentation-phrase-rest (phrase1)
10251038
"" ; FIXME
10261039
(while phrase1
1027-
(let ((starter-line parse-line-number)
1028-
(phrase phrase1))
1040+
(let ((phrase phrase1))
10291041
(setq phrase1 nil)
1030-
(let ((current-indent (current-column)))
1042+
(let ((current-indent (current-column))
1043+
(left-indent left-indent)
1044+
(layout-indent layout-indent))
10311045
(funcall (car phrase)))
10321046
(cond
10331047
((eq current-token 'end-tokens)
10341048
(cond ((null (cdr phrase))) ;; fallthrough
10351049
((equal following-token (cadr phrase))
10361050
(haskell-indentation-add-indentation starter-indent)
1051+
(unless (member following-token '("," ";"))
1052+
;; we want to keep comma and semicolon aligned always
1053+
(haskell-indentation-add-indentation left-indent))
10371054
(throw 'parse-end nil))
10381055
((string= (cadr phrase) "in")
10391056
(when (= left-indent layout-indent)
@@ -1082,11 +1099,13 @@ layout starts."
10821099
(+ left-indent haskell-indentation-left-offset)))
10831100

10841101
(defun haskell-indentation-push-indentation (indent)
1085-
"" ; FIXME
1086-
(when (or (null possible-indentations)
1087-
(< indent (car possible-indentations)))
1102+
"Add INDENT to list of possible indentations.
1103+
1104+
Add INDENT to `possible-indentations' if it is not there
1105+
yet. Keep the list in ascending order."
1106+
(unless (member indent possible-indentations)
10881107
(setq possible-indentations
1089-
(cons indent possible-indentations))))
1108+
(sort (cons indent possible-indentations) #'<))))
10901109

10911110
(defun haskell-indentation-read-next-token ()
10921111
"Go to the next token and set current-token to the next token.
@@ -1131,14 +1150,14 @@ line."
11311150
(if (>= (point) indentation-point)
11321151
(progn
11331152
(setq following-token
1134-
(if (= (point) indentation-point)
1153+
(if (and (not (eobp))
1154+
(= (point) indentation-point))
11351155
(haskell-indentation-peek-token)
11361156
'no-following-token))
11371157
(setq current-token 'end-tokens))
11381158
(when (= (current-column) (haskell-indentation-current-indentation))
11391159
;; on a new line
1140-
(setq current-indent (current-column))
1141-
(setq parse-line-number (+ parse-line-number 1)))
1160+
(setq current-indent (current-column)))
11421161
(cond ((and implicit-layout-active
11431162
(> layout-indent (current-column)))
11441163
(setq current-token 'layout-end))

0 commit comments

Comments
 (0)