diff --git a/nginxfmt.py b/nginxfmt.py index b592824..71721f7 100755 --- a/nginxfmt.py +++ b/nginxfmt.py @@ -1,11 +1,97 @@ #!/usr/bin/env python3 +"""add module description +""" + import argparse -argparser = argparse.ArgumentParser() +import re + +__author__ = "Michał Słomkowski" +__license__ = "Apache 2.0" + +INDENTATION = ' ' * 4 + + +def strip_line(single_line): + within_quotes = False + parts = [] + for part in re.split('"', single_line.strip()): + if within_quotes: + parts.append(part) + else: + parts.append(re.sub(r'[\s]+', ' ', part)) + within_quotes = not within_quotes + return '"'.join(parts) + + +def clean_lines(orig_lines): + cleaned_lines = [] + for line in orig_lines: + line = strip_line(line) + if line == "": + cleaned_lines.append("") + continue + else: + cleaned_lines.extend([l.strip() for l in re.split("([\\{\\}])", line) if l != ""]) + + return cleaned_lines + + +def join_opening_parenthesis(lines): + modified_lines = [] + for i in range(len(lines)): + if i > 0 and lines[i] == "{": + modified_lines[-1] += " {" + else: + modified_lines.append(lines[i]) + return modified_lines + + +def perform_indentation(lines): + indented_lines = [] + current_indent = 0 + for line in lines: + if line.endswith('}') and current_indent > 0: + current_indent -= 1 + + indented_lines.append(current_indent * INDENTATION + line) + + if line.endswith('{'): + current_indent += 1 + + return indented_lines + + +def format_config_file(contents): + lines = clean_lines(contents.splitlines()) + lines = join_opening_parenthesis(lines) + lines = perform_indentation(lines) + + return '\n'.join(lines) + '\n' + + +if __name__ == "__main__": + argparser = argparse.ArgumentParser(description=__doc__) + + argparser.add_argument("-v", "--verbose", action="store_true", help="show formatted file names") + argparser.add_argument("-b", "--backup-original", action="store_true", help="backup original config file") + argparser.add_argument("config_file", type=argparse.FileType('r'), nargs='+') + + args = argparser.parse_args() + + for config_file in args.config_file: + original_file_content = config_file.read() + config_file.close() -argparser.add_argument("-v", "--verbose", action="store_true", help="show formatted file names") -argparser.add_argument("-b", "--backup-original", action="store_true", help="backup original config file") -argparser.add_argument("config_file", type=argparse.FileType('r'), nargs='+') + with open(config_file.name, 'w') as fp: + fp.write(format_config_file(original_file_content)) + if args.verbose: + print("Formatted file %s" % config_file.name) -args = argparser.parse_args() + if args.backup_original: + backup_file_path = config_file.name + '~' + with open(backup_file_path, 'w') as fp: + fp.write(original_file_content) + if args.verbose: + print("Original saved to %s" % backup_file_path) diff --git a/test_nginxfmt.py b/test_nginxfmt.py new file mode 100644 index 0000000..8e5771c --- /dev/null +++ b/test_nginxfmt.py @@ -0,0 +1,79 @@ +import unittest + +from nginxfmt import * + + +class TestFormatter(unittest.TestCase): + def _check_formatting(self, original_text, formatted_text): + self.assertEqual(formatted_text, format_config_file(original_text)) + + def test_join_opening_parenthesis(self): + self.assertEqual(["foo", "bar {", "johan {", "tee", "ka", "}"], + join_opening_parenthesis(("foo", "bar {", "johan", "{", "tee", "ka", "}"))) + + def test_clear_lines(self): + self.assertEqual(["ala", "ma", "{", "kota", "}", "to;", "", "ook"], + clean_lines(("ala", "ma {", "kota", "}", "to;", "", "ook"))) + + self.assertEqual(["ala", "ma", "{", "{", "kota", "}", "to", "}", "ook"], + clean_lines(("ala", "ma {{", "kota", "}", "to}", "ook"))) + + self.assertEqual(["{", "ala", "ma", "{", "{", "kota", "}", "to", "}"], + clean_lines(("{", "ala ", "ma {{", " kota ", "}", " to} "))) + + def test_perform_indentation(self): + self.assertEqual([ + "foo bar {", + " fizz bazz;", + "}"], perform_indentation(("foo bar {", "fizz bazz;", "}"))) + + self.assertEqual([ + "foo bar {", + " fizz bazz {", + " lorem ipsum;", + " asdf asdf;", + " }", + "}"], perform_indentation(("foo bar {", "fizz bazz {", "lorem ipsum;", "asdf asdf;", "}", "}"))) + + self.assertEqual([ + "foo bar {", + " fizz bazz {", + " lorem ipsum;", + " }", + "}", + "}", + "foo {"], perform_indentation(("foo bar {", "fizz bazz {", "lorem ipsum;", "}", "}", "}", "foo {"))) + + def test_strip_line(self): + self.assertEqual("foo", strip_line(" foo ")) + self.assertEqual("bar foo", strip_line(" bar foo ")) + self.assertEqual("bar foo", strip_line(" bar \t foo ")) + self.assertEqual('lorem ipsum " foo bar zip "', strip_line(' lorem ipsum " foo bar zip " ')) + self.assertEqual('lorem ipsum " foo bar zip " or " dd aa " mi', + strip_line(' lorem ipsum " foo bar zip " or \t " dd aa " mi')) + + def test_indentation(self): + self._check_formatting( + " foo bar {\n" + + " lorem ipsum;\n" + + "}", + "foo bar {\n" + + " lorem ipsum;\n" + + "}\n") + + self._check_formatting( + " foo bar {\n" + + " lorem ipsum;\n" + + " kee {\n" + + "caak; \n" + + "}}", + "foo bar {\n" + + " lorem ipsum;\n" + + " kee {\n" + + " caak;\n" + + " }\n" + + "}\n") + + +if __name__ == '__main__': + unittest.main()