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:
class ParseError < Exception
end
module HTTP
  class RequestHandler
  end
end
alias NumericValue = Float32 | Float64 | Int32 | Int64
lib LibYAML
end
struct TagDirective
end
enum Time::DayOfWeek
end
Method names are snake_cased. For example:
class Person
  def first_name
  end
  def date_of_birth
  end
  def homepage_url
  end
end
Variable names are snake_cased. For example:
class Greeting
  @@default_greeting = "Hello world"
  def initialize(@custom_greeting = nil)
  end
  def print_greeting
    greeting = @custom_greeting || @@default_greeting
    puts greeting
  end
end
Constants are SCREAMING_SNAKE_CASED. For example:
LUCKY_NUMBERS     = [3, 7, 11]
DOCUMENTATION_URL = "http://crystal-lang.org/docs"
Exception messages are Sentence cased, although code or acronyms may start a message in lowercase. For example:
raise ArgumentError.new("Cannot create a string with a null pointer")
raise RuntimeError.new("getpeername failed")
{% raise "Expected size to be an integer literal" %}
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:
module Scorecard
  class Parser
    def parse(score_text)
      begin
        score_text.scan(SCORE_PATTERN) do |match|
          handle_match(match)
        end
      rescue err : ParseError
        # handle error ...
      end
    end
  end
end
Within a class, separate method definitions, constants and inner class definitions with one newline. For example:
module Money
  CURRENCIES = {
    "EUR" => 1.0,
    "ARS" => 10.55,
    "USD" => 1.12,
    "JPY" => 134.15,
  }
  class Amount
    getter :currency, :value
    def initialize(@currency, @value)
    end
  end
  class CurrencyConversion
    def initialize(@amount, @target_currency)
    end
    def amount
      # implement conversion ...
    end
  end
end