@@ -44,6 +44,11 @@ object AnsiColorParser {
4444 private var isReverse = false
4545 private var isDim = false
4646
47+ // Cờ báo hiệu đã gặp mã CSI xoá toàn bộ màn hình (ESC[2J / ESC[3J) trong lần parse() gần
48+ // nhất, để nơi gọi (DialogLogFragment) biết cần xoá sạch log buffer + UI, mô phỏng đúng
49+ // hành vi lệnh `clear` trong terminal thật (trước đây các mã này bị bỏ qua hoàn toàn).
50+ private var clearScreenRequested = false
51+
4752 private val ANSI_16_COLORS = intArrayOf(
4853 Color .BLACK ,
4954 Color .RED ,
@@ -107,8 +112,15 @@ object AnsiColorParser {
107112 val finalByte = m.group(3 )
108113 if (finalByte == " m" ) {
109114 parseAnsiParameters(params)
115+ } else if (finalByte == " J" ) {
116+ // Erase in Display: 2 = xoá toàn màn hình, 3 = xoá toàn màn hình + scrollback
117+ // (phần mở rộng của xterm, ncurses hiện đại thường phát cả 2 mã này khi
118+ // chạy lệnh `clear`). 0/1 chỉ xoá một phần màn hình nên không coi là "clear".
119+ if (params == " 2" || params == " 3" ) {
120+ clearScreenRequested = true
121+ }
110122 }
111- // Các CSI khác (cursor move, clear line, hide cursor...) -> bỏ qua, không render
123+ // Các CSI khác (cursor move, hide cursor...) -> bỏ qua, không render
112124 i = m.end()
113125 } else {
114126 i++ // escape hỏng/không đầy đủ, bỏ qua 1 ký tự để tránh vòng lặp vô hạn
@@ -425,5 +437,17 @@ object AnsiColorParser {
425437
426438 fun reset () {
427439 resetToDefault()
440+ clearScreenRequested = false
441+ }
442+
443+ /* *
444+ * Kiểm tra xem lần gọi parse() gần nhất có gặp mã xoá toàn màn hình (lệnh `clear`) hay
445+ * không, đồng thời "tiêu thụ" (reset) cờ này để lần gọi sau không bị báo lại. Nơi gọi
446+ * (DialogLogFragment) cần gọi hàm này ngay sau parse() để biết có cần xoá log buffer + UI.
447+ */
448+ fun consumePendingClear (): Boolean {
449+ val result = clearScreenRequested
450+ clearScreenRequested = false
451+ return result
428452 }
429453}
0 commit comments