Class: Lisp::Format::Directives::Number

Inherits:
Directive show all
Defined in:
lib/carat/lisp-format.rb

Overview

Super-class for number printing directives, namely ~D (Decimal, ~B (Binary), ~O (Octal), and ~X (Hexadecimal). The only difference between these directives is the output radix, which defaults to ten (10), which is decimal.

Direct Known Subclasses

Binary, Decimal, Hexadecimal, Octal

Instance Attribute Summary

Attributes inherited from Directive

#pos

Instance Method Summary collapse

Methods inherited from Directive

#join

Constructor Details

#initialize(params, modifiers, top, pos, radix = 10) ⇒ Number

Create a Number directive, using the given output radix radix.



643
644
645
646
# File 'lib/carat/lisp-format.rb', line 643

def initialize(params, modifiers, top, pos, radix = 10)
  super params, modifiers, top, pos
  @radix = radix
end

Instance Method Details

#execute(state) ⇒ Object

Output the given argument using its integral representation. The argument must respond to the :to_int message, or else it isn’t considered an integer. This is the normal way in which Ruby operates. The full form is

~mincol,padchar,commachar,commainterval:@[DBOX]

with the following interpretations

mincol (0)

minimum number of columns to output,

padchar (?s)

character to pad with,

commachar (,)

character to use for number grouping (see : below),

commainterval (3)

how often to output commachar above,

:

the number is output, with numbers grouped into commainterval sized groups of numbers, using commachar as separator,

@

numbers are always output with sign prepended.

An ArgumentError is raised if the argument does not respond to the #to_int message.



670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
# File 'lib/carat/lisp-format.rb', line 670

def execute(state)
  mincol = param(0, state, 0)
  padchar = param(1, state, ?\s).chr
  commachar = param(2, state, ?,).chr
  interval = param(3, state, 3)
  arg = state.next_arg
  if arg.respond_to? :to_int
    num = arg.to_int
    str = num.to_s(@radix)
    if colon_mod?
      str.gsub!(/(\d)(?=(\d{#{interval}})+(?!\d))/, "\\1#{commachar}")
    end
    str = '+' + str if at_mod? and num >= 0
#             puts(str.rjust(mincol, '-'))
    state.output str.rjust(mincol, padchar)
  else
    arg_error 'argument is not an integer'
  end
end