diff --git a/chromaterm/__init__.py b/chromaterm/__init__.py index 11e3a5ef..4d1c52ec 100644 --- a/chromaterm/__init__.py +++ b/chromaterm/__init__.py @@ -15,9 +15,10 @@ from .config import RESET_TYPES, eprint, parse_config, read_file # Sequences upon which ct will split during processing. This includes new lines, -# vertical spaces, form feeds, C1 set (ECMA-048), and CSI (excluding SGR). -SPLIT_RE = re.compile(r'(\r\n?|\n|\v|\f|\x1b[\x40-\x5a\x5c-\x5f]|' - r'\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x6c\x6e-\x7e])') +# vertical spaces, form feeds, C1 set (ECMA-048), CSI (excluding SGR), and OSC. +SPLIT_RE = re.compile(r'(\r\n?|\n|\v|\f|\x1b[\x40-\x5a\x5c\x5e\x5f]|' + r'\x1b\x5b[\x30-\x3f]*[\x20-\x2f]*[\x40-\x6c\x6e-\x7e]|' + r'\x1b\x5d[\x08-\x0d\x20-\x7e]*(?:\x07|\x1b\x5c))') # Select Graphic Rendition sequence (all types) SGR_RE = re.compile(r'\x1b\[[0-9;]*m') diff --git a/chromaterm/test___init__.py b/chromaterm/test___init__.py index 801bda45..cd53bc62 100644 --- a/chromaterm/test___init__.py +++ b/chromaterm/test___init__.py @@ -925,11 +925,13 @@ def test_split_buffer_form_feed(): def test_split_buffer_ecma_048_c1_set(): - """Split based on the ECMA-048 C1 set, excluding CSI.""" - c1_set_up_to_csi = range(int('40', 16), int('5b', 16)) - c1_set_above_csi = range(int('5c', 16), int('60', 16)) + """Split based on the ECMA-048 C1 set, excluding CSI and OSC.""" + c1_except_csi_and_osc = itertools.chain( + range(int('40', 16), int('5b', 16)), + [int('5c', 16), int('5e', 16), int('5f', 16)], + ) - for char_id in itertools.chain(c1_set_up_to_csi, c1_set_above_csi): + for char_id in c1_except_csi_and_osc: data = 'Hello \x1b{} World'.format(chr(char_id)) expected = [['Hello ', '\x1b' + chr(char_id)], [' World', '']] @@ -1007,6 +1009,17 @@ def test_split_buffer_ecma_048_csi_parameter_intermediate(): chromaterm.split_buffer(data)) == repr(expected) +def test_split_buffer_ecma_048_osc_title(): + """Operating System Command (OSC) can supply arbitrary commands within the + visible character set.""" + for end in ['\x07', '\x1b\x5c']: + osc = '\x1b]Ignored{}'.format(end) + data = '{}Hello world'.format(osc) + expected = [['', osc], ['Hello world', '']] + + assert repr(chromaterm.split_buffer(data)) == repr(expected) + + def test_tty_test_code_no_pipe(): """Baseline the test code with no pipes on stdin or stdout.""" master, slave = os.openpty()