Skip to content

Commit 7259aa6

Browse files
author
SqlRush
committed
Parse ESC device attributes query
1 parent fa7c847 commit 7259aa6

7 files changed

Lines changed: 27 additions & 0 deletions

File tree

docs/cc-100-roadmap.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ M7 补充:terminal ESC parser 现在也把 ISO-2022 charset shift 控制 (`ESC
342342

343343
M7 补充:terminal ESC parser 现在把 DEC line/screen attribute 序列 (`ESC # 3/4/5/6/8`) 解析成结构化 screen action,并在 terminal parser 中透传 alignment-test/line-size 控制,避免 ANSI snapshot 管线落入 unknown。
344344

345+
M7 补充:terminal ESC parser 现在把 DECID identify-terminal (`ESC Z`) 归入现有 device-attributes report action,和 `CSI c` 查询路径保持一致。
346+
345347
M7 补充:terminal CSI parser 现在把 DEC selective erase `CSI ? Ps J` / `CSI ? Ps K` 标记为 selective display/line erase,和普通 ED/EL 区分开。
346348

347349
M7 补充:terminal CSI parser 现在把 ECMA `CSI Ps N` / `CSI Ps O` 解析成 erase-in-field / erase-in-area action,覆盖 to-end/to-start/all 三种 region。
@@ -902,6 +904,8 @@ M7 补充:prompt history `LogEntry` 读取现在接受 `sessionID`/`session`/`
902904

903905
本轮补充:terminal ESC parser 把 DEC line/screen attribute (`ESC # 3/4/5/6/8`) 归入 screen action,terminal parser 会结构化透传 double-height top/bottom、single/double-width 和 alignment-test 控制,继续减少真实 ANSI 输出里的 unknown fallback。
904906

907+
本轮补充:terminal ESC parser 把 DECID identify-terminal (`ESC Z`) 归入 report action,terminal parser 会像 `CSI c` 一样暴露为 device-attributes report,避免老式终端识别查询落入 unknown。
908+
905909
本轮补充:renderer/snapshot 增加 opt-in DEC 2026 synchronized output 包裹入口,可用官方 BSU/ESU (`CSI ?2026h`/`CSI ?2026l`) 生成整帧 ANSI fixture,同时默认渲染保持不变。
906910

907911
本轮补充:terminal OSC helper 增加 OSC 0 title/icon 序列生成,输入会先 strip ANSI;`StripANSI` 现在会完整跳过 OSC/DCS/APC/PM/SOS payload,避免 title/snapshot 可见文本被终端控制串污染。

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ test/parity/ # golden tests against TS/official behavior
464464
- 本轮补充:terminal ESC parser 现在把 charset selection (`ESC ( B` / `ESC ) 0` / `ESC * B` / `ESC / A` / `ESC % G` 等) 解析成结构化 charset action,并在 terminal parser 可见文本管线中消费,避免常见终端 charset 选择序列残留为 unknown。
465465
- 本轮补充:terminal ESC parser 现在也把 ISO-2022 charset shift 控制 (`ESC N``ESC n``ESC o``ESC |``ESC }``ESC ~`) 解析成结构化 charset-shift action,并在可见文本管线中消费,继续减少真实终端输出里的 unknown 控制序列。
466466
- 本轮补充:terminal ESC parser 现在把 DEC line/screen attribute (`ESC # 3/4/5/6/8`) 解析成结构化 screen action,terminal parser 会透传 double-height top/bottom、single/double-width 和 alignment-test 控制。
467+
- 本轮补充:terminal ESC parser 现在把 DECID identify-terminal (`ESC Z`) 解析成 device-attributes report action,和 `CSI c` 查询路径保持一致。
467468
- 本轮补充:terminal CSI parser 现在把 DEC selective erase `CSI ? Ps J` / `CSI ? Ps K` 标记为 selective display/line erase,和普通 ED/EL 区分开。
468469
- 本轮补充:terminal CSI parser 现在把 ECMA `CSI Ps N` / `CSI Ps O` 解析成 erase-in-field / erase-in-area action,覆盖 to-end/to-start/all 三种 region。
469470
- 本轮补充:terminal CSI parser 把 DEC insert/delete columns (`CSI Ps ' }` / `CSI Ps ' ~`) 归入 edit action,避免列编辑控制序列落入 unknown fallback。

docs/first-second-parity-audit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ M7 progress now includes:
379379
- `internal/tui`: terminal CSI parsing now distinguishes parameterized `CSI Pl;Pr s` left/right horizontal margin regions from bare `CSI s` save-cursor semantics.
380380
- `internal/tui`: terminal CSI parsing now recognizes intermediate-space `CSI Ps SP @` / `CSI Ps SP A` scroll-left/right sequences instead of misclassifying them as insert-characters or cursor-up.
381381
- `internal/tui`: terminal ESC parsing now exposes DEC line/screen attribute controls (`ESC # 3/4/5/6/8`) as structured screen actions instead of falling back to unknown.
382+
- `internal/tui`: terminal ESC parsing now maps DECID identify-terminal (`ESC Z`) to the existing device-attributes report action, matching the `CSI c` query path.
382383
- `internal/tui`: terminal CSI parsing now marks DEC selective erase `CSI ? Ps J` / `CSI ? Ps K` separately from ordinary ED/EL erase actions.
383384
- `internal/tui`: terminal CSI parsing now exposes ECMA `CSI Ps N` / `CSI Ps O` erase-in-field and erase-in-area actions with the same to-end/to-start/all regions used by other erase operations.
384385
- `internal/tui`: terminal CSI parsing now treats explicit zero count/position params as ANSI defaults for cursor movement/position/column, insert/repeat/erase chars, and scroll actions while preserving raw zero selector semantics for mode/report/erase selector sequences.

internal/tui/terminal_esc.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const (
1111
ESCReverseIndex = "\x1bM"
1212
ESCNextLine = "\x1bE"
1313
ESCTabSet = "\x1bH"
14+
ESCDeviceAttributes = "\x1bZ"
1415
ESCScreenAttributes = '#'
1516
ESCFinalStart = 0x30
1617
ESCFinalEnd = 0x7e
@@ -36,6 +37,7 @@ type ESCActionType string
3637
const (
3738
ESCActionCursor ESCActionType = "cursor"
3839
ESCActionMode ESCActionType = "mode"
40+
ESCActionReport ESCActionType = "report"
3941
ESCActionReset ESCActionType = "reset"
4042
ESCActionCharset ESCActionType = "charset"
4143
ESCActionCharsetShift ESCActionType = "charsetShift"
@@ -61,6 +63,7 @@ type ESCAction struct {
6163
Type ESCActionType
6264
Cursor CSICursorAction
6365
Mode CSIModeAction
66+
Report CSIReportAction
6467
Screen ESCScreenAction
6568
CharsetSlot byte
6669
CharsetDesignator byte
@@ -113,6 +116,8 @@ func ParseESCContent(chars string) (ESCAction, bool) {
113116
return ESCAction{Type: ESCActionCursor, Cursor: CSICursorAction{Type: CSICursorActionNextLine, Count: 1}}, true
114117
case 'H':
115118
return ESCAction{Type: ESCActionCursor, Cursor: CSICursorAction{Type: CSICursorActionTabSet}}, true
119+
case 'Z':
120+
return ESCAction{Type: ESCActionReport, Report: CSIReportAction{Type: CSIReportActionDeviceAttrs}, Sequence: ESCPrefix + chars}, true
116121
}
117122
return ESCAction{Type: ESCActionUnknown, Sequence: ESCPrefix + chars}, true
118123
}

internal/tui/terminal_parser.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ func (p *TerminalParser) processSequence(sequence string) (TerminalAction, bool)
362362
return TerminalAction{Type: TerminalActionCursor, Cursor: action.ESC.Cursor}, true
363363
case ESCActionMode:
364364
return TerminalAction{Type: TerminalActionMode, Mode: action.ESC.Mode}, true
365+
case ESCActionReport:
366+
return TerminalAction{Type: TerminalActionReport, Report: action.ESC.Report}, true
365367
case ESCActionReset:
366368
p.Reset()
367369
return TerminalAction{Type: TerminalActionReset}, true

internal/tui/terminal_sequence_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ func TestParseTerminalSequenceDispatchesActions(t *testing.T) {
103103
if !ok || screen.Type != TerminalSequenceESC || screen.ESC.Type != ESCActionScreen || screen.ESC.Screen.Type != ESCScreenActionAlignmentTest {
104104
t.Fatalf("screen esc dispatch = %#v ok=%v", screen, ok)
105105
}
106+
report, ok := ParseTerminalSequence(ESCDeviceAttributes)
107+
if !ok || report.Type != TerminalSequenceESC || report.ESC.Type != ESCActionReport || report.ESC.Report.Type != CSIReportActionDeviceAttrs {
108+
t.Fatalf("device attributes esc dispatch = %#v ok=%v", report, ok)
109+
}
106110
if text, ok := ParseTerminalSequence("plain"); ok || text.Type != "" {
107111
t.Fatalf("plain dispatch = %#v ok=%v", text, ok)
108112
}

internal/tui/tui_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5829,6 +5829,11 @@ func TestParseESCSequenceActions(t *testing.T) {
58295829
t.Fatalf("reset action = %#v", reset)
58305830
}
58315831

5832+
report, ok := ParseESCSequence(ESCDeviceAttributes)
5833+
if !ok || report.Type != ESCActionReport || report.Report.Type != CSIReportActionDeviceAttrs {
5834+
t.Fatalf("device attributes action = %#v", report)
5835+
}
5836+
58325837
keypadCases := []struct {
58335838
seq string
58345839
enabled bool
@@ -5872,6 +5877,11 @@ func TestParseESCSequenceActions(t *testing.T) {
58725877
t.Fatalf("terminal parser screen actions = %#v", actions)
58735878
}
58745879

5880+
actions = parser.Feed(ESCDeviceAttributes)
5881+
if len(actions) != 1 || actions[0].Type != TerminalActionReport || actions[0].Report.Type != CSIReportActionDeviceAttrs {
5882+
t.Fatalf("terminal parser device attributes actions = %#v", actions)
5883+
}
5884+
58755885
unknown, ok := ParseESCContent("]not-osc")
58765886
if !ok || unknown.Type != ESCActionUnknown || unknown.Sequence != "\x1b]not-osc" {
58775887
t.Fatalf("unknown esc action = %#v", unknown)

0 commit comments

Comments
 (0)