Skip to content

Commit 1f93543

Browse files
tompngCopilot
andauthored
Improve scan of regexp handling (#1572)
Scanning regexp handling that I implemented in #1559 was not performant. 1. Run `string.scan` for each regexp handling once 2. Collect matched locations 3. Scan collected location from the beginning --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent c5eec14 commit 1f93543

1 file changed

Lines changed: 21 additions & 22 deletions

File tree

lib/rdoc/markup/formatter.rb

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -85,31 +85,30 @@ def convert(content)
8585
# Applies regexp handling to +text+ and returns an array of [text, converted?] pairs.
8686

8787
def apply_regexp_handling(text)
88-
output = []
89-
start = 0
90-
loop do
91-
pos = text.size
92-
matched_name = matched_text = nil
93-
@markup.regexp_handlings.each do |pattern, name|
94-
m = text.match(pattern, start)
95-
next unless m
88+
matched = []
89+
@markup.regexp_handlings.each_with_index do |(pattern, name), priority|
90+
text.scan(pattern) do
91+
m = Regexp.last_match
9692
idx = m[1] ? 1 : 0
97-
if m.begin(idx) < pos
98-
pos = m.begin(idx)
99-
matched_text = m[idx]
100-
matched_name = name
101-
end
102-
end
103-
output << [text[start...pos], false] if pos > start
104-
if matched_name
105-
handled = public_send(:"handle_regexp_#{matched_name}", matched_text)
106-
output << [handled, true]
107-
start = pos + matched_text.size
108-
else
109-
start = pos
93+
matched << [m.begin(idx), m.end(idx), m[idx], name, priority]
11094
end
111-
break if pos == text.size
11295
end
96+
# If the start positions are the same, prefer the earlier-registered one
97+
# (lower numeric priority from each_with_index).
98+
matched.sort_by! {|beg_pos, _, _, _, priority| [beg_pos, priority] }
99+
100+
pos = 0
101+
output = []
102+
matched.each do |beg_pos, end_pos, s, name|
103+
next if beg_pos < pos
104+
105+
output << [text[pos...beg_pos], false] if beg_pos != pos
106+
handled = public_send(:"handle_regexp_#{name}", s)
107+
output << [handled, true]
108+
pos = end_pos
109+
end
110+
111+
output << [text[pos..], false] if pos < text.size
113112
output
114113
end
115114

0 commit comments

Comments
 (0)