Skip to content

Commit 3fd943b

Browse files
committed
Update
1 parent 2bff8da commit 3fd943b

1 file changed

Lines changed: 61 additions & 2 deletions

File tree

app/src/main/java/com/omarea/krscript/executor/SimpleShellWatcher.java

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,69 @@ private void readStream(InputStream inputStream, final ShellHandlerBase shellHan
2626
InputStreamReader isr = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
2727
StringBuilder buffer = new StringBuilder();
2828
int ch;
29+
// Trạng thái nhận diện escape sequence đang đọc dở, để có thể flush ngay khi 1 escape
30+
// sequence (vd ESC[2J của lệnh `clear`) vừa đọc xong, thay vì phải đợi tới '\n'/'\r'
31+
// tiếp theo mới gửi đi. Rất nhiều escape sequence (clear màn hình, di chuyển con trỏ...)
32+
// KHÔNG kèm theo newline, nên nếu chỉ flush theo '\n'/'\r' như trước đây, dữ liệu clear
33+
// sẽ bị kẹt lại trong buffer của thread đọc này và không bao giờ tới được UI cho tới khi
34+
// có dòng output tiếp theo (hoặc tiến trình kết thúc) -> lệnh `clear` trông như "không xoá"
35+
// hoặc xoá bị trễ/xoá nhầm nội dung không liên quan.
36+
// 0 = bình thường, 1 = vừa gặp ESC (chờ ký tự kế tiếp để biết loại), 2 = trong chuỗi CSI
37+
// (ESC[...), chờ finalByte, 3 = trong chuỗi OSC (ESC]...), chờ BEL hoặc ESC\, 4 = trong
38+
// OSC vừa gặp ESC, chờ '\' để xác nhận kết thúc (ST).
39+
int escState = 0;
2940
while ((ch = isr.read()) != -1) {
3041
char c = (char) ch;
3142
buffer.append(c);
32-
if (c == '\n' || c == '\r') {
43+
boolean flush = false;
44+
45+
switch (escState) {
46+
case 0:
47+
if (c == '\u001B') {
48+
escState = 1;
49+
} else if (c == '\n' || c == '\r') {
50+
flush = true;
51+
}
52+
break;
53+
case 1:
54+
if (c == '[') {
55+
escState = 2; // CSI
56+
} else if (c == ']') {
57+
escState = 3; // OSC
58+
} else {
59+
// Escape đơn (vd ESC( ESC) ESC= ESC>...) coi như đã hoàn chỉnh ngay sau
60+
// ký tự này -> flush luôn để không bị kẹt buffer.
61+
escState = 0;
62+
flush = true;
63+
}
64+
break;
65+
case 2:
66+
// CSI kết thúc bằng 1 finalByte trong khoảng '@'..'~' (ECMA-48), vd 'J' (xoá
67+
// màn hình), 'm' (màu SGR), 'H' (di chuyển con trỏ)...
68+
if (c >= '@' && c <= '~') {
69+
escState = 0;
70+
flush = true;
71+
}
72+
break;
73+
case 3:
74+
if (c == '\u0007') {
75+
escState = 0;
76+
flush = true;
77+
} else if (c == '\u001B') {
78+
escState = 4;
79+
}
80+
break;
81+
case 4:
82+
if (c == '\\') {
83+
escState = 0;
84+
flush = true;
85+
} else {
86+
escState = 3;
87+
}
88+
break;
89+
}
90+
91+
if (flush) {
3392
String segment = buffer.toString();
3493
shellHandlerBase.sendMessage(
3594
shellHandlerBase.obtainMessage(what, shellTranslation.resolveRow(segment))
@@ -90,4 +149,4 @@ public void setHandler(Context context, Process process, final ShellHandlerBase
90149
readerError.start();
91150
waitExit.start();
92151
}
93-
}
152+
}

0 commit comments

Comments
 (0)