@@ -72,6 +72,22 @@ internal enum ParseResult<Output> {
7272 case indeterminate
7373}
7474
75+ /// Device attribute response types based on intermediate characters.
76+ ///
77+ /// Different device attribute queries return different types of information.
78+ /// The intermediate character in the CSI sequence indicates which type of
79+ /// response is being provided.
80+ public enum VTDeviceAttributesResponse : Equatable , Sendable {
81+ /// Primary device attributes (DA1) - basic terminal identification
82+ case primary( [ Int ] )
83+
84+ /// Secondary device attributes (DA2) - version and capability info
85+ case secondary( [ Int ] )
86+
87+ /// Tertiary device attributes (DA3) - unit identification
88+ case tertiary( [ Int ] )
89+ }
90+
7591/// Represents different types of parsed terminal input sequences.
7692///
7793/// Terminal input consists of various sequence types, from simple characters
@@ -86,6 +102,7 @@ internal enum ParseResult<Output> {
86102internal enum ParsedSequence {
87103 case character( Character )
88104 case cursor( direction: Direction , count: Int )
105+ case DeviceAttributes( VTDeviceAttributesResponse )
89106 case function( number: Int , modifiers: KeyModifiers )
90107 case unknown( sequence: [ UInt8 ] )
91108}
@@ -307,6 +324,21 @@ extension VTInputParser {
307324 input = input. dropFirst ( )
308325 return parse ( next: & input)
309326
327+ case 0x3d : // '=' (DEC Private Mode)
328+ state = . CSI( parameters: parameters, intermediate: intermediate + [ byte] )
329+ input = input. dropFirst ( )
330+ return parse ( next: & input)
331+
332+ case 0x3e : // '>' (DEC Private Mode)
333+ state = . CSI( parameters: parameters, intermediate: intermediate + [ byte] )
334+ input = input. dropFirst ( )
335+ return parse ( next: & input)
336+
337+ case 0x3f : // '?' (DEC Private Mode)
338+ state = . CSI( parameters: parameters, intermediate: intermediate + [ byte] )
339+ input = input. dropFirst ( )
340+ return parse ( next: & input)
341+
310342 case 0x40 ... 0x7e : // command
311343 state = . normal
312344 input = input. dropFirst ( )
@@ -376,7 +408,8 @@ extension VTInputParser {
376408 }
377409 input = input. dropFirst ( 2 )
378410 state = . normal
379- return . success( . unknown( sequence: [ 0x1b , 0x50 ] + data) , buffer: input)
411+ return . success( . unknown( sequence: [ 0x1b , 0x50 ] + data + [ 0x1b , byte] ) ,
412+ buffer: input)
380413 }
381414
382415 input = input. dropFirst ( )
@@ -416,6 +449,12 @@ extension VTInputParser {
416449 return . cursor( direction: . right, count: count)
417450 case 0x44 : // 'D' (CUB)
418451 return . cursor( direction: . left, count: count)
452+ case 0x63 where intermediate == [ 0x3f ] : // '\033[?...c' (DA1)
453+ return . DeviceAttributes( . primary( parameters) )
454+ case 0x63 where intermediate == [ 0x3e ] : // '\033[>...c' (DA2)
455+ return . DeviceAttributes( . secondary( parameters) )
456+ case 0x63 where intermediate == [ 0x3d ] : // '\033[=...c' (DA3)
457+ return . DeviceAttributes( . tertiary( parameters) )
419458 default :
420459 let sequence : [ UInt8 ] = [ UInt8 ( 0x1b ) , UInt8 ( 0x5b ) ] + parameters. flatMap { String ( $0) . utf8 } + [ UInt8 ( 0x3b ) ] + intermediate + [ command]
421460 return . unknown( sequence: sequence)
@@ -449,37 +488,35 @@ extension ParsedSequence {
449488 /// }
450489 /// ```
451490 ///
452- /// - Returns: A `KeyEvent ` if the sequence represents keyboard input,
453- /// `nil` otherwise.
454- internal var event : KeyEvent ? {
491+ /// - Returns: A `VTEvent ` if the sequence represents keyboard input,
492+ /// or a terminal response, `nil` otherwise.
493+ internal var event : VTEvent ? {
455494 return switch self {
456495 case let . character( character) :
457496 if character == " \u{1b} " {
458- KeyEvent ( character: character, keycode: VTKeyCode . escape, modifiers: [ ] , type: . press)
497+ . key ( . init ( character: character, keycode: VTKeyCode . escape, modifiers: [ ] , type: . press) )
459498 } else {
460- KeyEvent ( character: character, keycode: 0 , modifiers: [ ] , type: . press)
499+ . key ( . init ( character: character, keycode: 0 , modifiers: [ ] , type: . press) )
461500 }
462501
463502 case let . cursor( direction, _) :
464503 switch direction {
465504 case . up:
466- KeyEvent ( character: nil , keycode: VTKeyCode . up, modifiers: [ ] ,
467- type: . press)
505+ . key( . init( character: nil , keycode: VTKeyCode . up, modifiers: [ ] , type: . press) )
468506 case . down:
469- KeyEvent ( character: nil , keycode: VTKeyCode . down, modifiers: [ ] ,
470- type: . press)
507+ . key( . init( character: nil , keycode: VTKeyCode . down, modifiers: [ ] , type: . press) )
471508 case . left:
472- KeyEvent ( character: nil , keycode: VTKeyCode . left, modifiers: [ ] ,
473- type: . press)
509+ . key( . init( character: nil , keycode: VTKeyCode . left, modifiers: [ ] , type: . press) )
474510 case . right:
475- KeyEvent ( character: nil , keycode: VTKeyCode . right, modifiers: [ ] ,
476- type: . press)
511+ . key( . init( character: nil , keycode: VTKeyCode . right, modifiers: [ ] , type: . press) )
477512 }
478513
514+ case let . DeviceAttributes( attributes) :
515+ . response( attributes)
516+
479517 case let . function( number, modifiers) :
480- KeyEvent ( character: nil ,
481- keycode: UInt16 ( Int ( VTKeyCode . F1) + number - 1 ) ,
482- modifiers: modifiers, type: . press)
518+ . key( . init( character: nil , keycode: UInt16 ( Int ( VTKeyCode . F1) + number - 1 ) ,
519+ modifiers: modifiers, type: . press) )
483520
484521 case . unknown( _) :
485522 nil
0 commit comments