Class: Canopus::TabMap

Inherits:
Object
  • Object
show all
Defined in:
lib/canopus/tab_map.rb,
sig/display_stages.rbs

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tab_size: 4) ⇒ TabMap

Returns a new instance of TabMap.

Parameters:

  • tab_size: (Integer) (defaults to: 4)

Raises:

  • (ArgumentError)


6
7
8
9
# File 'lib/canopus/tab_map.rb', line 6

def initialize(tab_size: 4)
  raise ArgumentError, "tab size must be positive" unless tab_size.is_a?(Integer) && tab_size.positive?
  @tab_size = tab_size
end

Instance Attribute Details

#tab_size ⇒ Integer (readonly)

Returns the value of attribute tab_size.

Returns:

  • (Integer)


5
6
7
# File 'lib/canopus/tab_map.rb', line 5

def tab_size
  @tab_size
end

Instance Method Details

#transform(text, offsets, checkpoint: nil, overlays: nil) ⇒ [String, Array[Integer]], [String, Array[Integer], Array[DisplayMap::OverlayMap::Inline]]

Parameters:

  • text (String)
  • offsets (Array[Integer])
  • checkpoint: (^() -> void, nil) (defaults to: nil)
  • overlays: (Array[DisplayMap::OverlayMap::Inline], nil) (defaults to: nil)

Returns:



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/canopus/tab_map.rb', line 10

def transform(text, offsets, checkpoint: nil, overlays: nil)
  output, positions, column, i, input_byte = +"", [offsets.first], 0, 0, 0
  boundaries = {0 => 0} if overlays
  text.each_grapheme_cluster do |char|
    checkpoint&.call if (i & 1023).zero?
    if char == "\t"
      count = @tab_size - column % @tab_size
      output << " " * count
      (count - 1).times { positions << offsets[i] }
      positions << offsets[i + 1]
      column += count
    else
      output << char
      char.length.times { |index| positions << offsets[i + index + 1] }
      column += char.ascii_only? ? char.length : Zaniah::Unicode.width(char)
    end
    i += char.length
    input_byte += char.bytesize
    boundaries[input_byte] = output.bytesize if boundaries
  end
  return [output, positions] unless overlays

  [output, positions, overlays.map { |overlay| overlay.with(offset: boundaries.fetch(overlay.offset)) }.freeze]
end