dcs: xtgettcap: always reply with tigetstr(3) formatted "strings"

That is, instead of sometimes replying with a "source" encoded
string (where e.g. '\E' are returned just like that, and not as an
actual ESC), always unescape all string values.

This also includes \n \r \t \b \f \s, \^ \\ \ \:, as well as ^x-styled
escapes.

Closes #1701
This commit is contained in:
Daniel Eklöf 2024-04-27 09:38:55 +02:00
parent 4d4ef5eed5
commit a3debf7741
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 60 additions and 21 deletions

View file

@ -50,27 +50,33 @@ class IntCapability(Capability):
class StringCapability(Capability):
def __init__(self, name: str, value: str):
# Expand \E to literal ESC in non-parameterized capabilities
if '%' not in value:
# Ensure e.g. \E7 doesnt get translated to “\0337”, which
# would be interpreted as octal 337 by the C compiler
value = re.sub(r'\\E([0-7])', r'\\033" "\1', value)
# see terminfo(5) for valid escape sequences
# Replace \E with an actual escape
value = re.sub(r'\\E', r'\\033', value)
# Control characters
def translate_ctrl_chr(m):
ctrl = m.group(1)
if ctrl == '?':
return chr(0x7f)
return chr(ord(ctrl) - ord('@'))
value = re.sub('\^([@A-Z[\\\\\]^_?])', translate_ctrl_chr, value)
# Dont escape :
value = value.replace('\\:', ':')
# Ensure e.g. \E7 (or \e7) doesnt get translated to “\0337”,
# which would be interpreted as octal 337 by the C compiler
value = re.sub(r'(\\E|\\e)([0-7])', r'\\033" "\2', value)
else:
value = value.replace("\\", "\\\\")
# # Need to double-escape backslashes. These only occur in
# # \E\ combos. Note that \E itself is updated below
# value = value.replace('\\E\\\\', '\\E\\\\\\\\')
# Replace \E and \e with ESC
value = re.sub(r'\\E|\\e', r'\\033', value)
# # Need to double-escape \E in C string literals
# value = value.replace('\\E', '\\\\E')
# Unescape ,:^
value = re.sub(r'\\(,|:|\^)', r'\1', value)
# Replace \s with space
value = value.replace('\\s', ' ')
# Let \\, \n, \r, \t, \b and \f "fall through", to the C string literal
if re.search(r'\\l', value):
raise NotImplementedError('\\l escape sequence')
super().__init__(name, value)