Coverage for lintro / utils / ascii_normalize_cli.py: 100%

39 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""CLI to normalize ASCII art files to a standard size. 

2 

3Usage (via uv): 

4 uv run python -m lintro.utils.ascii_normalize_cli --width 80 --height 20 

5 

6By default processes all .txt files under lintro/ascii-art. 

7""" 

8 

9from __future__ import annotations 

10 

11import argparse 

12from pathlib import Path 

13 

14from lintro.utils.formatting import normalize_ascii_file_sections 

15 

16 

17def _ascii_art_dir() -> Path: 

18 return Path(__file__).resolve().parents[1] / "ascii-art" 

19 

20 

21def _write_sections( 

22 file_path: Path, 

23 sections: list[list[str]], 

24) -> None: 

25 # Join sections with a single blank line between them 

26 lines: list[str] = [] 

27 for idx, sec in enumerate(sections): 

28 lines.extend(sec) 

29 if idx != len(sections) - 1: 

30 lines.append("") 

31 file_path.write_text("\n".join(lines) + "\n", encoding="utf-8") 

32 

33 

34def main() -> int: 

35 """Normalize ASCII art files based on width/height and alignment. 

36 

37 Returns: 

38 int: Zero on success, non-zero when the base directory is missing. 

39 """ 

40 parser = argparse.ArgumentParser(description="Normalize ASCII art files.") 

41 parser.add_argument("files", nargs="*", help="Specific ASCII art files to process") 

42 parser.add_argument("--width", type=int, default=80) 

43 parser.add_argument("--height", type=int, default=20) 

44 parser.add_argument( 

45 "--align", 

46 choices=["left", "center", "right"], 

47 default="center", 

48 ) 

49 parser.add_argument( 

50 "--valign", 

51 choices=["top", "middle", "bottom"], 

52 default="middle", 

53 ) 

54 args = parser.parse_args() 

55 

56 base_dir = _ascii_art_dir() 

57 if not base_dir.exists(): 

58 print(f"ASCII art directory not found: {base_dir}") 

59 return 1 

60 

61 targets: list[Path] 

62 if args.files: 

63 targets = [base_dir / f for f in args.files] 

64 else: 

65 targets = sorted(base_dir.glob("*.txt")) 

66 

67 updated = 0 

68 for fp in targets: 

69 sections = normalize_ascii_file_sections( 

70 file_path=fp, 

71 width=args.width, 

72 height=args.height, 

73 align=args.align, 

74 valign=args.valign, 

75 ) 

76 if not sections: 

77 print(f"Skipping (no sections or unreadable): {fp.name}") 

78 continue 

79 _write_sections( 

80 file_path=fp, 

81 sections=sections, 

82 ) 

83 updated += 1 

84 print(f"Normalized: {fp.name} -> {args.width}x{args.height}") 

85 

86 print(f"Done. Updated {updated} file(s).") 

87 return 0 

88 

89 

90if __name__ == "__main__": # pragma: no cover - exercised via CLI in practice 

91 raise SystemExit(main())