├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── README-jaJP.md ├── README.md ├── Rakefile └── mix.exs /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | deps 3 | doc 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: ruby 4 | 5 | rvm: 6 | - 2.3.0 7 | 8 | install: 9 | - gem install mdl rake 10 | 11 | script: 12 | - rake test 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Elixir Style Guide 2 | 3 | First of all, thanks for wanting to contribute! :heart: 4 | 5 | You can contribute in several ways: 6 | 7 | * open up an issue if you find something plain old wrong in the style guide 8 | (e.g., typos or formatting); 9 | * open up an issue if you find inconsistencies in the style guide. This way, we 10 | can discuss the better way to eliminate those inconsistencies; 11 | * if you have any suggestions or opinions, open up an issue or (even better!) a 12 | pull request. 13 | 14 | If you edit the `README.md` file, please stick to this set of 15 | formatting/markup/style rules so that the style remains consistent: 16 | 17 | * don't make lines longer than 80 characters (most editors have an auto-wrapping 18 | functionality, for example [Emacs][Emacs LineWrap] or [Vim][Vim word wrap]); 19 | * use reference-style links, like `[an example][Example]`. Put the links in 20 | alphabetical order at the end of the document, and capitalize the first word 21 | of the link label. 22 | 23 | Use Ruby and [Markdownlint] to check your changes: 24 | 25 | ```sh 26 | gem install mdl rake 27 | rake test 28 | ``` 29 | 30 | **IMPORTANT**: By submitting a patch, you agree that your work will be 31 | licensed under the license used by the project. 32 | 33 | ## The Project Board 34 | 35 | If you are looking for issues to work on, the [project board][Project KanBan] 36 | is the place to go. Usually, you look at the issues from right to left, as 37 | the ones in the rightmost part are the closer to get merged and have higher 38 | priority. 39 | 40 | If you just want to dive in and start writing, the backlog has the 41 | 'ready to be picked up' issues. These issues have been discussed already and 42 | are most likely just waiting for someone to make a PR. Just look for the 43 | issues with the `enhancement` and/or `help wanted` labels. 44 | 45 | ## Collaborators 46 | 47 | If you have contributed to the repository you can be appointed as a collaborator 48 | after submitting a change and getting it merged. Collaborators are invited to 49 | manage issues, make corrections to the style guide, review pull requests, and 50 | merge approved changes. 51 | 52 | 1. All changes must pass automatic checks before being merged. 53 | 1. Minor changes and corrections can be merged without review. 54 | 1. Significant changes or new style rules should be discussed and approved in a 55 | pull request. 56 | 57 | ## Translations 58 | 59 | If you would like to help translate the Style Guide, check if there is 60 | an [existing translation][Translations] to contribute to. To create a new 61 | translation: 62 | 63 | 1. [Fork] this repository. 64 | 1. Clone your fork locally. 65 | 1. Copy `README.md` to a new file named after the country/language, like 66 | `README-jaJP.md`, and commit your translations there. 67 | 1. Add the main [repo][Repo] as an upstream remote, to fetch and merge changes. 68 | 69 | 70 | [Emacs LineWrap]: http://emacswiki.org/emacs/LineWrap 71 | [Fork]: https://github.com/christopheradams/elixir_style_guide#fork-destination-box 72 | [Markdownlint]: https://github.com/mivok/markdownlint 73 | [Project KanBan]: https://github.com/christopheradams/elixir_style_guide/projects/1 74 | [Repo]: https://github.com/christopheradams/elixir_style_guide.git 75 | [Translations]: README.md#translations 76 | [Vim word wrap]: http://vim.wikia.com/wiki/Automatic_word_wrapping 77 | -------------------------------------------------------------------------------- /README-jaJP.md: -------------------------------------------------------------------------------- 1 | # [The Elixir Style Guide][Elixir Style Guide] 2 | 3 | 4 | ## 目次 5 | 6 | * __[はじめに](#はじめに)__ 7 | * __[このガイドについて](#このガイドについて)__ 8 | * [ソースコードレイアウト](#ソースコードレイアウト) 9 | * [構文](#構文) 10 | * [命名](#命名) 11 | * [コメント](#コメント) 12 | * [注釈](#注釈) 13 | * [モジュール](#モジュール) 14 | * [ドキュメント](#ドキュメント) 15 | * [Typespecs](#typespecs) 16 | * [構造体](#構造体) 17 | * [例外](#例外) 18 | * [コレクション](#コレクション) 19 | * [文字列](#文字列) 20 | * _正規表現_ 21 | * [メタプログラミング](#メタプログラミング) 22 | * [その他のスタイル](#その他のスタイル) 23 | * [スタイルガイド](#スタイルガイド) 24 | * [ツール](#ツール) 25 | * __[コミュニティへの参加方法](#コミュニティへの参加方法)__ 26 | * [コントリビュート](#コントリビュート) 27 | * [広めてください](#広めてください) 28 | * __[コピーライト](#コピーライト)__ 29 | * [ライセンス](#ライセンス) 30 | * [帰属](#帰属) 31 | 32 | 33 | ## はじめに 34 | > まるでジャズみたいに一緒に即興で演奏するんだ。 35 | > 私が何かを作って、彼らも何かを作ることで答える 36 | 37 | > -フランク・ゲーリー 38 | 39 | スタイルは重要です。 [Elixir] には実に様々なスタイルがありますが、他の言語と同じように無視されがちです。 40 | スタイルを尊重しましょう。 41 | 42 | 43 | ## このガイドについて 44 | 45 | これは、プログラミング言語 [Elixir] のコミュニティスタイルガイドを作ろうという試みです。気軽にプルリクエストを送ってください。 46 | 実際より5倍も長生きしている言語のようにElixirのコミュニティを活発にしましょう。 47 | 48 | もし他に貢献できるプロジェクトを探しているなら[Hex package manager site][Hex]を見てみてください。 49 | 50 | 51 | このガイドは以下の言語にも翻訳されています。 52 | 53 | * [Chinese Traditional] 54 | * [Japanese] 55 | * [Korean] 56 | 57 | ### ソースコードのレイアウト 58 | 59 | 60 | 61 | * 62 | インデントは **スペース** 2つ。ハードタブは使わないこと。 63 | 64 | [[link](#spaces-indentation)] 65 | 66 | ```elixir 67 | # 悪い例 - スペースが4つ 68 | def some_function do 69 | do_something 70 | end 71 | 72 | # 良い例 73 | def some_function do 74 | do_something 75 | end 76 | ``` 77 | 78 | * 79 | Unixスタイルの改行コードを使うこと (\*BSD/Solaris/Linux/OSX ではこれがデフォルトです。Windowsを使っている場合は気をつけてください) 80 | [[link](#line-endings)] 81 | 82 | * 83 | Gitを使っている場合はWindowsの改行コードであなたのプロジェクトがめちゃくちゃになるのを防ぐために、このように設定してください。 84 | [[link](#autocrlf)] 85 | 86 | ```sh 87 | git config --global core.autocrlf true 88 | ``` 89 | 90 | * 91 | - オペレータの前後、カンマ、コロン、セミコロンの後にはスペースを入れてください。 92 | - ()や[]の間にはスペースを入れないでください。 93 | - Elixirの処理系にとって空白にほとんど意味はありませんが、コードを読みやすくするためには重要です。 94 | [[link](#spaces)] 95 | 96 | ```elixir 97 | sum = 1 + 2 98 | {a, b} = {2, 3} 99 | Enum.map(["one", <<"two">>, "three"], fn num -> IO.puts num end) 100 | ``` 101 | 102 | * 103 | `def`の間や関数内のロジックの区切りに空白行を入れてください。 104 | [[link](#def-spacing)] 105 | 106 | ```elixir 107 | def some_function(some_data) do 108 | altered_data = Module.function(data) 109 | end 110 | 111 | def some_function do 112 | result 113 | end 114 | 115 | def some_other_function do 116 | another_result 117 | end 118 | 119 | def a_longer_function do 120 | one 121 | two 122 | 123 | three 124 | four 125 | end 126 | ``` 127 | 128 | * 129 | 関数節に一行の`def`があるならまとめて定義してしまってもよい。 130 | [[link](#single-line-defs)] 131 | 132 | ```elixir 133 | def some_function(nil), do: {:err, "No Value"} 134 | def some_function([]), do: :ok 135 | def some_function([first|rest]) do 136 | some_function(rest) 137 | end 138 | ``` 139 | 140 | * 141 | `do:`を使った関数定義が長くなった場合は、改行後インデントしてから`do:`を入れてください。 142 | [[link](#long-dos)] 143 | 144 | ```elixir 145 | def some_function(args), 146 | do: Enum.map(args, fn(arg) -> arg <> " is on a very long line!" end) 147 | ``` 148 | 149 |  上記の規約を使用した関数節があり、かつ他に`do:`を使った関数節がある場合は 150 | すべての関数節で改行してから `do:`を入れてください: 151 | 152 | ```elixir 153 | # 悪い例 154 | def some_function([]), do: :empty 155 | def some_function(_), 156 | do: :very_long_line_here 157 | 158 | # 良い例 159 | def some_function([]), 160 | do: :empty 161 | def some_function(_), 162 | do: :very_long_line_here 163 | ``` 164 | 165 | * 166 | 複数行の関数節が一つ以上ある場合は一行の`def`を使わないこと。 167 | [[link](#multiple-function-defs)] 168 | 169 | ```elixir 170 | def some_function(nil) do 171 | {:err, "No Value"} 172 | end 173 | 174 | def some_function([]) do 175 | :ok 176 | end 177 | 178 | def some_function([first|rest]) do 179 | some_function(rest) 180 | end 181 | 182 | def some_function([first|rest], opts) do 183 | some_function(rest, opts) 184 | end 185 | ``` 186 | 187 | * 188 | 関数のチェインにはパイプライン演算子を使ってください。 189 | [[link](#pipe-operator)] 190 | 191 | ```elixir 192 | # 悪い例 193 | String.strip(String.downcase(some_string)) 194 | 195 | # 良い例 196 | some_string |> String.downcase |> String.strip 197 | 198 | # 複数行のパイプラインはインデントしないこと。 199 | some_string 200 | |> String.downcase 201 | |> String.strip 202 | 203 | # パターンマッチの右辺として複数行のパイプラインを使う場合は改行してから書くこと。 204 | sanitized_string = 205 | some_string 206 | |> String.downcase 207 | |> String.strip 208 | ``` 209 | 210 | これは好ましい書き方ですが少し注意が必要です。 211 | IExが次の行にパイプラインがあることを認識せずに最初の行を評価するため、複数行のパイプラインをIExにコピーすると構文エラーが発生する可能性があります。 212 | 213 | 214 | * 215 | 216 | パイプライン演算子を一度だけ使うのをやめましょう。 217 | [[link](#avoid-single-pipelines)] 218 | 219 | ```elixir 220 | # 悪い例 221 | some_string |> String.downcase 222 | 223 | # 良い例 224 | String.downcase(some_string) 225 | ``` 226 | 227 | * 228 | 関数チェインの最初の値は関数の戻り値ではなく、通常の変数を使ってください。 229 | [[link](#bare-variables)] 230 | 231 | ```elixir 232 | # これは最悪! 233 | # String.strip("nope" |> String.downcase).にパースされます 234 | String.strip "nope" |> String.downcase 235 | 236 | # 悪い例 237 | String.strip(some_string) |> String.downcase |> String.codepoints 238 | 239 | # 良い例 240 | some_string |> String.strip |> String.downcase |> String.codepoints 241 | ``` 242 | 243 | * 244 | 行末に余分な空白を入れないこと。 245 | [[link](#trailing-whitespace)] 246 | 247 | * 248 | ファイルの終わりには空行を入れること。 249 | [[link](#newline-eof)] 250 | 251 | 252 | ### 構文 253 | 254 | * 255 | `def` が引数をとる場合は括弧を使うこと。引数がない場合は省略すること。 256 | [[link](#parentheses)] 257 | 258 | ```elixir 259 | # 悪い例 260 | def some_function arg1, arg2 do 261 | # body omitted 262 | end 263 | 264 | def some_function() do 265 | # body omitted 266 | end 267 | 268 | # 良い例 269 | def some_function(arg1, arg2) do 270 | # body omitted 271 | end 272 | 273 | def some_function do 274 | # body omitted 275 | end 276 | ``` 277 | 278 | * 279 | 複数行の`if/unless`に `do:`を使ってはいけない。 280 | [[link](#do-with-multi-line-if-unless)] 281 | 282 | ```elixir 283 | # 悪い例 284 | if some_condition, do: 285 | # a line of code 286 | # another line of code 287 | # note no end in this block 288 | 289 | # 良い例 290 | if some_condition do 291 | # some 292 | # lines 293 | # of code 294 | end 295 | ``` 296 | 297 | * 298 | 一行の`if/unless` には`do:`を使うこと。 299 | [[link](#do-with-single-line-if-unless)] 300 | 301 | ```elixir 302 | # 良い例 303 | if some_condition, do: # some_stuff 304 | ``` 305 | 306 | * 307 | `unless` に `else`を使ってはいけない。 308 | 正常系が最初に来るように書き直してください。 309 | [[link](#unless-with-else)] 310 | 311 | ```elixir 312 | # 悪い例 313 | unless success? do 314 | IO.puts 'failure' 315 | else 316 | IO.puts 'success' 317 | end 318 | 319 | # 良い例 320 | if success? do 321 | IO.puts 'success' 322 | else 323 | IO.puts 'failure' 324 | end 325 | ``` 326 | 327 | * 328 | `cond`構文の最後の条件は常に`true`を使うこと。 329 | [[link](#true-as-last-condition)] 330 | 331 | ```elixir 332 | cond do 333 | 1 + 2 == 5 -> 334 | "Nope" 335 | 1 + 3 == 5 -> 336 | "Uh, uh" 337 | true -> 338 | "OK" 339 | end 340 | ``` 341 | 342 | * 343 |  関数名と括弧の間にはスペースを入れないこと。 344 | [[link](#function-names-with-parentheses)] 345 | 346 | ```elixir 347 | # 悪い例 348 | f (3 + 2) + 1 349 | 350 | # 良い例 351 | f(3 + 2) + 1 352 | ``` 353 | 354 | * 355 |  関数呼び出しには括弧を使うこと。特にパイプライン演算子の中では必ず使うこと。 356 | [[link](#function-calls-and-parentheses)] 357 | 358 | ```elixir 359 | # 悪い例 360 | f 3 361 | 362 | # 良い例 363 | f(3) 364 | 365 | # 悪い例. rem(2, (3 |> g)) にパースされてしまう 366 | 2 |> rem 3 |> g 367 | 368 | # 良い例 369 | 2 |> rem(3) |> g 370 | ``` 371 | 372 | * 373 | `do`ブロックをとるマクロの呼び出しでは括弧を省略すること。 374 | [[link](#macro-calls-and-parentheses)] 375 | 376 | ```elixir 377 | # 悪い例 378 | quote(do 379 | foo 380 | end) 381 | 382 | # 良い例 383 | quote do 384 | foo 385 | end 386 | ``` 387 | 388 | * 389 | 引数の最後が関数の場合は括弧を省略してもよい。 390 | [[link](#parentheses-and-function-expressions)] 391 | 392 | ```elixir 393 | # 良い例 394 | Enum.reduce(1..10, 0, fn x, acc -> 395 | x + acc 396 | end) 397 | 398 | # これも良い例 399 | Enum.reduce 1..10, 0, fn x, acc -> 400 | x + acc 401 | end 402 | ``` 403 | 404 | * 405 | 変数と区別するため引数がない関数呼び出しでも括弧を使うこと。 406 | (Elixir 1.4からは、このようなあいまいな記述があった場合には警告を出すようになりました) 407 | [[link](#parentheses-and-functions-with-zero-arity)] 408 | 409 | ```elixir 410 | defp do_stuff, do: ... 411 | 412 | # 悪い例 413 | def my_func do 414 | do_stuff # 関数呼び出しなのか変数なのかわからない 415 | end 416 | 417 | # 良い例 418 | def my_func do 419 | do_stuff() # 間違いなく関数呼び出し 420 | end 421 | ``` 422 | 423 | * 424 | 連続した`with`節はインデントを揃え、引数の`do:`を新しい行に入れてください。 425 | [[link](#with-clauses)] 426 | 427 | ```elixir 428 | with {:ok, foo} <- fetch(opts, :foo), 429 | {:ok, bar} <- fetch(opts, :bar), 430 | do: {:ok, foo, bar} 431 | ``` 432 | 433 | * 434 |  `with` に 複数行の`do`ブロックがある場合や、`else`オプションがある場合は複数行の構文を使用してください。 435 | [[link](#with-else)] 436 | 437 | ```elixir 438 | with {:ok, foo} <- fetch(opts, :foo), 439 | {:ok, bar} <- fetch(opts, :bar) do 440 | {:ok, foo, bar} 441 | else 442 | :error -> 443 | {:error, :bad_arg} 444 | end 445 | ``` 446 | 447 | ### 命名 448 | 449 | * 450 | アトム、関数、変数には `snake_case` を使うこと。 451 | [[link](#snake-case)] 452 | 453 | ```elixir 454 | # 悪い例 455 | :"some atom" 456 | :SomeAtom 457 | :someAtom 458 | 459 | someVar = 5 460 | 461 | def someFunction do 462 | ... 463 | end 464 | 465 | def SomeFunction do 466 | ... 467 | end 468 | 469 | # 良い例 470 | :some_atom 471 | 472 | some_var = 5 473 | 474 | def some_function do 475 | ... 476 | end 477 | ``` 478 | 479 | * 480 | モジュール名は`CamelCase`を使うこと(HTTP, RFC, XMLなどの頭字語はそのままでよい) 481 | [[link](#camel-case)] 482 | 483 | ```elixir 484 | # 悪い例 485 | defmodule Somemodule do 486 | ... 487 | end 488 | 489 | defmodule Some_Module do 490 | ... 491 | end 492 | 493 | defmodule SomeXml do 494 | ... 495 | end 496 | 497 | # 良い例 498 | defmodule SomeModule do 499 | ... 500 | end 501 | 502 | defmodule SomeXML do 503 | ... 504 | end 505 | ``` 506 | 507 | * 508 | ガード内で使用できる述語マクロ(コンパイル時にbooleanを返す関数になるもの)には`is_`接頭辞をつけること。 509 | ガード内で使用できる式については [Expressions in Guard Clauses](http://elixir-lang.org/getting-started/case-cond-and-if.html#expressions-in-guard-clauses)を参照してください。 510 | [[link](#predicate-macro-names-with-guards)] 511 | 512 | ```elixir 513 | defmacro is_cool(var) do 514 | quote do: unquote(var) == "cool" 515 | end 516 | ``` 517 | 518 | * 519 | ガード内で使わない述語関数は`is_`接頭辞ではなく末尾に`?`をつけること。 520 | [[link](#predicate-macro-names-no-guards)] 521 | 522 | ```elixir 523 | def cool?(var) do 524 | # Complex check if var is cool not possible in a pure function. 525 | end 526 | ``` 527 | 528 | * 529 | パブリック関数と同名のプライベート関数を定義したい場合は`do_`を頭につけること。 530 | [[link](#private-functions-with-same-name-as-public)] 531 | 532 | ```elixir 533 | def sum(list), do: do_sum(list, 0) 534 | 535 | # private functions 536 | defp do_sum([], total), do: total 537 | defp do_sum([head|tail], total), do: do_sum(tail, head + total) 538 | ``` 539 | 540 | 541 | ### コメント 542 | 543 | * 544 | 表現力豊かなコードを書いてください。 制御フロー、構造、命名を通じてプログラムの意図を伝えてください。 545 | [[link](#self-documenting-code)] 546 | 547 | * 548 | `#` とコメントの間にスペースを一つ入れること。 549 | [[link](#comment-leading-spaces)] 550 | 551 | * 552 | 一語以上のコメントは先頭を大文字にして句読点を使うこと。 553 | ピリオドの後には[スペースを一つ](http://en.wikipedia.org/wiki/Sentence_spacing)入れること。 554 | [[link](#comment-spacing)] 555 | 556 | ```elixir 557 | # 悪い例 558 | String.upcase(some_string) # Capitalize string. 559 | ``` 560 | 561 | #### 注釈 562 | 563 | * 564 | 注釈は関連するコードのすぐ上に書くこと。 565 | [[link](#annotations)] 566 | 567 | * 568 | 注釈キーワードの後には: とスペースを入れてから本文を書いてください。 569 | [[link](#annotation-keyword)] 570 | 571 | * 572 | もし問題の説明が複数行になる場合は#の後にスペースを2つ入れてください。 573 | [[link](#multiple-line-annotations)] 574 | 575 | * 576 | もし問題が明らかな場合は注釈キーワードだけを該当行の最後に入れてください。 577 | これは強制ではありません。 578 | [[link](#exceptions-to-annotations)] 579 | 580 | * 581 | 未実装や、将来の機能追加のための注釈には`TODO`を使ってください。 582 | [[link](#todo-notes)] 583 | 584 | * 585 | 壊れたコードの注釈には `FIXME` を使ってください。 586 | [[link](#fixme-notes)] 587 | 588 | * 589 | 遅かったり、非効率的なコードの注釈には`OPTIMIZE` を使ってください。 590 | [[link](#optimize-notes)] 591 | 592 | * 593 | コードの書き方に疑問の残る箇所の注釈には`HACK`を使ってください。 594 | [[link](#hack-notes)] 595 | 596 | * 597 | 正しく動くか確認する必要があるコードの注釈には `REVIEW` を使ってください。 598 | 例: `REVIEW: Are we sure this is how the client does X currently?` 599 | [[link](#review-notes)] 600 | 601 | * 602 | もし必要があるようなら独自の注釈キーワードを使ってもかまいませんが、それらはプロジェクトの `README` などに書かれるべきでしょう。 603 | [[link](#custom-keywords)] 604 | 605 | 606 | ### モジュール 607 | 608 | * 609 | モジュールは一つのファイルに一つだけ定義すること。 610 | ただし内部的にのみ使用しているモジュール(テストなど) の場合はこの限りではない。 611 | [[link](#one-module-per-file)] 612 | 613 | * 614 | キャメルケースのモジュール名をアンダースコア化したファイル名にすること。 615 | [[link](#underscored-filenames)] 616 | 617 | ```elixir 618 | # file is called some_module.ex 619 | 620 | defmodule SomeModule do 621 | end 622 | ``` 623 | 624 | * 625 | モジュール名のネストはディレクトリ構造を反映させること。 626 | [[link](#module-name-nesting)] 627 | 628 | ```elixir 629 | # file is called parser/core/xml_parser.ex 630 | 631 | defmodule Parser.Core.XMLParser do 632 | end 633 | ``` 634 | 635 | * 636 | `defmodule`の後に空行を入れてはいけない。 637 | [[link](#defmodule-spacing)] 638 | 639 | * 640 | モジュールレベルのコードブロックの後には空行を入れること。 641 | [[link](#module-block-spacing)] 642 | 643 | * 644 | モジュール内の定義順は下記のようにする。 645 | [[link](#module-attribute-ordering)] 646 | 647 | 1. `@moduledoc` 648 | 1. `@behaviour` 649 | 1. `use` 650 | 1. `import` 651 | 1. `alias` 652 | 1. `require` 653 | 1. `defstruct` 654 | 1. `@type` 655 | 1. `@module_attribute` 656 | 657 | それぞれのグループの間には空白行を入れ、アルファベット順でソートしてください。 658 | モジュール定義の例を以下に記します。 659 | 660 | ```elixir 661 | defmodule MyModule do 662 | @moduledoc """ 663 | An example module 664 | """ 665 | 666 | @behaviour MyBehaviour 667 | 668 | use GenServer 669 | 670 | import Something 671 | import SomethingElse 672 | 673 | alias My.Long.Module.Name 674 | alias My.Other.Module.Name 675 | 676 | require Integer 677 | 678 | defstruct name: nil, params: [] 679 | 680 | @type params :: [{binary, binary}] 681 | 682 | @module_attribute :foo 683 | @other_attribute 100 684 | 685 | ... 686 | end 687 | ``` 688 | 689 | * 690 | モジュールが自身を参照するには`__MODULE__`疑似変数を使用すること。 691 | これならモジュール名が変更されてもコードの変更が要りません。 692 | [[link](#module-pseudo-variable)] 693 | 694 | ```elixir 695 | defmodule SomeProject.SomeModule do 696 | defstruct [:name] 697 | 698 | def name(%__MODULE__{name: name}), do: name 699 | end 700 | ``` 701 | 702 | * 703 | もしモジュール自身の参照にもっとわかりやすい名前を使いたければaliasを使うことができます。 704 | [[link](#alias-self-referencing-modules)] 705 | 706 | ```elixir 707 | defmodule SomeProject.SomeModule do 708 | alias __MODULE__, as: SomeModule 709 | 710 | defstruct [:name] 711 | 712 | def name(%SomeModule{name: name}), do: name 713 | end 714 | ``` 715 | 716 | 717 | ### ドキュメント 718 | Elixrのドキュメント(`iex`の中で`h`を入力するか、[ExDoc](https://github.com/elixir-lang/ex_doc)で作られたもの) は[モジュールアトリビュート](http://elixir-lang.org/getting-started/module-attributes.html#as-annotations)である `@moduledoc` と `@doc`を使います。 719 | 720 | * 721 | `@moduledoc` は必ず`defmodule`の次の行に書くこと。 722 | [[link](#moduledocs)] 723 | 724 | ```elixir 725 | # 悪い例 726 | 727 | defmodule SomeModule do 728 | 729 | @moduledoc """ 730 | About the module 731 | """ 732 | ... 733 | end 734 | 735 | defmodule AnotherModule do 736 | use SomeModule 737 | @moduledoc """ 738 | About the module 739 | """ 740 | ... 741 | end 742 | 743 | # 良い例 744 | 745 | defmodule SomeModule do 746 | @moduledoc """ 747 | About the module 748 | """ 749 | ... 750 | end 751 | ``` 752 | 753 | * 754 | モジュールについてのドキュメントを書かない場合は `@moduledoc false`を使ってください。 755 | [[link](#moduledoc-false)] 756 | 757 | ```elixir 758 | defmodule SomeModule do 759 | @moduledoc false 760 | ... 761 | end 762 | ``` 763 | 764 | * 765 | `@moduledoc`の後には空白行を入れてください。 766 | [[link](#moduledoc-spacing)] 767 | 768 | ```elixir 769 | # 悪い例 770 | 771 | defmodule SomeModule do 772 | @moduledoc """ 773 | About the module 774 | """ 775 | use AnotherModule 776 | end 777 | 778 | # 良い例 779 | defmodule SomeModule do 780 | @moduledoc """ 781 | About the module 782 | """ 783 | 784 | use AnotherModule 785 | end 786 | ``` 787 | 788 | * 789 | ドキュメントのため、複数行コメント内ではmarkdownを使いましょう。 790 | [[link](#heredocs)] 791 | 792 | ```elixir 793 | # 悪い例 794 | 795 | defmodule SomeModule do 796 | @moduledoc "About the module" 797 | end 798 | 799 | defmodule SomeModule do 800 | @moduledoc """ 801 | About the module 802 | 803 | Examples: 804 | iex> SomeModule.some_function 805 | :result 806 | """ 807 | end 808 | 809 | # 良い例 810 | defmodule SomeModule do 811 | @moduledoc """ 812 | About the module 813 | 814 | ## Examples 815 | 816 | iex> SomeModule.some_function 817 | :result 818 | """ 819 | end 820 | ``` 821 | 822 | 823 | ### Typespecs 824 | 825 | typespecsは、型と仕様を宣言するための表記法です。 826 | ドキュメント、または静的解析ツールDialyzerに使用されます。 827 | カスタムタイプは、モジュール上部に他のタイプと一緒に定義する必要があります。 828 | ([モジュール](#modules)をみてください) 829 | 830 | * 831 | `@typedoc` と `@type` の定義は一緒に書き、それぞれのペア間には空白行を入れてください。 832 | [[link](#typedocs)] 833 | 834 | ```elixir 835 | defmodule SomeModule do 836 | @moduledoc false 837 | 838 | @typedoc "The name" 839 | @type name :: atom 840 | 841 | @typedoc "The result" 842 | @type result :: {:ok, term} | {:error, term} 843 | 844 | ... 845 | end 846 | ``` 847 | 848 | * 849 | 直和型の定義が長過ぎる場合は改行して戻り値の型で整列するようにインデントしてください。 850 | [[link](#union-types)] 851 | 852 | ```elixir 853 | # 悪い例 - インデントしていない 854 | @type long_union_type :: some_type | another_type | some_other_type 855 | | a_final_type 856 | 857 | # 良い例 858 | @type long_union_type :: some_type | another_type | some_other_type 859 | | a_final_type 860 | 861 | # これも良い例 - 一行ごとに型一つ 862 | @type long_union_type :: some_type 863 | | another_type 864 | | some_other_type 865 | | a_final_type 866 | ``` 867 | 868 | * 869 | モジュール内で定義された構造体などの型定義は `t`としてください。 870 | [[link](#naming-main-types)] 871 | 872 | ```elixir 873 | defstruct name: nil, params: [] 874 | 875 | @type t :: %__MODULE__{ 876 | name: String.t, 877 | params: Keyword.t 878 | } 879 | ``` 880 | 881 | * 882 | 型定義は関数のすぐ上に空白行無しで書いてください。 883 | [[link](#spec-spacing)] 884 | 885 | ```elixir 886 | @spec some_function(term) :: result 887 | def some_function(some_data) do 888 | {:ok, some_data} 889 | end 890 | ``` 891 | 892 | 893 | ### 構造体 894 | 895 | * 896 | もし構造体のフィールドのデフォルト値が全てnilならアトムのリストとしてください。 897 | [[link](#nil-struct-field-defaults)] 898 | 899 | ```elixir 900 | # 悪い例 901 | defstruct name: nil, params: nil 902 | 903 | # 良い例 904 | defstruct [:name, :params] 905 | ``` 906 | 907 | * 908 | 複数行に渡る構造体の定義の場合は、最初のキーの位置に合わせてインデントしてください。 909 | [[link](#additional-struct-def-lines)] 910 | 911 | ```elixir 912 | defstruct foo: "test", bar: true, baz: false, 913 | qux: false, quux: nil 914 | ``` 915 | 916 | 917 | ### 例外 918 | 919 | * 920 | 例外の名前は`Error`で終わること。 921 | [[link](#exception-names)] 922 | 923 | ```elixir 924 | # 悪い例 925 | defmodule BadHTTPCode do 926 | defexception [:message] 927 | end 928 | 929 | defmodule BadHTTPCodeException do 930 | defexception [:message] 931 | end 932 | 933 | # 良い例 934 | defmodule BadHTTPCodeError do 935 | defexception [:message] 936 | end 937 | ``` 938 | 939 | * 940 | エラーメッセージは小文字で句読点を省いてください。 941 | [[link](#lowercase-error-messages)] 942 | 943 | ```elixir 944 | # 悪い例 945 | raise ArgumentError, "This is not valid." 946 | 947 | # 良い例 948 | raise ArgumentError, "this is not valid" 949 | ``` 950 | 951 | 952 | ### コレクション 953 | 954 | * 955 | キーワードリストに対して常に特別な構文を使うこと。 956 | [[link](#keyword-list-syntax)] 957 | 958 | ```elixir 959 | # 悪い例 960 | some_value = [{:a, "baz"}, {:b, "qux"}] 961 | 962 | # 良い例 963 | some_value = [a: "baz", b: "qux"] 964 | ``` 965 | 966 | * 967 | マップのキーがすべてアトムの場合は短く書けるキーバリュー構文を使うこと。 968 | [[link](#map-key-atom)] 969 | 970 | ```elixir 971 | # 悪い例 972 | %{:a => 1, :b => 2, :c => 0} 973 | 974 | # 良い例 975 | %{a: 1, b: 2, c: 3} 976 | ``` 977 | 978 | * 979 | マップのキーにアトムではないものがある場合は冗長なキーバリュー構文を使うこと。 980 | [[link](#map-key-arrow)] 981 | 982 | ```elixir 983 | # 悪い例 984 | %{"c" => 0, a: 1, b: 2} 985 | 986 | # 良い例 987 | %{:a => 1, :b => 2, "c" => 0} 988 | ``` 989 | 990 | ### 文字列 991 | 992 | * 993 | 文字列のパターンマッチはバイナリではなく、文字列結合演算子を使用してください。 994 | [[link](#strings-matching-with-concatenator)] 995 | 996 | ```elixir 997 | # 悪い例 998 | <<"my"::utf8, _rest>> = "my string" 999 | 1000 | # 良い例 1001 | "my" <> _rest = "my string" 1002 | ``` 1003 | 1004 | 1005 | ### 正規表現 1006 | 1007 | _正規表現に関するガイドラインは今のところありません_ 1008 | 1009 | 1010 | ### メタプログラミング 1011 | 1012 | * 1013 | 不要なメタプログラミングをしてはいけない。 1014 | [[link](#avoid-metaprogramming)] 1015 | 1016 | 1017 | ### その他のスタイル 1018 | 1019 | あまり一般的ではないスタイルですが役立つ場合があるかもしれません。 1020 | 1021 | #### Cond 1022 | 1023 | * 1024 | アトムは`true`として評価されるので`cond`の最後に入れるすべてにマッチする節として使うことができます。 1025 | `:else` か `:otherwise` を使うと良いでしょう。 1026 | [[link](#atom-conditions)] 1027 | 1028 | ```elixir 1029 | cond do 1030 | 1 + 2 == 5 -> 1031 | "Nope" 1032 | 1 + 3 == 5 -> 1033 | "Uh, uh" 1034 | :else -> 1035 | "OK" 1036 | end 1037 | 1038 | # is the same as 1039 | cond do 1040 | 1 + 2 == 5 -> 1041 | "Nope" 1042 | 1 + 3 == 5 -> 1043 | "Uh, uh" 1044 | true -> 1045 | "OK" 1046 | end 1047 | ``` 1048 | 1049 | 1050 | ### スタイルガイド 1051 | 1052 | 他のスタイルガイドについては [Awesome Elixir][Style Guides] を見てください。 1053 | 1054 | 1055 | ### ツール 1056 | 1057 | [Awesome Elixir][Code Analysis] にコードの静的解析とlintのためのツールがあります。 1058 | 1059 | ## コミュニティへの参加方法 1060 | 1061 | 1062 | ### コントリビュート 1063 | 1064 | 私達はここがElixirのベストプラクティスに関する議論の中心になることを願っています。 1065 | 気軽にイシューを書いたりプルリクエストを送ってください。 1066 | [contributing guidelines](CONTRIBUTING.md)と [code of conduct](CODE_OF_CONDUCT.md) を確認してください。 1067 | 1068 | 1069 | ### 広めてください 1070 | コミュニティスタイルガイドは、コミュニティのサポートなしでは無意味です。 1071 | ツイートしたり、スターをつけたり、Elixirプログラマに広めてください。 1072 | 1073 | 1074 | ## コピーライト 1075 | 1076 | 1077 | ### ライセンス 1078 | 1079 | ![Creative Commons License](http://i.creativecommons.org/l/by/3.0/88x31.png) 1080 | 本翻訳のライセンスは[Creative Commons Attribution 3.0 Unported License][license]です。 1081 | 1082 | 1083 | ### 帰属 1084 | 1085 | このドキュメントの作成にあたり、ガイドの章立てやコード例の一部、そして原案の多くを[Ruby community style guide]から拝借しました。 1086 | それらの多くのことがElixirにも応用でき、また私達が議論するために _一部の_ ドキュメントを引くことが早くにできました。 1087 | 1088 | ここに、このプロジェクトに対して[親切にもコントリビュートして頂いた方々のリスト][Contributors]を記します。 1089 | 1090 | 1091 | [Chinese Traditional]: https://github.com/elixirtw/elixir_style_guide/blob/master/README_zhTW.md 1092 | [Elixir Style Guide]: https://github.com/christopheradams/elixir_style_guide 1093 | [Stargazers]: https://github.com/christopheradams/elixir_style_guide/stargazers 1094 | [Contributors]: https://github.com/christopheradams/elixir_style_guide/graphs/contributors 1095 | [Elixir]: http://elixir-lang.org 1096 | [Hex]: https://hex.pm/packages 1097 | [Japanese]: https://github.com/kenichirow/elixir_style_guide/blob/master/README-jaJP.md 1098 | [Korean]: https://github.com/marocchino/elixir_style_guide/blob/new-korean/README-koKR.md 1099 | [license]: http://creativecommons.org/licenses/by/3.0/deed.en_US 1100 | [Ruby community style guide]: https://github.com/bbatsov/ruby-style-guide 1101 | [Code Analysis]: https://github.com/h4cc/awesome-elixir#code-analysis 1102 | [Style Guides]: https://github.com/h4cc/awesome-elixir#styleguides 1103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [The Elixir Style Guide][Elixir Style Guide] 2 | 3 | ## Table of Contents 4 | 5 | * __[Prelude](#prelude)__ 6 | * __[About](#about)__ 7 | * __[Formatting](#formatting)__ 8 | * [Whitespace](#whitespace) 9 | * [Indentation](#indentation) 10 | * [Parentheses](#parentheses) 11 | * [Syntax](#syntax) 12 | * __[The Guide](#the-guide)__ 13 | * [Expressions](#expressions) 14 | * [Naming](#naming) 15 | * [Comments](#comments) 16 | * [Comment Annotations](#comment-annotations) 17 | * [Modules](#modules) 18 | * [Documentation](#documentation) 19 | * [Typespecs](#typespecs) 20 | * [Structs](#structs) 21 | * [Exceptions](#exceptions) 22 | * [Collections](#collections) 23 | * [Strings](#strings) 24 | * _Regular Expressions_ 25 | * [Metaprogramming](#metaprogramming) 26 | * [Testing](#testing) 27 | * __[Resources](#resources)__ 28 | * [Alternative Style Guides](#alternative-style-guides) 29 | * [Tools](#tools) 30 | * __[Getting Involved](#getting-involved)__ 31 | * [Contributing](#contributing) 32 | * [Spread the Word](#spread-the-word) 33 | * __[Copying](#copying)__ 34 | * [License](#license) 35 | * [Attribution](#attribution) 36 | 37 | ## Prelude 38 | 39 | > Liquid architecture. It's like jazz — you improvise, you work together, you 40 | > play off each other, you make something, they make something. 41 | > 42 | > —Frank Gehry 43 | 44 | Style matters. 45 | [Elixir] has plenty of style but like all languages it can be stifled. 46 | Don't stifle the style. 47 | 48 | ## About 49 | 50 | This is community style guide for the [Elixir programming language][Elixir]. 51 | Please feel free to make pull requests and suggestions, and be a part of 52 | Elixir's vibrant community. 53 | 54 | If you're looking for other projects to contribute to please see the 55 | [Hex package manager site][Hex]. 56 | 57 | 58 | Translations of the guide are available in the following languages: 59 | 60 | * [Chinese Simplified] 61 | * [Chinese Traditional] 62 | * [French] 63 | * [Japanese] 64 | * [Korean] 65 | * [Portuguese] 66 | * [Spanish] 67 | 68 | ## Formatting 69 | 70 | Elixir v1.6 introduced a [Code Formatter] and [Mix format] task. 71 | The formatter should be preferred for all new projects and source code. 72 | 73 | The rules in this section are applied automatically by the code formatter, but 74 | are provided here as examples of the preferred style. 75 | 76 | ### Whitespace 77 | 78 | * 79 | Avoid trailing whitespace. 80 | [[link](#trailing-whitespace)] 81 | 82 | * 83 | End each file with a newline. 84 | [[link](#newline-eof)] 85 | 86 | * 87 | Use Unix-style line endings (\*BSD/Solaris/Linux/OSX users are covered by 88 | default, Windows users have to be extra careful). 89 | [[link](#line-endings)] 90 | 91 | * 92 | If you're using Git you might want to add the following configuration 93 | setting to protect your project from Windows line endings creeping in: 94 | [[link](#autocrlf)] 95 | 96 | ```sh 97 | git config --global core.autocrlf true 98 | ``` 99 | 100 | * 101 | Limit lines to 98 characters. 102 | Otherwise, set the `:line_length` option in your `.formatter.exs` file. 103 | [[link](#line-length)] 104 | 105 | * 106 | Use spaces around operators, after commas, colons and semicolons. 107 | Do not put spaces around matched pairs like brackets, parentheses, etc. 108 | Whitespace might be (mostly) irrelevant to the Elixir runtime, but its proper 109 | use is the key to writing easily readable code. 110 | [[link](#spaces)] 111 | 112 | ```elixir 113 | sum = 1 + 2 114 | {a, b} = {2, 3} 115 | [first | rest] = [1, 2, 3] 116 | Enum.map(["one", <<"two">>, "three"], fn num -> IO.puts(num) end) 117 | ``` 118 | 119 | * 120 | Do not use spaces after non-word operators that only take one argument; or 121 | around the range operator. 122 | [[link](#no-spaces)] 123 | 124 | ```elixir 125 | 0 - 1 == -1 126 | ^pinned = some_func() 127 | 5 in 1..10 128 | ``` 129 | 130 | * 131 | Use blank lines between `def`s to break up a function into logical 132 | paragraphs. 133 | [[link](#def-spacing)] 134 | 135 | ```elixir 136 | def some_function(some_data) do 137 | some_data |> other_function() |> List.first() 138 | end 139 | 140 | def some_function do 141 | result 142 | end 143 | 144 | def some_other_function do 145 | another_result 146 | end 147 | 148 | def a_longer_function do 149 | one 150 | two 151 | 152 | three 153 | four 154 | end 155 | ``` 156 | 157 | * 158 | Don't put a blank line after `defmodule`. 159 | [[link](#defmodule-spacing)] 160 | 161 | * 162 | If the function head and `do:` clause are too long to fit on the same line, put 163 | `do:` on a new line, indented one level more than the previous line. 164 | [[link](#long-dos)] 165 | 166 | ```elixir 167 | def some_function([:foo, :bar, :baz] = args), 168 | do: Enum.map(args, fn arg -> arg <> " is on a very long line!" end) 169 | ``` 170 | 171 | When the `do:` clause starts on its own line, treat it as a multiline 172 | function by separating it with blank lines. 173 | 174 | ```elixir 175 | # not preferred 176 | def some_function([]), do: :empty 177 | def some_function(_), 178 | do: :very_long_line_here 179 | 180 | # preferred 181 | def some_function([]), do: :empty 182 | 183 | def some_function(_), 184 | do: :very_long_line_here 185 | ``` 186 | 187 | * 188 | Add a blank line after a multiline assignment as a 189 | visual cue that the assignment is 'over'. 190 | [[link](#add-blank-line-after-multiline-assignment)] 191 | 192 | ```elixir 193 | # not preferred 194 | some_string = 195 | "Hello" 196 | |> String.downcase() 197 | |> String.trim() 198 | another_string <> some_string 199 | 200 | # preferred 201 | some_string = 202 | "Hello" 203 | |> String.downcase() 204 | |> String.trim() 205 | 206 | another_string <> some_string 207 | ``` 208 | 209 | ```elixir 210 | # also not preferred 211 | something = 212 | if x == 2 do 213 | "Hi" 214 | else 215 | "Bye" 216 | end 217 | String.downcase(something) 218 | 219 | # preferred 220 | something = 221 | if x == 2 do 222 | "Hi" 223 | else 224 | "Bye" 225 | end 226 | 227 | String.downcase(something) 228 | ``` 229 | 230 | * 231 | If a list, map, or struct spans multiple lines, put each element, as well as 232 | the opening and closing brackets, on its own line. 233 | Indent each element one level, but not the brackets. 234 | [[link](#multiline-enums)] 235 | 236 | ```elixir 237 | # not preferred 238 | [:first_item, :second_item, :next_item, 239 | :final_item] 240 | 241 | # preferred 242 | [ 243 | :first_item, 244 | :second_item, 245 | :next_item, 246 | :final_item 247 | ] 248 | ``` 249 | 250 | * 251 | When assigning a list, map, or struct, keep the opening bracket on the same 252 | line as the assignment. 253 | [[link](#multiline-list-assign)] 254 | 255 | ```elixir 256 | # not preferred 257 | list = 258 | [ 259 | :first_item, 260 | :second_item 261 | ] 262 | 263 | # preferred 264 | list = [ 265 | :first_item, 266 | :second_item 267 | ] 268 | ``` 269 | 270 | * 271 | When `case` or `cond` clauses span multiple lines, separate each clause with a 272 | blank line. 273 | [[link](#multiline-case-clauses)] 274 | 275 | ```elixir 276 | # not preferred 277 | case arg do 278 | true -> 279 | :ok 280 | false -> 281 | :error 282 | end 283 | 284 | # preferred 285 | case arg do 286 | true -> 287 | :ok 288 | 289 | false -> 290 | :error 291 | end 292 | ``` 293 | 294 | * 295 | Place comments above the line they comment on. 296 | [[link](#comments-above-line)] 297 | 298 | ```elixir 299 | String.first(some_string) # not preferred 300 | 301 | # preferred 302 | String.first(some_string) 303 | ``` 304 | 305 | * 306 | Use one space between the leading `#` character of the comment and the text of 307 | the comment. 308 | [[link](#comment-leading-spaces)] 309 | 310 | ```elixir 311 | #not preferred 312 | String.first(some_string) 313 | 314 | # preferred 315 | String.first(some_string) 316 | ``` 317 | 318 | ### Indentation 319 | 320 | * 321 | Indent and align successive `with` clauses. 322 | Put the `do:` argument on a new line, aligned with the previous clauses. 323 | [[link](#with-clauses)] 324 | 325 | ```elixir 326 | with {:ok, foo} <- fetch(opts, :foo), 327 | {:ok, my_var} <- fetch(opts, :my_var), 328 | do: {:ok, foo, my_var} 329 | ``` 330 | 331 | * 332 | If the `with` expression has a `do` block with more than one line, or has an 333 | `else` option, use multiline syntax. 334 | [[link](#with-else)] 335 | 336 | ```elixir 337 | with {:ok, foo} <- fetch(opts, :foo), 338 | {:ok, my_var} <- fetch(opts, :my_var) do 339 | {:ok, foo, my_var} 340 | else 341 | :error -> 342 | {:error, :bad_arg} 343 | end 344 | ``` 345 | 346 | ### Parentheses 347 | 348 | * 349 | Use parentheses for one-arity functions when using the pipe operator (`|>`). 350 | [[link](#parentheses-pipe-operator)] 351 | 352 | ```elixir 353 | # not preferred 354 | some_string |> String.downcase |> String.trim 355 | 356 | # preferred 357 | some_string |> String.downcase() |> String.trim() 358 | ``` 359 | 360 | * 361 | Never put a space between a function name and the opening parenthesis. 362 | [[link](#function-names-with-parentheses)] 363 | 364 | ```elixir 365 | # not preferred 366 | f (3 + 2) 367 | 368 | # preferred 369 | f(3 + 2) 370 | ``` 371 | 372 | * 373 | Use parentheses in function calls, especially inside a pipeline. 374 | [[link](#function-calls-and-parentheses)] 375 | 376 | ```elixir 377 | # not preferred 378 | f 3 379 | 380 | # preferred 381 | f(3) 382 | 383 | # not preferred and parses as rem(2, (3 |> g)), which is not what you want. 384 | 2 |> rem 3 |> g 385 | 386 | # preferred 387 | 2 |> rem(3) |> g 388 | ``` 389 | 390 | * 391 | Omit square brackets from keyword lists whenever they are optional. 392 | [[link](#keyword-list-brackets)] 393 | 394 | ```elixir 395 | # not preferred 396 | some_function(foo, bar, [a: "baz", b: "qux"]) 397 | 398 | # preferred 399 | some_function(foo, bar, a: "baz", b: "qux") 400 | ``` 401 | 402 | ## The Guide 403 | 404 | The rules in this section may not be applied by the code formatter, but they are 405 | generally preferred practice. 406 | 407 | ### Expressions 408 | 409 | * 410 | Run single-line `def`s that match for the same function together, but separate 411 | multiline `def`s with a blank line. 412 | [[link](#single-line-defs)] 413 | 414 | ```elixir 415 | def some_function(nil), do: {:error, "No Value"} 416 | def some_function([]), do: :ok 417 | 418 | def some_function([first | rest]) do 419 | some_function(rest) 420 | end 421 | ``` 422 | 423 | * 424 | If you have more than one multiline `def`, do not use single-line `def`s. 425 | [[link](#multiple-function-defs)] 426 | 427 | ```elixir 428 | def some_function(nil) do 429 | {:error, "No Value"} 430 | end 431 | 432 | def some_function([]) do 433 | :ok 434 | end 435 | 436 | def some_function([first | rest]) do 437 | some_function(rest) 438 | end 439 | 440 | def some_function([first | rest], opts) do 441 | some_function(rest, opts) 442 | end 443 | ``` 444 | 445 | * 446 | Use the pipe operator to chain functions together. 447 | [[link](#pipe-operator)] 448 | 449 | ```elixir 450 | # not preferred 451 | String.trim(String.downcase(some_string)) 452 | 453 | # preferred 454 | some_string |> String.downcase() |> String.trim() 455 | 456 | # Multiline pipelines are not further indented 457 | some_string 458 | |> String.downcase() 459 | |> String.trim() 460 | 461 | # Multiline pipelines on the right side of a pattern match 462 | # should be indented on a new line 463 | sanitized_string = 464 | some_string 465 | |> String.downcase() 466 | |> String.trim() 467 | ``` 468 | 469 | While this is the preferred method, take into account that copy-pasting 470 | multiline pipelines into IEx might result in a syntax error, as IEx will 471 | evaluate the first line without realizing that the next line has a pipeline. 472 | To avoid this, you can wrap the pasted code in parentheses. 473 | 474 | * 475 | Avoid using the pipe operator just once. 476 | [[link](#avoid-single-pipelines)] 477 | 478 | ```elixir 479 | # not preferred 480 | some_string |> String.downcase() 481 | 482 | # preferred 483 | String.downcase(some_string) 484 | ``` 485 | 486 | * 487 | Use _bare_ variables in the first part of a function chain. 488 | [[link](#bare-variables)] 489 | 490 | ```elixir 491 | # not preferred 492 | String.trim(some_string) |> String.downcase() |> String.codepoints() 493 | 494 | # preferred 495 | some_string |> String.trim() |> String.downcase() |> String.codepoints() 496 | ``` 497 | 498 | * 499 | Use parentheses when a `def` has arguments, and omit them when it doesn't. 500 | [[link](#parentheses)] 501 | 502 | ```elixir 503 | # not preferred 504 | def some_function arg1, arg2 do 505 | # body omitted 506 | end 507 | 508 | def some_function() do 509 | # body omitted 510 | end 511 | 512 | # preferred 513 | def some_function(arg1, arg2) do 514 | # body omitted 515 | end 516 | 517 | def some_function do 518 | # body omitted 519 | end 520 | ``` 521 | 522 | * 523 | Use `do:` for single line `if/unless` statements. 524 | [[link](#do-with-single-line-if-unless)] 525 | 526 | ```elixir 527 | # preferred 528 | if some_condition, do: # some_stuff 529 | ``` 530 | 531 | * 532 | Never use `unless` with `else`. 533 | Rewrite these with the positive case first. 534 | [[link](#unless-with-else)] 535 | 536 | ```elixir 537 | # not preferred 538 | unless success do 539 | IO.puts('failure') 540 | else 541 | IO.puts('success') 542 | end 543 | 544 | # preferred 545 | if success do 546 | IO.puts('success') 547 | else 548 | IO.puts('failure') 549 | end 550 | ``` 551 | 552 | * 553 | Use `true` as the last condition of the `cond` special form when you need a 554 | clause that always matches. 555 | [[link](#true-as-last-condition)] 556 | 557 | ```elixir 558 | # not preferred 559 | cond do 560 | 1 + 2 == 5 -> 561 | "Nope" 562 | 563 | 1 + 3 == 5 -> 564 | "Uh, uh" 565 | 566 | :else -> 567 | "OK" 568 | end 569 | 570 | # preferred 571 | cond do 572 | 1 + 2 == 5 -> 573 | "Nope" 574 | 575 | 1 + 3 == 5 -> 576 | "Uh, uh" 577 | 578 | true -> 579 | "OK" 580 | end 581 | ``` 582 | 583 | * 584 | Use parentheses for calls to functions with zero arity, so they can be 585 | distinguished from variables. 586 | Starting in Elixir 1.4, the compiler will warn you about 587 | locations where this ambiguity exists. 588 | [[link](#parentheses-and-functions-with-zero-arity)] 589 | 590 | ```elixir 591 | defp do_stuff, do: ... 592 | 593 | # not preferred 594 | def my_func do 595 | # is this a variable or a function call? 596 | do_stuff 597 | end 598 | 599 | # preferred 600 | def my_func do 601 | # this is clearly a function call 602 | do_stuff() 603 | end 604 | ``` 605 | 606 | ### Naming 607 | 608 | * 609 | Use `snake_case` for atoms, functions and variables. 610 | [[link](#snake-case)] 611 | 612 | ```elixir 613 | # not preferred 614 | :"some atom" 615 | :SomeAtom 616 | :someAtom 617 | 618 | someVar = 5 619 | 620 | def someFunction do 621 | ... 622 | end 623 | 624 | # preferred 625 | :some_atom 626 | 627 | some_var = 5 628 | 629 | def some_function do 630 | ... 631 | end 632 | ``` 633 | 634 | * 635 | Use `CamelCase` for modules (keep acronyms like HTTP, RFC, XML uppercase). 636 | [[link](#camel-case)] 637 | 638 | ```elixir 639 | # not preferred 640 | defmodule Somemodule do 641 | ... 642 | end 643 | 644 | defmodule Some_Module do 645 | ... 646 | end 647 | 648 | defmodule SomeXml do 649 | ... 650 | end 651 | 652 | # preferred 653 | defmodule SomeModule do 654 | ... 655 | end 656 | 657 | defmodule SomeXML do 658 | ... 659 | end 660 | ``` 661 | 662 | * 663 | The names of predicate macros (compile-time generated functions that return a 664 | boolean value) _that can be used within guards_ should be prefixed with `is_`. 665 | For a list of allowed expressions, see the [Guard][Guard Expressions] docs. 666 | [[link](#predicate-macro-names-with-guards)] 667 | 668 | ```elixir 669 | defmacro is_cool(var) do 670 | quote do: unquote(var) == "cool" 671 | end 672 | ``` 673 | 674 | * 675 | The names of predicate functions _that cannot be used within guards_ should 676 | have a trailing question mark (`?`) rather than the `is_` (or similar) prefix. 677 | [[link](#predicate-macro-names-no-guards)] 678 | 679 | ```elixir 680 | def cool?(var) do 681 | # Complex check if var is cool not possible in a pure function. 682 | end 683 | ``` 684 | 685 | * 686 | Private functions with the same name as public functions should start with 687 | `do_`. 688 | [[link](#private-functions-with-same-name-as-public)] 689 | 690 | ```elixir 691 | def sum(list), do: do_sum(list, 0) 692 | 693 | # private functions 694 | defp do_sum([], total), do: total 695 | defp do_sum([head | tail], total), do: do_sum(tail, head + total) 696 | ``` 697 | 698 | ### Comments 699 | 700 | * 701 | Write expressive code and try to convey your program's intention through 702 | control-flow, structure and naming. 703 | [[link](#expressive-code)] 704 | 705 | * 706 | Comments longer than a word are capitalized, and sentences use punctuation. 707 | Use [one space][Sentence Spacing] after periods. 708 | [[link](#comment-grammar)] 709 | 710 | ```elixir 711 | # not preferred 712 | # these lowercase comments are missing punctuation 713 | 714 | # preferred 715 | # Capitalization example 716 | # Use punctuation for complete sentences. 717 | ``` 718 | 719 | * 720 | Limit comment lines to 100 characters. 721 | [[link](#comment-line-length)] 722 | 723 | #### Comment Annotations 724 | 725 | * 726 | Annotations should usually be written on the line immediately above the 727 | relevant code. 728 | [[link](#annotations)] 729 | 730 | * 731 | The annotation keyword is uppercase, and is followed by a colon and a space, 732 | then a note describing the problem. 733 | [[link](#annotation-keyword)] 734 | 735 | ```elixir 736 | # TODO: Deprecate in v1.5. 737 | def some_function(arg), do: {:ok, arg} 738 | ``` 739 | 740 | * 741 | In cases where the problem is so obvious that any documentation would be 742 | redundant, annotations may be left with no note. 743 | This usage should be the exception and not the rule. 744 | [[link](#exceptions-to-annotations)] 745 | 746 | ```elixir 747 | start_task() 748 | 749 | # FIXME 750 | Process.sleep(5000) 751 | ``` 752 | 753 | * 754 | Use `TODO` to note missing features or functionality that should be added at a 755 | later date. 756 | [[link](#todo-notes)] 757 | 758 | * 759 | Use `FIXME` to note broken code that needs to be fixed. 760 | [[link](#fixme-notes)] 761 | 762 | * 763 | Use `OPTIMIZE` to note slow or inefficient code that may cause performance 764 | problems. 765 | [[link](#optimize-notes)] 766 | 767 | * 768 | Use `HACK` to note code smells where questionable coding practices were used 769 | and should be refactored away. 770 | [[link](#hack-notes)] 771 | 772 | * 773 | Use `REVIEW` to note anything that should be looked at to confirm it is 774 | working as intended. 775 | For example: `REVIEW: Are we sure this is how the client does X currently?` 776 | [[link](#review-notes)] 777 | 778 | * 779 | Use other custom annotation keywords if it feels appropriate, but be sure to 780 | document them in your project's `README` or similar. 781 | [[link](#custom-keywords)] 782 | 783 | ### Modules 784 | 785 | * 786 | Use one module per file unless the module is only used internally by another 787 | module (such as a test). 788 | [[link](#one-module-per-file)] 789 | 790 | * 791 | Use `snake_case` file names for `CamelCase` module names. 792 | [[link](#underscored-filenames)] 793 | 794 | ```elixir 795 | # file is called some_module.ex 796 | 797 | defmodule SomeModule do 798 | end 799 | ``` 800 | 801 | * 802 | Represent each level of nesting within a module name as a directory. 803 | [[link](#module-name-nesting)] 804 | 805 | ```elixir 806 | # file is called parser/core/xml_parser.ex 807 | 808 | defmodule Parser.Core.XMLParser do 809 | end 810 | ``` 811 | 812 | * 813 | List module attributes and directives in the following order: 814 | [[link](#module-attribute-ordering)] 815 | 816 | 1. `@moduledoc` 817 | 1. `@behaviour` 818 | 1. `use` 819 | 1. `import` 820 | 1. `alias` 821 | 1. `require` 822 | 1. `@module_attribute` 823 | 1. `defstruct` 824 | 1. `@type` 825 | 1. `@callback` 826 | 1. `@macrocallback` 827 | 1. `@optional_callbacks` 828 | 829 | Add a blank line between each grouping, and sort the terms (like module names) 830 | alphabetically. 831 | Here's an overall example of how you should order things in your modules: 832 | 833 | ```elixir 834 | defmodule MyModule do 835 | @moduledoc """ 836 | An example module 837 | """ 838 | 839 | @behaviour MyBehaviour 840 | 841 | use GenServer 842 | 843 | import Something 844 | import SomethingElse 845 | 846 | alias My.Long.Module.Name 847 | alias My.Other.Module.Example 848 | 849 | require Integer 850 | 851 | @module_attribute :foo 852 | @other_attribute 100 853 | 854 | defstruct [:name, params: []] 855 | 856 | @type params :: [{binary, binary}] 857 | 858 | @callback some_function(term) :: :ok | {:error, term} 859 | 860 | @macrocallback macro_name(term) :: Macro.t() 861 | 862 | @optional_callbacks macro_name: 1 863 | 864 | ... 865 | end 866 | ``` 867 | 868 | * 869 | Use the `__MODULE__` pseudo variable when a module refers to itself. This 870 | avoids having to update any self-references when the module name changes. 871 | [[link](#module-pseudo-variable)] 872 | 873 | ```elixir 874 | defmodule SomeProject.SomeModule do 875 | defstruct [:name] 876 | 877 | def name(%__MODULE__{name: name}), do: name 878 | end 879 | ``` 880 | 881 | * 882 | If you want a prettier name for a module self-reference, set up an alias. 883 | [[link](#alias-self-referencing-modules)] 884 | 885 | ```elixir 886 | defmodule SomeProject.SomeModule do 887 | alias __MODULE__, as: SomeModule 888 | 889 | defstruct [:name] 890 | 891 | def name(%SomeModule{name: name}), do: name 892 | end 893 | ``` 894 | 895 | * 896 | Avoid repeating fragments in module names and namespaces. 897 | This improves overall readability and 898 | eliminates [ambiguous aliases][Conflicting Aliases]. 899 | [[link](#repetitive-module-names)] 900 | 901 | ```elixir 902 | # not preferred 903 | defmodule Todo.Todo do 904 | ... 905 | end 906 | 907 | # preferred 908 | defmodule Todo.Item do 909 | ... 910 | end 911 | ``` 912 | 913 | ### Documentation 914 | 915 | Documentation in Elixir (when read either in `iex` with `h` or generated with 916 | [ExDoc]) uses the [Module Attributes] `@moduledoc` and `@doc`. 917 | 918 | * 919 | Always include a `@moduledoc` attribute in the line right after `defmodule` in 920 | your module. 921 | [[link](#moduledocs)] 922 | 923 | ```elixir 924 | # not preferred 925 | 926 | defmodule AnotherModule do 927 | use SomeModule 928 | 929 | @moduledoc """ 930 | About the module 931 | """ 932 | ... 933 | end 934 | 935 | # preferred 936 | 937 | defmodule AThirdModule do 938 | @moduledoc """ 939 | About the module 940 | """ 941 | 942 | use SomeModule 943 | ... 944 | end 945 | ``` 946 | 947 | * 948 | Use `@moduledoc false` if you do not intend on documenting the module. 949 | [[link](#moduledoc-false)] 950 | 951 | ```elixir 952 | defmodule SomeModule do 953 | @moduledoc false 954 | ... 955 | end 956 | ``` 957 | 958 | * 959 | Separate code after the `@moduledoc` with a blank line. 960 | [[link](#moduledoc-spacing)] 961 | 962 | ```elixir 963 | # not preferred 964 | defmodule SomeModule do 965 | @moduledoc """ 966 | About the module 967 | """ 968 | use AnotherModule 969 | end 970 | 971 | # preferred 972 | defmodule SomeModule do 973 | @moduledoc """ 974 | About the module 975 | """ 976 | 977 | use AnotherModule 978 | end 979 | ``` 980 | 981 | * 982 | Use heredocs with markdown for documentation. 983 | [[link](#heredocs)] 984 | 985 | ```elixir 986 | # not preferred 987 | defmodule SomeModule do 988 | @moduledoc "About the module" 989 | end 990 | 991 | defmodule SomeModule do 992 | @moduledoc """ 993 | About the module 994 | 995 | Examples: 996 | iex> SomeModule.some_function 997 | :result 998 | """ 999 | end 1000 | 1001 | # preferred 1002 | defmodule SomeModule do 1003 | @moduledoc """ 1004 | About the module 1005 | 1006 | ## Examples 1007 | 1008 | iex> SomeModule.some_function 1009 | :result 1010 | """ 1011 | end 1012 | ``` 1013 | 1014 | ### Typespecs 1015 | 1016 | Typespecs are notation for declaring types and specifications, for 1017 | documentation or for the static analysis tool Dialyzer. 1018 | 1019 | Custom types should be defined at the top of the module with the other 1020 | directives (see [Modules](#modules)). 1021 | 1022 | * 1023 | Place `@typedoc` and `@type` definitions together, and separate each 1024 | pair with a blank line. 1025 | [[link](#typedocs)] 1026 | 1027 | ```elixir 1028 | defmodule SomeModule do 1029 | @moduledoc false 1030 | 1031 | @typedoc "The name" 1032 | @type name :: atom 1033 | 1034 | @typedoc "The result" 1035 | @type result :: {:ok, term} | {:error, term} 1036 | 1037 | ... 1038 | end 1039 | ``` 1040 | 1041 | * 1042 | If a union type is too long to fit on a single line, put each part of the 1043 | type on a separate line, indented one level past the name of the type. 1044 | [[link](#union-types)] 1045 | 1046 | ```elixir 1047 | # not preferred 1048 | @type long_union_type :: 1049 | some_type | another_type | some_other_type | one_more_type | a_final_type 1050 | 1051 | # preferred 1052 | @type long_union_type :: 1053 | some_type 1054 | | another_type 1055 | | some_other_type 1056 | | one_more_type 1057 | | a_final_type 1058 | ``` 1059 | 1060 | * 1061 | Name the main type for a module `t`, for example: the type specification for a 1062 | struct. 1063 | [[link](#naming-main-types)] 1064 | 1065 | ```elixir 1066 | defstruct [:name, params: []] 1067 | 1068 | @type t :: %__MODULE__{ 1069 | name: String.t() | nil, 1070 | params: Keyword.t() 1071 | } 1072 | ``` 1073 | 1074 | * 1075 | Place specifications right before the function definition, 1076 | without separating them by a blank line. 1077 | [[link](#spec-spacing)] 1078 | 1079 | ```elixir 1080 | @spec some_function(term) :: result 1081 | def some_function(some_data) do 1082 | {:ok, some_data} 1083 | end 1084 | ``` 1085 | 1086 | ### Structs 1087 | 1088 | * 1089 | Use a list of atoms for struct fields that default to `nil`, followed by the 1090 | other keywords. 1091 | [[link](#nil-struct-field-defaults)] 1092 | 1093 | ```elixir 1094 | # not preferred 1095 | defstruct name: nil, params: nil, active: true 1096 | 1097 | # preferred 1098 | defstruct [:name, :params, active: true] 1099 | ``` 1100 | 1101 | * 1102 | Omit square brackets when the argument of a `defstruct` is a keyword list. 1103 | [[link](#struct-def-brackets)] 1104 | 1105 | ```elixir 1106 | # not preferred 1107 | defstruct [params: [], active: true] 1108 | 1109 | # preferred 1110 | defstruct params: [], active: true 1111 | 1112 | # required - brackets are not optional, with at least one atom in the list 1113 | defstruct [:name, params: [], active: true] 1114 | ``` 1115 | 1116 | * 1117 | If a struct definition spans multiple lines, put each element on its own line, 1118 | keeping the elements aligned. 1119 | [[link](#multiline-structs)] 1120 | 1121 | ```elixir 1122 | defstruct foo: "test", 1123 | bar: true, 1124 | baz: false, 1125 | qux: false, 1126 | quux: 1 1127 | ``` 1128 | 1129 | If a multiline struct requires brackets, format it as a multiline list: 1130 | 1131 | ```elixir 1132 | defstruct [ 1133 | :name, 1134 | params: [], 1135 | active: true 1136 | ] 1137 | ``` 1138 | 1139 | ### Exceptions 1140 | 1141 | * 1142 | Make exception names end with a trailing `Error`. 1143 | [[link](#exception-names)] 1144 | 1145 | ```elixir 1146 | # not preferred 1147 | defmodule BadHTTPCode do 1148 | defexception [:message] 1149 | end 1150 | 1151 | defmodule BadHTTPCodeException do 1152 | defexception [:message] 1153 | end 1154 | 1155 | # preferred 1156 | defmodule BadHTTPCodeError do 1157 | defexception [:message] 1158 | end 1159 | ``` 1160 | 1161 | * 1162 | Use lowercase error messages when raising exceptions, with no trailing 1163 | punctuation. 1164 | [[link](#lowercase-error-messages)] 1165 | 1166 | ```elixir 1167 | # not preferred 1168 | raise ArgumentError, "This is not valid." 1169 | 1170 | # preferred 1171 | raise ArgumentError, "this is not valid" 1172 | ``` 1173 | 1174 | ### Collections 1175 | 1176 | * 1177 | Always use the special syntax for keyword lists. 1178 | [[link](#keyword-list-syntax)] 1179 | 1180 | ```elixir 1181 | # not preferred 1182 | some_value = [{:a, "baz"}, {:b, "qux"}] 1183 | 1184 | # preferred 1185 | some_value = [a: "baz", b: "qux"] 1186 | ``` 1187 | 1188 | * 1189 | Use the shorthand key-value syntax for maps when all of the keys are atoms. 1190 | [[link](#map-key-atom)] 1191 | 1192 | ```elixir 1193 | # not preferred 1194 | %{:a => 1, :b => 2, :c => 0} 1195 | 1196 | # preferred 1197 | %{a: 1, b: 2, c: 3} 1198 | ``` 1199 | 1200 | * 1201 | Use the verbose key-value syntax for maps if any key is not an atom. 1202 | [[link](#map-key-arrow)] 1203 | 1204 | ```elixir 1205 | # not preferred 1206 | %{"c" => 0, a: 1, b: 2} 1207 | 1208 | # preferred 1209 | %{:a => 1, :b => 2, "c" => 0} 1210 | ``` 1211 | 1212 | ### Strings 1213 | 1214 | * 1215 | Match strings using the string concatenator rather than binary patterns: 1216 | [[link](#strings-matching-with-concatenator)] 1217 | 1218 | ```elixir 1219 | # not preferred 1220 | <<"my"::utf8, _rest::bytes>> = "my string" 1221 | 1222 | # preferred 1223 | "my" <> _rest = "my string" 1224 | ``` 1225 | 1226 | ### Regular Expressions 1227 | 1228 | _No guidelines for regular expressions have been added yet._ 1229 | 1230 | ### Metaprogramming 1231 | 1232 | * 1233 | Avoid needless metaprogramming. 1234 | [[link](#avoid-metaprogramming)] 1235 | 1236 | ### Testing 1237 | 1238 | * 1239 | When writing [ExUnit] assertions, put the expression being tested to the left 1240 | of the operator, and the expected result to the right, unless the assertion is 1241 | a pattern match. 1242 | [[link](#testing-assert-order)] 1243 | 1244 | ```elixir 1245 | # preferred 1246 | assert actual_function(1) == true 1247 | 1248 | # not preferred 1249 | assert true == actual_function(1) 1250 | 1251 | # required - the assertion is a pattern match 1252 | assert {:ok, expected} = actual_function(3) 1253 | ``` 1254 | 1255 | ## Resources 1256 | 1257 | ### Alternative Style Guides 1258 | 1259 | * [Aleksei Magusev's Elixir Style Guide](https://github.com/lexmag/elixir-style-guide#readme) 1260 | — An opinionated Elixir style guide stemming from the coding style practiced 1261 | in the Elixir core libraries. 1262 | Developed by [Aleksei Magusev](https://github.com/lexmag) and 1263 | [Andrea Leopardi](https://github.com/whatyouhide), members of Elixir core team. 1264 | While the Elixir project doesn't adhere to any specific style guide, 1265 | this is the closest available guide to its conventions. 1266 | 1267 | * [Credo's Elixir Style Guide](https://github.com/rrrene/elixir-style-guide#readme) 1268 | — Style Guide for the Elixir language, implemented by 1269 | [Credo](http://credo-ci.org) static code analysis tool. 1270 | 1271 | ### Tools 1272 | 1273 | Refer to [Awesome Elixir][Code Analysis] for libraries and tools that can help 1274 | with code analysis and style linting. 1275 | 1276 | ## Getting Involved 1277 | 1278 | ### Contributing 1279 | 1280 | It's our hope that this will become a central hub for community discussion on 1281 | best practices in Elixir. 1282 | Feel free to open tickets or send pull requests with improvements. 1283 | Thanks in advance for your help! 1284 | 1285 | Check the [contributing guidelines][Contributing] for more information. 1286 | 1287 | ### Spread the Word 1288 | 1289 | A community style guide is meaningless without the community's support. Please 1290 | tweet, [star][Stargazers], and let any Elixir programmer know 1291 | about [this guide][Elixir Style Guide] so they can contribute. 1292 | 1293 | ## Copying 1294 | 1295 | ### License 1296 | 1297 | ![Creative Commons License](http://i.creativecommons.org/l/by/3.0/88x31.png) 1298 | This work is licensed under a 1299 | [Creative Commons Attribution 3.0 Unported License][License] 1300 | 1301 | ### Attribution 1302 | 1303 | The structure of this guide, bits of example code, and many of the initial 1304 | points made in this document were borrowed from the [Ruby community style guide]. 1305 | A lot of things were applicable to Elixir and allowed us to get _some_ document 1306 | out quicker to start the conversation. 1307 | 1308 | Here's the [list of people who have kindly contributed][Contributors] to this 1309 | project. 1310 | 1311 | 1312 | [Chinese Simplified]: https://github.com/geekerzp/elixir_style_guide/blob/master/README-zhCN.md 1313 | [Chinese Traditional]: https://github.com/elixirtw/elixir_style_guide/blob/master/README_zhTW.md 1314 | [Code Analysis]: https://github.com/h4cc/awesome-elixir#code-analysis 1315 | [Code Of Conduct]: https://github.com/elixir-lang/elixir/blob/master/CODE_OF_CONDUCT.md 1316 | [Code Formatter]: https://hexdocs.pm/elixir/Code.html#format_string!/2 1317 | [Conflicting Aliases]: https://elixirforum.com/t/using-aliases-for-fubar-fubar-named-module/1723 1318 | [Contributing]: https://github.com/christopheradams/elixir_style_guide/blob/master/CONTRIBUTING.md 1319 | [Contributors]: https://github.com/christopheradams/elixir_style_guide/graphs/contributors 1320 | [Elixir Style Guide]: https://github.com/christopheradams/elixir_style_guide 1321 | [Elixir]: http://elixir-lang.org 1322 | [ExDoc]: https://github.com/elixir-lang/ex_doc 1323 | [ExUnit]: https://hexdocs.pm/ex_unit/ExUnit.html 1324 | [French]: https://github.com/ronanboiteau/elixir_style_guide/blob/master/README_frFR.md 1325 | [Guard Expressions]: http://elixir-lang.org/getting-started/case-cond-and-if.html#expressions-in-guard-clauses 1326 | [Hex]: https://hex.pm/packages 1327 | [Japanese]: https://github.com/kenichirow/elixir_style_guide/blob/master/README-jaJP.md 1328 | [Korean]: https://github.com/marocchino/elixir_style_guide/blob/new-korean/README-koKR.md 1329 | [License]: http://creativecommons.org/licenses/by/3.0/deed.en_US 1330 | [Mix format]: https://hexdocs.pm/mix/Mix.Tasks.Format.html 1331 | [Module Attributes]: http://elixir-lang.org/getting-started/module-attributes.html#as-annotations 1332 | [Portuguese]: https://github.com/gusaiani/elixir_style_guide/blob/master/README_ptBR.md 1333 | [Ruby community style guide]: https://github.com/bbatsov/ruby-style-guide 1334 | [Sentence Spacing]: http://en.wikipedia.org/wiki/Sentence_spacing 1335 | [Spanish]: https://github.com/albertoalmagro/elixir_style_guide/blob/spanish/README_esES.md 1336 | [Stargazers]: https://github.com/christopheradams/elixir_style_guide/stargazers 1337 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | task :test do 2 | exit_code = 0 3 | files = ["README.md", "CONTRIBUTING.md"] 4 | # 'MD036' # Emphasis used instead of a header 5 | # 'MD033' # Inline HTML - allow for anchor links in each bullet point 6 | rules = ['~MD036', '~MD033'].join(",") 7 | files.each do |file| 8 | begin 9 | sh "mdl --rules #{rules} #{file}" 10 | rescue Exception => ex 11 | exit_code = 1 12 | end 13 | end 14 | 15 | exit exit_code 16 | end 17 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule ElixirStyleGuide.Mixfile do 2 | use Mix.Project 3 | 4 | @project_description """ 5 | A community driven style guide for Elixir 6 | """ 7 | 8 | @version "0.2.0-dev" 9 | @source_url "https://github.com/christopheradams/elixir_style_guide" 10 | 11 | def project do 12 | [ 13 | app: :elixir_style_guide, 14 | version: @version, 15 | elixir: "~> 1.0", 16 | build_embedded: Mix.env() == :prod, 17 | start_permanent: Mix.env() == :prod, 18 | docs: docs(), 19 | description: @project_description, 20 | source_url: @source_url, 21 | package: package(), 22 | deps: deps() 23 | ] 24 | end 25 | 26 | def application do 27 | [applications: [:logger]] 28 | end 29 | 30 | defp deps do 31 | [] 32 | end 33 | 34 | defp docs() do 35 | [ 36 | source_ref: "v#{@version}", 37 | main: "readme", 38 | extras: [ 39 | "README.md": [title: "README"] 40 | ] 41 | ] 42 | end 43 | 44 | defp package do 45 | [ 46 | name: :elixir_style_guide, 47 | maintainers: ["Christopher Adams"], 48 | licenses: ["CC-by"], 49 | links: %{ 50 | "GitHub" => @source_url 51 | } 52 | ] 53 | end 54 | end 55 | --------------------------------------------------------------------------------