From 2a210daad64d953d7a97f5dda998f57b16427c40 Mon Sep 17 00:00:00 2001 From: yongfu Date: Wed, 17 Oct 2018 09:00:16 +0800 Subject: [PATCH] fix multi semicolon --- nginxfmt.py | 74 ++++++++++++++++++++++++------------------------ test_nginxfmt.py | 3 ++ 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/nginxfmt.py b/nginxfmt.py index 24e9160..57a26f6 100755 --- a/nginxfmt.py +++ b/nginxfmt.py @@ -37,38 +37,42 @@ def strip_line(single_line): within_quotes = not within_quotes return '"'.join(parts) -def count_multi_semicolon(single_line): - """count multi_semicolon (except when within quotation marks).""" - single_line = single_line.strip() - if single_line.startswith('#'): - return 0, 0 - - within_quotes = False - q = 0 - c = 0 - for part in re.split('"', single_line): - if within_quotes: - q = 1 - else: - c += part.count(';') - within_quotes = not within_quotes - return q, c - def multi_semicolon(single_line): """break multi_semicolon into multiline (except when within quotation marks).""" + single_line = single_line.strip() if single_line.startswith('#'): - return single_line + return single_line, 0 + + m1 = re.match(r"^([^;#]*;)([\s]*#.*)?$", single_line) + m2 = re.match(r"^([^#]+)(;[\s]*)(#.*)?$", single_line) + + if m1 is not None: + return single_line, 0 + elif m2 is not None: + front = m2.group(1) + semicolon = m2.group(2) + comment = m2.group(3) + + within_quotes = False + parts = [] + c = 0 + for part in re.split('"', front): + if within_quotes: + parts.append(part) + else: + c += part.count(';') + parts.append(part.replace(";", ";\n")) + within_quotes = not within_quotes + multi_line = '"'.join(parts) + if semicolon is not None: + multi_line = multi_line + semicolon + if comment is not None: + multi_line = multi_line + comment + return multi_line, c + else: + return single_line, 0 - within_quotes = False - parts = [] - for part in re.split('"', single_line): - if within_quotes: - parts.append(part) - else: - parts.append(part.replace(";", ";\n")) - within_quotes = not within_quotes - return '"'.join(parts) def apply_variable_template_tags(line: str) -> str: """Replaces variable indicators ${ and } with tags, so subsequent formatting is easier.""" @@ -99,19 +103,15 @@ def clean_lines(orig_lines) -> list: if line.startswith("#"): cleaned_lines.append(strip_variable_template_tags(line)) else: - q , c = count_multi_semicolon(line) - if q == 1 and c > 1: - ml = multi_semicolon(line) - cleaned_lines.extend(clean_lines(ml.splitlines())) - elif q != 1 and c > 1: - newlines = line.split(";") - cleaned_lines.extend(clean_lines(["".join([ln, ";"]) for ln in newlines if ln != ""])) + mline, c = multi_semicolon(line) + if c > 0: + cleaned_lines.extend(clean_lines(mline.splitlines())) else: - if line.startswith("rewrite"): - cleaned_lines.append(strip_variable_template_tags(line)) + if mline.startswith("rewrite"): + cleaned_lines.append(strip_variable_template_tags(mline)) else: cleaned_lines.extend( - [strip_variable_template_tags(l).strip() for l in re.split(r"([{}])", line) if l != ""]) + [strip_variable_template_tags(l).strip() for l in re.split(r"([{}])", mline) if l != ""]) return cleaned_lines diff --git a/test_nginxfmt.py b/test_nginxfmt.py index 6eb9da7..20e1dbe 100644 --- a/test_nginxfmt.py +++ b/test_nginxfmt.py @@ -46,6 +46,9 @@ class TestFormatter(unittest.TestCase): self.assertEqual(["{", "aa;", "b b \"cc; dd; ee \";", "ssss;", "}"], clean_lines(("{", "aa; b b \"cc; dd; ee \"; ssss;", "}"))) + self.assertEqual(["{", "a aa;", "bb b \"ccc; dddd;\";", "ee e; # ff; ee ;", "}"], + clean_lines(("{", "a aa; bb b \"ccc; dddd;\"; ee e; # ff; ee ;", "}"))) + self.assertEqual(["location ~ /\.ht", "{"], clean_lines(["location ~ /\.ht {", ])) def test_perform_indentation(self):