diff --git a/dochooks/insert_whitespace_between_cn_and_en_char/check.py b/dochooks/insert_whitespace_between_cn_and_en_char/check.py index b2bf5c7..ccfb72e 100644 --- a/dochooks/insert_whitespace_between_cn_and_en_char/check.py +++ b/dochooks/insert_whitespace_between_cn_and_en_char/check.py @@ -1,6 +1,7 @@ from __future__ import annotations import argparse +from collections.abc import Iterable from typing import Sequence from dochooks import __version__ @@ -16,18 +17,27 @@ def check(string: str) -> bool: return True -def _check_file(file_path: str) -> ReturnCode: - return_code = PASS +def check_lines(lines: Iterable[str]) -> tuple[bool, list[tuple[int, str]]]: + diagnostics: list[tuple[int, str]] = [] + need_format = False pragma_manager = PragmaManager() + for lineno, line in enumerate(lines, 1): + with pragma_manager.scan(line) as skip_line: + if skip_line: + continue + if not check(line): + need_format = True + diagnostics.append((lineno, line)) + return need_format, diagnostics + + +def _check_file(file_path: str) -> ReturnCode: with open(file_path, encoding="utf8", newline="\n") as f: - for lineno, line in enumerate(f, 1): - with pragma_manager.scan(line) as skip_line: - if skip_line: - continue - if not check(line): - print(f"No spaces between EN and CN chars detected at: {file_path}:{lineno}:\t{line}") - return_code = FAIL - return return_code + need_format, diagnostics = check_lines(f) + if need_format: + for lineno, line in diagnostics: + print(f"No spaces between EN and CN chars detected at: {file_path}:{lineno}:\t{line.strip()}") + return FAIL if need_format else PASS def main(argv: Sequence[str] | None = None) -> ReturnCode: diff --git a/dochooks/insert_whitespace_between_cn_and_en_char/format.py b/dochooks/insert_whitespace_between_cn_and_en_char/format.py index 007888d..67bcf5b 100644 --- a/dochooks/insert_whitespace_between_cn_and_en_char/format.py +++ b/dochooks/insert_whitespace_between_cn_and_en_char/format.py @@ -1,6 +1,7 @@ from __future__ import annotations import argparse +from collections.abc import Iterable from typing import Sequence from dochooks import __version__ @@ -17,25 +18,34 @@ def format(text: str) -> str: return text -def _format_file(file_path: str) -> ReturnCode: - return_code = PASS +def format_lines(lines: Iterable[str]) -> tuple[bool, str, list[tuple[int, str]]]: + formatted_text: str = "" + diagnostics: list[tuple[int, str]] = [] + need_format = False pragma_manager = PragmaManager() - formatted_text = "" - with open(file_path, encoding="utf8", newline="\n") as f: - for lineno, line in enumerate(f, 1): - with pragma_manager.scan(line) as skip_line: - if skip_line: - formatted_text += line - continue - if not check(line): - line = format(line) - return_code = FAIL - print(f"Add spaces between EN and CN chars in: {file_path}:{lineno}:\t{line}") + for lineno, line in enumerate(lines, 1): + with pragma_manager.scan(line) as skip_line: + if skip_line: formatted_text += line - if return_code != PASS: + continue + if not check(line): + line = format(line) + need_format = True + diagnostics.append((lineno, line)) + formatted_text += line + return need_format, formatted_text, diagnostics + + +def _format_file(file_path: str) -> ReturnCode: + with open(file_path, encoding="utf8", newline="\n") as f: + need_format, formatted_text, diagnostics = format_lines(f) + + if formatted_text: with open(file_path, "w", encoding="utf8", newline="\n") as f: f.write(formatted_text) - return return_code + for lineno, line in diagnostics: + print(f"Add spaces between EN and CN chars in: {file_path}:{lineno}:\t{line.strip()}") + return FAIL if need_format else PASS def main(argv: Sequence[str] | None = None) -> ReturnCode: diff --git a/tests/test_insert_whitespace_between_cn_and_en_char/test_pragma.py b/tests/test_insert_whitespace_between_cn_and_en_char/test_pragma.py new file mode 100644 index 0000000..f4662fe --- /dev/null +++ b/tests/test_insert_whitespace_between_cn_and_en_char/test_pragma.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import pytest + +from dochooks.insert_whitespace_between_cn_and_en_char.check import check_lines +from dochooks.insert_whitespace_between_cn_and_en_char.format import format_lines + +NEED_FORMAT: bool = True +NEEDNT_FORMAT: bool = False +cases = [ + (NEEDNT_FORMAT, "中文and英文 # dochooks: skip-line", "中文and英文 # dochooks: skip-line"), + ( + NEED_FORMAT, + """ + 中文English # 需要格式化 + 中文English # dochooks: skip-line + 中文English # 需要格式化 + 中文English # dochooks: skip-line + 中文English # 需要格式化 + # dochooks: skip-next-line + 中文English + 中文English # 需要格式化 + # dochooks: skip-next-line + 中文English + 中文English # 需要格式化 + """, + """ + 中文 English # 需要格式化 + 中文English # dochooks: skip-line + 中文 English # 需要格式化 + 中文English # dochooks: skip-line + 中文 English # 需要格式化 + # dochooks: skip-next-line + 中文English + 中文 English # 需要格式化 + # dochooks: skip-next-line + 中文English + 中文 English # 需要格式化 + """, + ), +] + + +@pytest.mark.parametrize("need_format, unformatted, formatted", cases) +def test_check_and_format_lines(need_format: bool, unformatted: str, formatted: str): + need_format_from_check, _ = check_lines(unformatted.splitlines(keepends=True)) + need_format_from_format, formatted_text, _ = format_lines(unformatted.splitlines(keepends=True)) + assert need_format_from_check == need_format + assert need_format_from_format == need_format + + assert formatted_text == formatted