### Good application and module naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Example of correct naming for applications and modules. ```Erlang %% Good myapp/src/task_server.erl ``` -------------------------------- ### Good variable naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of correct variable naming conventions. ```Erlang %% Good FileName _File StoredID StoredId ``` -------------------------------- ### Correct usage of () in macro names Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples demonstrating correct usage of parentheses in macro names. ```Erlang %% Good -define(NOT_CONSTANT(), application:get_env(myapp, key)). -define(CONSTANT, 100). ``` -------------------------------- ### Good macro definition naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of correct naming for macro definitions. ```Erlang %% Good -define(SOME_VALUE, 100). -define(SOME_MACRO(), hidden:call()). -define(ANOTHER_MACRO, "another macro"). ``` -------------------------------- ### Good predicate function naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Example of correct naming for a predicate function. ```Erlang %% Good is_even(Num) -> ... ``` -------------------------------- ### Good function, attribute, and atom naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of correct naming for functions, attributes, and atoms. ```Erlang %% Good error bad_return read_file ``` -------------------------------- ### CHANGELOG.md Entry Example Source: https://github.com/whatsapp/erlfmt/blob/main/RELEASE.md An example of how to format an entry in the CHANGELOG.md file for a new release. ```markdown ### v.. Document features and Bug fixes since last release. See https://github.com/WhatsApp/erlfmt/blob/main/CHANGELOG.md for link to commits since last release. Add issue numbers or pull requests numbers using hashtags to the fixes and features If only bug fixes change the bug fix version If features were added change the minor version Major version changes should be a big conversation ``` -------------------------------- ### Good variable naming and function prefixes Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of descriptive variable names and avoiding 'do_' prefixes. ```Erlang %% Good validate_all([Key | Keys]) -> validate(Key), validate_all(Keys). ``` -------------------------------- ### Bad variable naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of incorrect variable naming conventions. ```Erlang %% Bad File_name File_Name _file Stored_id ``` -------------------------------- ### Good boolean operator usage with guards Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of correct usage of ',' and ';' within guards for boolean logic. ```Erlang %% Also good when is_atom(Name), Name =/= undefined. when is_binary(Task); is_atom(Task). ``` -------------------------------- ### Macro Handling Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md An example demonstrating various macros and how they are handled by Erlang formatters, with a focus on erlfmt's capabilities. ```erlang -module(macros). -include_lib("stdlib/include/assert.hrl"). -define(MACRO(), object). argument(?MACRO()) -> ok. match() -> ?assertMatch({ok, Num} when is_integer(Num), get_number()). -define(IMPORTANT_PARENS(Expr), (Expr) * (Expr)). -define(RECORD_NAME1, #foo). -define(RECORD_NAME2, foo). bar() -> ?IMPORTANT_PARENS(2 + 1), ?RECORD_NAME1{a = 1}, #?RECORD_NAME2{a = 1}. -define(NAME, name). ?NAME() -> ok. -define(FALLBACK_CLAUSE(Name), Name(_) -> default_action()). compute(X) when is_integer(X) -> ok; ?FALLBACK_CLAUSE(compute). ``` -------------------------------- ### Bad variable naming and function prefixes Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of poor variable naming and use of 'do_' prefixes. ```Erlang %% Bad validate([X | Xs]) -> do_validate(X), validate(Xs). ``` -------------------------------- ### New Release Draft Example Source: https://github.com/whatsapp/erlfmt/blob/main/RELEASE.md Example fields to fill when drafting a new release on GitHub. ```markdown Tag Version: v.. Release title: Pick most significant feature Description: Copy ChangeLog contents ``` -------------------------------- ### Bad function, attribute, and atom naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of incorrect naming for functions, attributes, and atoms. ```Erlang %% Bad 'Error' badReturn read_File ``` -------------------------------- ### Bad macro definition naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of incorrect naming for macro definitions. ```Erlang %% Bad -define(some_value, 100). -define(someMacro(), hidden:call()). -define(AnotherMacro, "another macro"). ``` -------------------------------- ### Exported functions format Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Example of correctly formatting exported functions in Erlang, with each function occupying one line. ```erlang %% Good -export([ api_function/1, api_another/2, api_another/3, api_third/4 ]). ``` -------------------------------- ### Suffix pattern example: starting with newline Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionCommas.md Example of a list with a trailing comma, where there is a newline after the opening bracket. ```erlang [ a, ...] ``` -------------------------------- ### DSLish Lists - Unformatted Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionIgnore.md An example of an unformatted DSLish list before erlfmt is applied. ```erlang gen_part({constructed,bif},TypeName,{_Name,parts,Tag,_Type}) -> emit([" case Data of",nl, " L when is_list(L) ->",nl, " 'dec_",TypeName,"'(lists:map(fun(X) -> element(1, ", {call,ber,ber_decode_erlang,["X"]},") end, L),",{asis,Tag},");",nl, " _ ->",nl, " [Res] = 'dec_",TypeName,"'([Data],",{asis,Tag},"),",nl, " Res",nl, " end"]) ``` -------------------------------- ### Related elvis configuration for module naming (reiteration) Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Elvis configuration snippet for module naming conventions. ```Erlang {elvis_style, module_naming_convention, #{regex => "^([a-z][a-z0-9]*_?)*(_SUITE)?$"}} ``` -------------------------------- ### Bad predicate function naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Example of incorrect naming for a predicate function. ```Erlang %% Bad evenp(Num) -> ... ``` -------------------------------- ### Pipes as Prefix Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionPipes.md Example of Erlang code formatting with pipes as a prefix. ```erlang -spec foo() -> term() | [term()] | error. ``` -------------------------------- ### Newline and single indentation example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example of `when` with multiline guards, single-indented. ```erlang bar(Some, Very, Long, Arguments) when is_tuple(X); is_list(X) -> body. ``` -------------------------------- ### Comment Handling - Input Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md An Erlang code snippet demonstrating comment placement before formatting. ```erlang -type foo() :: %% comment 1 fun( ( %% comment 2 ... ) -> %% comment 3 bar() ). ``` -------------------------------- ### Bad boolean operator usage Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of incorrect usage of 'and' and 'or' operators. ```Erlang %% Bad is_atom(Name) and Name =/= undefined. is_binary(Task) or is_atom(Task). ``` -------------------------------- ### Comma-space formatting Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Demonstrates correct single space usage after a comma in Erlang code. ```erlang %% Bad application:get_env(kernel,start_pg2) ``` ```erlang %% Good application:get_env(kernel, start_pg2) ``` -------------------------------- ### Binary operator spacing Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Illustrates the requirement for single spaces before and after binary operators in Erlang. ```erlang %% Bad Values=[ #{key=>value}, #rec{key=value,key2=value2}, 120-90, Server!Message ] ``` ```erlang %% Good Values = [ #{key => value}, #rec{key = value, key2 = value2}, 120 - 90, Server ! Message ] ``` -------------------------------- ### Floating guards example 1 Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example of `when` with multiline guards, using floating guards. ```erlang bar(X) when is_tuple(X); % some comment is_list(X) -> body. ``` -------------------------------- ### Compressed formatting example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md Example of list comprehension formatting with the 'compressed' option. ```erlang [function_with_long_name(A) || {A, B} <- Cs, filter(B)] ``` -------------------------------- ### Pipes as Suffix Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionPipes.md Example of Erlang code formatting with pipes as a suffix. ```erlang -spec foo() -> term() | [term()] | error. ``` -------------------------------- ### Newline and half indentation example 1 Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example of `when` with multiline guards, half-indented. ```erlang bar(X) when is_tuple(X); % some comment is_list(X) -> body. ``` -------------------------------- ### Good boolean operator usage with andalso/orelse Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples of correct usage of 'andalso' and 'orelse' for boolean logic. ```Erlang %% Good is_atom(Name) andalso Name =/= undefined. is_binary(Task) orelse is_atom(Task). ``` -------------------------------- ### Related elvis configuration for macro names Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Elvis configuration snippet for enforcing macro naming conventions. ```Erlang {elvis_style, macro_names} ``` -------------------------------- ### Macro with Magic Name Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionIgnore.md An example demonstrating the use of a macro with a magic name to influence formatting, specifically within a list processing function. ```erlang -define(IDERLFMT(ID), ID). gen_part({constructed, bif}, TypeName, {_Name, parts, Tag, _Type}) -> ?IDERLFMT(emit([" case Data of",nl, " L when is_list(L) ->",nl, " 'dec_",TypeName,"'(lists:map(fun(X) -> element(1, ", {call,ber,ber_decode_erlang,["X"]},") end, L),",{asis,Tag},");",nl, " _ ->",nl, " [Res] = 'dec_",TypeName,"'([Data],",{asis,Tag},"),",nl, " Res",nl, " end"])). ``` -------------------------------- ### Related elvis configuration for module and function naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Elvis configuration snippets for enforcing module and function naming conventions. ```Erlang {elvis_style, module_naming_convention, #{regex => "^([a-z][a-z0-9]*_?)*(_SUITE)?$"}}, {elvis_style, function_naming_convention, #{regex => "^([a-z]*_?)*$"}} ``` -------------------------------- ### Newline and no indentation example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example of `when` with multiline guards, not indented. ```erlang bar(X) when is_tuple(X); % some comment is_list(X) -> body. ``` -------------------------------- ### Newline and double indentation example 1 Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example of `when` with multiline guards, doubly-indented. ```erlang bar(X) when is_tuple(X); % some comment is_list(X) -> body. ``` -------------------------------- ### Newline and half indentation example 2 Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example of `when` with multiline guards, half-indented, for a function with many arguments. ```erlang insert_nested({Field, Meta, Key0, Value0}, Comments0) when Field =:= map_field_assoc; Field =:= map_field_exact; Field =:= record_field; Field =:= generate; Field =:= b_generate -> body. ``` -------------------------------- ### Preserving Representation - erl_tidy Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md Erlang code showing how erl_tidy simplifies all examples (lists, atoms, strings, numbers). ```erlang 1000000, "abc", "abcABC", [1, 2, 3], [1, 2, 3 | improper_list], {undefined, undefined}. ``` -------------------------------- ### Multiline string conversion Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Demonstrates how to handle multiline strings by concatenating them with newline characters in Erlang. ```erlang %% Bad Message = "erlfmt is a code formatter for Erlang. Arguments: files -- files to format ..." ``` ```erlang %% Good Message = "erlfmt is a code formatter for Erlang.\n" "\n" "Arguments:\n" "\n" " files -- files to format\n" "..." ``` ```erlang %% Also good Message = "erlfmt is a code formatter for Erlang.\n\n" "Arguments:\n\n" " files -- files to format\n" "..." ``` -------------------------------- ### Newline and double indentation example 2 Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example of `when` with multiline guards, doubly-indented, for a function with many arguments. ```erlang insert_nested({Field, Meta, Key0, Value0}, Comments0) when Field =:= map_field_assoc; Field =:= map_field_exact; Field =:= record_field; Field =:= generate; Field =:= b_generate -> body. ``` -------------------------------- ### Aligned comment example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionComments/Readme.md Example of aligned comments in Erlang. ```erlang #{ A => a, % aligned comment B => bb, % another aligned comment C => ccc % and yet another aligned comment } ``` -------------------------------- ### Compressed with 4 spaces formatting example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md Example of list comprehension formatting with 'compressed' and 4-space indentation. ```erlang [function_with_long_name(A) || A <- a_generator(), some_check(A)] ``` -------------------------------- ### Clause style consistency Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Illustrates consistent formatting for clauses within case, if, try, receive, and functions in Erlang. ```erlang %% Bad lookup(1) -> one; lookup(2) -> two. reverse_lookup(one) -> 1; reverse_lookup(two) -> 2. ``` ```erlang %% Good lookup(1) -> one; lookup(2) -> two. reverse_lookup(one) -> 1; reverse_lookup(two) -> 2. ``` -------------------------------- ### Directly following comment example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionComments/Readme.md Example of directly following comments in Erlang. ```erlang #{ A => a, % directly following comment B => bbbbb, % also directly following comment C => cccccc% also directly following if there is no space } ``` -------------------------------- ### Multi-line expression assignment Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Shows how to begin the expression on a new line when assigning the result of a multi-line expression in Erlang. ```erlang %% Bad Prefix = case Base of binary -> "2#"; octal -> "8#"; hex -> "16#" end. ``` ```erlang %% Good Prefix = case Base of binary -> "2#"; octal -> "8#"; hex -> "16#" end. ``` -------------------------------- ### All comments always on a newline - Example with pipe operator Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionComments.md An example demonstrating the 'all comments on a newline' style with the pipe operator. ```erlang X = % comment A | % another comment BB | % that comment CCC. ``` -------------------------------- ### DSLish Lists - Formatted Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionIgnore.md Demonstrates how erlfmt formats lists that do not fit on a single line, assigning each element its own line. ```erlang [ a_long_expression, b_long_expression, c_long_expression ] ``` -------------------------------- ### Floating guards example 3 (diff impact) Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example illustrating diff impact with floating guards when changing argument names. ```erlang insert_nested(KeyValue, Comments0) when Field =:= map_field_assoc; Field =:= map_field_exact; Field =:= record_field; Field =:= generate; Field =:= b_generate -> body. ``` -------------------------------- ### Related elvis configuration for variable naming Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Elvis configuration snippet for enforcing variable naming conventions. ```Erlang {elvis_style, variable_naming_convention, #{regex => "^([A-Z][0-9a-zA-Z]*)$"}} ``` -------------------------------- ### Prefix pattern example: ending with newline Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionCommas.md Example of a list with a leading comma, where there is a newline before the closing bracket. ```erlang ... , a ] ``` -------------------------------- ### Before erlfmt Source: https://github.com/whatsapp/erlfmt/blob/main/README.md Example of Erlang code before formatting by erlfmt. ```erl what_is(Erlang) -> case Erlang of movie->[hello(mike,joe,robert),credits]; language->formatting_arguments end . ``` -------------------------------- ### Floating guards example 2 (unformatted) Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionWhenMultilineGuards.md Example of `when` with multiline guards, using floating guards for a function with many arguments. Marked as unformatted. ```erlang insert_nested({Field, Meta, Key0, Value0}, Comments0) when Field =:= map_field_assoc; Field =:= map_field_exact; Field =:= record_field; Field =:= generate; Field =:= b_generate -> body. ``` -------------------------------- ### Dedent double pipes, just a little - Basic example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md The chosen formatting by erlfmt, with double pipes dedented slightly. ```erlang [ function_with_long_name(A) || {A, B} <- Cs, filter(B) ] ``` -------------------------------- ### Configure erlfmt options in rebar.config Source: https://github.com/whatsapp/erlfmt/blob/main/doc/RebarUsage.md Example of configuring erlfmt command-line options with defaults in rebar.config. ```erlang {erlfmt, [ write, {files, "{src,include,test}/*.{hrl,erl}}" ]}. ``` -------------------------------- ### Map with single-line comments Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionComments.md Example of a map with single-line comments on each key-value pair. ```erlang #{ A => a, % comment B => bb, % another comment C => ccc % that comment } ``` -------------------------------- ### After erlfmt Source: https://github.com/whatsapp/erlfmt/blob/main/README.md Example of Erlang code after formatting by erlfmt, demonstrating improved readability. ```erlang formatted demo2 what_is(Erlang) -> case Erlang of movie -> [hello(mike, joe, robert), credits]; language -> no_more_formatting_arguments end. ``` -------------------------------- ### Preserving Representation - rebar3_format Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md Erlang code showing how rebar3_format simplifies lists, atoms, and strings. ```erlang 1_000_000, "\x61\x62\x63", "abcABC", [1, 2, 3], [1, 2, 3 | improper_list], {undefined, undefined}. ``` -------------------------------- ### Two spaces after double pipes - Basic example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md An alternative formatting with two spaces after the double pipes for alignment. ```erlang [ function_with_long_name(A) || {A, B} <- Cs, filter(B) ] ``` -------------------------------- ### Compressed formatting with multiline expressions Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md Example showing inconsistent handling of multiline expressions with the 'compressed' option. ```erlang [function_with_long_name( A, AlongArgument ) || {A, B} <- Cs, filter(B)] ``` -------------------------------- ### Preserving Representation - erlfmt Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md Erlang code demonstrating how erlfmt preserves the exact representation of strings, atoms, and integers. ```erlang 1_000_000, "\x61\x62\x63", "\x61\x62\x63" "\x41\x42\x43", [1 | [2 | [3 | []]]], [1 | [2 | [3 | improper_list]]], {undefined, 'undefined'}. ``` -------------------------------- ### Dedent double pipes, just a little - Multiline argument Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md Example of the chosen formatting with a multiline function argument. ```erlang [ function_with_long_name( A, ALongArgument ) || {A, B} <- Cs, filter(B) ] ``` -------------------------------- ### Parentheses, braces, and brackets spacing Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Enforces no spaces around parentheses, braces, or brackets for function/record/maps/lists in Erlang. ```erlang %% Bad function_definition( { ok, Argument } ) -> mod:function_call(Argument). sort( [ 1,2,3 ] ). ``` ```erlang %% Good function_definition({ok, Argument}) -> mod:function_call(Argument). sort([1, 2, 3]). ``` -------------------------------- ### Dedent double pipes - Filter on same line Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md Example with dedented double pipes and the filter on the same line. ```erlang [ function_with_long_name(A) || {A, B} <- Cs, filter(B) ] ``` -------------------------------- ### Preserving Representation - steamroller Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md Erlang code showing how steamroller preserves lists but simplifies strings, atoms, and numbers. ```erlang 1000000, "abc", "abc" "ABC", [1 | [2 | [3 | []]]], [1 | [2 | [3 | improper_list]]], {undefined, undefined}. ``` -------------------------------- ### Incorrect omission of () in macro names Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Examples where parentheses should not be omitted in macro names. ```Erlang %% Bad -define(NOT_CONSTANT, application:get_env(myapp, key)). -define(CONSTANT(), 100). ``` -------------------------------- ### Dedent double pipes - Basic example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md A list comprehension where the double pipes are dedented to the left. ```erlang [ function_with_long_name(A) || {A, B} <- Cs, filter(B) ] ``` -------------------------------- ### Binary operator indentation Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Demonstrates indenting the right-hand side of a binary operator if it's on a new line in Erlang. ```erlang %% Bad f(Op, Atom) -> is_atom(Op) andalso Atom =/= '!' andalso Atom =/= '='. ``` ```erlang %% Good f(Op, Atom) -> is_atom(Op) andalso Atom =/= '!' andalso Atom =/= '='. ``` -------------------------------- ### Aligned Binary Strings with Ignore Comment Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionIgnore.md Example of aligned binary strings with comments, demonstrating the use of erlfmt-ignore for readability. ```erlang %% erlfmt-ignore << % Phase 0 Phase 1 Phase 2 Phase 3 Phase 4 Phase 5 Phase 6 % A B C D A B C D A B C D A B C D A B C D A B C D A B C D 2#01001000, 2#10100000, 2#00010000, 2#00010000, 2#00010011, 2#00000000, 2#00000000, % LUT0 - Black 2#01001000, 2#10100000, 2#10000000, 2#00000000, 2#00000011, 2#00000000, 2#00000000, % LUTT1 - White >> ``` -------------------------------- ### Double pipes on their own line - Filter on same line Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md Example with double pipes on their own line and the filter on the same line. ```erlang [ function_with_long_name(A) || {A, B} <- Cs, filter(B) ] ``` -------------------------------- ### erlfmt line break hints example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md Demonstrates how erlfmt preserves user-introduced line breaks and empty lines in lists and export statements. ```erlang -export([ %% public functions foo/1, foo/2, bar/1, %% testing helpers baz/5 ]). x() -> Foo = [ short, list ]. ``` -------------------------------- ### Double pipes on their own line - Basic example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md A list comprehension format where the double pipes are placed on their own line. ```erlang [ function_with_long_name(A) || {A, B} <- Cs, filter(B) ] ``` -------------------------------- ### Comment Handling - erlfmt Trailing Comment Example Input Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md An Erlang code snippet with trailing comments before erlfmt formatting. ```erlang %% Constants -define(VERSION_CHECK_INTERVAL_MILLIS_DEFAULT, 10000). % Minimum interval between health checks -define(MAX_WRITE_FAILURES, 3). ``` -------------------------------- ### View rebar3 help for all options Source: https://github.com/whatsapp/erlfmt/blob/main/doc/RebarUsage.md Command to display help for rebar3, including erlfmt options. ```sh $ rebar3 --help ``` -------------------------------- ### Standalone comment example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionComments/Readme.md Example of a standalone comment in Erlang. ```erlang %% My standalone comment case IAmOnTheNextLine of ... ``` -------------------------------- ### Rebar3 Configuration for Hex Plugin Source: https://github.com/whatsapp/erlfmt/blob/main/RELEASE.md Command to create the rebar3 configuration file to include the hex plugin. ```bash $ mkdir -p ~/.config/rebar3/ && echo "{plugins, [rebar3_hex]}.". >> ~/.config/rebar3/rebar.config ``` -------------------------------- ### Hex User Authentication Source: https://github.com/whatsapp/erlfmt/blob/main/RELEASE.md Command to authenticate the Hex user. ```bash $ rebar3 hex user auth ``` -------------------------------- ### Comment Handling - steamroller Reordering Example Input Source: https://github.com/whatsapp/erlfmt/blob/main/doc/ErlangFormatterComparison.md An Erlang code snippet with nested comments for testing steamroller's reordering. ```erlang comprehension() -> [ [ %% comment 1 X ] || X <- %% comment 3 [ %% comment 4 ] %% comment 5 ]. ``` -------------------------------- ### Build & Test Commands Source: https://github.com/whatsapp/erlfmt/blob/main/CLAUDE.md Commands for compiling, testing, static analysis, and full project checks. ```bash rebar3 compile # Compile rebar3 ct # Run all tests (Common Test) rebar3 ct --suite=test/erlfmt_SUITE --case= # Run a single test rebar3 dialyzer # Static type analysis make check # Full check: compile, test, dialyzer, format check ``` -------------------------------- ### Prefix pattern example: no newline before closing bracket Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionCommas.md Example of a list with a leading comma, where there is no newline immediately before the closing bracket. ```erlang ... , a/1 ] ``` -------------------------------- ### Suffix pattern example: no newline after opening bracket Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionCommas.md Example of a list with a trailing comma, where there is no newline immediately after the opening bracket. ```erlang [ a/1, ...] ``` -------------------------------- ### Plotting Comment Distribution by Column Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionComments/columns.html JavaScript code to plot the distribution of comments by their starting column number using Plotly.js. It visualizes the percentage of comments starting at different column positions for various Erlang projects. ```javascript var data = [ { x: [17, 19, 20, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 56, 76], y: [1.580135440180587, 1.3544018058690745, 3.6681715575620766, 2.0316027088036117, 1.580135440180587, 1.18510158013544, 1.7494356659142212, 1.693002257336343, 1.9751693002257336, 2.4266365688487586, 7.618510158013544, 2.6523702031602707, 1.580135440180587, 2.539503386004515, 2.4266365688487586, 1.1286681715575622, 1.4108352144469527, 5.756207674943567, 5.586907449209932, 2.200902934537246, 2.2573363431151243, 1.4108352144469527, 1.580135440180587, 2.144469525959368, 2.144469525959368, 1.4672686230248306, 2.37020316027088, 17.099322799097067, 1.4108352144469527, 1.2415349887133182, 2.0316027088036117, 1.0158013544018059], mode: 'markers', type: 'scatter', name: 'OTP' }, { x: [68, 72], y: [28.0, 20.0], mode: 'markers', type: 'scatter', name: 'kazoo' }, { x: [], y: [], mode: 'markers', type: 'scatter', name: 'Inaka' }, { x: [], y: [], mode: 'markers', type: 'scatter', name: 'MongooseIM' }, { x: [], y: [], mode: 'markers', type: 'scatter', name: 'ejabberd' }, { x: [9, 11, 17, 18, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 56, 58, 59, 60, 61, 68, 92], y: [2.593192868719611, 1.7017828200972447, 1.4181523500810373, 1.8638573743922204, 1.9448946515397083, 1.2155591572123177, 1.4181523500810373, 1.6207455429497568, 1.4586709886547813, 2.1880064829821717, 2.1880064829821717, 2.674230145867099, 2.3095623987034037, 1.2155591572123177, 1.0940032414910859, 4.416531604538087, 1.8233387358184765, 1.5802269043760129, 1.8233387358184765, 2.674230145867099, 2.512155591572123, 2.025931928687196, 1.8233387358184765, 3.9708265802269045, 1.7828200972447326, 3.282009724473258, 1.2965964343598055, 1.7017828200972447, 1.6207455429497568, 1.2560777957860616, 1.539708265802269, 1.9448946515397083, 1.1345218800648298, 1.539708265802269, 1.3371150729335495, 1.2965964343598055, 1.1750405186385737, 1.1345218800648298, 2.552674230145867, 2.025931928687196, 1.6612641815235007, 1.2560777957860616, 1.5802269043760129], mode: 'markers', type: 'scatter', name: 'WhatsApp' } ]; var layout = { title: 'Percentage of comments at column number', xaxis: { title: 'comment starts at column number' }, yaxis: { title: 'percentage of comments' } }; Plotly.newPlot('myPlot', data, layout); ``` -------------------------------- ### Unformatted Scenario Source: https://github.com/whatsapp/erlfmt/blob/main/README.md An example of a line that exceeds the length limit. ```erlang scenario(dial_phone_number(), ring(), hello(mike),hello(joe), hello(robert), system_working(), seems_to_be()) ``` -------------------------------- ### Command to reproduce analysis Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionComments/Readme.md Command to run the analysis after setting up the repositories and editing the paths. ```sh $ make ``` -------------------------------- ### Right Associative Operator Example Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionAssociative.md Demonstrates how right-associative binary operators like '++' are parsed and how erlfmt's greedy layout algorithm breaks them. ```erlang A ++ B ++ C ``` -------------------------------- ### Unformatted Split Tokens Source: https://github.com/whatsapp/erlfmt/blob/main/README.md An example of code where the line-length is exceeded, requiring manual intervention. ```erlang split_tokens([{TokenType, Meta, TokenValue} | Rest], TokenAcc, CommentAcc) -> split_tokens(Rest, [{TokenType, token_anno(erl_anno:to_term(Meta), #{}), TokenValue} | TokenAcc], CommentAcc). ``` -------------------------------- ### Expression group alignment Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Discourages aligning expression groups in Erlang code. ```erlang %% Bad Module = Env#env.module, Arity = length(Args). inspect(false) -> "false"; inspect(true) -> "true"; inspect(ok) -> "ok". ``` ```erlang %% Good Module = Env#env.module, Arity = length(Args). inspect(false) -> "false"; inspect(true) -> "true"; inspect(ok) -> "ok". ``` -------------------------------- ### Module Documentation Percentage Usage Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionComments/module_comments.md Empirical results showing the percentage of module documentation comments using %, %%, and %%% for various projects. ```text OTP %: 0.7% %%: 91.5% %%: 7.8% ejabberd %: 0.0% %%: 16.9% %%: 83.1% MongooseIM %: 0.2% %%: 40.1% %%: 59.7% Inaka %: 8.3% %%: 23.4% %%: 68.3% kazoo %: 0.0% %%: 0.0% %%: 100.0% WhatsApp %: 17.4% %%: 15.6% %%: 67.0% ``` -------------------------------- ### Function with Long Pattern Source: https://github.com/whatsapp/erlfmt/blob/main/README.md An example of a function head with a long pattern that might be split by the formatter. ```erlang my_function( #user{name: Name, age: Age, ...}, Arg2, Arg3 ) -> ... ``` -------------------------------- ### Dedent double pipes, just a little - Consistent alignment Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md Demonstrates consistent 4-space alignment with the chosen formatting. ```erlang [ function_with_long_name(A) || {A, B} <- Cs, filter(B) ] ``` -------------------------------- ### Unary operator spacing Source: https://github.com/whatsapp/erlfmt/blob/main/StyleGuide.md Shows that spaces should not be used after symbolic unary operators in Erlang. ```erlang %% Bad Angle = - 45, WithParens = - ( + 45 ). ``` ```erlang %% Good Angle = -45, WithParens = -(+45). ``` -------------------------------- ### Container Layouts: Expanded Source: https://github.com/whatsapp/erlfmt/blob/main/README.md Example of a list formatted in 'expanded' layout, where each element is printed on a separate line. ```erlang ```erlang formatted expanded [ Foo, Bar ] ``` ``` -------------------------------- ### Unaligned Matrix Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionIgnore.md An example of a matrix defined with alignment that would be lost if formatted by erlfmt. ```erlang -define(DELTA_MATRIX, [ [0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 0, 0, 0, 0, 0, 0, -16, 0, 0, 0], [0, 0, 0, -15, 0, 0, -17, 0, 0, 0, 0, 0, -16, 0, 0, 0, 0, 0, -15, 0], [0, 0, 0, -17, 0, 0, 0, 0, -16, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 0], [-17, 0, 0, -16, -16, 0, 0, 0, -15, 0, 0, 0, 0, 0, 0, 0, 0, -17, 0, 0], [-16, 0, 0, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, -33, -16, -31, -15, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -18, -17, -16, -15, -14, 0, 0, 0, 0, 0], [0, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], [0, 0, 14, 15, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 31], [16, 33, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 16, 0, 0, 17], [0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0], [0, 0, 0, 15, 0, 0, 0, 0, 16, 0, 0, 0, 0, 17, 0, 0, 0, 0, 15, 0], [0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 17, 0, 0, 15, 0, 0, 0, 0, 0, 0], [16, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ]). ``` -------------------------------- ### Container Layouts: Collapsed Source: https://github.com/whatsapp/erlfmt/blob/main/README.md Example of a list formatted in 'collapsed' layout where all elements are printed in a single line. ```erlang ```erlang formatted collapsed [Foo, Bar] ``` ``` -------------------------------- ### List with leading comma Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionCommas.md Example of a list where each element, except the last, is preceded by a comma. ```erlang [ x , y , z ] ``` -------------------------------- ### Compressed with 4 spaces and multiline expressions Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionListComprehensions.md Example showing inconsistent handling of multiline expressions with 'compressed' and 4-space indentation. ```erlang [function_with_long_name( A, AlongArgument ) || A <- a_generator(), some_check(A)] ``` -------------------------------- ### List with trailing comma Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionCommas.md Example of a list where each element, except the last, is followed by a comma. ```erlang [ x, y, z ] ``` -------------------------------- ### IO Format Tilde P style for lists Source: https://github.com/whatsapp/erlfmt/blob/main/doc/FormattingDecisionLists.md Shows the compact formatting of lists when using io:format("~p", [MyList]). ```erlang [the_first_and,second_element_fits_on_one_line, but_the_third_cannot_also_fit] ```