Class: Canopus::DisplayMap::LineBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/canopus/display_map/line_builder.rb

Overview

A builder owns immutable settings and a persistent Rope snapshot. Neither the background thread nor provisional reads mutate the visible Tree.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rope, fold, overlay, tab, wrap, blocks) ⇒ LineBuilder

Returns a new instance of LineBuilder.



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/canopus/display_map/line_builder.rb', line 14

def initialize(rope, fold, overlay, tab, wrap, blocks)
  @rope, @tab, @wrap = rope, tab, wrap
  @overlay = overlay.snapshot
  @fold = Canopus::FoldMap.new
  @fold.instance_variable_set(:@ranges, fold.ranges.dup.freeze)
  @fold.freeze
  @blocks = blocks.blocks.values.group_by(&:row).transform_values do |values|
    values.map { |block| Canopus::BlockMap::Block.new(block.id, block.row, block.text.dup.freeze, block.kind) }.freeze
  end.freeze
  freeze
end

Instance Attribute Details

#blocks ⇒ Object (readonly)

Returns the value of attribute blocks.



13
14
15
# File 'lib/canopus/display_map/line_builder.rb', line 13

def blocks
  @blocks
end

#fold ⇒ Object (readonly)

Returns the value of attribute fold.



13
14
15
# File 'lib/canopus/display_map/line_builder.rb', line 13

def fold
  @fold
end

#rope ⇒ Object (readonly)

Returns the value of attribute rope.



13
14
15
# File 'lib/canopus/display_map/line_builder.rb', line 13

def rope
  @rope
end

Instance Method Details

#line(row, provisional: false, from: 0, checkpoint: nil) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/canopus/display_map/line_builder.rb', line 26

def line(row, provisional: false, from: 0, checkpoint: nil)
  input = @fold.transform(@rope, row, max_bytes: provisional ? 16_384 : nil, from: from, checkpoint: checkpoint)
  return EMPTY_LINES unless input
  text, offsets = input
  overlays = @overlay.transform(@rope, row, text, offsets)
  wrapped = provisional ? [[text.freeze, offsets.freeze, overlays]] : @wrap.transform(text, offsets,
    checkpoint: checkpoint, overlays: overlays, tab_map: @tab)
  rows = wrapped.map do |value, positions, placements|
    placements ||= []
    value, positions, placements = @tab.transform(value, positions, checkpoint: checkpoint, overlays: placements) if provisional && !placements.empty?
    value, positions = @tab.transform(value, positions, checkpoint: checkpoint) if provisional && placements.empty?
    Row.new(value.freeze, positions.freeze, :text, placements.empty? ? nil : placements)
  end
  rows = overlay_blocks(row, :above) + rows + overlay_blocks(row, :below)
  (@blocks[row] || []).each do |block|
    block.text.split("\n", -1).each do |value|
      checkpoint&.call
      rows << Row.new(value.freeze, Array.new(value.length + 1, offsets.last).freeze, block.kind, block.id)
    end
  end
  LineSet.new(rows.freeze)
end

#pending_lines(first, count) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/canopus/display_map/line_builder.rb', line 49

def pending_lines(first, count)
  hidden = @fold.ranges.map { |range| (@rope.point_at(range.begin).row + 1)..@rope.point_at(range.end).row }
  pointer = 0
  Array.new(count) do |index|
    row = first + index
    pointer += 1 while hidden[pointer] && hidden[pointer].end < row
    if hidden[pointer]&.cover?(row)
      EMPTY_LINES
    else
      count = 1 + %i[above below].sum { |position| @overlay.blocks(row, position).sum(&:row_span) } +
        (@blocks[row] || []).sum { |block| block.text.count("\n") + 1 }
      count == 1 ? UNWRAPPED_LINE : PendingLineSet.new(count)
    end
  end
end