fatty 0.99.8 → 0.99.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +316 -211
- data/README.org +94 -0
- data/exe/fatty +58 -9
- data/exe/themer +273 -0
- data/lib/fatty/ansi/renderer.rb +17 -7
- data/lib/fatty/api/output.rb +4 -15
- data/lib/fatty/api/suspend.rb +9 -0
- data/lib/fatty/api.rb +1 -0
- data/lib/fatty/callback_environment.rb +1 -0
- data/lib/fatty/config_files/themes/capuchin_monk.yml +4 -8
- data/lib/fatty/config_files/themes/catppuccin_latte.yml +4 -8
- data/lib/fatty/config_files/themes/catppuccin_mocha.yml +4 -8
- data/lib/fatty/config_files/themes/cyberpunk.yml +4 -8
- data/lib/fatty/config_files/themes/dracula.yml +4 -8
- data/lib/fatty/config_files/themes/everforest_dark.yml +4 -8
- data/lib/fatty/config_files/themes/gruvbox_dark.yml +4 -8
- data/lib/fatty/config_files/themes/gruvbox_light.yml +4 -8
- data/lib/fatty/config_files/themes/mono.yml +6 -10
- data/lib/fatty/config_files/themes/monokai.yml +4 -8
- data/lib/fatty/config_files/themes/nordic.yml +16 -8
- data/lib/fatty/config_files/themes/onedark.yml +4 -8
- data/lib/fatty/config_files/themes/solarized_dark.yml +4 -8
- data/lib/fatty/config_files/themes/solarized_light.yml +4 -8
- data/lib/fatty/config_files/themes/terminal.yml +8 -12
- data/lib/fatty/config_files/themes/tokyo_night.yml +4 -8
- data/lib/fatty/config_files/themes/wordperfect.yml +1 -5
- data/lib/fatty/log_formats/json.rb +1 -1
- data/lib/fatty/log_formats/text.rb +1 -2
- data/lib/fatty/output_buffer.rb +40 -5
- data/lib/fatty/renderer/curses.rb +60 -8
- data/lib/fatty/renderer/truecolor.rb +46 -10
- data/lib/fatty/session/output_session.rb +25 -9
- data/lib/fatty/terminal.rb +12 -0
- data/lib/fatty/themes/manager.rb +12 -3
- data/lib/fatty/themes/resolver.rb +1 -1
- data/lib/fatty/version.rb +1 -1
- metadata +4 -1
|
@@ -25,20 +25,16 @@ region:
|
|
|
25
25
|
bg: "#bd93f9"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#282a36"
|
|
28
|
+
fg: "#25b13d"
|
|
30
29
|
|
|
31
30
|
info:
|
|
32
|
-
fg: "#
|
|
33
|
-
bg: "#282a36"
|
|
31
|
+
fg: "#5f9edd"
|
|
34
32
|
|
|
35
33
|
warn:
|
|
36
|
-
fg: "#
|
|
37
|
-
bg: "#f1fa8c"
|
|
34
|
+
fg: "#b99527"
|
|
38
35
|
|
|
39
36
|
error:
|
|
40
|
-
fg: "#
|
|
41
|
-
bg: "#ff5555"
|
|
37
|
+
fg: "#e37d7d"
|
|
42
38
|
|
|
43
39
|
pager_status:
|
|
44
40
|
fg: "#282a36"
|
|
@@ -25,20 +25,16 @@ region:
|
|
|
25
25
|
bg: "#7fbbb3"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#2d353b"
|
|
28
|
+
fg: "#28bd41"
|
|
30
29
|
|
|
31
30
|
info:
|
|
32
|
-
fg: "#
|
|
33
|
-
bg: "#2d353b"
|
|
31
|
+
fg: "#74abe2"
|
|
34
32
|
|
|
35
33
|
warn:
|
|
36
|
-
fg: "#
|
|
37
|
-
bg: "#dbbc7f"
|
|
34
|
+
fg: "#caa22b"
|
|
38
35
|
|
|
39
36
|
error:
|
|
40
|
-
fg: "#
|
|
41
|
-
bg: "#e67e80"
|
|
37
|
+
fg: "#e78d8d"
|
|
42
38
|
|
|
43
39
|
pager_status:
|
|
44
40
|
fg: "#2d353b"
|
|
@@ -25,20 +25,16 @@ region:
|
|
|
25
25
|
bg: "#fabd2f"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#282828"
|
|
28
|
+
fg: "#25b13d"
|
|
30
29
|
|
|
31
30
|
info:
|
|
32
|
-
fg: "#
|
|
33
|
-
bg: "#282828"
|
|
31
|
+
fg: "#5b9cdc"
|
|
34
32
|
|
|
35
33
|
warn:
|
|
36
|
-
fg: "#
|
|
37
|
-
bg: "#fabd2f"
|
|
34
|
+
fg: "#b99527"
|
|
38
35
|
|
|
39
36
|
error:
|
|
40
|
-
fg: "#
|
|
41
|
-
bg: "#cc241d"
|
|
37
|
+
fg: "#e27878"
|
|
42
38
|
|
|
43
39
|
pager_status:
|
|
44
40
|
fg: "#282828"
|
|
@@ -25,20 +25,16 @@ region:
|
|
|
25
25
|
bg: "#af3a03"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#fbf1c7"
|
|
28
|
+
fg: "#197628"
|
|
30
29
|
|
|
31
30
|
info:
|
|
32
|
-
fg: "#
|
|
33
|
-
bg: "#fbf1c7"
|
|
31
|
+
fg: "#2466a8"
|
|
34
32
|
|
|
35
33
|
warn:
|
|
36
|
-
fg: "#
|
|
37
|
-
bg: "#d79921"
|
|
34
|
+
fg: "#7a621a"
|
|
38
35
|
|
|
39
36
|
error:
|
|
40
|
-
fg: "#
|
|
41
|
-
bg: "#cc241d"
|
|
37
|
+
fg: "#c22929"
|
|
42
38
|
|
|
43
39
|
pager_status:
|
|
44
40
|
fg: "#fbf1c7"
|
|
@@ -25,23 +25,19 @@ region:
|
|
|
25
25
|
bg: "#d7d7d7"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#000000"
|
|
28
|
+
fg: "#1f9333"
|
|
30
29
|
attrs: [bold]
|
|
31
30
|
|
|
32
31
|
info:
|
|
33
|
-
fg: "#
|
|
34
|
-
bg: "#000000"
|
|
32
|
+
fg: "#2d80d2"
|
|
35
33
|
|
|
36
34
|
warn:
|
|
37
|
-
fg: "#
|
|
38
|
-
|
|
39
|
-
attrs: [bold]
|
|
35
|
+
fg: "#977a20"
|
|
36
|
+
attrs: [underline]
|
|
40
37
|
|
|
41
38
|
error:
|
|
42
|
-
fg: "#
|
|
43
|
-
|
|
44
|
-
attrs: [bold]
|
|
39
|
+
fg: "#d94a4a"
|
|
40
|
+
attrs: [bold, underline]
|
|
45
41
|
|
|
46
42
|
pager_status:
|
|
47
43
|
fg: "#000000"
|
|
@@ -25,20 +25,16 @@ region:
|
|
|
25
25
|
bg: "#66d9ef"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#272822"
|
|
28
|
+
fg: "#25ad3b"
|
|
30
29
|
|
|
31
30
|
info:
|
|
32
|
-
fg: "#
|
|
33
|
-
bg: "#272822"
|
|
31
|
+
fg: "#5b9cdc"
|
|
34
32
|
|
|
35
33
|
warn:
|
|
36
|
-
fg: "#
|
|
37
|
-
bg: "#e6db74"
|
|
34
|
+
fg: "#b99527"
|
|
38
35
|
|
|
39
36
|
error:
|
|
40
|
-
fg: "#
|
|
41
|
-
bg: "#f92672"
|
|
37
|
+
fg: "#e27878"
|
|
42
38
|
|
|
43
39
|
pager_status:
|
|
44
40
|
fg: "#272822"
|
|
@@ -23,21 +23,29 @@ region:
|
|
|
23
23
|
fg: "#2e3440"
|
|
24
24
|
bg: "#88c0d0"
|
|
25
25
|
|
|
26
|
+
# good:
|
|
27
|
+
# fg: "#22ee00"
|
|
28
|
+
|
|
29
|
+
# info:
|
|
30
|
+
# fg: "#33deff"
|
|
31
|
+
|
|
32
|
+
# warn:
|
|
33
|
+
# fg: "#d78700"
|
|
34
|
+
|
|
35
|
+
# error:
|
|
36
|
+
# fg: "#d700af"
|
|
37
|
+
|
|
26
38
|
good:
|
|
27
|
-
fg: "
|
|
28
|
-
bg: "#2e3440"
|
|
39
|
+
fg: "#28bd41"
|
|
29
40
|
|
|
30
41
|
info:
|
|
31
|
-
fg: "#
|
|
32
|
-
bg: "#2e3440"
|
|
42
|
+
fg: "#74abe2"
|
|
33
43
|
|
|
34
44
|
warn:
|
|
35
|
-
fg: "#
|
|
36
|
-
bg: "#ebcb8b"
|
|
45
|
+
fg: "#caa22b"
|
|
37
46
|
|
|
38
47
|
error:
|
|
39
|
-
fg: "#
|
|
40
|
-
bg: "#bf616a"
|
|
48
|
+
fg: "#e78d8d"
|
|
41
49
|
|
|
42
50
|
pager_status:
|
|
43
51
|
fg: "black"
|
|
@@ -25,20 +25,16 @@ region:
|
|
|
25
25
|
bg: "#61afef"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#282c34"
|
|
28
|
+
fg: "#26b53e"
|
|
30
29
|
|
|
31
30
|
info:
|
|
32
|
-
fg: "#
|
|
33
|
-
bg: "#282c34"
|
|
31
|
+
fg: "#63a1de"
|
|
34
32
|
|
|
35
33
|
warn:
|
|
36
|
-
fg: "#
|
|
37
|
-
bg: "#e5c07b"
|
|
34
|
+
fg: "#bd9828"
|
|
38
35
|
|
|
39
36
|
error:
|
|
40
|
-
fg: "#
|
|
41
|
-
bg: "#e06c75"
|
|
37
|
+
fg: "#e48181"
|
|
42
38
|
|
|
43
39
|
pager_status:
|
|
44
40
|
fg: "#282c34"
|
|
@@ -24,20 +24,16 @@ region:
|
|
|
24
24
|
bg: "#b58900"
|
|
25
25
|
|
|
26
26
|
good:
|
|
27
|
-
fg: "
|
|
28
|
-
bg: "#002b36"
|
|
27
|
+
fg: "#25ad3b"
|
|
29
28
|
|
|
30
29
|
info:
|
|
31
|
-
fg: "#
|
|
32
|
-
bg: "#002b36"
|
|
30
|
+
fg: "#5b9cdc"
|
|
33
31
|
|
|
34
32
|
warn:
|
|
35
|
-
fg: "#
|
|
36
|
-
bg: "#cb4b16"
|
|
33
|
+
fg: "#b59126"
|
|
37
34
|
|
|
38
35
|
error:
|
|
39
|
-
fg: "#
|
|
40
|
-
bg: "red"
|
|
36
|
+
fg: "#e27878"
|
|
41
37
|
|
|
42
38
|
pager_status:
|
|
43
39
|
fg: "black"
|
|
@@ -25,20 +25,16 @@ region:
|
|
|
25
25
|
bg: "#268bd2"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#fdf6e3"
|
|
28
|
+
fg: "#1a7a2a"
|
|
30
29
|
|
|
31
30
|
info:
|
|
32
|
-
fg: "#
|
|
33
|
-
bg: "#fdf6e3"
|
|
31
|
+
fg: "#256bb1"
|
|
34
32
|
|
|
35
33
|
warn:
|
|
36
|
-
fg: "#
|
|
37
|
-
bg: "#b58900"
|
|
34
|
+
fg: "#7e651b"
|
|
38
35
|
|
|
39
36
|
error:
|
|
40
|
-
fg: "#
|
|
41
|
-
bg: "#dc322f"
|
|
37
|
+
fg: "#ca2b2b"
|
|
42
38
|
|
|
43
39
|
pager_status:
|
|
44
40
|
fg: "#fdf6e3"
|
|
@@ -27,24 +27,20 @@ region:
|
|
|
27
27
|
bg: default
|
|
28
28
|
attrs: [reverse]
|
|
29
29
|
|
|
30
|
-
info:
|
|
31
|
-
fg: default
|
|
32
|
-
bg: default
|
|
33
|
-
|
|
34
30
|
good:
|
|
35
|
-
fg:
|
|
36
|
-
bg: default
|
|
31
|
+
fg: green
|
|
37
32
|
attrs: [bold]
|
|
38
33
|
|
|
34
|
+
info:
|
|
35
|
+
fg: blue
|
|
36
|
+
|
|
39
37
|
warn:
|
|
40
|
-
fg:
|
|
41
|
-
|
|
42
|
-
attrs: [reverse]
|
|
38
|
+
fg: yellow
|
|
39
|
+
attrs: [bold]
|
|
43
40
|
|
|
44
41
|
error:
|
|
45
|
-
fg:
|
|
46
|
-
|
|
47
|
-
attrs: [bold, reverse]
|
|
42
|
+
fg: red
|
|
43
|
+
attrs: [bold]
|
|
48
44
|
|
|
49
45
|
pager_status:
|
|
50
46
|
fg: default
|
|
@@ -25,20 +25,16 @@ region:
|
|
|
25
25
|
bg: "#7aa2f7"
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
|
-
fg: "#
|
|
29
|
-
bg: "#1a1b26"
|
|
28
|
+
fg: "#22a037"
|
|
30
29
|
|
|
31
30
|
info:
|
|
32
|
-
fg: "#
|
|
33
|
-
bg: "#1a1b26"
|
|
31
|
+
fg: "#468fd8"
|
|
34
32
|
|
|
35
33
|
warn:
|
|
36
|
-
fg: "#
|
|
37
|
-
bg: "#e0af68"
|
|
34
|
+
fg: "#a88724"
|
|
38
35
|
|
|
39
36
|
error:
|
|
40
|
-
fg: "#
|
|
41
|
-
bg: "#f7768e"
|
|
37
|
+
fg: "#df6868"
|
|
42
38
|
|
|
43
39
|
pager_status:
|
|
44
40
|
fg: "#1a1b26"
|
|
@@ -26,21 +26,17 @@ region:
|
|
|
26
26
|
|
|
27
27
|
good:
|
|
28
28
|
fg: lightgreen
|
|
29
|
-
bg: navy
|
|
30
29
|
attrs: [bold]
|
|
31
30
|
|
|
32
31
|
info:
|
|
33
32
|
fg: white
|
|
34
|
-
bg: navy
|
|
35
33
|
|
|
36
34
|
warn:
|
|
37
35
|
fg: orange
|
|
38
|
-
bg: navy
|
|
39
36
|
attrs: [bold]
|
|
40
37
|
|
|
41
38
|
error:
|
|
42
|
-
fg:
|
|
43
|
-
bg: red
|
|
39
|
+
fg: red
|
|
44
40
|
attrs: [bold]
|
|
45
41
|
|
|
46
42
|
pager_status:
|
data/lib/fatty/output_buffer.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Fatty
|
|
4
4
|
class OutputBuffer
|
|
5
|
+
Fragment = Data.define(:text, :role)
|
|
6
|
+
|
|
5
7
|
DEFAULT_MAX_LINES = 10_000
|
|
6
8
|
|
|
7
9
|
attr_reader :lines
|
|
@@ -9,15 +11,25 @@ module Fatty
|
|
|
9
11
|
|
|
10
12
|
def initialize(max_lines: DEFAULT_MAX_LINES)
|
|
11
13
|
@lines = []
|
|
14
|
+
@fragments = []
|
|
12
15
|
@scroll = 0
|
|
13
16
|
@max_lines = Integer(max_lines)
|
|
14
17
|
@line_open = false
|
|
15
18
|
end
|
|
16
19
|
|
|
20
|
+
def clear
|
|
21
|
+
@lines.clear
|
|
22
|
+
@fragments.clear
|
|
23
|
+
@scroll = 0
|
|
24
|
+
@line_open = false
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
|
|
17
29
|
# Append text to the output buffer. Text may contain complete lines,
|
|
18
30
|
# partial lines, or both. Returns the number of lines trimmed. The
|
|
19
31
|
# Terminal can use this to adjust the Viewport.
|
|
20
|
-
def append(text)
|
|
32
|
+
def append(text, role: nil)
|
|
21
33
|
ntrimmed = 0
|
|
22
34
|
str = text.to_s
|
|
23
35
|
return ntrimmed if str.empty?
|
|
@@ -30,13 +42,17 @@ module Fatty
|
|
|
30
42
|
ntrimmed += append_new_line("")
|
|
31
43
|
end
|
|
32
44
|
elsif !part.empty?
|
|
33
|
-
ntrimmed += append_fragment(part)
|
|
45
|
+
ntrimmed += append_fragment(part, role: role)
|
|
34
46
|
end
|
|
35
47
|
end
|
|
36
48
|
|
|
37
49
|
ntrimmed
|
|
38
50
|
end
|
|
39
51
|
|
|
52
|
+
def fragments_for(index)
|
|
53
|
+
@fragments[index] || []
|
|
54
|
+
end
|
|
55
|
+
|
|
40
56
|
def visible_lines(height)
|
|
41
57
|
start = [@lines.length - height - @scroll, 0].max
|
|
42
58
|
@lines[start, height] || []
|
|
@@ -54,27 +70,46 @@ module Fatty
|
|
|
54
70
|
|
|
55
71
|
# simplecov:disable
|
|
56
72
|
|
|
57
|
-
def append_fragment(fragment)
|
|
73
|
+
def append_fragment(fragment, role:)
|
|
58
74
|
ntrimmed = 0
|
|
59
75
|
if @line_open && @lines.any?
|
|
60
76
|
@lines[-1] = "#{@lines[-1]}#{fragment}".freeze
|
|
77
|
+
append_fragment_metadata(@fragments[-1], fragment, role)
|
|
61
78
|
else
|
|
62
|
-
ntrimmed += append_new_line(fragment)
|
|
79
|
+
ntrimmed += append_new_line(fragment, role: role)
|
|
63
80
|
@line_open = true
|
|
64
81
|
end
|
|
65
82
|
ntrimmed
|
|
66
83
|
end
|
|
67
84
|
|
|
68
|
-
def append_new_line(line)
|
|
85
|
+
def append_new_line(line, role: nil)
|
|
69
86
|
ntrimmed = 0
|
|
70
87
|
|
|
71
88
|
if @lines.length >= @max_lines
|
|
72
89
|
@lines.shift
|
|
90
|
+
@fragments.shift
|
|
73
91
|
ntrimmed = 1
|
|
74
92
|
end
|
|
75
93
|
|
|
76
94
|
@lines << line.to_s.dup.freeze
|
|
95
|
+
@fragments << []
|
|
96
|
+
append_fragment_metadata(@fragments[-1], line, role) unless line.to_s.empty?
|
|
77
97
|
ntrimmed
|
|
78
98
|
end
|
|
99
|
+
|
|
100
|
+
def append_fragment_metadata(fragments, text, role)
|
|
101
|
+
if fragments.any? && fragments[-1].role == role
|
|
102
|
+
previous = fragments[-1]
|
|
103
|
+
fragments[-1] = Fragment.new(
|
|
104
|
+
text: "#{previous.text}#{text}".freeze,
|
|
105
|
+
role: role,
|
|
106
|
+
)
|
|
107
|
+
else
|
|
108
|
+
fragments << Fragment.new(
|
|
109
|
+
text: text.to_s.dup.freeze,
|
|
110
|
+
role: role,
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
79
114
|
end
|
|
80
115
|
end
|
|
@@ -522,11 +522,13 @@ module Fatty
|
|
|
522
522
|
start_y = 0 if start_y < 0
|
|
523
523
|
|
|
524
524
|
(start_y...height).each do |y|
|
|
525
|
+
visible_line = lines[y]
|
|
525
526
|
draw_output_row(
|
|
526
527
|
win,
|
|
527
|
-
line:
|
|
528
|
+
line: visible_line.text,
|
|
529
|
+
fragments: visible_line.fragments,
|
|
528
530
|
y: y,
|
|
529
|
-
abs_line:
|
|
531
|
+
abs_line: visible_line.number - 1,
|
|
530
532
|
highlights: highlights,
|
|
531
533
|
)
|
|
532
534
|
end
|
|
@@ -535,11 +537,13 @@ module Fatty
|
|
|
535
537
|
count = height if count > height
|
|
536
538
|
|
|
537
539
|
(0...count).each do |y|
|
|
540
|
+
visible_line = lines[y]
|
|
538
541
|
draw_output_row(
|
|
539
542
|
win,
|
|
540
|
-
line:
|
|
543
|
+
line: visible_line.text,
|
|
544
|
+
fragments: visible_line.fragments,
|
|
541
545
|
y: y,
|
|
542
|
-
abs_line:
|
|
546
|
+
abs_line: visible_line.number - 1,
|
|
543
547
|
highlights: highlights,
|
|
544
548
|
)
|
|
545
549
|
end
|
|
@@ -618,6 +622,7 @@ module Fatty
|
|
|
618
622
|
draw_output_row(
|
|
619
623
|
win,
|
|
620
624
|
line: visible_line.text,
|
|
625
|
+
fragments: visible_line.fragments,
|
|
621
626
|
y: y,
|
|
622
627
|
abs_line: visible_line.number - 1,
|
|
623
628
|
highlights: highlights,
|
|
@@ -628,7 +633,7 @@ module Fatty
|
|
|
628
633
|
stage_window(win)
|
|
629
634
|
end
|
|
630
635
|
|
|
631
|
-
def draw_output_row(win, line:, y:, abs_line:, highlights:, line_number: nil, line_number_width: nil)
|
|
636
|
+
def draw_output_row(win, line:, fragments: nil, y:, abs_line:, highlights:, line_number: nil, line_number_width: nil)
|
|
632
637
|
base_attr = pair_attr(:output, fallback: ::Curses::A_NORMAL)
|
|
633
638
|
line_number_attr = base_attr | ::Curses::A_DIM
|
|
634
639
|
hi_attr = pair_attr(:match_current, fallback: ::Curses::A_REVERSE)
|
|
@@ -656,9 +661,7 @@ module Fatty
|
|
|
656
661
|
[from.to_i, to.to_i, attr]
|
|
657
662
|
end
|
|
658
663
|
|
|
659
|
-
slices =
|
|
660
|
-
ansi_style_attr(style, fallback: base_attr)
|
|
661
|
-
end
|
|
664
|
+
slices = output_slices(line, fragments: fragments, ranges: curses_ranges, base_attr: base_attr)
|
|
662
665
|
render_slices(win, slices)
|
|
663
666
|
win.clrtoeol
|
|
664
667
|
end
|
|
@@ -729,6 +732,55 @@ module Fatty
|
|
|
729
732
|
slices
|
|
730
733
|
end
|
|
731
734
|
|
|
735
|
+
def output_slices(line, fragments:, ranges:, base_attr:)
|
|
736
|
+
fragments = Array(fragments)
|
|
737
|
+
return build_line_slices(line.to_s, ranges: ranges) { |style|
|
|
738
|
+
ansi_style_attr(style, fallback: base_attr)
|
|
739
|
+
} if fragments.empty?
|
|
740
|
+
|
|
741
|
+
slices = []
|
|
742
|
+
offset = 0
|
|
743
|
+
|
|
744
|
+
fragments.each do |fragment|
|
|
745
|
+
role = fragment.role
|
|
746
|
+
role = :output unless role && palette[role]
|
|
747
|
+
|
|
748
|
+
fragment_attr = pair_attr(role, fallback: base_attr)
|
|
749
|
+
text = fragment.text.to_s
|
|
750
|
+
fragment_end = offset + Fatty::Ansi.plain_text(text).length
|
|
751
|
+
|
|
752
|
+
fragment_ranges =
|
|
753
|
+
Array(ranges).filter_map do |from, to, attr|
|
|
754
|
+
clipped_from = [from, offset].max
|
|
755
|
+
clipped_to = [to, fragment_end].min
|
|
756
|
+
next unless clipped_from < clipped_to
|
|
757
|
+
|
|
758
|
+
[
|
|
759
|
+
clipped_from - offset,
|
|
760
|
+
clipped_to - offset,
|
|
761
|
+
attr,
|
|
762
|
+
]
|
|
763
|
+
end
|
|
764
|
+
|
|
765
|
+
fragment_slices =
|
|
766
|
+
build_line_slices(text, ranges: fragment_ranges) do |style|
|
|
767
|
+
ansi_style_attr(
|
|
768
|
+
style,
|
|
769
|
+
fallback: fragment_attr,
|
|
770
|
+
fallback_role: role,
|
|
771
|
+
)
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
fragment_slices.each do |attr, slice_text|
|
|
775
|
+
emit_slice(slices, attr, slice_text)
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
offset = fragment_end
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
slices
|
|
782
|
+
end
|
|
783
|
+
|
|
732
784
|
def render_slices(win, slices)
|
|
733
785
|
Array(slices).each do |attr, text|
|
|
734
786
|
win.attrset(attr)
|
|
@@ -523,7 +523,13 @@ module Fatty
|
|
|
523
523
|
}
|
|
524
524
|
end
|
|
525
525
|
|
|
526
|
-
segments.concat(
|
|
526
|
+
segments.concat(
|
|
527
|
+
output_segments(
|
|
528
|
+
text,
|
|
529
|
+
fragments: visible_line&.fragments,
|
|
530
|
+
ranges: ranges,
|
|
531
|
+
),
|
|
532
|
+
)
|
|
527
533
|
queue_ansi_segments_line(
|
|
528
534
|
row: rect.row + y,
|
|
529
535
|
col: rect.col,
|
|
@@ -549,18 +555,48 @@ module Fatty
|
|
|
549
555
|
end
|
|
550
556
|
end
|
|
551
557
|
|
|
552
|
-
def output_segments(line, ranges:)
|
|
553
|
-
|
|
558
|
+
def output_segments(line, fragments:, ranges:)
|
|
559
|
+
fragments = Array(fragments)
|
|
554
560
|
base_segments = []
|
|
555
561
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
+
if fragments.empty?
|
|
563
|
+
Fatty.debug(
|
|
564
|
+
"output fragment role=:output spec=#{palette[:output].inspect}",
|
|
565
|
+
tag: :render,
|
|
566
|
+
)
|
|
567
|
+
Fatty::Ansi.segment(line.to_s).each do |text, style|
|
|
568
|
+
base_segments << {
|
|
569
|
+
text: text.to_s,
|
|
570
|
+
role: :output,
|
|
571
|
+
style: style,
|
|
572
|
+
}
|
|
573
|
+
end
|
|
574
|
+
else
|
|
575
|
+
fragments.each do |fragment|
|
|
576
|
+
role = fragment.role
|
|
577
|
+
role = :output unless role && palette[role]
|
|
578
|
+
|
|
579
|
+
Fatty.debug(
|
|
580
|
+
"output fragment role=#{role.inspect} spec=#{palette[role].inspect}",
|
|
581
|
+
tag: :render,
|
|
582
|
+
)
|
|
583
|
+
Fatty::Ansi.segment(fragment.text.to_s).each do |text, style|
|
|
584
|
+
base_segments << {
|
|
585
|
+
text: text.to_s,
|
|
586
|
+
role: role,
|
|
587
|
+
style: style,
|
|
588
|
+
}
|
|
589
|
+
end
|
|
590
|
+
end
|
|
562
591
|
end
|
|
563
|
-
|
|
592
|
+
|
|
593
|
+
plain = base_segments.map { |segment| segment[:text] }.join
|
|
594
|
+
|
|
595
|
+
apply_highlight_ranges_to_segments(
|
|
596
|
+
base_segments,
|
|
597
|
+
plain: plain,
|
|
598
|
+
ranges: ranges,
|
|
599
|
+
)
|
|
564
600
|
end
|
|
565
601
|
|
|
566
602
|
def apply_highlight_ranges_to_segments(segments, plain:, ranges:)
|