Changeset View
Changeset View
Standalone View
Standalone View
autotests/folding/highlight.cr.fold
- This file was added.
1 | # This file is a testcase for the highlighting of Crystal code | ||||
---|---|---|---|---|---|
2 | # Is a copy of Markdown parser included in Crystal STDLIB. | ||||
3 | | ||||
4 | <beginfold id='1'>class</beginfold id='1'> Markdown::Parser | ||||
5 | record PrefixHeader, count : Int32 | ||||
6 | record UnorderedList, char : Char | ||||
7 | | ||||
8 | @lines : Array(String) | ||||
9 | | ||||
10 | <beginfold id='1'>def</beginfold id='1'> initialize(text : String, @renderer : Renderer) | ||||
11 | @lines = text.lines | ||||
12 | @line = 0 | ||||
13 | <endfold id='1'>end</endfold id='1'> | ||||
14 | | ||||
15 | <beginfold id='1'>def</beginfold id='1'> parse | ||||
16 | <beginfold id='1'>while</beginfold id='1'> @line < @lines.size | ||||
17 | process_paragraph | ||||
18 | <endfold id='1'>end</endfold id='1'> | ||||
19 | <endfold id='1'>end</endfold id='1'> | ||||
20 | | ||||
21 | <beginfold id='1'>def</beginfold id='1'> process_paragraph | ||||
22 | line = @lines[@line] | ||||
23 | | ||||
24 | <beginfold id='1'>case</beginfold id='1'> item = classify(line) | ||||
25 | when :empty | ||||
26 | @line += 1 | ||||
27 | when :header1 | ||||
28 | render_header 1, line, 2 | ||||
29 | when :header2 | ||||
30 | render_header 2, line, 2 | ||||
31 | when PrefixHeader | ||||
32 | render_prefix_header(item.count, line) | ||||
33 | when :code | ||||
34 | render_code | ||||
35 | when :horizontal_rule | ||||
36 | render_horizontal_rule | ||||
37 | when UnorderedList | ||||
38 | render_unordered_list(item.char) | ||||
39 | when :fenced_code | ||||
40 | render_fenced_code | ||||
41 | when :ordered_list | ||||
42 | render_ordered_list | ||||
43 | when :quote | ||||
44 | render_quote | ||||
45 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
46 | render_paragraph | ||||
47 | <endfold id='1'>end</endfold id='1'> | ||||
48 | <endfold id='1'>end</endfold id='1'> | ||||
49 | | ||||
50 | <beginfold id='1'>def</beginfold id='1'> classify(line) | ||||
51 | <beginfold id='1'>if</beginfold id='1'> empty? line | ||||
52 | return :empty | ||||
53 | <endfold id='1'>end</endfold id='1'> | ||||
54 | | ||||
55 | <beginfold id='1'>if</beginfold id='1'> pounds = count_pounds line | ||||
56 | return PrefixHeader.new(pounds) | ||||
57 | <endfold id='1'>end</endfold id='1'> | ||||
58 | | ||||
59 | <beginfold id='1'>if</beginfold id='1'> line.starts_with? " " | ||||
60 | return :code | ||||
61 | <endfold id='1'>end</endfold id='1'> | ||||
62 | | ||||
63 | <beginfold id='1'>if</beginfold id='1'> horizontal_rule? line | ||||
64 | return :horizontal_rule | ||||
65 | <endfold id='1'>end</endfold id='1'> | ||||
66 | | ||||
67 | <beginfold id='1'>if</beginfold id='1'> starts_with_bullet_list_marker?(line, '*') | ||||
68 | return UnorderedList.new('*') | ||||
69 | <endfold id='1'>end</endfold id='1'> | ||||
70 | | ||||
71 | <beginfold id='1'>if</beginfold id='1'> starts_with_bullet_list_marker?(line, '+') | ||||
72 | return UnorderedList.new('+') | ||||
73 | <endfold id='1'>end</endfold id='1'> | ||||
74 | | ||||
75 | <beginfold id='1'>if</beginfold id='1'> starts_with_bullet_list_marker?(line, '-') | ||||
76 | return UnorderedList.new('-') | ||||
77 | <endfold id='1'>end</endfold id='1'> | ||||
78 | | ||||
79 | <beginfold id='1'>if</beginfold id='1'> starts_with_backticks? line | ||||
80 | return :fenced_code | ||||
81 | <endfold id='1'>end</endfold id='1'> | ||||
82 | | ||||
83 | <beginfold id='1'>if</beginfold id='1'> starts_with_digits_dot? line | ||||
84 | return :ordered_list | ||||
85 | <endfold id='1'>end</endfold id='1'> | ||||
86 | | ||||
87 | <beginfold id='1'>if</beginfold id='1'> line.starts_with? ">" | ||||
88 | return :quote | ||||
89 | <endfold id='1'>end</endfold id='1'> | ||||
90 | | ||||
91 | <beginfold id='1'>if</beginfold id='1'> next_line_is_all?('=') | ||||
92 | return :header1 | ||||
93 | <endfold id='1'>end</endfold id='1'> | ||||
94 | | ||||
95 | <beginfold id='1'>if</beginfold id='1'> next_line_is_all?('-') | ||||
96 | return :header2 | ||||
97 | <endfold id='1'>end</endfold id='1'> | ||||
98 | | ||||
99 | nil | ||||
100 | <endfold id='1'>end</endfold id='1'> | ||||
101 | | ||||
102 | <beginfold id='1'>def</beginfold id='1'> render_prefix_header(level, line) | ||||
103 | bytesize = line.bytesize | ||||
104 | str = line.to_unsafe | ||||
105 | pos = level | ||||
106 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize && str[pos].unsafe_chr.ascii_whitespace? | ||||
107 | pos += 1 | ||||
108 | <endfold id='1'>end</endfold id='1'> | ||||
109 | | ||||
110 | render_header level, line.byte_slice(pos), 1 | ||||
111 | <endfold id='1'>end</endfold id='1'> | ||||
112 | | ||||
113 | <beginfold id='1'>def</beginfold id='1'> render_header(level, line, increment) | ||||
114 | @renderer.begin_header level | ||||
115 | process_line line | ||||
116 | @renderer.end_header level | ||||
117 | @line += increment | ||||
118 | | ||||
119 | append_double_newline_if_has_more | ||||
120 | <endfold id='1'>end</endfold id='1'> | ||||
121 | | ||||
122 | <beginfold id='1'>def</beginfold id='1'> render_paragraph | ||||
123 | @renderer.begin_paragraph | ||||
124 | | ||||
125 | join_next_lines continue_on: nil | ||||
126 | process_line @lines[@line] | ||||
127 | @line += 1 | ||||
128 | | ||||
129 | @renderer.end_paragraph | ||||
130 | | ||||
131 | append_double_newline_if_has_more | ||||
132 | <endfold id='1'>end</endfold id='1'> | ||||
133 | | ||||
134 | <beginfold id='1'>def</beginfold id='1'> render_code | ||||
135 | @renderer.begin_code nil | ||||
136 | | ||||
137 | <beginfold id='1'>while</beginfold id='1'> true | ||||
138 | line = @lines[@line] | ||||
139 | | ||||
140 | break unless has_code_spaces? line | ||||
141 | | ||||
142 | @renderer.text line.byte_slice(Math.min(line.bytesize, 4)) | ||||
143 | @line += 1 | ||||
144 | | ||||
145 | <beginfold id='1'>if</beginfold id='1'> @line == @lines.size | ||||
146 | break | ||||
147 | <endfold id='1'>end</endfold id='1'> | ||||
148 | | ||||
149 | <beginfold id='1'>if</beginfold id='1'> next_lines_empty_of_code? | ||||
150 | break | ||||
151 | <endfold id='1'>end</endfold id='1'> | ||||
152 | | ||||
153 | newline | ||||
154 | <endfold id='1'>end</endfold id='1'> | ||||
155 | | ||||
156 | @renderer.end_code | ||||
157 | | ||||
158 | append_double_newline_if_has_more | ||||
159 | <endfold id='1'>end</endfold id='1'> | ||||
160 | | ||||
161 | <beginfold id='1'>def</beginfold id='1'> render_fenced_code | ||||
162 | line = @lines[@line] | ||||
163 | language = line[3..-1].strip | ||||
164 | | ||||
165 | <beginfold id='1'>if</beginfold id='1'> language.empty? | ||||
166 | @renderer.begin_code nil | ||||
167 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
168 | @renderer.begin_code language | ||||
169 | <endfold id='1'>end</endfold id='1'> | ||||
170 | | ||||
171 | @line += 1 | ||||
172 | | ||||
173 | <beginfold id='1'>if</beginfold id='1'> @line < @lines.size | ||||
174 | <beginfold id='1'>while</beginfold id='1'> true | ||||
175 | line = @lines[@line] | ||||
176 | | ||||
177 | @renderer.text line | ||||
178 | @line += 1 | ||||
179 | | ||||
180 | <beginfold id='1'>if</beginfold id='1'> (@line == @lines.size) | ||||
181 | break | ||||
182 | <endfold id='1'>end</endfold id='1'> | ||||
183 | | ||||
184 | <beginfold id='1'>if</beginfold id='1'> starts_with_backticks? @lines[@line] | ||||
185 | @line += 1 | ||||
186 | break | ||||
187 | <endfold id='1'>end</endfold id='1'> | ||||
188 | | ||||
189 | newline | ||||
190 | <endfold id='1'>end</endfold id='1'> | ||||
191 | <endfold id='1'>end</endfold id='1'> | ||||
192 | | ||||
193 | @renderer.end_code | ||||
194 | | ||||
195 | append_double_newline_if_has_more | ||||
196 | <endfold id='1'>end</endfold id='1'> | ||||
197 | | ||||
198 | <beginfold id='1'>def</beginfold id='1'> render_quote | ||||
199 | @renderer.begin_quote | ||||
200 | | ||||
201 | join_next_lines continue_on: :quote | ||||
202 | line = @lines[@line] | ||||
203 | | ||||
204 | process_line line.byte_slice(line.index('>').not_nil! + 1) | ||||
205 | | ||||
206 | @line += 1 | ||||
207 | | ||||
208 | @renderer.end_quote | ||||
209 | | ||||
210 | append_double_newline_if_has_more | ||||
211 | <endfold id='1'>end</endfold id='1'> | ||||
212 | | ||||
213 | <beginfold id='1'>def</beginfold id='1'> render_unordered_list(prefix = '*') | ||||
214 | @renderer.begin_unordered_list | ||||
215 | | ||||
216 | <beginfold id='1'>while</beginfold id='1'> true | ||||
217 | break unless starts_with_bullet_list_marker?(@lines[@line], prefix) | ||||
218 | | ||||
219 | join_next_lines continue_on: nil, stop_on: UnorderedList.new(prefix) | ||||
220 | line = @lines[@line] | ||||
221 | | ||||
222 | <beginfold id='1'>if</beginfold id='1'> empty? line | ||||
223 | @line += 1 | ||||
224 | | ||||
225 | <beginfold id='1'>if</beginfold id='1'> @line == @lines.size | ||||
226 | break | ||||
227 | <endfold id='1'>end</endfold id='1'> | ||||
228 | | ||||
229 | next | ||||
230 | <endfold id='1'>end</endfold id='1'> | ||||
231 | | ||||
232 | <beginfold id='1'>if</beginfold id='1'> line.starts_with?(" ") && previous_line_is_not_intended_and_starts_with_bullet_list_marker?(prefix) | ||||
233 | @renderer.begin_unordered_list | ||||
234 | <endfold id='1'>end</endfold id='1'> | ||||
235 | | ||||
236 | @renderer.begin_list_item | ||||
237 | process_line line.byte_slice(line.index(prefix).not_nil! + 1) | ||||
238 | @renderer.end_list_item | ||||
239 | | ||||
240 | <beginfold id='1'>if</beginfold id='1'> line.starts_with?(" ") && next_line_is_not_intended? | ||||
241 | @renderer.end_unordered_list | ||||
242 | <endfold id='1'>end</endfold id='1'> | ||||
243 | | ||||
244 | @line += 1 | ||||
245 | | ||||
246 | <beginfold id='1'>if</beginfold id='1'> @line == @lines.size | ||||
247 | break | ||||
248 | <endfold id='1'>end</endfold id='1'> | ||||
249 | <endfold id='1'>end</endfold id='1'> | ||||
250 | | ||||
251 | @renderer.end_unordered_list | ||||
252 | | ||||
253 | append_double_newline_if_has_more | ||||
254 | <endfold id='1'>end</endfold id='1'> | ||||
255 | | ||||
256 | <beginfold id='1'>def</beginfold id='1'> render_ordered_list | ||||
257 | @renderer.begin_ordered_list | ||||
258 | | ||||
259 | <beginfold id='1'>while</beginfold id='1'> true | ||||
260 | break unless starts_with_digits_dot? @lines[@line] | ||||
261 | | ||||
262 | join_next_lines continue_on: nil, stop_on: :ordered_list | ||||
263 | line = @lines[@line] | ||||
264 | | ||||
265 | <beginfold id='1'>if</beginfold id='1'> empty? line | ||||
266 | @line += 1 | ||||
267 | | ||||
268 | <beginfold id='1'>if</beginfold id='1'> @line == @lines.size | ||||
269 | break | ||||
270 | <endfold id='1'>end</endfold id='1'> | ||||
271 | | ||||
272 | next | ||||
273 | <endfold id='1'>end</endfold id='1'> | ||||
274 | | ||||
275 | @renderer.begin_list_item | ||||
276 | process_line line.byte_slice(line.index('.').not_nil! + 1) | ||||
277 | @renderer.end_list_item | ||||
278 | @line += 1 | ||||
279 | | ||||
280 | <beginfold id='1'>if</beginfold id='1'> @line == @lines.size | ||||
281 | break | ||||
282 | <endfold id='1'>end</endfold id='1'> | ||||
283 | <endfold id='1'>end</endfold id='1'> | ||||
284 | | ||||
285 | @renderer.end_ordered_list | ||||
286 | | ||||
287 | append_double_newline_if_has_more | ||||
288 | <endfold id='1'>end</endfold id='1'> | ||||
289 | | ||||
290 | <beginfold id='1'>def</beginfold id='1'> append_double_newline_if_has_more | ||||
291 | <beginfold id='1'>if</beginfold id='1'> @line < @lines.size | ||||
292 | newline | ||||
293 | newline | ||||
294 | <endfold id='1'>end</endfold id='1'> | ||||
295 | <endfold id='1'>end</endfold id='1'> | ||||
296 | | ||||
297 | <beginfold id='1'>def</beginfold id='1'> process_line(line) | ||||
298 | bytesize = line.bytesize | ||||
299 | str = line.to_unsafe | ||||
300 | pos = 0 | ||||
301 | | ||||
302 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize && str[pos].unsafe_chr.ascii_whitespace? | ||||
303 | pos += 1 | ||||
304 | <endfold id='1'>end</endfold id='1'> | ||||
305 | | ||||
306 | cursor = pos | ||||
307 | one_star = false | ||||
308 | two_stars = false | ||||
309 | one_underscore = false | ||||
310 | two_underscores = false | ||||
311 | one_backtick = false | ||||
312 | in_link = false | ||||
313 | last_is_space = true | ||||
314 | | ||||
315 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize | ||||
316 | <beginfold id='1'>case</beginfold id='1'> str[pos].unsafe_chr | ||||
317 | when '*' | ||||
318 | <beginfold id='1'>if</beginfold id='1'> pos + 1 < bytesize && str[pos + 1].unsafe_chr == '*' | ||||
319 | <beginfold id='1'>if</beginfold id='1'> two_stars || has_closing?('*', 2, str, (pos + 2), bytesize) | ||||
320 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
321 | pos += 1 | ||||
322 | cursor = pos + 1 | ||||
323 | <beginfold id='1'>if</beginfold id='1'> two_stars | ||||
324 | @renderer.end_bold | ||||
325 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
326 | @renderer.begin_bold | ||||
327 | <endfold id='1'>end</endfold id='1'> | ||||
328 | two_stars = !two_stars | ||||
329 | <endfold id='1'>end</endfold id='1'> | ||||
330 | <endfold id='1'>elsif</endfold id='1'> one_star || has_closing?('*', 1, str, (pos + 1), bytesize)<beginfold id='1'>elsif</beginfold id='1'> one_star || has_closing?('*', 1, str, (pos + 1), bytesize) | ||||
331 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
332 | cursor = pos + 1 | ||||
333 | <beginfold id='1'>if</beginfold id='1'> one_star | ||||
334 | @renderer.end_italic | ||||
335 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
336 | @renderer.begin_italic | ||||
337 | <endfold id='1'>end</endfold id='1'> | ||||
338 | one_star = !one_star | ||||
339 | <endfold id='1'>end</endfold id='1'> | ||||
340 | when '_' | ||||
341 | <beginfold id='1'>if</beginfold id='1'> pos + 1 < bytesize && str[pos + 1].unsafe_chr == '_' | ||||
342 | <beginfold id='1'>if</beginfold id='1'> two_underscores || (last_is_space && has_closing?('_', 2, str, (pos + 2), bytesize)) | ||||
343 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
344 | pos += 1 | ||||
345 | cursor = pos + 1 | ||||
346 | <beginfold id='1'>if</beginfold id='1'> two_underscores | ||||
347 | @renderer.end_bold | ||||
348 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
349 | @renderer.begin_bold | ||||
350 | <endfold id='1'>end</endfold id='1'> | ||||
351 | two_underscores = !two_underscores | ||||
352 | <endfold id='1'>end</endfold id='1'> | ||||
353 | <endfold id='1'>elsif</endfold id='1'> one_underscore || (last_is_space && has_closing?('_', 1, str, (pos + 1), bytesize))<beginfold id='1'>elsif</beginfold id='1'> one_underscore || (last_is_space && has_closing?('_', 1, str, (pos + 1), bytesize)) | ||||
354 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
355 | cursor = pos + 1 | ||||
356 | <beginfold id='1'>if</beginfold id='1'> one_underscore | ||||
357 | @renderer.end_italic | ||||
358 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
359 | @renderer.begin_italic | ||||
360 | <endfold id='1'>end</endfold id='1'> | ||||
361 | one_underscore = !one_underscore | ||||
362 | <endfold id='1'>end</endfold id='1'> | ||||
363 | when '`' | ||||
364 | <beginfold id='1'>if</beginfold id='1'> one_backtick || has_closing?('`', 1, str, (pos + 1), bytesize) | ||||
365 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
366 | cursor = pos + 1 | ||||
367 | <beginfold id='1'>if</beginfold id='1'> one_backtick | ||||
368 | @renderer.end_inline_code | ||||
369 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
370 | @renderer.begin_inline_code | ||||
371 | <endfold id='1'>end</endfold id='1'> | ||||
372 | one_backtick = !one_backtick | ||||
373 | <endfold id='1'>end</endfold id='1'> | ||||
374 | when '!' | ||||
375 | <beginfold id='1'>if</beginfold id='1'> pos + 1 < bytesize && str[pos + 1] === '[' | ||||
376 | link = check_link str, (pos + 2), bytesize | ||||
377 | <beginfold id='1'>if</beginfold id='1'> link | ||||
378 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
379 | | ||||
380 | bracket_idx = (str + pos + 2).to_slice(bytesize - pos - 2).index(']'.ord).not_nil! | ||||
381 | alt = line.byte_slice(pos + 2, bracket_idx) | ||||
382 | | ||||
383 | @renderer.image link, alt | ||||
384 | | ||||
385 | paren_idx = (str + pos + 2 + bracket_idx + 1).to_slice(bytesize - pos - 2 - bracket_idx - 1).index(')'.ord).not_nil! | ||||
386 | pos += 2 + bracket_idx + 1 + paren_idx | ||||
387 | cursor = pos + 1 | ||||
388 | <endfold id='1'>end</endfold id='1'> | ||||
389 | <endfold id='1'>end</endfold id='1'> | ||||
390 | when '[' | ||||
391 | <beginfold id='1'>unless</beginfold id='1'> in_link | ||||
392 | link = check_link str, (pos + 1), bytesize | ||||
393 | <beginfold id='1'>if</beginfold id='1'> link | ||||
394 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
395 | cursor = pos + 1 | ||||
396 | @renderer.begin_link link | ||||
397 | in_link = true | ||||
398 | <endfold id='1'>end</endfold id='1'> | ||||
399 | <endfold id='1'>end</endfold id='1'> | ||||
400 | when ']' | ||||
401 | <beginfold id='1'>if</beginfold id='1'> in_link | ||||
402 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
403 | @renderer.end_link | ||||
404 | | ||||
405 | paren_idx = (str + pos + 1).to_slice(bytesize - pos - 1).index(')'.ord).not_nil! | ||||
406 | pos += paren_idx + 1 | ||||
407 | cursor = pos + 1 | ||||
408 | in_link = false | ||||
409 | <endfold id='1'>end</endfold id='1'> | ||||
410 | <endfold id='1'>end</endfold id='1'> | ||||
411 | last_is_space = pos < bytesize && str[pos].unsafe_chr.ascii_whitespace? | ||||
412 | pos += 1 | ||||
413 | <endfold id='1'>end</endfold id='1'> | ||||
414 | | ||||
415 | @renderer.text line.byte_slice(cursor, pos - cursor) | ||||
416 | <endfold id='1'>end</endfold id='1'> | ||||
417 | | ||||
418 | <beginfold id='1'>def</beginfold id='1'> empty?(line) | ||||
419 | line_is_all? line, ' ' | ||||
420 | <endfold id='1'>end</endfold id='1'> | ||||
421 | | ||||
422 | <beginfold id='1'>def</beginfold id='1'> has_closing?(char, count, str, pos, bytesize) | ||||
423 | str += pos | ||||
424 | bytesize -= pos | ||||
425 | idx = str.to_slice(bytesize).index char.ord | ||||
426 | return false unless idx | ||||
427 | | ||||
428 | <beginfold id='1'>if</beginfold id='1'> count == 2 | ||||
429 | return false unless idx + 1 < bytesize && str[idx + 1].unsafe_chr == char | ||||
430 | <endfold id='1'>end</endfold id='1'> | ||||
431 | | ||||
432 | !str[idx - 1].unsafe_chr.ascii_whitespace? | ||||
433 | <endfold id='1'>end</endfold id='1'> | ||||
434 | | ||||
435 | <beginfold id='1'>def</beginfold id='1'> check_link(str, pos, bytesize) | ||||
436 | # We need to count nested brackets to do it right | ||||
437 | bracket_count = 1 | ||||
438 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize | ||||
439 | <beginfold id='1'>case</beginfold id='1'> str[pos].unsafe_chr | ||||
440 | when '[' | ||||
441 | bracket_count += 1 | ||||
442 | when ']' | ||||
443 | bracket_count -= 1 | ||||
444 | <beginfold id='1'>if</beginfold id='1'> bracket_count == 0 | ||||
445 | break | ||||
446 | <endfold id='1'>end</endfold id='1'> | ||||
447 | <endfold id='1'>end</endfold id='1'> | ||||
448 | pos += 1 | ||||
449 | <endfold id='1'>end</endfold id='1'> | ||||
450 | | ||||
451 | return nil unless bracket_count == 0 | ||||
452 | bracket_idx = pos | ||||
453 | | ||||
454 | return nil unless str[bracket_idx + 1] === '(' | ||||
455 | | ||||
456 | paren_idx = (str + bracket_idx + 1).to_slice(bytesize - bracket_idx - 1).index ')'.ord | ||||
457 | return nil unless paren_idx | ||||
458 | | ||||
459 | String.new(Slice.new(str + bracket_idx + 2, paren_idx - 1)) | ||||
460 | <endfold id='1'>end</endfold id='1'> | ||||
461 | | ||||
462 | <beginfold id='1'>def</beginfold id='1'> next_line_is_all?(char) | ||||
463 | return false unless @line + 1 < @lines.size | ||||
464 | | ||||
465 | line = @lines[@line + 1] | ||||
466 | return false if line.empty? | ||||
467 | | ||||
468 | line_is_all? line, char | ||||
469 | <endfold id='1'>end</endfold id='1'> | ||||
470 | | ||||
471 | <beginfold id='1'>def</beginfold id='1'> line_is_all?(line, char) | ||||
472 | line.each_byte <beginfold id='1'>do</beginfold id='1'> |byte| | ||||
473 | return false if byte != char.ord | ||||
474 | <endfold id='1'>end</endfold id='1'> | ||||
475 | true | ||||
476 | <endfold id='1'>end</endfold id='1'> | ||||
477 | | ||||
478 | <beginfold id='1'>def</beginfold id='1'> next_line_starts_with_backticks? | ||||
479 | return false unless @line + 1 < @lines.size | ||||
480 | starts_with_backticks? @lines[@line + 1] | ||||
481 | <endfold id='1'>end</endfold id='1'> | ||||
482 | | ||||
483 | <beginfold id='1'>def</beginfold id='1'> count_pounds(line) | ||||
484 | bytesize = line.bytesize | ||||
485 | str = line.to_unsafe | ||||
486 | pos = 0 | ||||
487 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize && pos < 6 && str[pos].unsafe_chr == '#' | ||||
488 | pos += 1 | ||||
489 | <endfold id='1'>end</endfold id='1'> | ||||
490 | pos == 0 ? nil : pos | ||||
491 | <endfold id='1'>end</endfold id='1'> | ||||
492 | | ||||
493 | <beginfold id='1'>def</beginfold id='1'> has_code_spaces?(line) | ||||
494 | bytesize = line.bytesize | ||||
495 | str = line.to_unsafe | ||||
496 | pos = 0 | ||||
497 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize && pos < 4 && str[pos].unsafe_chr.ascii_whitespace? | ||||
498 | pos += 1 | ||||
499 | <endfold id='1'>end</endfold id='1'> | ||||
500 | | ||||
501 | <beginfold id='1'>if</beginfold id='1'> pos < 4 | ||||
502 | pos == bytesize | ||||
503 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
504 | true | ||||
505 | <endfold id='1'>end</endfold id='1'> | ||||
506 | <endfold id='1'>end</endfold id='1'> | ||||
507 | | ||||
508 | <beginfold id='1'>def</beginfold id='1'> starts_with_bullet_list_marker?(line, prefix = nil) | ||||
509 | bytesize = line.bytesize | ||||
510 | str = line.to_unsafe | ||||
511 | pos = 0 | ||||
512 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize && str[pos].unsafe_chr.ascii_whitespace? | ||||
513 | pos += 1 | ||||
514 | <endfold id='1'>end</endfold id='1'> | ||||
515 | | ||||
516 | return false unless pos < bytesize | ||||
517 | return false unless prefix ? str[pos].unsafe_chr == prefix : (str[pos].unsafe_chr == '*' || str[pos].unsafe_chr == '-' || str[pos].unsafe_chr == '+') | ||||
518 | | ||||
519 | pos += 1 | ||||
520 | | ||||
521 | return false unless pos < bytesize | ||||
522 | str[pos].unsafe_chr.ascii_whitespace? | ||||
523 | <endfold id='1'>end</endfold id='1'> | ||||
524 | | ||||
525 | <beginfold id='1'>def</beginfold id='1'> previous_line_is_not_intended_and_starts_with_bullet_list_marker?(prefix) | ||||
526 | previous_line = @lines[@line - 1] | ||||
527 | !previous_line.starts_with?(" ") && starts_with_bullet_list_marker?(previous_line, prefix) | ||||
528 | <endfold id='1'>end</endfold id='1'> | ||||
529 | | ||||
530 | <beginfold id='1'>def</beginfold id='1'> next_line_is_not_intended? | ||||
531 | return true unless @line + 1 < @lines.size | ||||
532 | | ||||
533 | next_line = @lines[@line + 1] | ||||
534 | !next_line.starts_with?(" ") | ||||
535 | <endfold id='1'>end</endfold id='1'> | ||||
536 | | ||||
537 | <beginfold id='1'>def</beginfold id='1'> starts_with_backticks?(line) | ||||
538 | line.starts_with? "```" | ||||
539 | <endfold id='1'>end</endfold id='1'> | ||||
540 | | ||||
541 | <beginfold id='1'>def</beginfold id='1'> starts_with_digits_dot?(line) | ||||
542 | bytesize = line.bytesize | ||||
543 | str = line.to_unsafe | ||||
544 | pos = 0 | ||||
545 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize && str[pos].unsafe_chr.ascii_whitespace? | ||||
546 | pos += 1 | ||||
547 | <endfold id='1'>end</endfold id='1'> | ||||
548 | | ||||
549 | return false unless pos < bytesize | ||||
550 | return false unless str[pos].unsafe_chr.ascii_number? | ||||
551 | | ||||
552 | <beginfold id='1'>while</beginfold id='1'> pos < bytesize && str[pos].unsafe_chr.ascii_number? | ||||
553 | pos += 1 | ||||
554 | <endfold id='1'>end</endfold id='1'> | ||||
555 | | ||||
556 | return false unless pos < bytesize | ||||
557 | str[pos].unsafe_chr == '.' | ||||
558 | <endfold id='1'>end</endfold id='1'> | ||||
559 | | ||||
560 | <beginfold id='1'>def</beginfold id='1'> next_lines_empty_of_code? | ||||
561 | line_number = @line | ||||
562 | | ||||
563 | <beginfold id='1'>while</beginfold id='1'> line_number < @lines.size | ||||
564 | line = @lines[line_number] | ||||
565 | | ||||
566 | <beginfold id='1'>if</beginfold id='1'> empty? line | ||||
567 | # Nothing | ||||
568 | <endfold id='1'>elsif</endfold id='1'> has_code_spaces? line<beginfold id='1'>elsif</beginfold id='1'> has_code_spaces? line | ||||
569 | return false | ||||
570 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
571 | return true | ||||
572 | <endfold id='1'>end</endfold id='1'> | ||||
573 | | ||||
574 | line_number += 1 | ||||
575 | <endfold id='1'>end</endfold id='1'> | ||||
576 | | ||||
577 | return true | ||||
578 | <endfold id='1'>end</endfold id='1'> | ||||
579 | | ||||
580 | <beginfold id='1'>def</beginfold id='1'> horizontal_rule?(line) | ||||
581 | non_space_char = nil | ||||
582 | count = 1 | ||||
583 | | ||||
584 | line.each_char <beginfold id='1'>do</beginfold id='1'> |char| | ||||
585 | next if char.ascii_whitespace? | ||||
586 | | ||||
587 | <beginfold id='1'>if</beginfold id='1'> non_space_char | ||||
588 | <beginfold id='1'>if</beginfold id='1'> char == non_space_char | ||||
589 | count += 1 | ||||
590 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
591 | return false | ||||
592 | <endfold id='1'>end</endfold id='1'> | ||||
593 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
594 | <beginfold id='1'>case</beginfold id='1'> char | ||||
595 | when '*', '-', '_' | ||||
596 | non_space_char = char | ||||
597 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
598 | return false | ||||
599 | <endfold id='1'>end</endfold id='1'> | ||||
600 | <endfold id='1'>end</endfold id='1'> | ||||
601 | <endfold id='1'>end</endfold id='1'> | ||||
602 | | ||||
603 | count >= 3 | ||||
604 | <endfold id='1'>end</endfold id='1'> | ||||
605 | | ||||
606 | <beginfold id='1'>def</beginfold id='1'> render_horizontal_rule | ||||
607 | @renderer.horizontal_rule | ||||
608 | @line += 1 | ||||
609 | <endfold id='1'>end</endfold id='1'> | ||||
610 | | ||||
611 | <beginfold id='1'>def</beginfold id='1'> newline | ||||
612 | @renderer.text "\n" | ||||
613 | <endfold id='1'>end</endfold id='1'> | ||||
614 | | ||||
615 | # Join this line with next lines if they form a paragraph, | ||||
616 | # until next lines don't start another entity like a list, | ||||
617 | # header, etc. | ||||
618 | <beginfold id='1'>def</beginfold id='1'> join_next_lines(continue_on = :none, stop_on = :none) | ||||
619 | start = @line | ||||
620 | line = @line | ||||
621 | line += 1 | ||||
622 | <beginfold id='1'>while</beginfold id='1'> line < @lines.size | ||||
623 | item = classify(@lines[line]) | ||||
624 | | ||||
625 | <beginfold id='1'>case</beginfold id='1'> item | ||||
626 | when continue_on | ||||
627 | # continue | ||||
628 | when stop_on | ||||
629 | line -= 1 | ||||
630 | break | ||||
631 | when nil | ||||
632 | # paragraph: continue | ||||
633 | <endfold id='1'>else</endfold id='1'><beginfold id='1'>else</beginfold id='1'> | ||||
634 | line -= 1 | ||||
635 | break | ||||
636 | <endfold id='1'>end</endfold id='1'> | ||||
637 | | ||||
638 | line += 1 | ||||
639 | <endfold id='1'>end</endfold id='1'> | ||||
640 | line -= 1 if line == @lines.size | ||||
641 | | ||||
642 | <beginfold id='1'>if</beginfold id='1'> line > start | ||||
643 | @lines[line] = (start..line).join("\n") <beginfold id='1'>{</beginfold id='1'> |i| @lines[i] <endfold id='1'>}</endfold id='1'> | ||||
644 | @line = line | ||||
645 | <endfold id='1'>end</endfold id='1'> | ||||
646 | <endfold id='1'>end</endfold id='1'> | ||||
647 | <endfold id='1'>end</endfold id='1'> |