From a1d66a700d4bf9bf31f33d9c9eb36cdc81111289 Mon Sep 17 00:00:00 2001 From: Orion Date: Tue, 28 Jul 2026 09:01:40 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(core):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E5=90=8C=E6=AD=A5=E5=88=B7=E6=96=B0=E4=B8=8E?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E5=8C=BA=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 引入终端同步更新转义序列以减少屏幕闪烁 * 重构缓冲区机制,区分普通数据与传输数据缓存 * 新增前缀匹配算法函数用于处理跨分段的标记位识别 * 完善同步状态机逻辑,实现对同步更新区域的精确追踪 * 优化输入流读取与分发流程,提升终端输出稳定性 --- homebrew/brew-upgrade-manager.sh | 107 +++++++++++++++++++++++++------ 1 file changed, 88 insertions(+), 19 deletions(-) diff --git a/homebrew/brew-upgrade-manager.sh b/homebrew/brew-upgrade-manager.sh index 2db211f..170119c 100644 --- a/homebrew/brew-upgrade-manager.sh +++ b/homebrew/brew-upgrade-manager.sh @@ -674,13 +674,36 @@ sub colorize_line { } } -my $buffer = ""; -while (sysread(STDIN, my $chunk, 8192)) { - $buffer .= $chunk; +my $sync_begin = "\e[?2026h"; +my $sync_end = "\e[?2026l"; +my $transport_buffer = ""; +my $normal_buffer = ""; +my $inside_sync_update = 0; - while (length $buffer) { - my $newline = index($buffer, "\n"); - my $carriage = index($buffer, "\r"); +sub suffix_prefix_length { + my ($text, $marker) = @_; + my $maximum = length($marker) - 1; + $maximum = length($text) if length($text) < $maximum; + + for (my $length = $maximum; $length > 0; $length--) { + return $length if substr($text, -$length) eq substr($marker, 0, $length); + } + return 0; +} + +sub emit_leading_control_sequences { + while ($normal_buffer =~ s/\A(\e\[[0-?]*[ -\/]*[@-~])//) { + print $1; + } +} + +sub drain_normal_output { + my ($final) = @_; + emit_leading_control_sequences(); + + while (length $normal_buffer) { + my $newline = index($normal_buffer, "\n"); + my $carriage = index($normal_buffer, "\r"); my $position; if ($newline < 0) { $position = $carriage; @@ -689,33 +712,79 @@ while (sysread(STDIN, my $chunk, 8192)) { } else { $position = $newline < $carriage ? $newline : $carriage; } - last if $position < 0; - my $separator = substr($buffer, $position, 1); + if ($position < 0) { + if ($final) { + colorize_line($normal_buffer); + $normal_buffer = ""; + } + return; + } + + my $separator = substr($normal_buffer, $position, 1); # 分块时 CR 可能正好在 CRLF 的边界,等待下一块再决定它是换行还是进度重绘。 - last if $separator eq "\r" && $position + 1 == length($buffer); + return if !$final && $separator eq "\r" && $position + 1 == length($normal_buffer); - my $record = substr($buffer, 0, $position); - if ($separator eq "\r" && substr($buffer, $position + 1, 1) eq "\n") { - substr($buffer, 0, $position + 2, ""); + my $record = substr($normal_buffer, 0, $position); + if ($separator eq "\r" && substr($normal_buffer, $position + 1, 1) eq "\n") { + substr($normal_buffer, 0, $position + 2, ""); colorize_line($record); } elsif ($separator eq "\n") { - substr($buffer, 0, $position + 1, ""); + substr($normal_buffer, 0, $position + 1, ""); colorize_line($record); } else { - substr($buffer, 0, $position + 1, ""); + substr($normal_buffer, 0, $position + 1, ""); print $record, "\r"; } + emit_leading_control_sequences(); } } -if (length $buffer) { - if ($buffer =~ s/\r\z//) { - print $buffer, "\r"; - } else { - colorize_line($buffer); +sub drain_transport_output { + my ($final) = @_; + + while (length $transport_buffer) { + if ($inside_sync_update) { + my $end_position = index($transport_buffer, $sync_end); + if ($end_position >= 0) { + my $length = $end_position + length($sync_end); + print substr($transport_buffer, 0, $length, ""); + $inside_sync_update = 0; + next; + } + + my $keep = $final ? 0 : suffix_prefix_length($transport_buffer, $sync_end); + my $available = length($transport_buffer) - $keep; + print substr($transport_buffer, 0, $available, "") if $available > 0; + return; + } + + my $begin_position = index($transport_buffer, $sync_begin); + if ($begin_position >= 0) { + $normal_buffer .= substr($transport_buffer, 0, $begin_position, ""); + drain_normal_output(0); + print substr($transport_buffer, 0, length($sync_begin), ""); + $inside_sync_update = 1; + next; + } + + my $keep = $final ? 0 : suffix_prefix_length($transport_buffer, $sync_begin); + my $available = length($transport_buffer) - $keep; + if ($available > 0) { + $normal_buffer .= substr($transport_buffer, 0, $available, ""); + drain_normal_output(0); + } + return; } } + +while (sysread(STDIN, my $chunk, 8192)) { + $transport_buffer .= $chunk; + drain_transport_output(0); +} + +drain_transport_output(1); +drain_normal_output(1); ' }