Skip to content

Commit 17ad390

Browse files
committed
Track pending ANSI reset codes to preserve correct carry-over behavior
Previously a boolean flag (`matched_reset`) was used, which failed when multiple reset codes appeared. Replacing it with a counter (`pending_resets`) allows nested ANSI states to unwind correctly during line wrapping.
1 parent 803d27d commit 17ad390

2 files changed

Lines changed: 6 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Fixed
66

77
* Fix IndexError in `Strings::Wrap.wrap` and correct ANSI color insertion on wrap (@onk)
8+
* Track unclosed ANSI sequences to preserve correct color state across wraps (@onk)
89

910
## [v0.2.1] - 2021-03-09
1011

lib/strings/wrap.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,24 +135,25 @@ def insert_ansi(string, ansi_stack = [])
135135
new_stack = []
136136
output = string.dup
137137
length = string.size
138-
matched_reset = false
138+
pending_resets = 0
139139
ansi_reset = Strings::ANSI::RESET
140140

141141
# Reversed so that string index don't count ansi
142142
ansi_stack.reverse_each do |ansi|
143143
if ansi[0] =~ /#{Regexp.quote(ansi_reset)}/
144-
matched_reset = true
144+
pending_resets += 1
145145
output.insert(ansi[1], ansi_reset)
146146
next
147-
elsif !matched_reset # ansi without reset
148-
matched_reset = false
147+
elsif pending_resets.zero? # ansi without reset
149148
new_stack.unshift([ansi[0], 0]) # carry over ANSI to the start of next line preserving order
150149
next if ansi[1] == length
151150
if output.end_with?(NEWLINE)
152151
output.insert(-2, ansi_reset)
153152
else
154153
output.insert(-1, ansi_reset) # add reset at the end
155154
end
155+
else
156+
pending_resets -= 1
156157
end
157158

158159
output.insert(ansi[1], ansi[0])

0 commit comments

Comments
 (0)