Skip to content

Instantly share code, notes, and snippets.

@BJTerry
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BJTerry/13477b152b8202f33d0c to your computer and use it in GitHub Desktop.
Save BJTerry/13477b152b8202f33d0c to your computer and use it in GitHub Desktop.
Make erlang-mode not double-indent after a fun ->
(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