topmark 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 (57) hide show
  1. topmark-0.1.0/LICENSE +21 -0
  2. topmark-0.1.0/PKG-INFO +308 -0
  3. topmark-0.1.0/README.md +262 -0
  4. topmark-0.1.0/pyproject.toml +247 -0
  5. topmark-0.1.0/setup.cfg +4 -0
  6. topmark-0.1.0/src/topmark/__init__.py +14 -0
  7. topmark-0.1.0/src/topmark/cli/__init__.py +23 -0
  8. topmark-0.1.0/src/topmark/cli/cli_types.py +299 -0
  9. topmark-0.1.0/src/topmark/cli/commands/__init__.py +11 -0
  10. topmark-0.1.0/src/topmark/cli/commands/default.py +295 -0
  11. topmark-0.1.0/src/topmark/cli/commands/dump_config.py +108 -0
  12. topmark-0.1.0/src/topmark/cli/commands/filetypes.py +39 -0
  13. topmark-0.1.0/src/topmark/cli/commands/init_config.py +60 -0
  14. topmark-0.1.0/src/topmark/cli/commands/show_defaults.py +54 -0
  15. topmark-0.1.0/src/topmark/cli/commands/version.py +32 -0
  16. topmark-0.1.0/src/topmark/cli/config_resolver.py +82 -0
  17. topmark-0.1.0/src/topmark/cli/main.py +464 -0
  18. topmark-0.1.0/src/topmark/cli/options.py +276 -0
  19. topmark-0.1.0/src/topmark/cli/utils.py +245 -0
  20. topmark-0.1.0/src/topmark/config/__init__.py +520 -0
  21. topmark-0.1.0/src/topmark/config/logging.py +148 -0
  22. topmark-0.1.0/src/topmark/constants.py +24 -0
  23. topmark-0.1.0/src/topmark/file_resolver.py +228 -0
  24. topmark-0.1.0/src/topmark/filetypes/__init__.py +16 -0
  25. topmark-0.1.0/src/topmark/filetypes/base.py +81 -0
  26. topmark-0.1.0/src/topmark/filetypes/instances.py +327 -0
  27. topmark-0.1.0/src/topmark/filetypes/policy.py +44 -0
  28. topmark-0.1.0/src/topmark/filetypes/registry.py +79 -0
  29. topmark-0.1.0/src/topmark/pipeline/__init__.py +25 -0
  30. topmark-0.1.0/src/topmark/pipeline/context.py +363 -0
  31. topmark-0.1.0/src/topmark/pipeline/contracts.py +22 -0
  32. topmark-0.1.0/src/topmark/pipeline/pipelines.py +93 -0
  33. topmark-0.1.0/src/topmark/pipeline/processors/__init__.py +96 -0
  34. topmark-0.1.0/src/topmark/pipeline/processors/base.py +754 -0
  35. topmark-0.1.0/src/topmark/pipeline/processors/pound.py +154 -0
  36. topmark-0.1.0/src/topmark/pipeline/processors/xml.py +278 -0
  37. topmark-0.1.0/src/topmark/pipeline/runner.py +49 -0
  38. topmark-0.1.0/src/topmark/pipeline/steps/__init__.py +11 -0
  39. topmark-0.1.0/src/topmark/pipeline/steps/builder.py +135 -0
  40. topmark-0.1.0/src/topmark/pipeline/steps/comparer.py +73 -0
  41. topmark-0.1.0/src/topmark/pipeline/steps/patcher.py +171 -0
  42. topmark-0.1.0/src/topmark/pipeline/steps/reader.py +173 -0
  43. topmark-0.1.0/src/topmark/pipeline/steps/renderer.py +64 -0
  44. topmark-0.1.0/src/topmark/pipeline/steps/resolver.py +103 -0
  45. topmark-0.1.0/src/topmark/pipeline/steps/scanner.py +146 -0
  46. topmark-0.1.0/src/topmark/pipeline/steps/updater.py +128 -0
  47. topmark-0.1.0/src/topmark/py.typed +1 -0
  48. topmark-0.1.0/src/topmark/rendering/api.py +80 -0
  49. topmark-0.1.0/src/topmark/rendering/formats.py +26 -0
  50. topmark-0.1.0/src/topmark/utils/__init__.py +11 -0
  51. topmark-0.1.0/src/topmark/utils/file.py +42 -0
  52. topmark-0.1.0/src/topmark.egg-info/PKG-INFO +308 -0
  53. topmark-0.1.0/src/topmark.egg-info/SOURCES.txt +55 -0
  54. topmark-0.1.0/src/topmark.egg-info/dependency_links.txt +1 -0
  55. topmark-0.1.0/src/topmark.egg-info/entry_points.txt +2 -0
  56. topmark-0.1.0/src/topmark.egg-info/requires.txt +33 -0
  57. topmark-0.1.0/src/topmark.egg-info/top_level.txt +1 -0
