module Protobuf::Generators::Printable

def comment(message)


Print a one-line comment.
def comment(message)
  puts "# #{message}"
end

def header(message)

#
# Lorem ipsum dolor
##
header("Lorem ipsum dolor")

Print a "header" comment.
def header(message)
  puts
  puts "##"
  puts "# #{message}"
  puts "#"
end

def indent


(after the block is finished).
Increase the indent level. An outdent will only occur if given a block
def indent
  self.current_indent += 1
  yield
  outdent
end

def init_printer(indent_level)


Must be called by any class/module that includes the Printable module.
Initialize the printer.
def init_printer(indent_level)
  @io = ::StringIO.new
  self.current_indent = indent_level.to_i
end

def modulize(name)


modulize("foo.bar.BAZ") -> "::Foo::Bar::BAZ"
modulize("foo.bar.baz") -> "::Foo::Bar::Baz"
modulize("foo.bar.Baz") -> "::Foo::Bar::Baz"

token's definition.
as a constant. Otherwise we do not attempt to change the
to capitalize the first character to ensure ruby will treat the value
(e.g. CamelCase, Underscore_Case, SCREAMING_SNAKE_CASE), we only want
Due to the nature of varying standards about how class/modules are named
Take a string and upcase the first character of each namespace.
def modulize(name)
  name = name.gsub(/\./, '::')
  name = name.gsub(/(^(?:::)?[a-z]|::[a-z])/, &:upcase)
  name
end

def outdent


Decrease the indent level. Cannot be negative.
def outdent
  self.current_indent -= 1 unless current_indent.zero?
end

def parent_class(type)


will be thrown.
Valid types are :message, :enum, and :service, otherwise an error
Return the parent class for a given type.
def parent_class(type)
  case type
  when :message then
    PARENT_CLASS_MESSAGE
  when :enum then
    PARENT_CLASS_ENUM
  when :service then
    PARENT_CLASS_SERVICE
  else
    fail "Unknown parent class type #{type}: #{caller[0..5].join("\n")}"
  end
end

def print(contents)


Print the given message raw, no indent.
def print(contents)
  @io.print(contents)
end

def print_block(name, parent_klass, type)


Otherwise, end the block on the same line.
If a block is given, call the block from within an indent block.
If a class, can be given a parent class to inherit from.
Print a class or module block, indicated by type.
def print_block(name, parent_klass, type)
  name = modulize(name)
  block_def = "#{type} #{name}"
  block_def += " < #{parent_class(parent_klass)}" if parent_klass
  if block_given?
    puts block_def
    indent { yield }
    puts "end"
    puts
  else
    block_def += "; end"
    puts block_def
  end
end

def print_class(name, parent_klass, &block)


to inherit from. Accepts a block for use with print_block.
Use print_block to print a class, with optional parent class
def print_class(name, parent_klass, &block)
  print_block(name, parent_klass, :class, &block)
end

def print_contents


Returns the contents of the underlying StringIO object.
def print_contents
  @io.rewind
  @io.read
end

def print_module(name, &block)


Accepts a block for use with print_block.
Use print_block to print a module.
def print_module(name, &block)
  print_block(name, nil, :module, &block)
end

def print_require(file, relative = false)


print_require('foo/bar/baz') -> "require 'foo/bar/baz'"

Print a file require.
def print_require(file, relative = false)
  puts "require#{'_relative' if relative} '#{file}'"
end

def puts(message = nil)


If no message is given print a newline.
Puts the given message prefixed by the indent level.
def puts(message = nil)
  if message
    @io.puts(("  " * current_indent) + message)
  else
    @io.puts
  end
end