Skip to content

Commit

Permalink
Merge pull request haskell#1290 from gracjan/or-indentation-fixes
Browse files Browse the repository at this point in the history
Allow more indentation positions in haskell-indentation
  • Loading branch information
gracjan committed Apr 25, 2016
2 parents 235b19b + b94cbc6 commit 773540c
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 139 deletions.
117 changes: 68 additions & 49 deletions haskell-indentation.el
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,6 @@ fixes up only indentation."
(defvar starter-indent) ;; column at a keyword
(defvar current-indent) ;; the most right indentation
(defvar layout-indent) ;; the column of the layout list
(defvar parse-line-number) ;; the number of lines parsed
(defvar possible-indentations) ;; the return value of the indentations
(defvar indentation-point) ;; where to stop parsing
(defvar implicit-layout-active) ;; is "off-side" rule active?
Expand Down Expand Up @@ -409,7 +408,6 @@ fixes up only indentation."
(skip-syntax-forward "-")
(let ((indentation-point (point))
(layout-indent 0)
(parse-line-number 0)
(current-indent haskell-indentation-layout-offset)
(starter-indent haskell-indentation-layout-offset)
(left-indent haskell-indentation-layout-offset)
Expand Down Expand Up @@ -616,8 +614,9 @@ After a lambda (backslash) there are two possible cases:
((eq current-token 'end-tokens)
(when (member following-token
'(value operator no-following-token
"->" "(" "[" "{" "::"))
(haskell-indentation-add-indentation current-indent))
"(" "[" "{" "::"))
(haskell-indentation-add-indentation current-indent)
(haskell-indentation-add-indentation left-indent))
(throw 'return nil))
(t (let ((parser (assoc current-token haskell-indentation-type-list)))
(if (not parser)
Expand Down Expand Up @@ -884,41 +883,46 @@ parser. If parsing ends here, set indentation to left-indent."
(defun haskell-indentation-expression ()
"Parse an expression until an unknown token is encountered."
(catch 'return
(while t
(cond
((memq current-token '(value operator))
(haskell-indentation-read-next-token))
((eq current-token 'end-tokens)
(cond ((string= following-token "where")
(haskell-indentation-add-where-pre-indent)) ; before a where
((haskell-indentation-expression-token-p following-token)
(haskell-indentation-add-indentation
current-indent))) ; a normal expression
(throw 'return nil))
(t (let ((parser (assoc current-token
haskell-indentation-expression-list)))
(when (null parser)
(throw 'return nil)) ; not expression token, so exit
(funcall (cdr parser)) ; run parser
(when (and (eq current-token 'end-tokens)
(string= (car parser) "let")
(= haskell-indentation-layout-offset current-indent)
(haskell-indentation-expression-token-p following-token))
;; inside a layout, after a let construct
;; for example: "do let a = 20"
(haskell-indentation-add-layout-indent)
(throw 'parse-end nil))
;; after an 'open' expression such as 'if', exit
(unless (member (car parser) '("(" "[" "{" "case"))
(throw 'return nil))))))))
(let ((current-indent (current-column)))
(while t
(cond
((memq current-token '(value operator))
(haskell-indentation-read-next-token))
((eq current-token 'end-tokens)
(cond ((string= following-token "where")
(haskell-indentation-add-where-pre-indent)) ; before a where
((haskell-indentation-expression-token-p following-token)
;; a normal expression can be either continued or have
;; left indent
(haskell-indentation-add-indentation
current-indent)
(haskell-indentation-add-indentation
left-indent)))
(throw 'return nil))
(t (let ((parser (assoc current-token
haskell-indentation-expression-list)))
(when (null parser)
(throw 'return nil)) ; not expression token, so exit
(funcall (cdr parser)) ; run parser
(when (and (eq current-token 'end-tokens)
(string= (car parser) "let")
(= haskell-indentation-layout-offset current-indent)
(haskell-indentation-expression-token-p following-token))
;; inside a layout, after a let construct
;; for example: "do let a = 20"
(haskell-indentation-add-layout-indent)
(throw 'parse-end nil))
;; after an 'open' expression such as 'if', exit
(unless (member (car parser) '("(" "[" "{" "case"))
(throw 'return nil)))))))))

(defun haskell-indentation-separated (parser separator &optional stmt-separator)
"Evaluate PARSER separated by SEPARATOR and STMT-SEPARATOR.
If STMT-SEPARATOR is not NIL, it will be used to set a new starter-indent.
For example:
[ i | i <- [1..10]
[ i | i <- [1..10]
,"
(catch 'return
(unless (listp separator)
Expand All @@ -935,13 +939,21 @@ For example:
(haskell-indentation-at-separator))

((eq current-token 'end-tokens)
(cond ((or (member following-token separator)
(member following-token stmt-separator))
;; Set an indentation before a separator, for example:
;; [ 1 or [ 1 | a
;; , 2 , 20
(haskell-indentation-add-indentation starter-indent)
(throw 'parse-end nil)))
(when (or (member following-token separator)
(member following-token stmt-separator))
;; Set an indentation before a separator, for example:
;; [ 1 or [ 1 | a
;; , 2 , 20
(haskell-indentation-add-indentation starter-indent)
(when (< left-indent starter-indent)
(haskell-indentation-add-indentation left-indent))
(throw 'parse-end nil))
(when (equal following-token 'no-following-token)
;; Set an indentation before a separator, for example:
;; [ 1 or [ 1 | a
;; , 2 , 20
(haskell-indentation-add-indentation starter-indent)
(haskell-indentation-add-indentation left-indent))
(throw 'return nil))
(t (throw 'return nil))))))

Expand All @@ -960,6 +972,7 @@ l = [ 1
(haskell-indentation-read-next-token)
(cond ((eq current-token 'end-tokens)
(haskell-indentation-add-indentation current-indent)
(haskell-indentation-add-indentation left-indent)
(throw 'return nil))
(separator-column ; on the beginning of the line
(setq current-indent (current-column))
Expand Down Expand Up @@ -1024,16 +1037,20 @@ layout starts."
(defun haskell-indentation-phrase-rest (phrase1)
"" ; FIXME
(while phrase1
(let ((starter-line parse-line-number)
(phrase phrase1))
(let ((phrase phrase1))
(setq phrase1 nil)
(let ((current-indent (current-column)))
(let ((current-indent (current-column))
(left-indent left-indent)
(layout-indent layout-indent))
(funcall (car phrase)))
(cond
((eq current-token 'end-tokens)
(cond ((null (cdr phrase))) ;; fallthrough
((equal following-token (cadr phrase))
(haskell-indentation-add-indentation starter-indent)
(unless (member following-token '("," ";"))
;; we want to keep comma and semicolon aligned always
(haskell-indentation-add-indentation left-indent))
(throw 'parse-end nil))
((string= (cadr phrase) "in")
(when (= left-indent layout-indent)
Expand Down Expand Up @@ -1082,11 +1099,13 @@ layout starts."
(+ left-indent haskell-indentation-left-offset)))

(defun haskell-indentation-push-indentation (indent)
"" ; FIXME
(when (or (null possible-indentations)
(< indent (car possible-indentations)))
"Add INDENT to list of possible indentations.
Add INDENT to `possible-indentations' if it is not there
yet. Keep the list in ascending order."
(unless (member indent possible-indentations)
(setq possible-indentations
(cons indent possible-indentations))))
(sort (cons indent possible-indentations) #'<))))

(defun haskell-indentation-read-next-token ()
"Go to the next token and set current-token to the next token.
Expand Down Expand Up @@ -1131,14 +1150,14 @@ line."
(if (>= (point) indentation-point)
(progn
(setq following-token
(if (= (point) indentation-point)
(if (and (not (eobp))
(= (point) indentation-point))
(haskell-indentation-peek-token)
'no-following-token))
(setq current-token 'end-tokens))
(when (= (current-column) (haskell-indentation-current-indentation))
;; on a new line
(setq current-indent (current-column))
(setq parse-line-number (+ parse-line-number 1)))
(setq current-indent (current-column)))
(cond ((and implicit-layout-active
(> layout-indent (current-column)))
(setq current-token 'layout-end))
Expand Down
Loading

0 comments on commit 773540c

Please sign in to comment.