Coding Style

This style is used in the standard library. You can use it in your own project to make it familiar to other developers.

Naming

Type names are PascalCased. For example:

  1. class ParseError < Exception
  2. end
  3. module HTTP
  4. class RequestHandler
  5. end
  6. end
  7. alias NumericValue = Float32 | Float64 | Int32 | Int64
  8. lib LibYAML
  9. end
  10. struct TagDirective
  11. end
  12. enum Time::DayOfWeek
  13. end

Method names are snake_cased. For example:

  1. class Person
  2. def first_name
  3. end
  4. def date_of_birth
  5. end
  6. def homepage_url
  7. end
  8. end

Variable names are snake_cased. For example:

  1. class Greeting
  2. @@default_greeting = "Hello world"
  3. def initialize(@custom_greeting = nil)
  4. end
  5. def print_greeting
  6. greeting = @custom_greeting || @@default_greeting
  7. puts greeting
  8. end
  9. end

Constants are SCREAMING_SNAKE_CASED. For example:

  1. LUCKY_NUMBERS = [3, 7, 11]
  2. DOCUMENTATION_URL = "http://crystal-lang.org/docs"

Acronyms

In class names, acronyms are all-uppercase. For example, HTTP, and LibXML.

In method names, acronyms are all-lowercase. For example #from_json, #to_io.

Libs

Lib names are prefixed with Lib. For example: LibC, LibEvent2.

Directory and File Names

Within a project:

  • / contains a readme, any project configurations (eg, CI or editor configs), and any other project-level documentation (eg, changelog or contributing guide).
  • src/ contains the project’s source code.
  • spec/ contains the project’s specs, which can be run with crystal spec.
  • bin/ contains any executables.

File paths match the namespace of their contents. Files are named after the class or namespace they define, with snake_case.

For example, HTTP::WebSocket is defined in src/http/web_socket.cr.

Indentation

Use two spaces to indent code inside namespaces, methods, blocks or other nested contexts. For example:

  1. module Scorecard
  2. class Parser
  3. def parse(score_text)
  4. begin
  5. score_text.scan(SCORE_PATTERN) do |match|
  6. handle_match(match)
  7. end
  8. rescue err : ParseError
  9. # handle error ...
  10. end
  11. end
  12. end
  13. end

Within a class, separate method definitions, constants and inner class definitions with one newline. For example:

  1. module Money
  2. CURRENCIES = {
  3. "EUR" => 1.0,
  4. "ARS" => 10.55,
  5. "USD" => 1.12,
  6. "JPY" => 134.15,
  7. }
  8. class Amount
  9. getter :currency, :value
  10. def initialize(@currency, @value)
  11. end
  12. end
  13. class CurrencyConversion
  14. def initialize(@amount, @target_currency)
  15. end
  16. def amount
  17. # implement conversion ...
  18. end
  19. end
  20. end