@@ -6,12 +6,29 @@ import (
66 "github.com/google/go-cmp/cmp"
77)
88
9- // newTestInputHandler creates an InputHandler with default services for testing.
9+ // allVtExtensions returns a VtExtensions with every extension enabled.
10+ func allVtExtensions () VtExtensions {
11+ t := true
12+ return VtExtensions {
13+ KittyKeyboard : true ,
14+ ColorSchemeQuery : & t ,
15+ Win32InputMode : true ,
16+ KittySgrBoldFaintControl : & t ,
17+ }
18+ }
19+
20+ // newTestInputHandler creates an InputHandler with all VtExtensions enabled.
1021func newTestInputHandler (cols , rows int ) * InputHandler {
22+ return newTestInputHandlerWithVtExt (cols , rows , allVtExtensions ())
23+ }
24+
25+ // newTestInputHandlerWithVtExt creates an InputHandler with the given VtExtensions.
26+ func newTestInputHandlerWithVtExt (cols , rows int , ext VtExtensions ) * InputHandler {
1127 opts := DefaultOptions ()
1228 opts .Cols = cols
1329 opts .Rows = rows
1430 opts .Scrollback = 1000
31+ opts .VtExtensions = ext
1532 optsSvc := NewOptionsService (& opts )
1633 bufSvc := NewBufferService (optsSvc )
1734 charSvc := NewCharsetService ()
@@ -577,6 +594,7 @@ func newTestInputHandlerWithTermName(cols, rows int, termName string) *InputHand
577594 opts .Rows = rows
578595 opts .Scrollback = 1000
579596 opts .TermName = termName
597+ opts .VtExtensions = allVtExtensions ()
580598 optsSvc := NewOptionsService (& opts )
581599 bufSvc := NewBufferService (optsSvc )
582600 charSvc := NewCharsetService ()
@@ -1838,3 +1856,167 @@ func TestWindowOptionsReportTerminalLevel(t *testing.T) {
18381856 })
18391857}
18401858
1859+ // --- VtExtensions gating tests ---
1860+
1861+ func TestVtExtensions_Win32InputModeGating (t * testing.T ) {
1862+ t .Parallel ()
1863+
1864+ t .Run ("DECRPM_reports_not_recognized_when_disabled" , func (t * testing.T ) {
1865+ t .Parallel ()
1866+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {})
1867+ var response string
1868+ h .coreService .OnDataEmitter .Event (func (data string ) {
1869+ response = data
1870+ })
1871+ h .ParseString ("\x1b [?9001$p" )
1872+ expected := "\x1b [?9001;0$y"
1873+ if response != expected {
1874+ t .Errorf ("expected %q, got %q" , expected , response )
1875+ }
1876+ })
1877+
1878+ t .Run ("DECSET_ignored_when_disabled" , func (t * testing.T ) {
1879+ t .Parallel ()
1880+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {})
1881+ h .ParseString ("\x1b [?9001h" )
1882+ if h .coreService .DecPrivateModes .Win32InputMode {
1883+ t .Error ("Win32InputMode should remain false when vtExtensions.Win32InputMode is disabled" )
1884+ }
1885+ })
1886+
1887+ t .Run ("DECRST_ignored_when_disabled" , func (t * testing.T ) {
1888+ t .Parallel ()
1889+ ext := allVtExtensions ()
1890+ h := newTestInputHandlerWithVtExt (80 , 24 , ext )
1891+ h .ParseString ("\x1b [?9001h" )
1892+ if ! h .coreService .DecPrivateModes .Win32InputMode {
1893+ t .Fatal ("precondition: Win32InputMode should be true" )
1894+ }
1895+ h .optionsService .Options .VtExtensions .Win32InputMode = false
1896+ h .ParseString ("\x1b [?9001l" )
1897+ if ! h .coreService .DecPrivateModes .Win32InputMode {
1898+ t .Error ("Win32InputMode should remain true when vtExtensions.Win32InputMode is disabled" )
1899+ }
1900+ })
1901+
1902+ t .Run ("DECRPM_reports_set_when_enabled" , func (t * testing.T ) {
1903+ t .Parallel ()
1904+ h := newTestInputHandlerWithVtExt (80 , 24 , allVtExtensions ())
1905+ var response string
1906+ h .coreService .OnDataEmitter .Event (func (data string ) {
1907+ response = data
1908+ })
1909+ h .ParseString ("\x1b [?9001h" )
1910+ h .ParseString ("\x1b [?9001$p" )
1911+ expected := "\x1b [?9001;1$y"
1912+ if response != expected {
1913+ t .Errorf ("expected %q, got %q" , expected , response )
1914+ }
1915+ })
1916+ }
1917+
1918+ func TestVtExtensions_ColorSchemeQueryGating (t * testing.T ) {
1919+ t .Parallel ()
1920+
1921+ t .Run ("DECRPM_reports_not_recognized_when_disabled" , func (t * testing.T ) {
1922+ t .Parallel ()
1923+ f := false
1924+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {ColorSchemeQuery : & f })
1925+ var response string
1926+ h .coreService .OnDataEmitter .Event (func (data string ) {
1927+ response = data
1928+ })
1929+ h .ParseString ("\x1b [?2031$p" )
1930+ expected := "\x1b [?2031;0$y"
1931+ if response != expected {
1932+ t .Errorf ("expected %q, got %q" , expected , response )
1933+ }
1934+ })
1935+
1936+ t .Run ("DECSET_ignored_when_disabled" , func (t * testing.T ) {
1937+ t .Parallel ()
1938+ f := false
1939+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {ColorSchemeQuery : & f })
1940+ h .ParseString ("\x1b [?2031h" )
1941+ if h .coreService .DecPrivateModes .ColorSchemeUpdates {
1942+ t .Error ("ColorSchemeUpdates should remain false when vtExtensions.ColorSchemeQuery is false" )
1943+ }
1944+ })
1945+
1946+ t .Run ("enabled_by_default_when_nil" , func (t * testing.T ) {
1947+ t .Parallel ()
1948+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {})
1949+ h .ParseString ("\x1b [?2031h" )
1950+ if ! h .coreService .DecPrivateModes .ColorSchemeUpdates {
1951+ t .Error ("ColorSchemeUpdates should be settable when ColorSchemeQuery is nil (default true)" )
1952+ }
1953+ })
1954+ }
1955+
1956+ func TestVtExtensions_KittyKeyboardGating (t * testing.T ) {
1957+ t .Parallel ()
1958+
1959+ t .Run ("set_ignored_when_disabled" , func (t * testing.T ) {
1960+ t .Parallel ()
1961+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {})
1962+ h .ParseString ("\x1b [=3;3u" )
1963+ if h .coreService .KittyKeyboard .Flags != 0 {
1964+ t .Errorf ("expected flags 0, got %d" , h .coreService .KittyKeyboard .Flags )
1965+ }
1966+ })
1967+
1968+ t .Run ("query_no_response_when_disabled" , func (t * testing.T ) {
1969+ t .Parallel ()
1970+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {})
1971+ var response string
1972+ h .coreService .OnDataEmitter .Event (func (data string ) {
1973+ response = data
1974+ })
1975+ h .ParseString ("\x1b [?u" )
1976+ if response != "" {
1977+ t .Errorf ("expected no response, got %q" , response )
1978+ }
1979+ })
1980+
1981+ t .Run ("push_ignored_when_disabled" , func (t * testing.T ) {
1982+ t .Parallel ()
1983+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {})
1984+ h .coreService .KittyKeyboard .Flags = 5
1985+ h .ParseString ("\x1b [>3u" )
1986+ if len (h .coreService .KittyKeyboard .MainStack ) != 0 {
1987+ t .Errorf ("expected empty stack, got %v" , h .coreService .KittyKeyboard .MainStack )
1988+ }
1989+ if h .coreService .KittyKeyboard .Flags != 5 {
1990+ t .Errorf ("expected flags unchanged at 5, got %d" , h .coreService .KittyKeyboard .Flags )
1991+ }
1992+ })
1993+
1994+ t .Run ("pop_ignored_when_disabled" , func (t * testing.T ) {
1995+ t .Parallel ()
1996+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {})
1997+ h .coreService .KittyKeyboard .Flags = 5
1998+ h .coreService .KittyKeyboard .MainStack = []int {3 }
1999+ h .ParseString ("\x1b [<u" )
2000+ if h .coreService .KittyKeyboard .Flags != 5 {
2001+ t .Errorf ("expected flags unchanged at 5, got %d" , h .coreService .KittyKeyboard .Flags )
2002+ }
2003+ if len (h .coreService .KittyKeyboard .MainStack ) != 1 {
2004+ t .Errorf ("expected stack unchanged, got %v" , h .coreService .KittyKeyboard .MainStack )
2005+ }
2006+ })
2007+
2008+ t .Run ("alt_buffer_swap_skipped_when_disabled" , func (t * testing.T ) {
2009+ t .Parallel ()
2010+ h := newTestInputHandlerWithVtExt (80 , 24 , VtExtensions {})
2011+ h .coreService .KittyKeyboard .Flags = 5
2012+ h .coreService .KittyKeyboard .AltFlags = 2
2013+ h .ParseString ("\x1b [?1049h" )
2014+ if h .coreService .KittyKeyboard .Flags != 5 {
2015+ t .Errorf ("expected flags unchanged at 5, got %d" , h .coreService .KittyKeyboard .Flags )
2016+ }
2017+ if h .coreService .KittyKeyboard .MainFlags != 0 {
2018+ t .Errorf ("expected MainFlags unchanged at 0, got %d" , h .coreService .KittyKeyboard .MainFlags )
2019+ }
2020+ })
2021+ }
2022+
0 commit comments