Skip to content

Commit 9d300d9

Browse files
author
SqlRush
committed
Preserve device status params
1 parent e7bd186 commit 9d300d9

5 files changed

Lines changed: 25 additions & 3 deletions

File tree

docs/claude-code-go-rewrite-plan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ test/parity/ # golden tests against TS/official behavior
414414
- 本轮补充:terminal CSI parser 现在保留 DECRQM mode-request 的完整参数列表,例如 `CSI ?25;1000$p` 会同时暴露首个 mode code 和原始 params。
415415
- 本轮补充:terminal CSI parser 把 CPR cursor-position responses (`CSI row;col R` / DEC private `CSI ? row;col R`) 归入 report action,结构化暴露 row/column 并保持 visible-text stripping。
416416
- 本轮补充:terminal CSI parser 继续补齐 DEC 私有 DSR/CPR,`CSI ?6n` 现在归入 cursor-position report query,`CSI ?row;col;page R` 会保留 page 元数据。
417+
- 本轮补充:terminal CSI parser 现在保留 DSR/device-status report 的完整参数列表,例如 `CSI ?6;1n` 会同时暴露首个 report code 和原始 params。
417418
- 本轮补充:terminal CSI parser 把 xterm window manipulation/report (`CSI t`) 归入 report action,覆盖常见 `CSI 14t`/`CSI 18t` 查询,并把 `CSI 4;height;width t``CSI 8;rows;cols t` 的 pixel/text-area 尺寸参数结构化暴露。
418419
- 本轮补充:terminal CSI parser 现在保留 xterm window report 的完整参数列表,例如 `CSI 3;x;y t``CSI 4;height;width t``CSI 8;rows;cols t` 不再丢失 report code 后面的原始字段。
419420
- 本轮补充:terminal CSI parser 把 DECRPM mode status report (`CSI Ps;Ps $ y` / `CSI ? Ps;Ps $ y`) 归入 report action,保留 mode code、status 和 DEC private marker。

docs/first-second-parity-audit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ M7 progress now includes:
323323
- `internal/tui`: terminal CSI parsing now accepts multi-parameter mode set/reset sequences such as `CSI ?1000;1006;2004h` and exposes the full mode list while preserving the first mode for existing single-mode callers.
324324
- `internal/tui`: terminal CSI parser now emits structured edit actions for insert/delete chars and insert/delete lines, plus forward/back tab cursor actions; output `CSI M` is parsed as delete-lines while input tokenization still keeps X10 mouse payload handling separate.
325325
- `internal/tui`: terminal CSI parser now emits report actions for DSR `CSI n`, including device-status, cursor-position, and private-mode unknown reports.
326+
- `internal/tui`: terminal CSI parsing now preserves complete DSR/device-status parameter lists such as `CSI ?6;1n` while keeping the existing first-code and private-marker fields.
326327
- `internal/tui`: terminal CSI parser now emits report actions for CPR cursor-position responses such as `CSI row;col R` and DEC private `CSI ? row;col R`, preserving row/column metadata while keeping visible text clean.
327328
- `internal/tui`: terminal CSI parser now treats DEC private `CSI ?6n` as a cursor-position report query and preserves the optional page field from `CSI ?row;col;page R` CPR responses.
328329
- `internal/tui`: terminal sequence dispatcher and parser now classify DCS/APC/PM/SOS string-control sequences as `stringControl` actions with payload, terminator, and incomplete-flush state while keeping visible text extraction free of those invisible payloads.

internal/tui/terminal_csi.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ func ParseCSISequence(sequence string) (CSIAction, bool) {
470470
case CSICommandDeleteLines:
471471
return csiEdit(CSIEditActionDeleteLines, p0), true
472472
case CSICommandDSR:
473-
return csiReport(rawP0, privateMode), true
473+
return csiReport(rawP0, params, privateMode), true
474474
case CSICommandSoftReset:
475475
if intermediate == "!" && privateMode == 0 && len(params) == 0 {
476476
return CSIAction{Type: CSIActionReset}, true
@@ -578,7 +578,7 @@ func csiEdit(actionType CSIEditActionType, count int) CSIAction {
578578
}
579579
}
580580

581-
func csiReport(code int, privateMode byte) CSIAction {
581+
func csiReport(code int, params []int, privateMode byte) CSIAction {
582582
actionType := CSIReportActionUnknown
583583
switch code {
584584
case 5:
@@ -590,9 +590,13 @@ func csiReport(code int, privateMode byte) CSIAction {
590590
actionType = CSIReportActionCursorPosition
591591
}
592592
}
593+
report := CSIReportAction{Type: actionType, Code: code, PrivateMode: privateMode}
594+
if len(params) > 1 {
595+
report.Params = append([]int(nil), params...)
596+
}
593597
return CSIAction{
594598
Type: CSIActionReport,
595-
Report: CSIReportAction{Type: actionType, Code: code, PrivateMode: privateMode},
599+
Report: report,
596600
}
597601
}
598602

internal/tui/terminal_parser_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,21 @@ func TestTerminalParserDispatchesCursorPositionReports(t *testing.T) {
510510
}
511511
}
512512

513+
func TestTerminalParserDispatchesDeviceStatusReports(t *testing.T) {
514+
parser := NewTerminalParser()
515+
input := "a" + CSISequence("?6;1n") + "b"
516+
actions := parser.Feed(input)
517+
if len(actions) != 3 {
518+
t.Fatalf("actions = %#v", actions)
519+
}
520+
if actions[1].Type != TerminalActionReport || actions[1].Report.Type != CSIReportActionCursorPosition || actions[1].Report.Code != 6 || actions[1].Report.PrivateMode != '?' || !reflect.DeepEqual(actions[1].Report.Params, []int{6, 1}) {
521+
t.Fatalf("device status report action = %#v", actions[1])
522+
}
523+
if got := TerminalVisibleText(input); got != "ab" {
524+
t.Fatalf("visible = %q", got)
525+
}
526+
}
527+
513528
func TestTerminalParserUsesOutputTokenizerForCSIM(t *testing.T) {
514529
parser := NewTerminalParser()
515530
actions := parser.Feed("\x1b[M`rK")

internal/tui/tui_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5282,6 +5282,7 @@ func TestParseCSISequenceActions(t *testing.T) {
52825282
{seq: CSISequence(6, "n"), want: CSIReportAction{Type: CSIReportActionCursorPosition, Code: 6}},
52835283
{seq: CSISequence(0, "n"), want: CSIReportAction{Type: CSIReportActionUnknown, Code: 0}},
52845284
{seq: CSISequence("?6n"), want: CSIReportAction{Type: CSIReportActionCursorPosition, Code: 6, PrivateMode: '?'}},
5285+
{seq: CSISequence("?6;1n"), want: CSIReportAction{Type: CSIReportActionCursorPosition, Code: 6, Params: []int{6, 1}, PrivateMode: '?'}},
52855286
{seq: CSISequence("?25n"), want: CSIReportAction{Type: CSIReportActionUnknown, Code: 25, PrivateMode: '?'}},
52865287
{seq: CSISequence(12, 34, "R"), want: CSIReportAction{Type: CSIReportActionCursorPosition, Row: 12, Column: 34}},
52875288
{seq: CSISequence("0;0R"), want: CSIReportAction{Type: CSIReportActionCursorPosition, Row: 1, Column: 1}},

0 commit comments

Comments
 (0)