Last active
August 29, 2015 14:19
-
-
Save BJTerry/13477b152b8202f33d0c to your computer and use it in GitHub Desktop.
Make erlang-mode not double-indent after a fun ->
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defun erlang-calculate-stack-indent (indent-point state) | |
"From the given last position and state (stack) calculate indentation. | |
Return nil if inside string, t if in a comment." | |
(let* ((stack (and state (car state))) | |
(token (nth 1 state)) | |
(stack-top (and stack (car stack)))) | |
(cond ((null state) ;No state | |
0) | |
((nth 3 state) | |
;; Return nil or t. | |
(eq (nth 3 state) 'comment)) | |
((null stack) | |
(if (looking-at "when[^_a-zA-Z0-9]") | |
erlang-indent-guard | |
0)) | |
((eq (car stack-top) '\() | |
;; Element of list, tuple or part of an expression, | |
(cond ((null erlang-argument-indent) | |
;; indent to next column. | |
(1+ (nth 2 stack-top))) | |
((= (char-syntax (following-char)) ?\)) | |
(goto-char (nth 1 stack-top)) | |
(cond ((looking-at "[({]\\s *\\($\\|%\\)") | |
;; Line ends with parenthesis. | |
(let ((previous (erlang-indent-find-preceding-expr)) | |
(stack-pos (nth 2 stack-top))) | |
(if (>= previous stack-pos) stack-pos | |
(- (+ previous erlang-argument-indent) 1)))) | |
(t | |
(nth 2 stack-top)))) | |
((= (following-char) ?,) | |
;; a comma at the start of the line: line up with opening parenthesis. | |
(nth 2 stack-top)) | |
(t | |
(goto-char (nth 1 stack-top)) | |
(let ((base (cond ((looking-at "[({]\\s *\\($\\|%\\)") | |
;; Line ends with parenthesis. | |
(erlang-indent-parenthesis (nth 2 stack-top))) | |
(t | |
;; Indent to the same column as the first | |
;; argument. | |
(goto-char (1+ (nth 1 stack-top))) | |
(skip-chars-forward " \t") | |
(current-column))))) | |
(erlang-indent-standard indent-point token base 't))))) | |
;; | |
((eq (car stack-top) '<<) | |
;; Element of binary (possible comprehension) expression, | |
(cond ((null erlang-argument-indent) | |
;; indent to next column. | |
(+ 2 (nth 2 stack-top))) | |
((looking-at "\\(>>\\)[^_a-zA-Z0-9]") | |
(nth 2 stack-top)) | |
(t | |
(goto-char (nth 1 stack-top)) | |
;; Indent to the same column as the first | |
;; argument. | |
(goto-char (+ 2 (nth 1 stack-top))) | |
(skip-chars-forward " \t") | |
(current-column)))) | |
((memq (car stack-top) '(icr fun spec)) | |
;; The default indentation is the column of the option | |
;; directly following the keyword. (This does not apply to | |
;; `case'.) Should no option be on the same line, the | |
;; indentation is the indentation of the keyword + | |
;; `erlang-indent-level'. | |
;; | |
;; `after' should be indented to the same level as the | |
;; corresponding receive. | |
(cond ((looking-at "\\(after\\|of\\)\\($\\|[^_a-zA-Z0-9]\\)") | |
(nth 2 stack-top)) | |
((looking-at "when[^_a-zA-Z0-9]") | |
;; Handling one when part | |
(+ (nth 2 stack-top) erlang-indent-level erlang-indent-guard)) | |
(t | |
(save-excursion | |
(goto-char (nth 1 stack-top)) | |
(if (looking-at "case[^_a-zA-Z0-9]") | |
(+ (nth 2 stack-top) erlang-indent-level) | |
(skip-chars-forward "a-z") | |
(skip-chars-forward " \t") | |
(if (memq (following-char) '(?% ?\n)) | |
(+ (nth 2 stack-top) erlang-indent-level) | |
(current-column)))))) | |
) | |
((and (eq (car stack-top) '||) (looking-at "\\(]\\|>>\\)[^_a-zA-Z0-9]")) | |
(nth 2 (car (cdr stack)))) | |
;; Real indentation, where operators create extra indentation etc. | |
((memq (car stack-top) '(-> || try begin)) | |
(if (looking-at "\\(of\\)[^_a-zA-Z0-9]") | |
(nth 2 stack-top) | |
(goto-char (nth 1 stack-top)) | |
;; Check if there is more code after the '->' on the | |
;; same line. If so use this indentation as base, else | |
;; use parent indentation + 2 * level as base. | |
(let ((off erlang-indent-level) | |
(skip 2)) | |
(cond ((null (cdr stack))) ; Top level in function. | |
((eq (car stack-top) 'begin) | |
(setq skip 5)) | |
((eq (car stack-top) 'try) | |
(setq skip 5)) | |
((eq (car stack-top) '->) | |
;; If in fun definition use standard indent level not double | |
;;(if (not (eq (car (car (cdr stack))) 'fun)) | |
;; Removed it made multi clause fun's look to bad | |
(if (and (cdr stack) (eq (car (car (cdr stack))) 'icr)) ;<----- THIS IS THE SECTION I CHANGED | |
(setq off (* 2 erlang-indent-level)) | |
(setq off (* 1 erlang-indent-level))))) ;; ) | |
(let ((base (erlang-indent-find-base stack indent-point off skip))) | |
;; Special cases | |
(goto-char indent-point) | |
(cond ((looking-at "\\(end\\|after\\)\\($\\|[^_a-zA-Z0-9]\\)") | |
(if (eq (car stack-top) '->) | |
(erlang-pop stack)) | |
(if stack | |
(erlang-caddr (car stack)) | |
0)) | |
((looking-at "catch\\b\\($\\|[^_a-zA-Z0-9]\\)") | |
;; Are we in a try | |
(let ((start (if (eq (car stack-top) '->) | |
(car (cdr stack)) | |
stack-top))) | |
(if (null start) nil | |
(goto-char (nth 1 start))) | |
(cond ((looking-at "try\\($\\|[^_a-zA-Z0-9]\\)") | |
(progn | |
(if (eq (car stack-top) '->) | |
(erlang-pop stack)) | |
(if stack | |
(erlang-caddr (car stack)) | |
0))) | |
(t (erlang-indent-standard indent-point token base 'nil))))) ;; old catch | |
(t | |
(erlang-indent-standard indent-point token base 'nil) | |
)))) | |
)) | |
((eq (car stack-top) 'when) | |
(goto-char (nth 1 stack-top)) | |
(if (looking-at "when\\s *\\($\\|%\\)") | |
(progn | |
(erlang-pop stack) | |
(if (and stack (memq (nth 0 (car stack)) '(icr fun))) | |
(progn | |
(goto-char (nth 1 (car stack))) | |
(+ (nth 2 (car stack)) erlang-indent-guard | |
;; receive XYZ or receive | |
;; XYZ | |
;; This if thing does not seem to be needed | |
;;(if (looking-at "[a-z]+\\s *\\($\\|%\\)") | |
;; erlang-indent-level | |
;; (* 2 erlang-indent-level)))) | |
(* 2 erlang-indent-level))) | |
;;erlang-indent-level)) | |
(+ erlang-indent-level erlang-indent-guard))) | |
;; "when" is followed by code, let's indent to the same | |
;; column. | |
(forward-char 4) ; Skip "when" | |
(skip-chars-forward " \t") | |
(current-column))) | |
;; Type and Spec indentation | |
((eq (car stack-top) '::) | |
(if (looking-at "}") | |
;; Closing record definition with types | |
;; pop stack and recurse | |
(erlang-calculate-stack-indent indent-point | |
(cons (erlang-pop stack) (cdr state))) | |
(cond ((null erlang-argument-indent) | |
;; indent to next column. | |
(+ 2 (nth 2 stack-top))) | |
((looking-at "::[^_a-zA-Z0-9]") | |
(nth 2 stack-top)) | |
(t | |
(let ((start-alternativ (if (looking-at "|") 2 0))) | |
(goto-char (nth 1 stack-top)) | |
(- (cond ((looking-at "::\\s *\\($\\|%\\)") | |
;; Line ends with :: | |
(if (eq (car (car (last stack))) 'spec) | |
(+ (erlang-indent-find-preceding-expr 1) | |
erlang-argument-indent) | |
(+ (erlang-indent-find-preceding-expr 2) | |
erlang-argument-indent))) | |
(t | |
;; Indent to the same column as the first | |
;; argument. | |
(goto-char (+ 2 (nth 1 stack-top))) | |
(skip-chars-forward " \t") | |
(current-column))) start-alternativ)))))) | |
))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment