42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/rfix/highlighter.rb', line 42
def stream(tokens, &block)
max_with = TTY::Screen.width
lines = token_lines(tokens)
pastel = Pastel.new
prefix_spaces = 2
indentation = lines.map.with_index(1) do |tokens, lineno|
next unless visible_lines.include?(lineno)
text = tokens.map(&:last).join
next if text.empty?
text.chars.take_while do |char|
char.strip.empty?
end.length
end.compact.min || 0
is_h = lines.reduce([0, 1, EMPTY_HASH]) do |(position, lineno, lookup), tokens|
tokens.reduce([position, lineno, lookup.dup]) do |(index, lineno, lookup), (_, value)|
[index + value.length, lineno, lookup].tap do
if highlight.include?(index)
lookup[lineno] = true
end
end
end.then do |index, lineno, lookup|
[index.succ, lineno.succ, lookup]
end
end.last
lines.reduce([0, 1]) do |(position, lineno), tokens|
print_line_number = lambda do
style = is_h[lineno] ? pastel.yellow.detach : pastel.dim.detach
block.call((SPACE * 2) + style.call(lineno.to_s.ljust(4, SPACE)) + SPACE)
end
tokens.reduce(position) do |index, (token, value)|
(index + value.length).tap do
if index == position
value = value.chars.drop(indentation).join
if visible_lines.include?(lineno)
print_line_number.call
end
end
if highlight.include?(index) && visible_lines.include?(lineno)
if index == position
head = value.chars.take_while(&:blank?).join
tail = value.chars.drop_while(&:blank?).join
super([[TEXT, head]], &block)
super([[token, tail]], &block)
else
super([[token, value]], &block)
end
elsif visible_lines.include?(lineno)
super([[token, value]], &block)
end
end
end.tap do |new_position|
if visible_lines.include?(lineno)
if position == new_position
print_line_number.call
end
super([[TEXT, NEWLINE]], &block)
end
end.then do |position|
[position.succ, lineno.succ]
end
end
end
|