class AsciiMath::LatexBuilder

Constants

COLOURS
DEFAULT_DISPLAY_SYMBOL_TABLE
SPECIAL_CHARACTERS

Attributes

symbol_table[R]

Public Class Methods

new(symbol_table = nil) click to toggle source
# File lib/asciimath/latex.rb, line 7
def initialize(symbol_table = nil)
  @latex = ''
  @symbol_table = symbol_table.nil? ? DEFAULT_DISPLAY_SYMBOL_TABLE : symbol_table
end

Public Instance Methods

append_expression(expression) click to toggle source
# File lib/asciimath/latex.rb, line 16
def append_expression(expression)
  append(expression)
  self
end
to_s() click to toggle source
# File lib/asciimath/latex.rb, line 12
def to_s
  @latex
end

Private Instance Methods

append(expression, separator = " ") click to toggle source
# File lib/asciimath/latex.rb, line 127
def append(expression, separator = " ")
  case expression
    when Array
      expression.each { |e| append(e, separator) }
    when String
      @latex << expression
    when Symbol
      @latex << expression.to_s
    when AsciiMath::AST::Sequence, AsciiMath::AST::MatrixRow 
      c = expression.length

      expression.each do |e|
        c -= 1
        append(e)
        @latex << separator if c > 0
      end

    when AsciiMath::AST::Symbol
      @latex << resolve_symbol(expression.value)

    when AsciiMath::AST::Identifier
      append_escaped(expression.value)

    when AsciiMath::AST::Text
      text do
        append_escaped(expression.value)
      end

    when AsciiMath::AST::Number
      @latex << expression.value

    when AsciiMath::AST::Paren
      parens(expression.lparen, expression.rparen, expression.expression)

    when AsciiMath::AST::Group
      append(expression.expression)

    when AsciiMath::AST::SubSup
      sub = expression.sub_expression
      sup = expression.sup_expression
      e = expression.base_expression

      curly(e)

      if sub
        @latex << "_"
        curly(sub)
      end       

      if sup
        @latex << "^"
        curly(sup)
      end

    when AsciiMath::AST::UnaryOp
      op = expression.operator.value

      case op
      when :norm
        parens(:lvert, :rvert, expression.operand)
      when :floor
        parens(:lfloor, :rfloor, expression.operand)
      when :ceil
        parens(:lceiling, :rceiling, expression.operand)
      when :overarc
        overset do
          @latex << "\\frown"
        end
        
        curly do
          append(expression.operand)
        end
      else
        macro(op) do
          append(expression.operand)
        end
      end

    when AsciiMath::AST::BinaryOp, AsciiMath::AST::InfixOp
      op = expression.operator.value

      case op
      when :root
        macro("sqrt", expression.operand1) do
          append(expression.operand2)
        end
    
      when :color
        curly do
          color_value = expression.operand1
          red = color_value.red
          green = color_value.green
          blue = color_value.blue

          if COLOURS.has_key? [red, green, blue]
              color do
                @latex << COLOURS[[red, green, blue]]
              end
          else
            color('RGB') do
              @latex << red.to_s << ',' << green.to_s << ',' << blue.to_s
            end
          end

          @latex << " "
          append(expression.operand2)
        end

      else
        @latex << resolve_symbol(op)

        curly do
          append(expression.operand1)
        end

        curly do
          append(expression.operand2)
        end
      end
    
    when AsciiMath::AST::Matrix
      parens(expression.lparen, expression.rparen) do
        c = expression.length
        @latex << "\\begin{matrix} "

        expression.each do |row|
          c -= 1
          append(row, " & ")
          @latex << " \\\\ " if c > 0
        end

        @latex << " \\end{matrix}"
      end
  end
end
append_escaped(text) click to toggle source
# File lib/asciimath/latex.rb, line 331
def append_escaped(text)
  text.each_codepoint do |cp|
    @latex << "\\" if SPECIAL_CHARACTERS.include? cp
    @latex << cp
  end
end
curly(expression = nil) { |self| ... } click to toggle source
# File lib/asciimath/latex.rb, line 308
def curly(expression = nil, &block)
  if block_given?
    @latex << ?{
    yield self
    @latex << ?}
  else
    case expression
    when AsciiMath::AST::Symbol, AsciiMath::AST::Text
      append(expression)
      return
    when AsciiMath::AST::Identifier, AsciiMath::AST::Number
      if expression.value.length <= 1
        append(expression)
        return
      end
    end

    @latex << ?{
    append(expression)
    @latex << ?}
  end
end
is_small(e) click to toggle source
# File lib/asciimath/latex.rb, line 353
def is_small(e)
  case e
    when AsciiMath::AST::SubSup
      is_very_small(e.sub_expression) and is_very_small(e.sup_expression) and is_very_small(e.base_expression)
    when AsciiMath::AST::Sequence
      e.all? { |s| is_small(s) }
    else
      is_very_small(e)
  end
end
is_very_small(e) click to toggle source
# File lib/asciimath/latex.rb, line 364
def is_very_small(e)
  case e
  when AsciiMath::AST::Identifier, AsciiMath::AST::Number
    e.value.length <= 1
  when AsciiMath::AST::Symbol
    case e.value
    when :plus, :minus, :cdot, :dx, :dy, :dz, :dt, :f, :g, :mod
      true
    else
      false
    end
  when AsciiMath::AST::UnaryOp
    case e.operator
    when :hat, :overline, :underline, :vec, :dot, :ddot, :color
      is_very_small(e.operand)
    else
      false
    end
  when AsciiMath::AST::Group
    is_very_small(e.expression)
  when AsciiMath::AST::Sequence
    e.all? { |s| is_very_small(s) }
  when nil
    true
  else
    false
  end
end
macro(macro, *args) { |self| ... } click to toggle source
# File lib/asciimath/latex.rb, line 263
def macro(macro, *args)
  @latex << resolve_symbol(macro)

  if args.length != 0
    @latex << "["
    append(args, "][")
    @latex << "]"
  end

  if block_given?
    curly do
      yield self
    end
  end
end
method_missing(meth, *args, &block) click to toggle source
# File lib/asciimath/latex.rb, line 279
def method_missing(meth, *args, &block)
  macro(meth, *args, &block)
end
parens(lparen, rparen, content = nil) { |self| ... } click to toggle source
# File lib/asciimath/latex.rb, line 283
def parens(lparen, rparen, content = nil, &block)
  l = lparen.is_a?(AsciiMath::AST::Symbol) ? lparen.value : lparen
  r = rparen.is_a?(AsciiMath::AST::Symbol) ? rparen.value : rparen

  if block_given?
    if l || r
      @latex << "\\left " << resolve_symbol(l) << " "
      yield self
      @latex << " \\right " << resolve_symbol(r)
    else
      yield self
    end
  else
    needs_left_right = !is_small(content)

    @latex << "\\left " if needs_left_right
    @latex << resolve_symbol(l) << " " if l or needs_left_right

    append(content)

    @latex << " \\right" if needs_left_right
    @latex << " " << resolve_symbol(r) if r or needs_left_right
  end
end
resolve_symbol(s) click to toggle source
# File lib/asciimath/latex.rb, line 338
def resolve_symbol(s)
  symbol = @symbol_table[s]

  case symbol
  when String
    return symbol
  when Hash
    return symbol[:value]
  when nil
    return "\\#{s.to_s}"
  else
    raise "Invalid entry in symbol table"
  end
end