[erlang-patches] [PATCH] Fix indentation of record fields in Emacs

Tomas Abrahamsson <>
Tue Jun 12 16:18:53 CEST 2012


No problems, thanks for including the patch.

BRs
Tomas

On Tue, Jun 12, 2012 at 11:41 AM, Henrik Nord <> wrote:
> Hi Tomas
>
> Yes this is probably my bad that it is not included.
>
> It has already been reviewed and approved and marked as answered so the only
> thing missing is the Email notification for you and the list, and the merger
> itself.
>
> I will run it through the tests real fast.
>
> Apologies for the wait, and thank you for the contribution!
>
> /Henrik
>
>
> On 06/11/2012 03:54 PM, Tomas Abrahamsson wrote:
>>
>> Hi,
>>
>> I never received any feedback on the patch to the emacs
>> record indentation, it was not included in pu and not the R15B01.
>> Was it good? Bad? Ugly? Or just forgotten?
>>
>> We've been using it extensively in a project with lots
>> of records, and folks seem happy with it. We haven't
>> seen any bad cases of indentation due to it.
>>
>> BRs
>> Tomas
>>
>> On Sat, Feb 11, 2012 at 9:55 PM, Tomas Abrahamsson
>> <>  wrote:
>>>
>>> In some situations, the indentation of record fields in Emacs was
>>> strange. This example below shows how Emacs previously would indent
>>> two similar pieces of code very differently:
>>>
>>>    some_function_with_a_very_long_name() ->
>>>        #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>>                                         field1=a,
>>>                                         field2=b}.
>>>
>>>    x() ->
>>>        #some_record_name{
>>>       field1=a,
>>>       field2=b}.
>>>
>>> This changes the indentation to be like below for both cases:
>>>
>>>    some_function() ->
>>>        #some_record{
>>>           field1=a,
>>>           field2=b}.
>>> ---
>>>  lib/tools/emacs/erlang.el         |   58
>>> +++++++++++++++++++++++++++++-------
>>>  lib/tools/emacs/test.erl.indented |   38 ++++++++++++++++++++++++
>>>  lib/tools/emacs/test.erl.orig     |   38 ++++++++++++++++++++++++
>>>  3 files changed, 122 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
>>> index bc7a190..2f6c7f5 100644
>>> --- a/lib/tools/emacs/erlang.el
>>> +++ b/lib/tools/emacs/erlang.el
>>> @@ -2986,18 +2986,52 @@ This assumes that the preceding expression is
>>> either simple
>>>     (forward-sexp (- arg))
>>>     (let ((col (current-column)))
>>>       (skip-chars-backward " \t")
>>> -      ;; Needed to match the colon in "'foo':'bar'".
>>> -      (if (not (memq (preceding-char) '(?# ?:)))
>>> -          col
>>> -        ;; Special hack to handle: (note line break)
>>> -        ;; [#myrecord{
>>> -        ;;  foo = foo}]
>>> -        (or
>>> -         (ignore-errors
>>> -           (backward-char 1)
>>> -           (forward-sexp -1)
>>> -           (current-column))
>>> -         col)))))
>>> +      ;; Special hack to handle: (note line break)
>>> +      ;; [#myrecord{
>>> +      ;;  foo = foo}]
>>> +      ;; where the call (forward-sexp -1) will fail when point is at the
>>> `#'.
>>> +      (or
>>> +       (ignore-errors
>>> +        ;; Needed to match the colon in "'foo':'bar'".
>>> +        (cond ((eq (preceding-char) ?:)
>>> +               (backward-char 1)
>>> +               (forward-sexp -1)
>>> +               (current-column))
>>> +              ((eq  (preceding-char) ?#)
>>> +               ;; We may now be at:
>>> +               ;; - either a construction of a new record
>>> +               ;; - or update of a record, in which case we want
>>> +               ;;   the column of the expression to be updated.
>>> +               ;;
>>> +               ;; To see which of the two cases we are at, we first
>>> +               ;; move an expression backwards, check for keywords,
>>> +               ;; then immediately an expression forwards.  Moving
>>> +               ;; backwards skips past tokens like `,' or `->', but
>>> +               ;; when moving forwards again, we won't skip past such
>>> +               ;; tokens.  We use this: if, after having moved
>>> +               ;; forwards, we're back where we started, then it was
>>> +               ;; a record update.
>>> +               ;; The check for keywords is to detect cases like:
>>> +               ;;   case Something of #record_construction{...}
>>> +               (backward-char 1)
>>> +               (let ((record-start (point))
>>> +                     (record-start-col (current-column)))
>>> +                 (forward-sexp -1)
>>> +                 (let ((preceding-expr-col (current-column))
>>> +                       ;; white space definition according to erl_scan
>>> +                       (white-space "\000-\040\200-\240"))
>>> +                   (if (erlang-at-keyword)
>>> +                       ;; The (forward-sexp -1) call moved past a
>>> keyword
>>> +                       (1+ record-start-col)
>>> +                     (forward-sexp 1)
>>> +                     (skip-chars-forward white-space record-start)
>>> +                     ;; Are we back where we started?  If so, it was an
>>> update.
>>> +                     (if (= (point) record-start)
>>> +                           preceding-expr-col
>>> +                       (goto-char record-start)
>>> +                       (1+ (current-column)))))))
>>> +              (t col)))
>>> +       col))))
>>>
>>>  (defun erlang-indent-parenthesis (stack-position)
>>>   (let ((previous (erlang-indent-find-preceding-expr)))
>>> diff --git a/lib/tools/emacs/test.erl.indented
>>> b/lib/tools/emacs/test.erl.indented
>>> index 2948ccf..e0593c6 100644
>>> --- a/lib/tools/emacs/test.erl.indented
>>> +++ b/lib/tools/emacs/test.erl.indented
>>> @@ -657,3 +657,41 @@ indent_comprehensions() ->
>>>  foo() ->
>>>     [#foo{
>>>        foo = foo}].
>>> +
>>> +%% Record indentation
>>> +some_function_with_a_very_long_name() ->
>>> +    #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>> +       field1=a,
>>> +       field2=b},
>>> +    case dummy_function_with_a_very_very_long_name(x) of
>>> +       #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>> +          field1=a,
>>> +          field2=b} ->
>>> +           ok;
>>> +       Var =
>>> #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>> +                field1=a,
>>> +                field2=b} ->
>>> +
>>> Var#'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>> +             field1=a,
>>> +             field2=b};
>>> +       #xyz{
>>> +          a=1,
>>> +          b=2} ->
>>> +           ok
>>> +    end.
>>> +
>>> +another_function_with_a_very_very_long_name() ->
>>> +    #rec{
>>> +       field1=1,
>>> +       field2=1}.
>>> +
>>> +some_function_name_xyz(xyzzy, #some_record{
>>> +                                field1=Field1,
>>> +                                field2=Field2}) ->
>>> +    SomeVariable = f(#'Some-long-record-name'{
>>> +                       field_a = 1,
>>> +                       'inter-xyz-parameters' =
>>> +                           #'Some-other-very-long-record-name'{
>>> +                              field2 = Field1,
>>> +                              field2 = Field2}}),
>>> +    {ok, SomeVariable}.
>>> diff --git a/lib/tools/emacs/test.erl.orig
>>> b/lib/tools/emacs/test.erl.orig
>>> index 1221c56..69356ac 100644
>>> --- a/lib/tools/emacs/test.erl.orig
>>> +++ b/lib/tools/emacs/test.erl.orig
>>> @@ -657,3 +657,41 @@ ok.
>>>  foo() ->
>>>  [#foo{
>>>  foo = foo}].
>>> +
>>> +%% Record indentation
>>> +some_function_with_a_very_long_name() ->
>>> + #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>> + field1=a,
>>> + field2=b},
>>> + case dummy_function_with_a_very_very_long_name(x) of
>>> + #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>> + field1=a,
>>> + field2=b} ->
>>> + ok;
>>> + Var = #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>> + field1=a,
>>> + field2=b} ->
>>> + Var#'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
>>> + field1=a,
>>> + field2=b};
>>> + #xyz{
>>> + a=1,
>>> + b=2} ->
>>> + ok
>>> + end.
>>> +
>>> +another_function_with_a_very_very_long_name() ->
>>> + #rec{
>>> + field1=1,
>>> + field2=1}.
>>> +
>>> +some_function_name_xyz(xyzzy, #some_record{
>>> + field1=Field1,
>>> + field2=Field2}) ->
>>> + SomeVariable = f(#'Some-long-record-name'{
>>> + field_a = 1,
>>> + 'inter-xyz-parameters' =
>>> + #'Some-other-very-long-record-name'{
>>> + field2 = Field1,
>>> + field2 = Field2}}),
>>> + {ok, SomeVariable}.
>>> --
>>> 1.7.5.4
>>>
>> _______________________________________________
>> erlang-patches mailing list
>> 
>> http://erlang.org/mailman/listinfo/erlang-patches
>
>
> --
> /Henrik Nord Erlang/OTP
>


More information about the erlang-patches mailing list