pyprettyvba 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (460) hide show
  1. pyprettyvba-0.1.0/.gitattributes +4 -0
  2. pyprettyvba-0.1.0/.github/workflows/ci.yml +57 -0
  3. pyprettyvba-0.1.0/.github/workflows/publish.yml +113 -0
  4. pyprettyvba-0.1.0/.gitignore +15 -0
  5. pyprettyvba-0.1.0/.pre-commit-hooks.yaml +22 -0
  6. pyprettyvba-0.1.0/AGENTS.md +34 -0
  7. pyprettyvba-0.1.0/CHANGELOG.md +28 -0
  8. pyprettyvba-0.1.0/CONTRIBUTING.md +86 -0
  9. pyprettyvba-0.1.0/LICENSE +21 -0
  10. pyprettyvba-0.1.0/PKG-INFO +245 -0
  11. pyprettyvba-0.1.0/README.md +207 -0
  12. pyprettyvba-0.1.0/docs/architecture.md +126 -0
  13. pyprettyvba-0.1.0/docs/configuration.md +144 -0
  14. pyprettyvba-0.1.0/docs/rules.md +490 -0
  15. pyprettyvba-0.1.0/docs/suppression.md +54 -0
  16. pyprettyvba-0.1.0/docs/vbe-evidence.md +140 -0
  17. pyprettyvba-0.1.0/pyproject.toml +87 -0
  18. pyprettyvba-0.1.0/src/pyprettyvba/__init__.py +62 -0
  19. pyprettyvba-0.1.0/src/pyprettyvba/__main__.py +7 -0
  20. pyprettyvba-0.1.0/src/pyprettyvba/api.py +414 -0
  21. pyprettyvba-0.1.0/src/pyprettyvba/chars.py +57 -0
  22. pyprettyvba-0.1.0/src/pyprettyvba/cli.py +532 -0
  23. pyprettyvba-0.1.0/src/pyprettyvba/config.py +532 -0
  24. pyprettyvba-0.1.0/src/pyprettyvba/contextual.py +109 -0
  25. pyprettyvba-0.1.0/src/pyprettyvba/data/names.json.gz +0 -0
  26. pyprettyvba-0.1.0/src/pyprettyvba/document.py +615 -0
  27. pyprettyvba-0.1.0/src/pyprettyvba/engine.py +278 -0
  28. pyprettyvba-0.1.0/src/pyprettyvba/keywords.py +180 -0
  29. pyprettyvba-0.1.0/src/pyprettyvba/lexer.py +386 -0
  30. pyprettyvba-0.1.0/src/pyprettyvba/literals.py +733 -0
  31. pyprettyvba-0.1.0/src/pyprettyvba/names.py +87 -0
  32. pyprettyvba-0.1.0/src/pyprettyvba/office.py +228 -0
  33. pyprettyvba-0.1.0/src/pyprettyvba/py.typed +0 -0
  34. pyprettyvba-0.1.0/src/pyprettyvba/rules/__init__.py +55 -0
  35. pyprettyvba-0.1.0/src/pyprettyvba/rules/alignment.py +112 -0
  36. pyprettyvba-0.1.0/src/pyprettyvba/rules/base.py +178 -0
  37. pyprettyvba-0.1.0/src/pyprettyvba/rules/casing.py +278 -0
  38. pyprettyvba-0.1.0/src/pyprettyvba/rules/comments.py +183 -0
  39. pyprettyvba-0.1.0/src/pyprettyvba/rules/layout.py +676 -0
  40. pyprettyvba-0.1.0/src/pyprettyvba/rules/literals.py +134 -0
  41. pyprettyvba-0.1.0/src/pyprettyvba/rules/reporting.py +69 -0
  42. pyprettyvba-0.1.0/src/pyprettyvba/rules/spacing.py +488 -0
  43. pyprettyvba-0.1.0/src/pyprettyvba/rules/statements.py +249 -0
  44. pyprettyvba-0.1.0/src/pyprettyvba/safety.py +254 -0
  45. pyprettyvba-0.1.0/src/pyprettyvba/scopes.py +251 -0
  46. pyprettyvba-0.1.0/src/pyprettyvba/structure.py +329 -0
  47. pyprettyvba-0.1.0/src/pyprettyvba/suppression.py +204 -0
  48. pyprettyvba-0.1.0/src/pyprettyvba/textio.py +64 -0
  49. pyprettyvba-0.1.0/tests/conftest.py +24 -0
  50. pyprettyvba-0.1.0/tests/fixture_support.py +199 -0
  51. pyprettyvba-0.1.0/tests/fixtures/cli/check-fix/case.toml +10 -0
  52. pyprettyvba-0.1.0/tests/fixtures/cli/check-fix/input.bas +3 -0
  53. pyprettyvba-0.1.0/tests/fixtures/cli/check-fix/output.bas +3 -0
  54. pyprettyvba-0.1.0/tests/fixtures/cli/check-fix/stdout.txt +3 -0
  55. pyprettyvba-0.1.0/tests/fixtures/cli/check-github/case.toml +9 -0
  56. pyprettyvba-0.1.0/tests/fixtures/cli/check-github/input.bas +5 -0
  57. pyprettyvba-0.1.0/tests/fixtures/cli/check-github/stdout.txt +19 -0
  58. pyprettyvba-0.1.0/tests/fixtures/cli/check-grouped/case.toml +9 -0
  59. pyprettyvba-0.1.0/tests/fixtures/cli/check-grouped/input.bas +5 -0
  60. pyprettyvba-0.1.0/tests/fixtures/cli/check-grouped/stdout.txt +20 -0
  61. pyprettyvba-0.1.0/tests/fixtures/cli/check-json/case.toml +9 -0
  62. pyprettyvba-0.1.0/tests/fixtures/cli/check-json/input.bas +5 -0
  63. pyprettyvba-0.1.0/tests/fixtures/cli/check-json/stdout.txt +192 -0
  64. pyprettyvba-0.1.0/tests/fixtures/cli/check-statistics/case.toml +9 -0
  65. pyprettyvba-0.1.0/tests/fixtures/cli/check-statistics/input.bas +5 -0
  66. pyprettyvba-0.1.0/tests/fixtures/cli/check-statistics/stdout.txt +4 -0
  67. pyprettyvba-0.1.0/tests/fixtures/cli/check-text/case.toml +11 -0
  68. pyprettyvba-0.1.0/tests/fixtures/cli/check-text/input.bas +5 -0
  69. pyprettyvba-0.1.0/tests/fixtures/cli/check-text/stdout.txt +21 -0
  70. pyprettyvba-0.1.0/tests/fixtures/cli/config/case.toml +10 -0
  71. pyprettyvba-0.1.0/tests/fixtures/cli/config/files/pyprettyvba.toml +3 -0
  72. pyprettyvba-0.1.0/tests/fixtures/cli/config/input.bas +5 -0
  73. pyprettyvba-0.1.0/tests/fixtures/cli/config/stdout.txt +30 -0
  74. pyprettyvba-0.1.0/tests/fixtures/cli/format-check/case.toml +10 -0
  75. pyprettyvba-0.1.0/tests/fixtures/cli/format-check/input.bas +5 -0
  76. pyprettyvba-0.1.0/tests/fixtures/cli/format-check/stdout.txt +3 -0
  77. pyprettyvba-0.1.0/tests/fixtures/cli/format-diff/case.toml +9 -0
  78. pyprettyvba-0.1.0/tests/fixtures/cli/format-diff/input.bas +5 -0
  79. pyprettyvba-0.1.0/tests/fixtures/cli/format-diff/stdout.txt +13 -0
  80. pyprettyvba-0.1.0/tests/fixtures/cli/format-write/case.toml +10 -0
  81. pyprettyvba-0.1.0/tests/fixtures/cli/format-write/input.bas +5 -0
  82. pyprettyvba-0.1.0/tests/fixtures/cli/format-write/output.bas +5 -0
  83. pyprettyvba-0.1.0/tests/fixtures/cli/format-write/stdout.txt +2 -0
  84. pyprettyvba-0.1.0/tests/fixtures/cli/rules/case.toml +9 -0
  85. pyprettyvba-0.1.0/tests/fixtures/cli/rules/stdout.txt +20 -0
  86. pyprettyvba-0.1.0/tests/fixtures/cli/rules-describe/case.toml +9 -0
  87. pyprettyvba-0.1.0/tests/fixtures/cli/rules-describe/stdout.txt +21 -0
  88. pyprettyvba-0.1.0/tests/fixtures/cli/select-rules/case.toml +10 -0
  89. pyprettyvba-0.1.0/tests/fixtures/cli/select-rules/input.bas +5 -0
  90. pyprettyvba-0.1.0/tests/fixtures/cli/select-rules/stdout.txt +13 -0
  91. pyprettyvba-0.1.0/tests/fixtures/cli/stdin/case.toml +12 -0
  92. pyprettyvba-0.1.0/tests/fixtures/cli/stdin/stdout.txt +3 -0
  93. pyprettyvba-0.1.0/tests/fixtures/config/extend/case.toml +11 -0
  94. pyprettyvba-0.1.0/tests/fixtures/config/extend/files/base.toml +1 -0
  95. pyprettyvba-0.1.0/tests/fixtures/config/extend/files/pyprettyvba.toml +3 -0
  96. pyprettyvba-0.1.0/tests/fixtures/config/extend/input.bas +4 -0
  97. pyprettyvba-0.1.0/tests/fixtures/config/extend/stdout.txt +11 -0
  98. pyprettyvba-0.1.0/tests/fixtures/config/invalid/case.toml +11 -0
  99. pyprettyvba-0.1.0/tests/fixtures/config/invalid/files/pyprettyvba.toml +3 -0
  100. pyprettyvba-0.1.0/tests/fixtures/config/invalid/input.bas +2 -0
  101. pyprettyvba-0.1.0/tests/fixtures/config/invalid/stdout.txt +2 -0
  102. pyprettyvba-0.1.0/tests/fixtures/config/overrides/case.toml +13 -0
  103. pyprettyvba-0.1.0/tests/fixtures/config/overrides/check.txt +4 -0
  104. pyprettyvba-0.1.0/tests/fixtures/config/overrides/input.bas +6 -0
  105. pyprettyvba-0.1.0/tests/fixtures/config/overrides/output.bas +6 -0
  106. pyprettyvba-0.1.0/tests/fixtures/config/pyproject/case.toml +10 -0
  107. pyprettyvba-0.1.0/tests/fixtures/config/pyproject/files/pyproject.toml +5 -0
  108. pyprettyvba-0.1.0/tests/fixtures/config/pyproject/input.bas +3 -0
  109. pyprettyvba-0.1.0/tests/fixtures/config/pyproject/stdout.txt +9 -0
  110. pyprettyvba-0.1.0/tests/fixtures/config/rule-options/case.toml +14 -0
  111. pyprettyvba-0.1.0/tests/fixtures/config/rule-options/check.txt +11 -0
  112. pyprettyvba-0.1.0/tests/fixtures/config/rule-options/input.bas +12 -0
  113. pyprettyvba-0.1.0/tests/fixtures/config/rule-options/output.bas +11 -0
  114. pyprettyvba-0.1.0/tests/fixtures/files/ansi-code-page/case.toml +8 -0
  115. pyprettyvba-0.1.0/tests/fixtures/files/ansi-code-page/check.txt +2 -0
  116. pyprettyvba-0.1.0/tests/fixtures/files/ansi-code-page/input.bas +4 -0
  117. pyprettyvba-0.1.0/tests/fixtures/files/ansi-code-page/output.bas +4 -0
  118. pyprettyvba-0.1.0/tests/fixtures/files/class-module/case.toml +6 -0
  119. pyprettyvba-0.1.0/tests/fixtures/files/class-module/check.txt +29 -0
  120. pyprettyvba-0.1.0/tests/fixtures/files/class-module/input.cls +18 -0
  121. pyprettyvba-0.1.0/tests/fixtures/files/class-module/output.cls +20 -0
  122. pyprettyvba-0.1.0/tests/fixtures/files/document-module/case.toml +6 -0
  123. pyprettyvba-0.1.0/tests/fixtures/files/document-module/check.txt +19 -0
  124. pyprettyvba-0.1.0/tests/fixtures/files/document-module/input.cls +15 -0
  125. pyprettyvba-0.1.0/tests/fixtures/files/document-module/output.cls +15 -0
  126. pyprettyvba-0.1.0/tests/fixtures/files/empty/case.toml +5 -0
  127. pyprettyvba-0.1.0/tests/fixtures/files/empty/check.txt +0 -0
  128. pyprettyvba-0.1.0/tests/fixtures/files/empty/input.bas +0 -0
  129. pyprettyvba-0.1.0/tests/fixtures/files/lf-endings/case.toml +6 -0
  130. pyprettyvba-0.1.0/tests/fixtures/files/lf-endings/check.txt +6 -0
  131. pyprettyvba-0.1.0/tests/fixtures/files/lf-endings/input.bas +3 -0
  132. pyprettyvba-0.1.0/tests/fixtures/files/lf-endings/output.bas +3 -0
  133. pyprettyvba-0.1.0/tests/fixtures/files/unicode-identifiers/case.toml +8 -0
  134. pyprettyvba-0.1.0/tests/fixtures/files/unicode-identifiers/check.txt +4 -0
  135. pyprettyvba-0.1.0/tests/fixtures/files/unicode-identifiers/input.bas +5 -0
  136. pyprettyvba-0.1.0/tests/fixtures/files/unicode-identifiers/output.bas +5 -0
  137. pyprettyvba-0.1.0/tests/fixtures/files/userform/case.toml +6 -0
  138. pyprettyvba-0.1.0/tests/fixtures/files/userform/check.txt +9 -0
  139. pyprettyvba-0.1.0/tests/fixtures/files/userform/input.frm +16 -0
  140. pyprettyvba-0.1.0/tests/fixtures/files/userform/output.frm +16 -0
  141. pyprettyvba-0.1.0/tests/fixtures/files/utf8-bom/case.toml +5 -0
  142. pyprettyvba-0.1.0/tests/fixtures/files/utf8-bom/check.txt +1 -0
  143. pyprettyvba-0.1.0/tests/fixtures/files/utf8-bom/input.bas +3 -0
  144. pyprettyvba-0.1.0/tests/fixtures/files/utf8-bom/output.bas +3 -0
  145. pyprettyvba-0.1.0/tests/fixtures/presets/default/case.toml +8 -0
  146. pyprettyvba-0.1.0/tests/fixtures/presets/default/check.txt +91 -0
  147. pyprettyvba-0.1.0/tests/fixtures/presets/default/input.bas +19 -0
  148. pyprettyvba-0.1.0/tests/fixtures/presets/default/output.bas +20 -0
  149. pyprettyvba-0.1.0/tests/fixtures/presets/minimal/case.toml +8 -0
  150. pyprettyvba-0.1.0/tests/fixtures/presets/minimal/check.txt +0 -0
  151. pyprettyvba-0.1.0/tests/fixtures/presets/minimal/input.bas +19 -0
  152. pyprettyvba-0.1.0/tests/fixtures/presets/none/case.toml +8 -0
  153. pyprettyvba-0.1.0/tests/fixtures/presets/none/check.txt +0 -0
  154. pyprettyvba-0.1.0/tests/fixtures/presets/none/input.bas +19 -0
  155. pyprettyvba-0.1.0/tests/fixtures/presets/strict/case.toml +8 -0
  156. pyprettyvba-0.1.0/tests/fixtures/presets/strict/check.txt +94 -0
  157. pyprettyvba-0.1.0/tests/fixtures/presets/strict/input.bas +19 -0
  158. pyprettyvba-0.1.0/tests/fixtures/presets/strict/output.bas +21 -0
  159. pyprettyvba-0.1.0/tests/fixtures/presets/vbe/case.toml +8 -0
  160. pyprettyvba-0.1.0/tests/fixtures/presets/vbe/check.txt +80 -0
  161. pyprettyvba-0.1.0/tests/fixtures/presets/vbe/input.bas +19 -0
  162. pyprettyvba-0.1.0/tests/fixtures/presets/vbe/output.bas +19 -0
  163. pyprettyvba-0.1.0/tests/fixtures/presets/xlide/case.toml +8 -0
  164. pyprettyvba-0.1.0/tests/fixtures/presets/xlide/check.txt +84 -0
  165. pyprettyvba-0.1.0/tests/fixtures/presets/xlide/input.bas +19 -0
  166. pyprettyvba-0.1.0/tests/fixtures/presets/xlide/output.bas +19 -0
  167. pyprettyvba-0.1.0/tests/fixtures/project/casing/case.toml +7 -0
  168. pyprettyvba-0.1.0/tests/fixtures/project/casing/check.txt +7 -0
  169. pyprettyvba-0.1.0/tests/fixtures/project/casing/input/Orders.bas +7 -0
  170. pyprettyvba-0.1.0/tests/fixtures/project/casing/input/Settings.bas +6 -0
  171. pyprettyvba-0.1.0/tests/fixtures/project/casing/input/ShoppingBasket.cls +14 -0
  172. pyprettyvba-0.1.0/tests/fixtures/project/casing/output/Orders.bas +8 -0
  173. pyprettyvba-0.1.0/tests/fixtures/project/casing/output/Settings.bas +7 -0
  174. pyprettyvba-0.1.0/tests/fixtures/project/casing/output/ShoppingBasket.cls +15 -0
  175. pyprettyvba-0.1.0/tests/fixtures/rules/align-declarations/basic/case.toml +13 -0
  176. pyprettyvba-0.1.0/tests/fixtures/rules/align-declarations/basic/check.txt +4 -0
  177. pyprettyvba-0.1.0/tests/fixtures/rules/align-declarations/basic/input.bas +15 -0
  178. pyprettyvba-0.1.0/tests/fixtures/rules/align-declarations/basic/output.bas +15 -0
  179. pyprettyvba-0.1.0/tests/fixtures/rules/blank-lines/basic/case.toml +14 -0
  180. pyprettyvba-0.1.0/tests/fixtures/rules/blank-lines/basic/check.txt +8 -0
  181. pyprettyvba-0.1.0/tests/fixtures/rules/blank-lines/basic/input.bas +21 -0
  182. pyprettyvba-0.1.0/tests/fixtures/rules/blank-lines/basic/output.bas +18 -0
  183. pyprettyvba-0.1.0/tests/fixtures/rules/blank-lines/strict/case.toml +11 -0
  184. pyprettyvba-0.1.0/tests/fixtures/rules/blank-lines/strict/check.txt +3 -0
  185. pyprettyvba-0.1.0/tests/fixtures/rules/blank-lines/strict/input.bas +11 -0
  186. pyprettyvba-0.1.0/tests/fixtures/rules/blank-lines/strict/output.bas +12 -0
  187. pyprettyvba-0.1.0/tests/fixtures/rules/comment-space/basic/case.toml +12 -0
  188. pyprettyvba-0.1.0/tests/fixtures/rules/comment-space/basic/check.txt +2 -0
  189. pyprettyvba-0.1.0/tests/fixtures/rules/comment-space/basic/input.bas +8 -0
  190. pyprettyvba-0.1.0/tests/fixtures/rules/comment-space/basic/output.bas +8 -0
  191. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/closing-paren-indent/case.toml +12 -0
  192. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/closing-paren-indent/check.txt +1 -0
  193. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/closing-paren-indent/input.bas +4 -0
  194. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/closing-paren-indent/output.bas +4 -0
  195. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/hanging/case.toml +13 -0
  196. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/hanging/check.txt +2 -0
  197. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/hanging/input.bas +5 -0
  198. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/hanging/output.bas +5 -0
  199. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/relative/case.toml +15 -0
  200. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/relative/check.txt +9 -0
  201. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/relative/input.bas +14 -0
  202. pyprettyvba-0.1.0/tests/fixtures/rules/continuation-indent/relative/output.bas +14 -0
  203. pyprettyvba-0.1.0/tests/fixtures/rules/date-literals/basic/case.toml +13 -0
  204. pyprettyvba-0.1.0/tests/fixtures/rules/date-literals/basic/check.txt +6 -0
  205. pyprettyvba-0.1.0/tests/fixtures/rules/date-literals/basic/input.bas +10 -0
  206. pyprettyvba-0.1.0/tests/fixtures/rules/date-literals/basic/output.bas +10 -0
  207. pyprettyvba-0.1.0/tests/fixtures/rules/end-of-file/final-newline/case.toml +12 -0
  208. pyprettyvba-0.1.0/tests/fixtures/rules/end-of-file/final-newline/check.txt +1 -0
  209. pyprettyvba-0.1.0/tests/fixtures/rules/end-of-file/final-newline/input.bas +2 -0
  210. pyprettyvba-0.1.0/tests/fixtures/rules/end-of-file/final-newline/output.bas +2 -0
  211. pyprettyvba-0.1.0/tests/fixtures/rules/end-of-file/trailing-blank-lines/case.toml +11 -0
  212. pyprettyvba-0.1.0/tests/fixtures/rules/end-of-file/trailing-blank-lines/check.txt +1 -0
  213. pyprettyvba-0.1.0/tests/fixtures/rules/end-of-file/trailing-blank-lines/input.bas +5 -0
  214. pyprettyvba-0.1.0/tests/fixtures/rules/end-of-file/trailing-blank-lines/output.bas +2 -0
  215. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/builtins/case.toml +14 -0
  216. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/builtins/check.txt +17 -0
  217. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/builtins/input.bas +11 -0
  218. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/builtins/output.bas +11 -0
  219. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/declarations/case.toml +14 -0
  220. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/declarations/check.txt +14 -0
  221. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/declarations/input.bas +21 -0
  222. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/declarations/output.bas +21 -0
  223. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/declare/case.toml +13 -0
  224. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/declare/check.txt +3 -0
  225. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/declare/input.bas +10 -0
  226. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/declare/output.bas +10 -0
  227. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/library-names/case.toml +18 -0
  228. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/library-names/check.txt +14 -0
  229. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/library-names/input.bas +9 -0
  230. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/library-names/output.bas +9 -0
  231. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/module-scope/case.toml +16 -0
  232. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/module-scope/check.txt +4 -0
  233. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/module-scope/input.bas +13 -0
  234. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/module-scope/output.bas +13 -0
  235. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/type-members/case.toml +15 -0
  236. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/type-members/check.txt +1 -0
  237. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/type-members/input.bas +10 -0
  238. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/type-members/output.bas +10 -0
  239. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/undeclared-last/case.toml +14 -0
  240. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/undeclared-last/check.txt +4 -0
  241. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/undeclared-last/input.bas +8 -0
  242. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/undeclared-last/output.bas +8 -0
  243. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/word-host/case.toml +13 -0
  244. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/word-host/check.txt +4 -0
  245. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/word-host/input.bas +6 -0
  246. pyprettyvba-0.1.0/tests/fixtures/rules/identifier-case/word-host/output.bas +6 -0
  247. pyprettyvba-0.1.0/tests/fixtures/rules/indent/basic/case.toml +13 -0
  248. pyprettyvba-0.1.0/tests/fixtures/rules/indent/basic/check.txt +26 -0
  249. pyprettyvba-0.1.0/tests/fixtures/rules/indent/basic/input.bas +33 -0
  250. pyprettyvba-0.1.0/tests/fixtures/rules/indent/basic/output.bas +33 -0
  251. pyprettyvba-0.1.0/tests/fixtures/rules/indent/broken-structure/case.toml +14 -0
  252. pyprettyvba-0.1.0/tests/fixtures/rules/indent/broken-structure/check.txt +2 -0
  253. pyprettyvba-0.1.0/tests/fixtures/rules/indent/broken-structure/input.bas +9 -0
  254. pyprettyvba-0.1.0/tests/fixtures/rules/indent/broken-structure/output.bas +9 -0
  255. pyprettyvba-0.1.0/tests/fixtures/rules/indent/case-flat/case.toml +12 -0
  256. pyprettyvba-0.1.0/tests/fixtures/rules/indent/case-flat/check.txt +26 -0
  257. pyprettyvba-0.1.0/tests/fixtures/rules/indent/case-flat/input.bas +33 -0
  258. pyprettyvba-0.1.0/tests/fixtures/rules/indent/case-flat/output.bas +33 -0
  259. pyprettyvba-0.1.0/tests/fixtures/rules/indent/comments-next/case.toml +13 -0
  260. pyprettyvba-0.1.0/tests/fixtures/rules/indent/comments-next/check.txt +6 -0
  261. pyprettyvba-0.1.0/tests/fixtures/rules/indent/comments-next/input.bas +8 -0
  262. pyprettyvba-0.1.0/tests/fixtures/rules/indent/comments-next/output.bas +8 -0
  263. pyprettyvba-0.1.0/tests/fixtures/rules/indent/debug-column-zero/case.toml +12 -0
  264. pyprettyvba-0.1.0/tests/fixtures/rules/indent/debug-column-zero/check.txt +2 -0
  265. pyprettyvba-0.1.0/tests/fixtures/rules/indent/debug-column-zero/input.bas +5 -0
  266. pyprettyvba-0.1.0/tests/fixtures/rules/indent/debug-column-zero/output.bas +5 -0
  267. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives/case.toml +15 -0
  268. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives/check.txt +8 -0
  269. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives/input.bas +18 -0
  270. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives/output.bas +18 -0
  271. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives-column-zero/case.toml +12 -0
  272. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives-column-zero/check.txt +4 -0
  273. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives-column-zero/input.bas +18 -0
  274. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives-column-zero/output.bas +18 -0
  275. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives-flat/case.toml +12 -0
  276. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives-flat/check.txt +6 -0
  277. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives-flat/input.bas +18 -0
  278. pyprettyvba-0.1.0/tests/fixtures/rules/indent/directives-flat/output.bas +18 -0
  279. pyprettyvba-0.1.0/tests/fixtures/rules/indent/keep/case.toml +14 -0
  280. pyprettyvba-0.1.0/tests/fixtures/rules/indent/keep/check.txt +3 -0
  281. pyprettyvba-0.1.0/tests/fixtures/rules/indent/keep/input.bas +6 -0
  282. pyprettyvba-0.1.0/tests/fixtures/rules/indent/keep/output.bas +6 -0
  283. pyprettyvba-0.1.0/tests/fixtures/rules/indent/labels/case.toml +13 -0
  284. pyprettyvba-0.1.0/tests/fixtures/rules/indent/labels/check.txt +9 -0
  285. pyprettyvba-0.1.0/tests/fixtures/rules/indent/labels/input.bas +11 -0
  286. pyprettyvba-0.1.0/tests/fixtures/rules/indent/labels/output.bas +11 -0
  287. pyprettyvba-0.1.0/tests/fixtures/rules/indent/procedure-body-flat/case.toml +12 -0
  288. pyprettyvba-0.1.0/tests/fixtures/rules/indent/procedure-body-flat/check.txt +20 -0
  289. pyprettyvba-0.1.0/tests/fixtures/rules/indent/procedure-body-flat/input.bas +33 -0
  290. pyprettyvba-0.1.0/tests/fixtures/rules/indent/procedure-body-flat/output.bas +33 -0
  291. pyprettyvba-0.1.0/tests/fixtures/rules/indent/tabs/case.toml +12 -0
  292. pyprettyvba-0.1.0/tests/fixtures/rules/indent/tabs/check.txt +26 -0
  293. pyprettyvba-0.1.0/tests/fixtures/rules/indent/tabs/input.bas +33 -0
  294. pyprettyvba-0.1.0/tests/fixtures/rules/indent/tabs/output.bas +33 -0
  295. pyprettyvba-0.1.0/tests/fixtures/rules/indent/width-two/case.toml +12 -0
  296. pyprettyvba-0.1.0/tests/fixtures/rules/indent/width-two/check.txt +26 -0
  297. pyprettyvba-0.1.0/tests/fixtures/rules/indent/width-two/input.bas +33 -0
  298. pyprettyvba-0.1.0/tests/fixtures/rules/indent/width-two/output.bas +33 -0
  299. pyprettyvba-0.1.0/tests/fixtures/rules/keyword-case/basic/case.toml +16 -0
  300. pyprettyvba-0.1.0/tests/fixtures/rules/keyword-case/basic/check.txt +51 -0
  301. pyprettyvba-0.1.0/tests/fixtures/rules/keyword-case/basic/input.bas +22 -0
  302. pyprettyvba-0.1.0/tests/fixtures/rules/keyword-case/basic/output.bas +22 -0
  303. pyprettyvba-0.1.0/tests/fixtures/rules/keyword-case/keep-endif/case.toml +12 -0
  304. pyprettyvba-0.1.0/tests/fixtures/rules/keyword-case/keep-endif/check.txt +6 -0
  305. pyprettyvba-0.1.0/tests/fixtures/rules/keyword-case/keep-endif/input.bas +5 -0
  306. pyprettyvba-0.1.0/tests/fixtures/rules/keyword-case/keep-endif/output.bas +5 -0
  307. pyprettyvba-0.1.0/tests/fixtures/rules/let-keyword/basic/case.toml +12 -0
  308. pyprettyvba-0.1.0/tests/fixtures/rules/let-keyword/basic/check.txt +1 -0
  309. pyprettyvba-0.1.0/tests/fixtures/rules/let-keyword/basic/input.bas +3 -0
  310. pyprettyvba-0.1.0/tests/fixtures/rules/let-keyword/basic/output.bas +3 -0
  311. pyprettyvba-0.1.0/tests/fixtures/rules/line-endings/crlf/case.toml +14 -0
  312. pyprettyvba-0.1.0/tests/fixtures/rules/line-endings/crlf/check.txt +1 -0
  313. pyprettyvba-0.1.0/tests/fixtures/rules/line-endings/crlf/input.bas +4 -0
  314. pyprettyvba-0.1.0/tests/fixtures/rules/line-endings/crlf/output.bas +4 -0
  315. pyprettyvba-0.1.0/tests/fixtures/rules/line-endings/mixed/case.toml +12 -0
  316. pyprettyvba-0.1.0/tests/fixtures/rules/line-endings/mixed/check.txt +1 -0
  317. pyprettyvba-0.1.0/tests/fixtures/rules/line-endings/mixed/input.bas +5 -0
  318. pyprettyvba-0.1.0/tests/fixtures/rules/line-endings/mixed/output.bas +5 -0
  319. pyprettyvba-0.1.0/tests/fixtures/rules/max-line-length/basic/case.toml +12 -0
  320. pyprettyvba-0.1.0/tests/fixtures/rules/max-line-length/basic/check.txt +1 -0
  321. pyprettyvba-0.1.0/tests/fixtures/rules/max-line-length/basic/input.bas +3 -0
  322. pyprettyvba-0.1.0/tests/fixtures/rules/numeric-literals/basic/case.toml +16 -0
  323. pyprettyvba-0.1.0/tests/fixtures/rules/numeric-literals/basic/check.txt +16 -0
  324. pyprettyvba-0.1.0/tests/fixtures/rules/numeric-literals/basic/input.bas +19 -0
  325. pyprettyvba-0.1.0/tests/fixtures/rules/numeric-literals/basic/output.bas +19 -0
  326. pyprettyvba-0.1.0/tests/fixtures/rules/numeric-literals/quiet/case.toml +12 -0
  327. pyprettyvba-0.1.0/tests/fixtures/rules/numeric-literals/quiet/check.txt +1 -0
  328. pyprettyvba-0.1.0/tests/fixtures/rules/numeric-literals/quiet/input.bas +5 -0
  329. pyprettyvba-0.1.0/tests/fixtures/rules/numeric-literals/quiet/output.bas +5 -0
  330. pyprettyvba-0.1.0/tests/fixtures/rules/rem-comments/basic/case.toml +11 -0
  331. pyprettyvba-0.1.0/tests/fixtures/rules/rem-comments/basic/check.txt +2 -0
  332. pyprettyvba-0.1.0/tests/fixtures/rules/rem-comments/basic/input.bas +4 -0
  333. pyprettyvba-0.1.0/tests/fixtures/rules/rem-comments/basic/output.bas +4 -0
  334. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/basic/case.toml +15 -0
  335. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/basic/check.txt +41 -0
  336. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/basic/input.bas +19 -0
  337. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/basic/output.bas +19 -0
  338. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/columns/case.toml +14 -0
  339. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/columns/check.txt +7 -0
  340. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/columns/input.bas +10 -0
  341. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/columns/output.bas +10 -0
  342. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/insert-only/case.toml +12 -0
  343. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/insert-only/check.txt +4 -0
  344. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/insert-only/input.bas +5 -0
  345. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/insert-only/output.bas +5 -0
  346. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/protected/case.toml +15 -0
  347. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/protected/check.txt +2 -0
  348. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/protected/input.bas +9 -0
  349. pyprettyvba-0.1.0/tests/fixtures/rules/spacing/protected/output.bas +9 -0
  350. pyprettyvba-0.1.0/tests/fixtures/rules/split-statements/basic/case.toml +14 -0
  351. pyprettyvba-0.1.0/tests/fixtures/rules/split-statements/basic/check.txt +7 -0
  352. pyprettyvba-0.1.0/tests/fixtures/rules/split-statements/basic/input.bas +9 -0
  353. pyprettyvba-0.1.0/tests/fixtures/rules/split-statements/basic/output.bas +14 -0
  354. pyprettyvba-0.1.0/tests/fixtures/rules/split-statements/keep-case/case.toml +11 -0
  355. pyprettyvba-0.1.0/tests/fixtures/rules/split-statements/keep-case/check.txt +0 -0
  356. pyprettyvba-0.1.0/tests/fixtures/rules/split-statements/keep-case/input.bas +6 -0
  357. pyprettyvba-0.1.0/tests/fixtures/rules/statement-form/basic/case.toml +12 -0
  358. pyprettyvba-0.1.0/tests/fixtures/rules/statement-form/basic/check.txt +2 -0
  359. pyprettyvba-0.1.0/tests/fixtures/rules/statement-form/basic/input.bas +7 -0
  360. pyprettyvba-0.1.0/tests/fixtures/rules/statement-form/basic/output.bas +7 -0
  361. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/align/case.toml +12 -0
  362. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/align/check.txt +2 -0
  363. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/align/input.bas +7 -0
  364. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/align/output.bas +7 -0
  365. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/keep-column/case.toml +15 -0
  366. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/keep-column/check.txt +4 -0
  367. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/keep-column/input.bas +5 -0
  368. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/keep-column/output.bas +5 -0
  369. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/one-space/case.toml +12 -0
  370. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/one-space/check.txt +2 -0
  371. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/one-space/input.bas +4 -0
  372. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-comments/one-space/output.bas +4 -0
  373. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-whitespace/basic/case.toml +13 -0
  374. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-whitespace/basic/check.txt +5 -0
  375. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-whitespace/basic/input.bas +7 -0
  376. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-whitespace/basic/output.bas +7 -0
  377. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-whitespace/blank-indent/case.toml +13 -0
  378. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-whitespace/blank-indent/check.txt +2 -0
  379. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-whitespace/blank-indent/input.bas +8 -0
  380. pyprettyvba-0.1.0/tests/fixtures/rules/trailing-whitespace/blank-indent/output.bas +8 -0
  381. pyprettyvba-0.1.0/tests/fixtures/safety/broken-structure/case.toml +6 -0
  382. pyprettyvba-0.1.0/tests/fixtures/safety/broken-structure/check.txt +1 -0
  383. pyprettyvba-0.1.0/tests/fixtures/safety/broken-structure/input.bas +6 -0
  384. pyprettyvba-0.1.0/tests/fixtures/safety/comment-continuation/case.toml +8 -0
  385. pyprettyvba-0.1.0/tests/fixtures/safety/comment-continuation/check.txt +2 -0
  386. pyprettyvba-0.1.0/tests/fixtures/safety/comment-continuation/input.bas +5 -0
  387. pyprettyvba-0.1.0/tests/fixtures/safety/comment-continuation/output.bas +5 -0
  388. pyprettyvba-0.1.0/tests/fixtures/safety/continuation-trailing-space/case.toml +7 -0
  389. pyprettyvba-0.1.0/tests/fixtures/safety/continuation-trailing-space/check.txt +3 -0
  390. pyprettyvba-0.1.0/tests/fixtures/safety/continuation-trailing-space/input.bas +4 -0
  391. pyprettyvba-0.1.0/tests/fixtures/safety/continuation-trailing-space/output.bas +4 -0
  392. pyprettyvba-0.1.0/tests/fixtures/safety/declare-entry-point/case.toml +7 -0
  393. pyprettyvba-0.1.0/tests/fixtures/safety/declare-entry-point/check.txt +1 -0
  394. pyprettyvba-0.1.0/tests/fixtures/safety/declare-entry-point/input.bas +5 -0
  395. pyprettyvba-0.1.0/tests/fixtures/safety/declare-entry-point/output.bas +5 -0
  396. pyprettyvba-0.1.0/tests/fixtures/safety/glue/case.toml +7 -0
  397. pyprettyvba-0.1.0/tests/fixtures/safety/glue/check.txt +5 -0
  398. pyprettyvba-0.1.0/tests/fixtures/safety/glue/input.bas +7 -0
  399. pyprettyvba-0.1.0/tests/fixtures/safety/glue/output.bas +7 -0
  400. pyprettyvba-0.1.0/tests/fixtures/safety/precision/case.toml +7 -0
  401. pyprettyvba-0.1.0/tests/fixtures/safety/precision/check.txt +2 -0
  402. pyprettyvba-0.1.0/tests/fixtures/safety/precision/input.bas +3 -0
  403. pyprettyvba-0.1.0/tests/fixtures/safety/precision/output.bas +3 -0
  404. pyprettyvba-0.1.0/tests/fixtures/safety/single-line-if/case.toml +12 -0
  405. pyprettyvba-0.1.0/tests/fixtures/safety/single-line-if/check.txt +8 -0
  406. pyprettyvba-0.1.0/tests/fixtures/safety/single-line-if/input.bas +4 -0
  407. pyprettyvba-0.1.0/tests/fixtures/safety/single-line-if/output.bas +5 -0
  408. pyprettyvba-0.1.0/tests/fixtures/showcase/before-and-after/case.toml +6 -0
  409. pyprettyvba-0.1.0/tests/fixtures/showcase/before-and-after/check.txt +94 -0
  410. pyprettyvba-0.1.0/tests/fixtures/showcase/before-and-after/input.bas +20 -0
  411. pyprettyvba-0.1.0/tests/fixtures/showcase/before-and-after/output.bas +21 -0
  412. pyprettyvba-0.1.0/tests/fixtures/suppression/file/case.toml +6 -0
  413. pyprettyvba-0.1.0/tests/fixtures/suppression/file/check.txt +3 -0
  414. pyprettyvba-0.1.0/tests/fixtures/suppression/file/input.bas +4 -0
  415. pyprettyvba-0.1.0/tests/fixtures/suppression/file/output.bas +4 -0
  416. pyprettyvba-0.1.0/tests/fixtures/suppression/invalid/case.toml +8 -0
  417. pyprettyvba-0.1.0/tests/fixtures/suppression/invalid/check.txt +9 -0
  418. pyprettyvba-0.1.0/tests/fixtures/suppression/invalid/input.bas +8 -0
  419. pyprettyvba-0.1.0/tests/fixtures/suppression/invalid/output.bas +8 -0
  420. pyprettyvba-0.1.0/tests/fixtures/suppression/line/case.toml +6 -0
  421. pyprettyvba-0.1.0/tests/fixtures/suppression/line/check.txt +3 -0
  422. pyprettyvba-0.1.0/tests/fixtures/suppression/line/input.bas +4 -0
  423. pyprettyvba-0.1.0/tests/fixtures/suppression/line/output.bas +4 -0
  424. pyprettyvba-0.1.0/tests/fixtures/suppression/next-line/case.toml +7 -0
  425. pyprettyvba-0.1.0/tests/fixtures/suppression/next-line/check.txt +2 -0
  426. pyprettyvba-0.1.0/tests/fixtures/suppression/next-line/input.bas +8 -0
  427. pyprettyvba-0.1.0/tests/fixtures/suppression/next-line/output.bas +8 -0
  428. pyprettyvba-0.1.0/tests/fixtures/suppression/region/case.toml +7 -0
  429. pyprettyvba-0.1.0/tests/fixtures/suppression/region/check.txt +9 -0
  430. pyprettyvba-0.1.0/tests/fixtures/suppression/region/input.bas +9 -0
  431. pyprettyvba-0.1.0/tests/fixtures/suppression/region/output.bas +9 -0
  432. pyprettyvba-0.1.0/tests/fixtures/suppression/rules/case.toml +6 -0
  433. pyprettyvba-0.1.0/tests/fixtures/suppression/rules/check.txt +1 -0
  434. pyprettyvba-0.1.0/tests/fixtures/suppression/rules/input.bas +3 -0
  435. pyprettyvba-0.1.0/tests/fixtures/suppression/rules/output.bas +3 -0
  436. pyprettyvba-0.1.0/tests/oracle/vbe_rendering.json +3874 -0
  437. pyprettyvba-0.1.0/tests/test_config.py +127 -0
  438. pyprettyvba-0.1.0/tests/test_corpus.py +88 -0
  439. pyprettyvba-0.1.0/tests/test_docs.py +17 -0
  440. pyprettyvba-0.1.0/tests/test_document.py +116 -0
  441. pyprettyvba-0.1.0/tests/test_engine.py +86 -0
  442. pyprettyvba-0.1.0/tests/test_fixtures.py +59 -0
  443. pyprettyvba-0.1.0/tests/test_lexer.py +139 -0
  444. pyprettyvba-0.1.0/tests/test_literals.py +105 -0
  445. pyprettyvba-0.1.0/tests/test_live.py +178 -0
  446. pyprettyvba-0.1.0/tests/test_office.py +344 -0
  447. pyprettyvba-0.1.0/tests/test_oracle.py +181 -0
  448. pyprettyvba-0.1.0/tests/test_packaging.py +44 -0
  449. pyprettyvba-0.1.0/tests/test_properties.py +77 -0
  450. pyprettyvba-0.1.0/tests/test_safety.py +70 -0
  451. pyprettyvba-0.1.0/tests/test_structure.py +80 -0
  452. pyprettyvba-0.1.0/tests/test_suppression.py +89 -0
  453. pyprettyvba-0.1.0/tests/vba_strategies.py +491 -0
  454. pyprettyvba-0.1.0/tools/build_docs.py +125 -0
  455. pyprettyvba-0.1.0/tools/build_gallery.py +837 -0
  456. pyprettyvba-0.1.0/tools/build_names.py +192 -0
  457. pyprettyvba-0.1.0/tools/fixtures.py +46 -0
  458. pyprettyvba-0.1.0/tools/vbe_oracle.py +889 -0
  459. pyprettyvba-0.1.0/tools/xlide_differential.py +134 -0
  460. pyprettyvba-0.1.0/tools/xlide_format.mjs +22 -0