topmark-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Olivier Biot
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
13
+ all 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
21
+ THE SOFTWARE.
topmark-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.4
2
+ Name: topmark
3
+ Version: 0.1.0
4
+ Summary: A tool to inspect, validate, and manage file headers in diverse codebases
5
+ Author-email: Olivier Biot <olivier.biot@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/shutterfreak/topmark
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: <3.14,>=3.10
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: pathspec
17
+ Requires-Dist: tomlkit
18
+ Requires-Dist: toml
19
+ Requires-Dist: yachalk
20
+ Requires-Dist: click
21
+ Provides-Extra: dev
22
+ Requires-Dist: ruff; extra == "dev"
23
+ Requires-Dist: pylint; extra == "dev"
24
+ Requires-Dist: mypy; extra == "dev"
25
+ Requires-Dist: pyright; extra == "dev"
26
+ Requires-Dist: mdformat; extra == "dev"
27
+ Requires-Dist: mdformat-tables; extra == "dev"
28
+ Requires-Dist: taplo; extra == "dev"
29
+ Requires-Dist: pip-tools>=7.4; extra == "dev"
30
+ Requires-Dist: pre-commit; extra == "dev"
31
+ Requires-Dist: tox>=4.0; extra == "dev"
32
+ Requires-Dist: build; extra == "dev"
33
+ Requires-Dist: twine; extra == "dev"
34
+ Provides-Extra: docs
35
+ Requires-Dist: mkdocs>=1.6; extra == "docs"
36
+ Requires-Dist: mkdocs-material>=9.5; extra == "docs"
37
+ Requires-Dist: mkdocstrings[python]>=0.25; extra == "docs"
38
+ Requires-Dist: pymdown-extensions>=10.8; extra == "docs"
39
+ Provides-Extra: test
40
+ Requires-Dist: pytest; extra == "test"
41
+ Requires-Dist: pytest-xdist; extra == "test"
42
+ Provides-Extra: typing
43
+ Requires-Dist: mypy; extra == "typing"
44
+ Requires-Dist: types-toml; extra == "typing"
45
+ Dynamic: license-file
46
+
47
+ <!--
48
+ topmark:header:start
49
+
50
+ file : README.md
51
+ file_relpath : README.md
52
+ project : TopMark
53
+ license : MIT
54
+ copyright : (c) 2025 Olivier Biot
55
+
56
+ topmark:header:end
57
+ -->
58
+
59
+ # TopMark
60
+
61
+ **TopMark** is a command-line tool to inspect, validate, and manage file headers in diverse
62
+ codebases. It helps maintain consistent header metadata across projects by supporting per-file-type
63
+ header formats, customizable fields, inclusion/exclusion rules, and dry-run safety.
64
+
65
+ ## ✨ Features
66
+
67
+ - File header detection, insertion, and replacement
68
+ - Supports multiple file types (Python, Makefile, Markdown, `.env`, ...)
69
+ - Configurable comment styles and header fields
70
+ - Inclusion and exclusion logic (via CLI, globs, stdin, or config)
71
+ - Dry-run by default; safe for CI/CD integration
72
+ - Configuration via `pyproject.toml` or `topmark.toml`
73
+ - Shell completion for enum-based options
74
+ - Colorized CLI output (via `yachalk`)
75
+ - Python ≥3.10
76
+ - Integrated pre-commit hooks for automated checks
77
+ - Formatting and linting support via Makefile targets
78
+ - CI-friendly design for safe automated use
79
+ - Strict static typing with mypy and Pyright, using PEP 604 union syntax
80
+ - Google-style docstrings without redundant type declarations
81
+ - Selective removal
82
+ - Preserves original newline style (LF/CRLF/CR) and BOM
83
+ - Idempotent updates (re-running does not change already-correct files)
84
+
85
+ ## 🚀 Installation
86
+
87
+ ```bash
88
+ git clone https://github.com/shutterfreak/topmark.git
89
+ cd topmark
90
+ make setup # creates virtualenv, installs dependencies and tools
91
+ ```
92
+
93
+ Or install into an existing virtualenv:
94
+
95
+ ```bash
96
+ pip install -e .
97
+ ```
98
+
99
+ Or install the latest release from PyPI:
100
+
101
+ ```bash
102
+ pip install topmark
103
+ ```
104
+
105
+ ## ⚙️ Usage
106
+
107
+ ```bash
108
+ topmark [OPTIONS] [PATHS]...
109
+ ```
110
+
111
+ TopMark uses Click 8.2 and supports shell completions. The base command performs a dry‑run *check*
112
+ by default and applies changes when `--apply` is provided.
113
+
114
+ Logging verbosity is controlled globally:
115
+
116
+ - `-v`, `--verbose`: Increase verbosity (can be repeated)
117
+ - `-q`, `--quiet`: Suppress most output (overrides verbosity)
118
+
119
+ All other options, such as `--stdin`, `--file-type`, and path filters, are specific to individual
120
+ subcommands like `check` or `apply`.
121
+
122
+ ### Examples
123
+
124
+ ```bash
125
+ # Check Python files in the src/ directory
126
+ topmark --file-type python src/
127
+
128
+ # Use exclusion patterns, and compute relative paths from src
129
+ topmark --file-type python --exclude .venv --relative-to src src/
130
+
131
+ # Add one verbosity level to topmark, use exclusion patterns from .gitignore
132
+ topmark -v --file-type python --exclude-from .gitignore src/
133
+
134
+ # Read files from stdin, generate summary
135
+ find . -name "*.py" | topmark --file-type python --summary --stdin
136
+
137
+ # Process all files in a Git repo
138
+ git ls-files -c -o --exclude-standard | sort -u | topmark --stdin --apply
139
+
140
+ # Dump the merged configuration (after loading all applicable config layers)
141
+ topmark dump-config --file-type python --exclude .venv --exclude-from .gitignore
142
+
143
+ # Display the default configuration without any merging
144
+ topmark show-defaults
145
+
146
+ # Output a starter configuration to stdout
147
+ topmark init-config
148
+
149
+ # Show TopMark version
150
+ topmark version
151
+
152
+ # Apply changes to files in-place
153
+ topmark --apply src/
154
+ ```
155
+
156
+ ## 📐 Header placement rules
157
+
158
+ TopMark is comment-aware and places the header block according to the file type and its policy.
159
+
160
+ ### Pound-style files (e.g., Python, Shell, Ruby, Makefile, YAML, TOML, Dockerfile)
161
+
162
+ Rules:
163
+
164
+ - If a **shebang** is present (e.g., `#!/usr/bin/env python3`), place the header **after** the
165
+ shebang and ensure **exactly one** blank line in-between.
166
+ - If a **coding/encoding line** follows the shebang (PEP 263 style), place the header **after**
167
+ shebang **and** encoding line.
168
+ - Otherwise, place the header **at the top of the file**.
169
+ - Ensure **one trailing blank line** after the header block when the next line is not already blank.
170
+
171
+ Example (Python):
172
+
173
+ ```py
174
+ #!/usr/bin/env python3
175
+
176
+ # topmark:header:start
177
+ #
178
+ # file :
179
+ # file_relpath :
180
+ #
181
+ # topmark:header:end
182
+
183
+ print("hello")
184
+ ```
185
+
186
+ ### XML-style files (XML, HTML/XHTML, SVG, Vue/Svelte/Markdown via HTML comments)
187
+
188
+ Rules:
189
+
190
+ - If present, place the header **after the XML declaration** and **DOCTYPE**, with **one blank
191
+ line** before the header block.
192
+ - Otherwise, place the header **at the top of the file**.
193
+ - The header uses the file’s native comment syntax; for XML/HTML it’s a comment block wrapper:
194
+
195
+ ```html
196
+ <!--
197
+ topmark:header:start
198
+
199
+ file :
200
+ file_relpath :
201
+
202
+ topmark:header:end
203
+ -->
204
+
205
+ <html>...</html>
206
+ ```
207
+
208
+ ### General guarantees
209
+
210
+ - **Newline preservation:** The inserted header uses the same newline style as the file
211
+ (LF/CRLF/CR).
212
+ - **BOM preservation:** If a UTF‑8 BOM is present, it is preserved.
213
+ - **Idempotency:** Re-running TopMark on a file with a correct header makes **no changes**.
214
+
215
+ ### Common Options
216
+
217
+ The following options can be used with most commands.
218
+
219
+ | Option | Description |
220
+ | ---------------- | ---------------------------------------- |
221
+ | `--file-type` | Specify file type (python, markdown, …) |
222
+ | `--relative-to` | Set base path for relative header fields |
223
+ | `--include` | Include paths or glob patterns |
224
+ | `--include-from` | Read inclusion patterns from file |
225
+ | `--exclude` | Exclude paths or glob patterns |
226
+ | `--exclude-from` | Read exclusion patterns from file |
227
+ | `--stdin` | Read file paths from stdin |
228
+ | `--apply` | Actually modify files instead of dry-run |
229
+ | `-v, --verbose` | Increase verbosity (can be repeated) |
230
+ | `-q, --quiet` | Suppress most output |
231
+
232
+ ### Subcommands
233
+
234
+ | Command | Description |
235
+ | --------------- | -------------------------------------------------- |
236
+ | `dump-config` | Show the resolved configuration in TOML format |
237
+ | `filetypes` | List supported file types and their comment styles |
238
+ | `version` | Print TopMark version |
239
+ | `show-defaults` | Show default config (without merging) |
240
+ | `init-config` | Output a starter configuration file |
241
+
242
+ ## 🧩 Supported file types
243
+
244
+ | Processor | File types (examples) |
245
+ | -------------------- | -------------------------------------------------------------------------- |
246
+ | PoundHeaderProcessor | python, shell, ruby, r, julia, perl, makefile, dockerfile, yaml, toml, env |
247
+ | XmlHeaderProcessor | xml, xhtml, html, svg, xsl/xslt, vue, svelte, markdown |
248
+
249
+ ## 🛠 Configuration
250
+
251
+ You can specify one or more `--config` files, or rely on local fallback resolution:
252
+
253
+ - `topmark.toml` in the working directory
254
+ - `pyproject.toml` using the `[tool.topmark]` table
255
+
256
+ TopMark reads configuration from one or more TOML files. Configuration is merged from:
257
+
258
+ 1. Built-in defaults
259
+ 2. Local project config (if not disabled via `--no-config`)
260
+ 3. Additional files via `--config`
261
+ 4. CLI overrides
262
+
263
+ Example configuration snippet (`topmark.toml`):
264
+
265
+ ```toml
266
+ [fields]
267
+ project = "TopMark"
268
+ license = "MIT"
269
+ copyright = "(c) 2025 Olivier Biot"
270
+
271
+ [header]
272
+ fields = [ "file", "file_relpath", "project", "license", "copyright",]
273
+
274
+ [formatting]
275
+ align_fields = true
276
+ raw_header = false
277
+
278
+ [files]
279
+ file_types = [ "python", "markdown", "env" ]
280
+ include = []
281
+ include_from = []
282
+ exclude = []
283
+ exclude_from = [ ".gitignore" ]
284
+ relative_to = "."
285
+ ```
286
+
287
+ ### Notes
288
+
289
+ - `formatting.align_fields = true` vertically aligns the field names within the rendered header
290
+ lines for readability.
291
+ - File-type specific behavior (shebang handling, XML prolog, blank line policies) is driven by
292
+ internal **FileTypeHeaderPolicy** defaults and can be extended to new types.
293
+
294
+ The `EnumParam` class enables shell completion for enum-based CLI options.
295
+
296
+ ## 🧪 Development Setup
297
+
298
+ For development setup and contribution guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
299
+
300
+ To verify compatibility across supported Python versions (3.10–3.13), use `tox` to run tests and
301
+ type checks in each environment.
302
+
303
+ ## 📄 License
304
+
305
+ MIT License © 2025 Olivier Biot
306
+
307
+ Markdown formatting is handled by `mdformat` with the `mdformat-tables` plugin, and configuration is
308
+ read from `pyproject.toml`.
@@ -0,0 +1,262 @@
1
+ <!--
2
+ topmark:header:start
3
+
4
+ file : README.md
5
+ file_relpath : README.md
6
+ project : TopMark
7
+ license : MIT
8
+ copyright : (c) 2025 Olivier Biot
9
+
10
+ topmark:header:end
11
+ -->
12
+
13
+ # TopMark
14
+
15
+ **TopMark** is a command-line tool to inspect, validate, and manage file headers in diverse
16
+ codebases. It helps maintain consistent header metadata across projects by supporting per-file-type
17
+ header formats, customizable fields, inclusion/exclusion rules, and dry-run safety.
18
+
19
+ ## ✨ Features
20
+
21
+ - File header detection, insertion, and replacement
22
+ - Supports multiple file types (Python, Makefile, Markdown, `.env`, ...)
23
+ - Configurable comment styles and header fields
24
+ - Inclusion and exclusion logic (via CLI, globs, stdin, or config)
25
+ - Dry-run by default; safe for CI/CD integration
26
+ - Configuration via `pyproject.toml` or `topmark.toml`
27
+ - Shell completion for enum-based options
28
+ - Colorized CLI output (via `yachalk`)
29
+ - Python ≥3.10
30
+ - Integrated pre-commit hooks for automated checks
31
+ - Formatting and linting support via Makefile targets
32
+ - CI-friendly design for safe automated use
33
+ - Strict static typing with mypy and Pyright, using PEP 604 union syntax
34
+ - Google-style docstrings without redundant type declarations
35
+ - Selective removal
36
+ - Preserves original newline style (LF/CRLF/CR) and BOM
37
+ - Idempotent updates (re-running does not change already-correct files)
38
+
39
+ ## 🚀 Installation
40
+
41
+ ```bash
42
+ git clone https://github.com/shutterfreak/topmark.git
43
+ cd topmark
44
+ make setup # creates virtualenv, installs dependencies and tools
45
+ ```
46
+
47
+ Or install into an existing virtualenv:
48
+
49
+ ```bash
50
+ pip install -e .
51
+ ```
52
+
53
+ Or install the latest release from PyPI:
54
+
55
+ ```bash
56
+ pip install topmark
57
+ ```
58
+
59
+ ## ⚙️ Usage
60
+
61
+ ```bash
62
+ topmark [OPTIONS] [PATHS]...
63
+ ```
64
+
65
+ TopMark uses Click 8.2 and supports shell completions. The base command performs a dry‑run *check*
66
+ by default and applies changes when `--apply` is provided.
67
+
68
+ Logging verbosity is controlled globally:
69
+
70
+ - `-v`, `--verbose`: Increase verbosity (can be repeated)
71
+ - `-q`, `--quiet`: Suppress most output (overrides verbosity)
72
+
73
+ All other options, such as `--stdin`, `--file-type`, and path filters, are specific to individual
74
+ subcommands like `check` or `apply`.
75
+
76
+ ### Examples
77
+
78
+ ```bash
79
+ # Check Python files in the src/ directory
80
+ topmark --file-type python src/
81
+
82
+ # Use exclusion patterns, and compute relative paths from src
83
+ topmark --file-type python --exclude .venv --relative-to src src/
84
+
85
+ # Add one verbosity level to topmark, use exclusion patterns from .gitignore
86
+ topmark -v --file-type python --exclude-from .gitignore src/
87
+
88
+ # Read files from stdin, generate summary
89
+ find . -name "*.py" | topmark --file-type python --summary --stdin
90
+
91
+ # Process all files in a Git repo
92
+ git ls-files -c -o --exclude-standard | sort -u | topmark --stdin --apply
93
+
94
+ # Dump the merged configuration (after loading all applicable config layers)
95
+ topmark dump-config --file-type python --exclude .venv --exclude-from .gitignore
96
+
97
+ # Display the default configuration without any merging
98
+ topmark show-defaults
99
+
100
+ # Output a starter configuration to stdout
101
+ topmark init-config
102
+
103
+ # Show TopMark version
104
+ topmark version
105
+
106
+ # Apply changes to files in-place
107
+ topmark --apply src/
108
+ ```
109
+
110
+ ## 📐 Header placement rules
111
+
112
+ TopMark is comment-aware and places the header block according to the file type and its policy.
113
+
114
+ ### Pound-style files (e.g., Python, Shell, Ruby, Makefile, YAML, TOML, Dockerfile)
115
+
116
+ Rules:
117
+
118
+ - If a **shebang** is present (e.g., `#!/usr/bin/env python3`), place the header **after** the
119
+ shebang and ensure **exactly one** blank line in-between.
120
+ - If a **coding/encoding line** follows the shebang (PEP 263 style), place the header **after**
121
+ shebang **and** encoding line.
122
+ - Otherwise, place the header **at the top of the file**.
123
+ - Ensure **one trailing blank line** after the header block when the next line is not already blank.
124
+
125
+ Example (Python):
126
+
127
+ ```py
128
+ #!/usr/bin/env python3
129
+
130
+ # topmark:header:start
131
+ #
132
+ # file :
133
+ # file_relpath :
134
+ #
135
+ # topmark:header:end
136
+
137
+ print("hello")
138
+ ```
139
+
140
+ ### XML-style files (XML, HTML/XHTML, SVG, Vue/Svelte/Markdown via HTML comments)
141
+
142
+ Rules:
143
+
144
+ - If present, place the header **after the XML declaration** and **DOCTYPE**, with **one blank
145
+ line** before the header block.
146
+ - Otherwise, place the header **at the top of the file**.
147
+ - The header uses the file’s native comment syntax; for XML/HTML it’s a comment block wrapper:
148
+
149
+ ```html
150
+ <!--
151
+ topmark:header:start
152
+
153
+ file :
154
+ file_relpath :
155
+
156
+ topmark:header:end
157
+ -->
158
+
159
+ <html>...</html>
160
+ ```
161
+
162
+ ### General guarantees
163
+
164
+ - **Newline preservation:** The inserted header uses the same newline style as the file
165
+ (LF/CRLF/CR).
166
+ - **BOM preservation:** If a UTF‑8 BOM is present, it is preserved.
167
+ - **Idempotency:** Re-running TopMark on a file with a correct header makes **no changes**.
168
+
169
+ ### Common Options
170
+
171
+ The following options can be used with most commands.
172
+
173
+ | Option | Description |
174
+ | ---------------- | ---------------------------------------- |
175
+ | `--file-type` | Specify file type (python, markdown, …) |
176
+ | `--relative-to` | Set base path for relative header fields |
177
+ | `--include` | Include paths or glob patterns |
178
+ | `--include-from` | Read inclusion patterns from file |
179
+ | `--exclude` | Exclude paths or glob patterns |
180
+ | `--exclude-from` | Read exclusion patterns from file |
181
+ | `--stdin` | Read file paths from stdin |
182
+ | `--apply` | Actually modify files instead of dry-run |
183
+ | `-v, --verbose` | Increase verbosity (can be repeated) |
184
+ | `-q, --quiet` | Suppress most output |
185
+
186
+ ### Subcommands
187
+
188
+ | Command | Description |
189
+ | --------------- | -------------------------------------------------- |
190
+ | `dump-config` | Show the resolved configuration in TOML format |
191
+ | `filetypes` | List supported file types and their comment styles |
192
+ | `version` | Print TopMark version |
193
+ | `show-defaults` | Show default config (without merging) |
194
+ | `init-config` | Output a starter configuration file |
195
+
196
+ ## 🧩 Supported file types
197
+
198
+ | Processor | File types (examples) |
199
+ | -------------------- | -------------------------------------------------------------------------- |
200
+ | PoundHeaderProcessor | python, shell, ruby, r, julia, perl, makefile, dockerfile, yaml, toml, env |
201
+ | XmlHeaderProcessor | xml, xhtml, html, svg, xsl/xslt, vue, svelte, markdown |
202
+
203
+ ## 🛠 Configuration
204
+
205
+ You can specify one or more `--config` files, or rely on local fallback resolution:
206
+
207
+ - `topmark.toml` in the working directory
208
+ - `pyproject.toml` using the `[tool.topmark]` table
209
+
210
+ TopMark reads configuration from one or more TOML files. Configuration is merged from:
211
+
212
+ 1. Built-in defaults
213
+ 2. Local project config (if not disabled via `--no-config`)
214
+ 3. Additional files via `--config`
215
+ 4. CLI overrides
216
+
217
+ Example configuration snippet (`topmark.toml`):
218
+
219
+ ```toml
220
+ [fields]
221
+ project = "TopMark"
222
+ license = "MIT"
223
+ copyright = "(c) 2025 Olivier Biot"
224
+
225
+ [header]
226
+ fields = [ "file", "file_relpath", "project", "license", "copyright",]
227
+
228
+ [formatting]
229
+ align_fields = true
230
+ raw_header = false
231
+
232
+ [files]
233
+ file_types = [ "python", "markdown", "env" ]
234
+ include = []
235
+ include_from = []
236
+ exclude = []
237
+ exclude_from = [ ".gitignore" ]
238
+ relative_to = "."
239
+ ```
240
+
241
+ ### Notes
242
+
243
+ - `formatting.align_fields = true` vertically aligns the field names within the rendered header
244
+ lines for readability.
245
+ - File-type specific behavior (shebang handling, XML prolog, blank line policies) is driven by
246
+ internal **FileTypeHeaderPolicy** defaults and can be extended to new types.
247
+
248
+ The `EnumParam` class enables shell completion for enum-based CLI options.
249
+
250
+ ## 🧪 Development Setup
251
+
252
+ For development setup and contribution guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
253
+
254
+ To verify compatibility across supported Python versions (3.10–3.13), use `tox` to run tests and
255
+ type checks in each environment.
256
+
257
+ ## 📄 License
258
+
259
+ MIT License © 2025 Olivier Biot
260
+
261
+ Markdown formatting is handled by `mdformat` with the `mdformat-tables` plugin, and configuration is
262
+ read from `pyproject.toml`.