marvi 0.4.0 → 0.4.1
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/CHANGELOG.md +4 -0
- data/lib/marvi/ast_walker.rb +38 -9
- data/lib/marvi/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 519a600dd8ba2e4c6934cf57f37914337ce252ced2a51d6b05dff2ab2c1dda4b
|
|
4
|
+
data.tar.gz: '02669ac614cde421459555a5068429e1371036dd90eb549f5a90d6f3e3aea90c'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37a67589e93f21f02d2c7cec09130e2a63ce83e88ebe21c61cf643b4810506ff4ece12ca39d8c36a40cbccaca35ecf8984e1c8276f953b0e17bf2b9caf4f98de
|
|
7
|
+
data.tar.gz: 12fa9234e6fb3dd1b13b72b5008a239acea242b049ae4086d6e2a8565435b4727fd5850c5766d79f05bbc48332719f7a2b97609725c8834ca1f6083d4a7acf02
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.4.1] - 2026-05-26
|
|
4
|
+
|
|
5
|
+
- Wrap long text in bulleted/ordered lists, paragraphs, headers, and blockquotes so it no longer overflows the terminal width. List items and headers use a hanging indent for continuation lines. (#1)
|
|
6
|
+
|
|
3
7
|
## [0.4.0] - 2026-05-18
|
|
4
8
|
|
|
5
9
|
- Bind `Ctrl-D` / `Ctrl-U` for vim-style half-page scrolling in the curses pager.
|
data/lib/marvi/ast_walker.rb
CHANGED
|
@@ -29,7 +29,8 @@ module Marvi
|
|
|
29
29
|
render_header(el)
|
|
30
30
|
when :p
|
|
31
31
|
src = el.options[:location]
|
|
32
|
-
|
|
32
|
+
wrapped = wrap_spans(render_inline_children(el), @max_width)
|
|
33
|
+
wrapped.each_with_index.map { |spans, i| RichLine.new(spans, source_line: (i.zero? ? src : nil)) } + [RichLine.blank]
|
|
33
34
|
when :ul
|
|
34
35
|
el.children.flat_map { |child| render_block(child, indent: indent, list_type: :ul) } + [RichLine.blank]
|
|
35
36
|
when :ol
|
|
@@ -62,12 +63,15 @@ module Marvi
|
|
|
62
63
|
content = render_inline_children(el).map do |s|
|
|
63
64
|
Span.new(text: s.text, bold: true, italic: s.italic, color: s.color || color, bg_color: s.bg_color)
|
|
64
65
|
end
|
|
65
|
-
|
|
66
|
+
wrap_with_prefix([prefix], content, @max_width, source_line: src) + [RichLine.blank]
|
|
66
67
|
end
|
|
67
68
|
|
|
68
69
|
def render_li(el, indent:, list_type:, list_index:)
|
|
69
70
|
bullet = (list_type == :ol) ? "#{list_index}." : "•"
|
|
70
71
|
prefix = Span.new(text: "#{" " * indent}#{bullet} ", color: :cyan)
|
|
72
|
+
prefix_width = spans_display_width([prefix])
|
|
73
|
+
hanging = Span.new(text: " " * prefix_width)
|
|
74
|
+
inner_width = [@max_width - prefix_width, MIN_COL_WIDTH].max
|
|
71
75
|
src = el.options[:location]
|
|
72
76
|
lines = []
|
|
73
77
|
|
|
@@ -78,16 +82,25 @@ module Marvi
|
|
|
78
82
|
nested.pop while nested.last&.plain_text&.empty?
|
|
79
83
|
lines += nested
|
|
80
84
|
when :p
|
|
85
|
+
content_spans = render_inline_children(child)
|
|
81
86
|
if lines.empty?
|
|
82
|
-
lines
|
|
87
|
+
lines += wrap_with_prefix([prefix], content_spans, @max_width, source_line: src)
|
|
83
88
|
else
|
|
84
|
-
|
|
89
|
+
child_src = child.options[:location]
|
|
90
|
+
wrapped = wrap_spans(content_spans, inner_width)
|
|
91
|
+
wrapped.each_with_index do |spans, i|
|
|
92
|
+
lines << RichLine.new([hanging] + spans, source_line: (i.zero? ? child_src : nil))
|
|
93
|
+
end
|
|
94
|
+
lines << RichLine.blank
|
|
85
95
|
end
|
|
86
96
|
else
|
|
87
|
-
|
|
88
|
-
|
|
97
|
+
content_spans = render_inline(child)
|
|
98
|
+
if lines.empty?
|
|
99
|
+
lines += wrap_with_prefix([prefix], content_spans, @max_width, source_line: src)
|
|
89
100
|
else
|
|
90
|
-
|
|
101
|
+
wrap_spans(content_spans, inner_width).each do |spans|
|
|
102
|
+
lines << RichLine.new([hanging] + spans)
|
|
103
|
+
end
|
|
91
104
|
end
|
|
92
105
|
end
|
|
93
106
|
end
|
|
@@ -110,9 +123,14 @@ module Marvi
|
|
|
110
123
|
end
|
|
111
124
|
|
|
112
125
|
def render_blockquote(el)
|
|
113
|
-
inner = el.children.flat_map { |child| render_block(child) }
|
|
114
126
|
prefix = Span.new(text: "│ ", color: :cyan)
|
|
115
|
-
|
|
127
|
+
prefix_width = spans_display_width([prefix])
|
|
128
|
+
# Reduce @max_width while rendering inner content so the │ prefix fits within @max_width
|
|
129
|
+
# without forcing a second wrap pass on already-wrapped lines.
|
|
130
|
+
saved_width = @max_width
|
|
131
|
+
@max_width = [saved_width - prefix_width, MIN_COL_WIDTH].max
|
|
132
|
+
inner = el.children.flat_map { |child| render_block(child) }
|
|
133
|
+
@max_width = saved_width
|
|
116
134
|
inner.map { |line| RichLine.new([prefix] + line.spans, source_line: line.source_line) } + [RichLine.blank]
|
|
117
135
|
end
|
|
118
136
|
|
|
@@ -177,6 +195,17 @@ module Marvi
|
|
|
177
195
|
shrunk
|
|
178
196
|
end
|
|
179
197
|
|
|
198
|
+
def wrap_with_prefix(prefix_spans, content_spans, max_width, source_line: nil)
|
|
199
|
+
prefix_width = spans_display_width(prefix_spans)
|
|
200
|
+
inner_width = [max_width - prefix_width, MIN_COL_WIDTH].max
|
|
201
|
+
wrapped = wrap_spans(content_spans, inner_width)
|
|
202
|
+
indent = Span.new(text: " " * prefix_width)
|
|
203
|
+
wrapped.each_with_index.map do |spans, i|
|
|
204
|
+
line_prefix = i.zero? ? prefix_spans : [indent]
|
|
205
|
+
RichLine.new(line_prefix + spans, source_line: (i.zero? ? source_line : nil))
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
180
209
|
def wrap_spans(spans, width)
|
|
181
210
|
lines = [[]]
|
|
182
211
|
current_width = 0
|
data/lib/marvi/version.rb
CHANGED