diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 12a2950..2f4363b 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -783,7 +783,7 @@ def escape_empty(val): _esc = r"\x1b" _csi = rf"{_esc}\[" _osc = rf"{_esc}\]" -_st = rf"{_esc}\\" +_st = rf"(?:{_esc}\\|\x07)" _ansi_escape_pat = rf""" ( @@ -795,11 +795,11 @@ def escape_empty(val): | # terminal hyperlinks {_osc}8; # OSC opening - (\w+=\w+:?)* # key=value params list (submatch 2) + ([\w.-]+=[\w.-]+:?)* # key=value params list (submatch 2) ; # delimiter - ([^{_esc}]+) # URI - anything but ESC (submatch 3) + ([^{_esc}\x07]+) # URI - anything but ESC or BEL (submatch 3) {_st} # ST - ([^{_esc}]+) # link text - anything but ESC (submatch 4) + ([^{_esc}\x07]+) # link text - anything but ESC or BEL (submatch 4) {_osc}8;;{_st} # "closing" OSC sequence ) """ diff --git a/test/test_regression.py b/test/test_regression.py index 9555676..db0c528 100644 --- a/test/test_regression.py +++ b/test/test_regression.py @@ -598,3 +598,25 @@ def test_github_escape_pipe_character(): result = tabulate([["foo|bar"]], headers=("spam|eggs",), tablefmt="github") expected = "| spam\\|eggs |\n|:------------|\n| foo\\|bar |" assert_equal(expected, result) + + +def test_alignment_of_bel_and_param_link_cells(): + "Regression: Align OSC-8 links terminated by BEL (0x07) or with hyphenated params." + linktable = [ + ("test", 42, "\x1b]8;;target\x07test\x1b]8;;\x07"), + ("test", 101, "\x1b]8;id=doc-1;target\x1b\\test\x1b]8;;\x1b\\"), + ] + linkheaders = ("test", "\x1b]8;;target\x07test\x1b]8;;\x07", "test") + formatted = tabulate(linktable, linkheaders, "grid") + expected = "\n".join( + [ + "+--------+--------+--------+", + "| test | \x1b]8;;target\x07test\x1b]8;;\x07 | test |", + "+========+========+========+", + "| test | 42 | \x1b]8;;target\x07test\x1b]8;;\x07 |", + "+--------+--------+--------+", + "| test | 101 | \x1b]8;id=doc-1;target\x1b\\test\x1b]8;;\x1b\\ |", + "+--------+--------+--------+", + ] + ) + assert_equal(expected, formatted)