106 lines
3.1 KiB
Python
106 lines
3.1 KiB
Python
# Validate the asciidoc environment directives in the given file(s).
|
|
# Errors are printed to the standard output stream.
|
|
#
|
|
# "ifdef" commands has to start the line without any leading spaces,
|
|
# as per asciidoc format.
|
|
#
|
|
# Only one form is allowed:
|
|
# ifdef::env-github,rspecator-view[]
|
|
#
|
|
# The closing command is:
|
|
# endif::env-github,rspecator-view[]
|
|
#
|
|
# It must be in the same file.
|
|
# Only one such environment is allowed per file.
|
|
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
|
|
VALID_IFDEF = "ifdef::env-github,rspecator-view[]"
|
|
VALID_ENDIF = "endif::env-github,rspecator-view[]"
|
|
|
|
|
|
class Checker:
|
|
def __init__(self, file: Path):
|
|
assert file.exists()
|
|
assert file.is_file()
|
|
|
|
self._file = file
|
|
self._is_env_open = False
|
|
self._has_env = False
|
|
self._is_valid = True
|
|
|
|
def process(self) -> bool:
|
|
content = self._file.read_text(encoding="utf-8")
|
|
lines = content.splitlines(keepends=False)
|
|
for line_index, line in enumerate(lines):
|
|
line_number = line_index + 1
|
|
if line.startswith("ifdef::"):
|
|
self._process_open(line_number, line)
|
|
if line.startswith("endif::"):
|
|
self._process_close(line_number, line)
|
|
|
|
if self._is_env_open:
|
|
self._on_error(len(lines), "The ifdef command is not closed.")
|
|
|
|
return self._is_valid
|
|
|
|
def _process_open(self, line_number: int, line: str):
|
|
if self._has_env:
|
|
self._on_error(line_number, "Only one ifdef command is allowed per file.")
|
|
|
|
if self._is_env_open:
|
|
self._on_error(line_number, "The previous ifdef command was not closed.")
|
|
|
|
self._has_env = True
|
|
self._is_env_open = True
|
|
|
|
# IDEs should be configured to properly display the description,
|
|
# not the other way around.
|
|
# "env-vscode" was used in the passed. Instead, user should be able to
|
|
# toggle the rspecator view based on their needs. Help these users migrate.
|
|
if "vscode" in line:
|
|
self._on_error(
|
|
line_number,
|
|
"Configure VS Code to display rspecator-view by setting the asciidoctor attribute.",
|
|
)
|
|
|
|
if line != VALID_IFDEF:
|
|
self._on_error(
|
|
line_number,
|
|
f'Incorrect asciidoc environment. "{VALID_IFDEF}" should be used instead.',
|
|
)
|
|
|
|
def _process_close(self, line_number: int, line: str):
|
|
if not self._is_env_open:
|
|
self._on_error(line_number, "Unexpected endif command.")
|
|
|
|
self._is_env_open = False
|
|
|
|
if line != VALID_ENDIF:
|
|
self._on_error(
|
|
line_number,
|
|
f'Incorrect endif command. "{VALID_ENDIF}" should be used instead.',
|
|
)
|
|
|
|
def _on_error(self, line_number: int, message: str):
|
|
print(f"{self._file}:{line_number} {message}")
|
|
self._is_valid = False
|
|
|
|
|
|
def main():
|
|
files = sys.argv[1:]
|
|
if not files:
|
|
sys.exit("Missing input files")
|
|
|
|
valid = True
|
|
for file in files:
|
|
if not Checker(Path(file)).process():
|
|
valid = False
|
|
if not valid:
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|