term: add functions for detecting Sixel support + example (#21665)

This commit is contained in:
Larpon 2024-06-11 18:59:58 +02:00 committed by GitHub
parent dfdd752106
commit 47e93d1c39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 152 additions and 0 deletions

View file

@ -111,3 +111,107 @@ pub fn clear() bool {
flush_stdout()
return true
}
// supports_sixel returns `true` if the terminal supports Sixel graphics
//
// For more info on the sixel format:
// See https://en.wikipedia.org/wiki/Sixel
// See https://www.digiater.nl/openvms/decus/vax90b1/krypton-nasa/all-about-sixels.text
// For more info on terminal support:
// See https://www.arewesixelyet.com
pub fn supports_sixel() bool {
if os.is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' {
return false
}
if os.getenv('TERM') == 'yaft' {
return true
}
mut old_state := termios.Termios{}
if termios.tcgetattr(0, mut old_state) != 0 {
return false
}
defer {
// restore the old terminal state:
termios.tcsetattr(0, C.TCSANOW, mut old_state)
}
mut state := termios.Termios{}
if termios.tcgetattr(0, mut state) != 0 {
return false
}
state.c_lflag &= termios.invert(u32(C.ICANON) | u32(C.ECHO))
termios.tcsetattr(0, C.TCSANOW, mut state)
// Send a "Query Device Code"
print('\e[c')
flush_stdout()
// Terminal answers with a "Report Device Code" in the format `\e[<code>`
mut buf := []u8{cap: 64} // xterm's output can be long
for {
w := unsafe { C.getchar() }
if w < 0 {
return false
} else if w == `c` {
break
} else {
buf << u8(w)
}
}
sa := buf.bytestr().all_after('?').split(';')
// returns `true` if the digit literal "4" is found in a "slot" in the response, before the ending `c`.
return '4' in sa
}
// graphics_num_colors returns the number of color registers the terminal
// graphic attribute is set to use. This can be useful to know if the terminal
// is configured to support Sixel graphics.
//
// See "CSI ? Pi ; Pa ; Pv S" from https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
pub fn graphics_num_colors() u16 {
if os.is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' {
return 0
}
if os.getenv('TERM') == 'yaft' {
return 256
}
mut old_state := termios.Termios{}
if termios.tcgetattr(0, mut old_state) != 0 {
return 0
}
defer {
// restore the old terminal state:
termios.tcsetattr(0, C.TCSANOW, mut old_state)
}
mut state := termios.Termios{}
if termios.tcgetattr(0, mut state) != 0 {
return 0
}
state.c_lflag &= termios.invert(u32(C.ICANON) | u32(C.ECHO))
termios.tcsetattr(0, C.TCSANOW, mut state)
// Send "CSI ? Pi ; Pa ; Pv S"
print('\e[?1;1;0S')
flush_stdout()
mut buf := []u8{cap: 20}
for {
w := unsafe { C.getchar() }
if w < 0 {
return 0
} else if w == `S` {
break
} else if w == `;` {
buf.clear()
} else {
buf << u8(w)
}
}
return buf.bytestr().u16()
}

View file

@ -132,3 +132,26 @@ pub fn clear() bool {
C.SetConsoleCursorPosition(hconsole, csbi.dwCursorPosition)
return true
}
// supports_sixel returns `true` if the terminal supports Sixel graphics
//
// For more info on the sixel format:
// See https://en.wikipedia.org/wiki/Sixel
// See https://www.digiater.nl/openvms/decus/vax90b1/krypton-nasa/all-about-sixels.text
// For more info on terminal support:
// See https://www.arewesixelyet.com
pub fn supports_sixel() bool {
// According to (2024) https://www.arewesixelyet.com/#windows-console there's no support
return false
}
// graphics_num_colors returns the number of color registers the terminal
// graphic attribute is set to use. This can be useful to know if the terminal
// is configured to support Sixel graphics.
//
// See "CSI ? Pi ; Pa ; Pv S" from https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
pub fn graphics_num_colors() u16 {
// Since this call is related to sixel terminal graphics and Windows Console and Terminal
// does not have support for querying the graphics setup this call returns 0
return 0
}