@@ -0,0 +1,4 @@
1
+ * text=auto
2
+ # Fixtures and oracle evidence are byte-exact: never convert their line endings.
3
+ tests/fixtures/** -text
4
+ tests/oracle/** -text
@@ -0,0 +1,57 @@
1
+ name: CI
2
+
3
+ # Lint, type-check and test on every push to main and every pull request.
4
+
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ pull_request:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ # A new push to the same branch or pull request cancels the run in progress.
14
+ concurrency:
15
+ group: ci-${{ github.ref }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+ lint:
20
+ name: Lint and type check
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v7
24
+ - uses: actions/setup-python@v7
25
+ with:
26
+ python-version: "3.12"
27
+ cache: pip
28
+ cache-dependency-path: pyproject.toml
29
+ - run: python -m pip install -e ".[dev]"
30
+ - name: Ruff
31
+ run: python -m ruff check src tests tools
32
+ - name: Mypy
33
+ run: python -m mypy
34
+
35
+ test:
36
+ name: Test (Python ${{ matrix.python-version }}, ${{ matrix.os }})
37
+ runs-on: ${{ matrix.os }}
38
+ strategy:
39
+ fail-fast: false
40
+ matrix:
41
+ os: [ubuntu-latest]
42
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
43
+ include:
44
+ # Reading and writing module files depends on the platform's code
45
+ # page, so the whole suite runs on Windows too.
46
+ - os: windows-latest
47
+ python-version: "3.12"
48
+ steps:
49
+ - uses: actions/checkout@v7
50
+ - uses: actions/setup-python@v7
51
+ with:
52
+ python-version: ${{ matrix.python-version }}
53
+ cache: pip
54
+ cache-dependency-path: pyproject.toml
55
+ - run: python -m pip install -e ".[dev]"
56
+ - name: Pytest
57
+ run: python -m pytest -q
@@ -0,0 +1,113 @@
1
+ name: Publish to PyPI
2
+
3
+ # A pushed tag vX.Y.Z builds, checks and publishes that version to PyPI
4
+ # through Trusted Publishing (no token is stored), then makes the GitHub
5
+ # release from the changelog.
6
+
7
+ on:
8
+ push:
9
+ tags:
10
+ - "v*.*.*"
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ jobs:
17
+ build:
18
+ name: Build distributions
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
+
23
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
24
+ with:
25
+ python-version: "3.12"
26
+
27
+ - name: Verify tag matches package version
28
+ if: github.ref_type == 'tag'
29
+ run: |
30
+ TAG="${GITHUB_REF_NAME#v}"
31
+ PKG=$(sed -n 's/^__version__ = "\(.*\)"$/\1/p' src/pyprettyvba/__init__.py)
32
+ if [ "$TAG" != "$PKG" ]; then
33
+ echo "ERROR: tag '$TAG' does not match __version__ '$PKG'"
34
+ exit 1
35
+ fi
36
+ echo "Version check passed: $PKG"
37
+
38
+ - name: Test
39
+ run: |
40
+ python -m pip install -e ".[dev]"
41
+ python -m pytest -q
42
+
43
+ - name: Build sdist and wheel
44
+ run: |
45
+ python -m pip install --upgrade build twine
46
+ python -m build
47
+
48
+ - name: Validate metadata
49
+ run: python -m twine check dist/*
50
+
51
+ - name: Upload artifact
52
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
53
+ with:
54
+ name: dist
55
+ path: dist/
56
+ if-no-files-found: error
57
+
58
+ publish:
59
+ name: Publish to PyPI
60
+ needs: build
61
+ if: github.ref_type == 'tag'
62
+ runs-on: ubuntu-latest
63
+ environment:
64
+ name: pypi
65
+ url: https://pypi.org/project/pyprettyvba/
66
+ permissions:
67
+ # Required for PyPI Trusted Publishing (OIDC).
68
+ id-token: write
69
+ steps:
70
+ - name: Download artifact
71
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
72
+ with:
73
+ name: dist
74
+ path: dist/
75
+
76
+ - name: Publish to PyPI
77
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
78
+
79
+ github-release:
80
+ name: Create GitHub Release
81
+ needs: publish
82
+ runs-on: ubuntu-latest
83
+ permissions:
84
+ contents: write
85
+ steps:
86
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
87
+
88
+ - name: Download artifact
89
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
90
+ with:
91
+ name: dist
92
+ path: dist/
93
+
94
+ - name: Extract changelog section for this tag
95
+ run: |
96
+ TAG="${GITHUB_REF_NAME#v}"
97
+ awk -v ver="$TAG" '
98
+ index($0, "## " ver) == 1 { capture=1; next }
99
+ capture && /^## / { exit }
100
+ capture { print }
101
+ ' CHANGELOG.md > release_notes.md
102
+ if [ ! -s release_notes.md ]; then
103
+ echo "Release $TAG" > release_notes.md
104
+ fi
105
+
106
+ - name: Create GitHub Release
107
+ uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
108
+ with:
109
+ name: ${{ github.ref_name }}
110
+ tag_name: ${{ github.ref_name }}
111
+ body_path: release_notes.md
112
+ files: dist/*
113
+ fail_on_unmatched_files: true
@@ -0,0 +1,15 @@
1
+ # Generated by tools (the XLIDE bundle, the fixture gallery).
2
+ artifacts/
3
+
4
+ # Python and its tools.
5
+ __pycache__/
6
+ *.py[cod]
7
+ *.egg-info/
8
+ build/
9
+ dist/
10
+ .venv/
11
+ venv/
12
+ .pytest_cache/
13
+ .mypy_cache/
14
+ .ruff_cache/
15
+ .hypothesis/
@@ -0,0 +1,22 @@
1
+ # Hooks for https://pre-commit.com. In a project's .pre-commit-config.yaml:
2
+ #
3
+ # - repo: https://github.com/WilliamSmithEdward/pyPrettyVBA
4
+ # rev: v0.1.0
5
+ # hooks:
6
+ # - id: pyprettyvba-format
7
+
8
+ - id: pyprettyvba-format
9
+ name: pyprettyvba format
10
+ description: Format VBA modules in place.
11
+ entry: pyprettyvba format
12
+ language: python
13
+ files: \.(bas|cls|frm|doccls)$
14
+ require_serial: true
15
+
16
+ - id: pyprettyvba-check
17
+ name: pyprettyvba check
18
+ description: Report what pyPrettyVBA would change in VBA modules, without changing them.
19
+ entry: pyprettyvba check
20
+ language: python
21
+ files: \.(bas|cls|frm|doccls)$
22
+ require_serial: true
@@ -0,0 +1,34 @@
1
+ # Notes for coding agents
2
+
3
+ pyPrettyVBA is a VBA formatter: a pipeline of named rules over a lossless
4
+ token model, with a check that refuses output which runs differently from
5
+ the input. Read `docs/architecture.md` first.
6
+
7
+ ## Commands
8
+
9
+ ```bash
10
+ pip install -e .[dev]
11
+ ruff check src tests tools
12
+ mypy
13
+ python -m pytest # fast; no Office needed
14
+ python tools/fixtures.py bless [PREFIX] # rewrite expected fixture files
15
+ python tools/build_docs.py # regenerate docs/rules.md
16
+ ```
17
+
18
+ ## Rules of the road
19
+
20
+ - Formatting must never change what code does. Do not loosen
21
+ `safety.first_difference` to make a test pass; a `SafetyError` means a
22
+ rule is wrong.
23
+ - Every rule claim about what the VBE does needs evidence in
24
+ `tests/oracle/vbe_rendering.json`. Recording it needs Windows, Excel and
25
+ pyVBAharness (`tools/vbe_oracle.py record`); say so rather than guessing.
26
+ - Bless fixtures only after reading the diff of the expected files, and
27
+ explain every changed output.
28
+ - A rule's docstring is its user documentation (`docs/rules.md` is built
29
+ from it, and `tests/test_docs.py` fails when it is stale).
30
+ - The package imports the standard library and pyOpenVBA, nothing else
31
+ (`tests/test_packaging.py` checks). Other third-party packages are for
32
+ development only.
33
+ - Keep text in files plain ASCII, apart from test data that is about
34
+ non-ASCII text.
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-09-29)
4
+
5
+ The first version.
6
+
7
+ - Twenty rules: keyword and identifier casing, spacing, numeric and date
8
+ literals, statement forms, statement splitting, indentation, continuation
9
+ lines, declaration alignment, end-of-line comments, comment style, blank
10
+ lines, trailing whitespace, end of file, line endings, line length, and
11
+ directive checking. Each can be enabled, disabled and configured.
12
+ - Presets: `default`, `vbe` (only what the VBE does), `xlide` (XLIDE's
13
+ Format Document), `strict`, `minimal` and `none`.
14
+ - Suppression with `'@prettyvba-ignore` comments, for a line, the next line,
15
+ a region or a module, per rule.
16
+ - Configuration in `pyprettyvba.toml` or `pyproject.toml`, with per-file
17
+ overrides and `extend`.
18
+ - A command line (`format`, `check`, `rules`, `config`, `init`) with text,
19
+ grouped, JSON and GitHub output, and a Python API.
20
+ - Projects formatted together share their modules' spellings.
21
+ - The VBA inside Excel, Word, PowerPoint and Access files, checked and
22
+ formatted in place through pyOpenVBA.
23
+ - A digitally signed VBA project is left alone unless `--remove-signatures`
24
+ is given; then it is formatted and its signature removed.
25
+ - A safety check that refuses output which runs differently from the input.
26
+ - Rule behavior measured against Excel's VBE and replayed by the tests.
27
+ - Python 3.11 or later, and one dependency: pyOpenVBA, which is pure Python
28
+ with no dependencies of its own.
@@ -0,0 +1,86 @@
1
+ # Contributing
2
+
3
+ ## Set up
4
+
5
+ ```bash
6
+ python -m venv .venv
7
+ .venv/Scripts/activate # Windows; source .venv/bin/activate elsewhere
8
+ pip install -e .[dev] # pytest, hypothesis, ruff, mypy
9
+ pip install -e .[verify] # pyVBAanalysis, and pyVBAharness on Windows
10
+ ```
11
+
12
+ ## Check
13
+
14
+ ```bash
15
+ ruff check src tests tools
16
+ mypy # strict, on src/pyprettyvba
17
+ python -m pytest # everything that needs no Office
18
+ ```
19
+
20
+ The suite runs in a few seconds. Longer and heavier runs:
21
+
22
+ ```bash
23
+ HYPOTHESIS_PROFILE=thorough python -m pytest tests/test_properties.py
24
+ PYPRETTYVBA_CORPUS=path/to/modules python -m pytest -m corpus
25
+ python -m pytest -m live # Windows, desktop Excel, pyVBAharness
26
+ ```
27
+
28
+ The property tests generate random token soup for every preset, and whole
29
+ modules scrambled in every way the default preset repairs; `thorough` runs
30
+ 3000 examples of each. The corpus tests format every module under the given
31
+ directories with every preset and compare pyVBAanalysis's diagnostics before
32
+ and after. The live tests import the `vbe` preset's output into a real VBE
33
+ and compile fixtures before and after formatting.
34
+
35
+ ## Fixtures
36
+
37
+ Each directory under `tests/fixtures/` with a `case.toml` is a case: an
38
+ input, a configuration, and the expected output and report (the layout is
39
+ described in `tests/fixture_support.py`). To add one, write `case.toml` and
40
+ the input, then let the formatter write the expected files and read what it
41
+ wrote:
42
+
43
+ ```bash
44
+ python tools/fixtures.py bless rules/indent/my-case
45
+ git diff tests/fixtures
46
+ ```
47
+
48
+ `bless` with no argument rewrites every case; the diff is the review.
49
+
50
+ ## Adding a rule
51
+
52
+ 1. Write the rule class in the `rules/` module for its area. Its docstring is
53
+ its documentation: say what it changes, what it leaves alone and why,
54
+ and what the VBE does, with the evidence.
55
+ 2. Add it to `RULES` in `rules/__init__.py` at the point in the pipeline
56
+ where it belongs, and to the presets in `config.py` that should run it.
57
+ 3. Add fixture cases under `tests/fixtures/rules/<code>/`: a basic case, and
58
+ one for each option.
59
+ 4. Run `python tools/build_docs.py` to regenerate `docs/rules.md`.
60
+
61
+ A rule must never change what code does. Leave the gaps around an
62
+ `UNKNOWN` token alone; never add or remove the space between a name and a
63
+ glued `&`, `!`, `#`, `^` or `.`; and check what a changed line reads as at
64
+ the start of a line (a label? a line number? a directive?). The engine's
65
+ safety check refuses output that runs differently, and the property tests
66
+ go looking for such output; a `SafetyError` in a test is a bug in the
67
+ rule, never in the check.
68
+
69
+ ## Recording what the VBE does
70
+
71
+ `tools/vbe_oracle.py record` re-records `tests/oracle/vbe_rendering.json`
72
+ from a real Excel. Record on purpose, read the diff, and keep the probe
73
+ names' `zq` prefix: the VBE keeps one spelling per name for a whole
74
+ project, and the prefix keeps probes from changing each other's casing.
75
+ Questions about how names interact go in `ISOLATED_PROBES`, which run in a
76
+ workbook each.
77
+
78
+ ## Other tools
79
+
80
+ - `tools/build_names.py` rebuilds `src/pyprettyvba/data/names.json.gz`, the
81
+ library names identifier-case spells, from pyVBAanalysis's object models.
82
+ - `tools/xlide_differential.py PATH` formats modules with the `xlide`
83
+ preset and with XLIDE's own Format Document, and lists where they differ.
84
+ - `tools/build_gallery.py` renders every fixture case as one
85
+ self-contained page (`artifacts/gallery/index.html`): input beside output
86
+ with the changes marked, the configuration, and the report.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 William Smith Edward
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,245 @@
1
+ Metadata-Version: 2.5
2
+ Name: pyprettyvba
3
+ Version: 0.1.0
4
+ Summary: A configurable formatter for VBA, with autofix and rule suppression
5
+ Project-URL: Homepage, https://github.com/WilliamSmithEdward/pyPrettyVBA
6
+ Project-URL: Repository, https://github.com/WilliamSmithEdward/pyPrettyVBA
7
+ Project-URL: Issues, https://github.com/WilliamSmithEdward/pyPrettyVBA/issues
8
+ Author: William Smith Edward
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: code-style,excel,formatter,linter,office,prettier,vba
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Software Development :: Quality Assurance
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: pyopenvba>=6.0
26
+ Provides-Extra: build
27
+ Requires-Dist: build>=1.2; extra == 'build'
28
+ Requires-Dist: twine>=5; extra == 'build'
29
+ Provides-Extra: dev
30
+ Requires-Dist: hypothesis>=6; extra == 'dev'
31
+ Requires-Dist: mypy==2.3.1; extra == 'dev'
32
+ Requires-Dist: pytest==9.1.1; extra == 'dev'
33
+ Requires-Dist: ruff==0.16.8; extra == 'dev'
34
+ Provides-Extra: verify
35
+ Requires-Dist: pyvbaanalysis>=2.2; extra == 'verify'
36
+ Requires-Dist: pyvbaharness>=1.1; (sys_platform == 'win32') and extra == 'verify'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # pyPrettyVBA
40
+
41
+ A formatter for VBA, in exported modules (`.bas`, `.cls`, `.frm`) or right
42
+ inside Office files (`.xlsm`, `.docm`, `.pptm`, `.accdb` and more). It is
43
+ in the spirit of Prettier but configurable: every change it makes belongs
44
+ to a named rule that can be switched off, tuned, or suppressed for one
45
+ line, a region or a whole module. It spells code the way the VBE spells
46
+ it, lays it out the way you configure, and refuses to return output that
47
+ would run differently from the input.
48
+
49
+ Before:
50
+
51
+ ```vba
52
+ public function RestockList(ws as worksheet) as collection
53
+ dim r as long,qty as long,result as new collection
54
+ on error goto fail
55
+ for r=2 to ws.cells(ws.rows.count,1).end(xlup).row
56
+ qty=ws.cells(r,3).value
57
+ if qty<low_stock then
58
+ result.add ws.cells(r,1).value
59
+ elseif qty=0 then result.add ws.cells(r,1).value & " (out)"
60
+ end if
61
+ next r
62
+ ```
63
+
64
+ After `pyprettyvba format`:
65
+
66
+ ```vba
67
+ Public Function RestockList(ws As Worksheet) As Collection
68
+ Dim r As Long, qty As Long, result As New Collection
69
+ On Error GoTo fail
70
+ For r = 2 To ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
71
+ qty = ws.Cells(r, 3).Value
72
+ If qty < LOW_STOCK Then
73
+ result.Add ws.Cells(r, 1).Value
74
+ ElseIf qty = 0 Then result.Add ws.Cells(r, 1).Value & " (out)"
75
+ End If
76
+ Next r
77
+ ```
78
+
79
+ The whole module, before and after, is in
80
+ [tests/fixtures/showcase](tests/fixtures/showcase/before-and-after/).
81
+
82
+ ## Install
83
+
84
+ pyPrettyVBA needs Python 3.11 or later. Its one dependency is
85
+ [pyOpenVBA](https://github.com/WilliamSmithEdward/pyOpenVBA), which reads
86
+ and writes the VBA inside Office files and is pure Python with no
87
+ dependencies of its own.
88
+
89
+ ```bash
90
+ pip install pyprettyvba
91
+ ```
92
+
93
+ ## Use
94
+
95
+ ```bash
96
+ pyprettyvba format src/ # format every module under src/ in place
97
+ pyprettyvba format --check src/ # exit 1 if anything would change
98
+ pyprettyvba format --diff src/ # show the changes, write nothing
99
+ pyprettyvba check src/ # list what each rule found, by line
100
+ pyprettyvba check --fix src/ # fix what can be fixed, list the rest
101
+ pyprettyvba rules # every rule, on or off, fixable or not
102
+ pyprettyvba rules indent # one rule's options
103
+ pyprettyvba config src/Module1.bas # the settings that apply to a file
104
+ pyprettyvba init # write a starter pyprettyvba.toml
105
+ ```
106
+
107
+ `check` prints one violation per line, `file:line:column: rule message`, with
108
+ `[*]` on the ones formatting fixes. `--output-format` also offers `grouped`,
109
+ `json` and `github` (workflow annotations), and `--statistics` counts them by
110
+ rule. A path of `-` reads standard input. Exit codes: 0 clean, 1 findings or
111
+ changes, 2 an error.
112
+
113
+ From Python:
114
+
115
+ ```python
116
+ from pyprettyvba import Config, format_source
117
+
118
+ result = format_source(source_text, Config({"preset": "vbe"}))
119
+ result.output # the formatted text
120
+ result.violations # what each rule found, with line and column in the input
121
+ ```
122
+
123
+ `format_file` and `format_paths` read and write files; `project_names`
124
+ gathers what a project's modules declare, so that a name declared in one
125
+ module is spelled the same way in the others.
126
+
127
+ ## Office files
128
+
129
+ The VBA inside a workbook, document, presentation or database is checked
130
+ and formatted in place, with no Office installed:
131
+
132
+ ```bash
133
+ pyprettyvba check Book1.xlsm # Book1.xlsm:Module1:12:5: spacing ...
134
+ pyprettyvba format --diff Book1.xlsm
135
+ pyprettyvba format Book1.xlsm
136
+ ```
137
+
138
+ Excel (`.xlsm`, `.xlsb`, `.xlam`, `.xls`), Word (`.docm`, `.dotm`,
139
+ `.doc`), PowerPoint (`.pptm`, `.potm`, `.ppt`) and Access (`.accdb`,
140
+ `.mdb`) files are read and written through pyOpenVBA. The modules of a
141
+ file are one project, as they are in the VBE, so a name one of them
142
+ declares is spelled its way in the others. The file is saved beside the
143
+ original and then moved over it, so an interrupted save changes nothing.
144
+ A project with a digital signature is left unwritten, since any edit
145
+ would invalidate the signature. `--remove-signatures`
146
+ (`remove_signatures=True` from Python) writes it anyway and removes the
147
+ signature, for you to sign the project again in the VBE. The signature is
148
+ found in the zip-based files; in an `.xls`, `.doc`, `.ppt` or Access file
149
+ it is not recognized, and formatting leaves it out of date. A
150
+ password-protected project is written, and keeps its password and its
151
+ lock.
152
+
153
+ Office files are formatted when named on the command line. Formatting a
154
+ directory takes module files only, unless an `include` pattern names
155
+ Office files too (see [configuration](docs/configuration.md)).
156
+
157
+ From Python, `format_office_file("Book1.xlsm", write=True)` returns one
158
+ result per module.
159
+
160
+ ## Presets
161
+
162
+ | Preset | What it does |
163
+ | --- | --- |
164
+ | `default` | What the VBE does to each line (casing, spacing, literal spelling), plus indentation, blank lines and line endings. |
165
+ | `vbe` | Only what the VBE itself does to code it reads in, so the VBE has nothing left to change (the exceptions are listed in [docs/vbe-evidence.md](docs/vbe-evidence.md)). |
166
+ | `xlide` | What XLIDE's Format Document does: indentation, casing and inserted spaces, never removing a space or a line. |
167
+ | `strict` | The defaults plus every style rule: one statement per line, `'` comments with a space, no `Let`, aligned declarations. |
168
+ | `minimal` | Whitespace only: trailing whitespace, the end of the file, line endings. |
169
+ | `none` | Nothing but checking suppression directives; a base for enabling rules one by one. |
170
+
171
+ ## Rules
172
+
173
+ Twenty rules, each documented with its options in
174
+ [docs/rules.md](docs/rules.md): keyword and identifier casing, spacing,
175
+ numeric and date literal spelling, statement forms, indentation (block
176
+ structure, `Case` arms, `#If` blocks, labels, continuation lines), end-of-line
177
+ comments, blank lines, trailing whitespace, line endings, and a handful of
178
+ optional style rules.
179
+
180
+ ## Configuration
181
+
182
+ A `pyprettyvba.toml` (or a `[tool.pyprettyvba]` table in `pyproject.toml`)
183
+ next to the code, or in any directory above it:
184
+
185
+ ```toml
186
+ preset = "default"
187
+ indent-width = 4
188
+ line-ending = "crlf"
189
+
190
+ [rules]
191
+ blank-lines = { max-consecutive = 1 }
192
+ comment-space = true
193
+ numeric-literals = false
194
+
195
+ [[overrides]]
196
+ files = ["legacy/**"]
197
+ rules = { indent = false }
198
+ ```
199
+
200
+ See [docs/configuration.md](docs/configuration.md) for every key.
201
+
202
+ ## Suppression
203
+
204
+ ```vba
205
+ x = 1 '@prettyvba-ignore: spacing -- aligned on purpose
206
+ '@prettyvba-ignore-next-line: indent
207
+ '@prettyvba-ignore-start
208
+ table(0) = Array("id", "name")
209
+ '@prettyvba-ignore-end
210
+ ```
211
+
212
+ See [docs/suppression.md](docs/suppression.md).
213
+
214
+ ## Safety
215
+
216
+ Whitespace and letter case are not always meaningless in VBA. `s&t` is a
217
+ syntax error where `s & t` concatenates; `Foo .Bar` passes a With member
218
+ where `Foo.Bar` calls one; a comment ending in ` _` swallows the next line;
219
+ a `Declare` without an `Alias` looks its entry point up case-sensitively.
220
+ Before it returns anything, the formatter reduces the input and the output
221
+ to the statements they run and compares them, and it refuses output that
222
+ differs. Property-based tests, a corpus of 336 real modules, and the VBE
223
+ itself (below) check that this never has to happen.
224
+
225
+ ## What the VBE does, measured
226
+
227
+ The rules that claim to do what the VBE does are checked against the VBE:
228
+ probe modules pasted into Excel and exported again, compile checks, run-time
229
+ checks, and whole modules imported from files. The recording is replayed by
230
+ the test suite without Office. See [docs/vbe-evidence.md](docs/vbe-evidence.md).
231
+
232
+ ## Development
233
+
234
+ ```bash
235
+ pip install -e .[dev]
236
+ python -m pytest # unit tests, fixtures, properties, oracle replay
237
+ python -m pytest -m live # against a real VBE (Windows, Excel, pyVBAharness)
238
+ ```
239
+
240
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the fixture workflow, the corpus
241
+ and property tests, and how to add a rule.
242
+
243
+ ## License
244
+
245
+ MIT. See [LICENSE](LICENSE).