[erlang-patches] erlang.el patch for try/after

Dan Gudmundsson <>
Mon Oct 12 08:56:49 CEST 2009


Thanks, but I have just re-wrote how the try-after is handled (and a lot of other
fixes) in the mode.

I will apply your word boundary match.

/Dan



Steve Vinoski wrote:
> I've found that erlang.el doesn't properly indent try/after without an
> intervening catch -- the after keyword ends up being indented to the same
> level as the code within the try clause rather than being indented to the
> same level as the try keyword. Also, the second and subsequent lines within
> the after clause are indented only half the correct distance.
> Another issue is that a lot of the regular expressions used within erlang.el
> try to match word boundaries using [^_a-zA-Z0-9] rather than just using the
> \b word boundary backslash construct.
> 
> The patch below is for erlang.el from Erlang/OTP version R13B02-1 and it
> fixes these issues. The same patch also works for versions at least as far
> back as R12B-5, but with different line offsets.
> 
> --steve
> 
> --- erlang.el.orig 2009-10-11 17:31:48.000000000 -0400
> +++ erlang.el 2009-10-11 18:18:18.000000000 -0400
> @@ -3353,7 +3353,7 @@
> 
>       ;; Word constituent: check and handle keywords.
>       ((= cs ?w)
> -      (cond ((looking-at "\\(end\\|after\\)[^_a-zA-Z0-9]")
> +      (cond ((looking-at "\\b\\(end\\|after\\)\\b")
>       ;; Must pop top icr layer, `after' will push a new
>       ;; layer next.
>       (progn
> @@ -3361,7 +3361,7 @@
>   (erlang-pop stack))
>         (if (and stack (memq (car (car stack)) '(icr begin)))
>     (erlang-pop stack))))
> -    ((looking-at "catch[^,\n\\of]*\n")
> +    ((looking-at "\\bcatch[^,\n\\of]*\n")
>       ;; Must pop top icr layer, `catch' in try/catch
>       ;;will push a new layer next.
>       (progn
> @@ -3378,10 +3378,10 @@
>      ;;     (if (and stack (memq (car (car stack)) '(icr begin)))
>      ;;   (erlang-pop stack))))
>      )
> -      (cond ((looking-at "\\(if\\|case\\|receive\\|try\\)[^_a-zA-Z0-9]")
> +      (cond ((looking-at "\\b\\(if\\|case\\|receive\\|try\\)\\b")
>       ;; Must push a new icr (if/case/receive) layer.
>       (erlang-push (list 'icr token (current-column)) stack))
> -    ((looking-at "\\(fun\\)[^_a-zA-Z0-9]")
> +    ((looking-at "\\b\\(fun\\)\\b")
>       ;; Push a new icr layer if we are defining a `fun'
>       ;; expression, not when we are refering an existing
>       ;; function.
> @@ -3390,7 +3390,7 @@
>     (erlang-skip-blank to)
>     (eq (following-char) ?\())
>   (erlang-push (list 'icr token (current-column)) stack)))
> -    ((looking-at "\\(begin\\|query\\)[^_a-zA-Z0-9]")
> +    ((looking-at "\\b\\(begin\\|query\\)\\b")
>       (erlang-push (list 'begin token (current-column)) stack))
>      ;; In test suites you may want to do something like
>      ;; ?match(Mem when integer(Mem), mnesia:table_info(Tab,
> @@ -3399,22 +3399,22 @@
>      ;; erlang mode to think the 'when' in the argument is a
>      ;; "real" when. The following three clauses will avoid
>      ;; this problem.
> -    ((looking-at "when[^->\.]*if[^->\.]*->"))
> -    ((looking-at "when[^->\.]*case[^->\.]*->"))
> -    ((looking-at "when[^->\.]*receive[^->\.]*->"))
> +    ((looking-at "\\bwhen[^->\.]*if[^->\.]*->"))
> +    ((looking-at "\\bwhen[^->\.]*case[^->\.]*->"))
> +    ((looking-at "\\bwhen[^->\.]*receive[^->\.]*->"))
>      ;; Normal when case
> -    ((looking-at "when [^->\.]*->")
> +    ((looking-at "\\bwhen [^->\.]*->")
>       (erlang-push (list 'when token (current-column)) stack))
> -    ((looking-at "after[.]+->")
> +    ((looking-at "\\bafter[.]+->")
>       (erlang-push (list 'icr token (current-column)) stack))
> -    ((looking-at "after[^_a-zA-Z0-9->]")
> -     ;; Probably in try-statment, fake "->" to get right
> +    ((looking-at "\\bafter\\b")
> +     ;; Probably in try-statement, fake "->" to get right
>       ;; indentation in erlang-calculate-stack-indent. If it
>       ;; was an ordinary catch without try, these entries will
>       ;; be popped of the stack at a later ocaccion.
>       (erlang-push (list 'icr token (current-column)) stack)
>       (erlang-push (list '-> token (current-column)) stack))
> -    ((looking-at "catch[^,\n\\of]*\n")
> +    ((looking-at "\\bcatch[^,\n\\of]*\n")
>       (erlang-push (list 'icr token (current-column)) stack)
>       (erlang-push (list '-> token (current-column)) stack))
>      ;;((looking-at "^of$")
> @@ -3469,7 +3469,7 @@
>         ((looking-at "->\\|:-")
>   (save-excursion
>    (back-to-indentation)
> -  (cond ((looking-at "after[^_a-zA-Z0-9]")
> +  (cond ((looking-at "\\bafter\\b")
>   (erlang-pop stack))))
>   (if (and stack (eq (car (car stack)) 'when))
>      (erlang-pop stack))
> @@ -3580,7 +3580,7 @@
>     ;; Return nil or t.
>     (eq (nth 3 state) 'comment))
>    ((null stack)
> -   (if (looking-at "when[^_a-zA-Z0-9]")
> +   (if (looking-at "\\bwhen\\b")
>         erlang-indent-guard
>       0))
>    ((eq (car stack-top) '\()
> @@ -3608,28 +3608,34 @@
>     ;;
>     ;; `after' should be indented to the save level as the
>     ;; corresponding receive.
> -   (if (looking-at "after[^_a-zA-Z0-9]")
> -       (nth 2 stack-top)
> -     (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)))))
> -   (if (looking-at "catch[^_a-zA-Z0-9]")
> -       (nth 2 stack-top)
> -     (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)))))
> +           (let ((top-word (save-excursion
> +                             (goto-char (nth 1 stack-top))
> +                             (looking-at "\\b\\(\\w+\\)\\b")
> +                             (match-string 0))))
> +             (if (and (looking-at "\\bafter\\b")
> +                      (not (string= top-word "try")))
> +                 (if (string= top-word "case")
> +                     (+ (nth 2 stack-top) erlang-indent-level)
> +                   (save-excursion
> +                     (goto-char (nth 1 stack-top))
> +                     (skip-chars-forward "a-z")
> +                     (skip-chars-forward " \t")
> +                     (if (memq (following-char) '(?% ?\n))
> +                         (+ (nth 2 stack-top) erlang-indent-level)
> +                       (current-column)))))
> +             (if (or (looking-at "\\bcatch\\b")
> +                     (and (looking-at "\\bafter\\b")
> +                          (string= top-word "try")))
> +                 (nth 2 stack-top)
> +               (if (string= top-word "case")
> +                   (+ (nth 2 stack-top) erlang-indent-level)
> +                 (save-excursion
> +                   (goto-char (nth 1 stack-top))
> +                   (skip-chars-forward "a-z")
> +                   (skip-chars-forward " \t")
> +                   (if (memq (following-char) '(?% ?\n))
> +                       (+ (nth 2 stack-top) erlang-indent-level)
> +                     (current-column))))))
>     )
>    ;; Real indentation, where operators create extra indentation etc.
>    ((memq (car stack-top) '(-> || begin))
> @@ -3638,7 +3644,8 @@
>     ;; same line. If so use this indentation as base, else
>     ;; use parent indentation + 2 * level as base.
>     (let ((off erlang-indent-level)
> - (skip 2))
> + (skip 2)
> +                 (is-after (looking-at "\\bafter\\b")))
>       (cond ((null (cdr stack))) ; Top level in function.
>     ((eq (car stack-top) 'begin)
>      (setq skip 5))
> @@ -3648,7 +3655,9 @@
>         ;; Look at last thing to see how we are to move relative
>         ;; to the base.
>         (goto-char token)
> -       (cond ((looking-at "||\\|,\\|->\\|:-")
> +               (cond ((and is-after (looking-at ","))
> +                      off)
> +                     ((looking-at "||\\|,\\|->\\|:-")
>        base)
>       ((erlang-at-keyword)
>        (+ (current-column) erlang-indent-level))
> @@ -3665,7 +3674,7 @@
>      ;; the block.  (Here we have a choice: should
>      ;; the user be forced to reindent continued
>      ;; lines, or should the "end" be reindented?)
> -    ((looking-at "\\(end\\|after\\|catch\\)[^_a-zA-Z0-9]\\|$")
> +    ((looking-at "\\b\\(end\\|after\\|catch\\)\\b\\|$")
>       (if (eq (car (car stack)) '->)
>   (erlang-pop stack))
>       (if stack
> @@ -3680,7 +3689,7 @@
>     )
>    ((eq (car stack-top) 'when)
>     (goto-char (nth 1 stack-top))
> -   (if (looking-at "when\\s *\\($\\|%\\)")
> +   (if (looking-at "\\bwhen\\s *\\($\\|%\\)")
>         (progn
>   (erlang-pop stack)
>   (if (and stack (eq (nth 0 (car stack)) 'icr))
> @@ -3757,13 +3766,13 @@
> 
>  (defun erlang-at-keyword ()
>    "Are we looking at an Erlang keyword which will increase indentation?"
> -  (looking-at (concat "\\(when\\|if\\|fun\\|case\\|begin\\|query\\|"
> -      "of\\|receive\\|after\\|catch\\)[^_a-zA-Z0-9]")))
> +  (looking-at (concat "\\b\\(when\\|if\\|fun\\|case\\|begin\\|query\\|"
> +      "of\\|receive\\|after\\|catch\\)\\b")))
> 
>  (defun erlang-at-operator ()
>    "Are we looking at an Erlang operator?"
>    (looking-at
> -   "\\(bnot\\|div\\|mod\\|band\\|bor\\|bxor\\|bsl\\|bsr\\)[^_a-zA-Z0-9]"))
> +   "\\b\\(bnot\\|div\\|mod\\|band\\|bor\\|bxor\\|bsl\\|bsr\\)\\b"))
> 
>  (defun erlang-comment-indent ()
>    "Compute Erlang comment indentation.
> @@ -4813,7 +4822,7 @@
>  This function is designed to be a member of a criteria list."
>    (save-excursion
>      (erlang-skip-blank)
> -    (looking-at "end[^_a-zA-Z0-9]")))
> +    (looking-at "\\bend\\b")))
> 
>  
>  ;; Erlang tags support which is aware of erlang modules.
> 


More information about the erlang-patches mailing list