mkdocs-cdoc 1.0.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.
- mkdocs-cdoc-1.0.0/LICENSE +21 -0
- mkdocs-cdoc-1.0.0/PKG-INFO +14 -0
- mkdocs-cdoc-1.0.0/README.md +372 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc/__init__.py +9 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc/convert.py +96 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc/parser.py +1341 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc/plugin.py +1508 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc/renderer.py +241 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc.egg-info/PKG-INFO +14 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc.egg-info/SOURCES.txt +15 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc.egg-info/dependency_links.txt +1 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc.egg-info/entry_points.txt +3 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc.egg-info/requires.txt +1 -0
- mkdocs-cdoc-1.0.0/mkdocs_cdoc.egg-info/top_level.txt +1 -0
- mkdocs-cdoc-1.0.0/pyproject.toml +71 -0
- mkdocs-cdoc-1.0.0/setup.cfg +4 -0
- mkdocs-cdoc-1.0.0/setup.py +19 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pawel Sikora
|
|
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,14 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: mkdocs-cdoc
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: UNKNOWN
|
|
5
|
+
Home-page: https://github.com/pawelsikora/mkdocs-cdoc/
|
|
6
|
+
Author: Pawel Sikora
|
|
7
|
+
Author-email: sikor6@gmail.com
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Keywords: mkdocs cdoc hawkmoth documentation gtk-doc python
|
|
10
|
+
Platform: UNKNOWN
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
|
|
13
|
+
UNKNOWN
|
|
14
|
+
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# mkdocs-cdoc
|
|
2
|
+
|
|
3
|
+
[](https://github.com/pawelsikora/mkdocs-cdoc/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/mkdocs-cdoc/)
|
|
5
|
+
[](https://pypi.org/project/mkdocs-cdoc/)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.mkdocs.org/)
|
|
8
|
+
[](https://github.com/psf/black)
|
|
9
|
+
|
|
10
|
+
**Generate browsable API documentation from C/C++ source comments directly in MkDocs** — with cross-referencing, symbol indexing, and basic support for test catalogs.
|
|
11
|
+
|
|
12
|
+
Parses `/** ... */` doc comments using libclang (with a regex fallback), converts reST and gtk-doc markup to Markdown, and builds a fully linked API reference with per-symbol anchors, an A–Z index, and automatic cross-references across all your source files and hand-written pages.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **Autodoc from C/C++ sources** — scans source trees, extracts doc comments, generates per-file pages with function signatures, parameter tables, and struct/enum member listings.
|
|
19
|
+
- **Cross-reference everything** — `:func:`, `:struct:`, `:file:`, backtick auto-linking. Works across generated pages and hand-written Markdown alike.
|
|
20
|
+
- **Multiple source groups** — separate nav sections for core libraries, drivers, tests, etc., each with their own A–Z index and overview.
|
|
21
|
+
- **IGT test catalog** — parses `TEST:` / `SUBTEST:` structured comments and `igt_subtest()` / `igt_describe()` macros to build test documentation with metadata tables, "By Category" / "By Functionality" index pages, and per-subtest anchors.
|
|
22
|
+
- **gtk-doc migration** — converts `#TypeName`, `function()`, `%CONSTANT`, `@param` markup at parse time, plus a CLI for one-time batch conversion of source files.
|
|
23
|
+
- **Clang + regex** — uses libclang when available for accurate signatures and types, falls back to regex parsing so it works everywhere.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install mkdocs-cdoc
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
For full clang-based parsing (recommended):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Ubuntu / Debian
|
|
37
|
+
sudo apt install python3-clang libclang-dev
|
|
38
|
+
|
|
39
|
+
# Or via pip
|
|
40
|
+
pip install mkdocs-cdoc[clang]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
Minimal setup — point it at a source directory:
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
plugins:
|
|
49
|
+
- cdoc:
|
|
50
|
+
source_root: src/
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Multiple source trees with their own nav sections:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
plugins:
|
|
57
|
+
- cdoc:
|
|
58
|
+
project_name: My Project
|
|
59
|
+
version_file: version.json
|
|
60
|
+
|
|
61
|
+
sources:
|
|
62
|
+
- root: src/core
|
|
63
|
+
nav_title: Core API
|
|
64
|
+
output_dir: api/core
|
|
65
|
+
|
|
66
|
+
- root: src/drivers
|
|
67
|
+
nav_title: Driver API
|
|
68
|
+
output_dir: api/drivers
|
|
69
|
+
extensions: [".c"]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The `version_file` is scanned for a line matching `version: 'X.Y'` (or `VERSION = "1.2.3"`, `"version": "2.0"`, etc.) — it works with JSON, YAML, Python, meson.build, or any file with a version key-value pair.
|
|
73
|
+
|
|
74
|
+
With multiple source groups, a top-level overview page is generated automatically showing the project name, a version badge, and links to each group. Individual source file pages are generated and reachable via cross-references and the index — they just don't crowd the nav:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
API Reference
|
|
78
|
+
Core API
|
|
79
|
+
Overview
|
|
80
|
+
Driver API
|
|
81
|
+
Overview
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Source group options
|
|
85
|
+
|
|
86
|
+
Each entry under `sources:` accepts:
|
|
87
|
+
|
|
88
|
+
| Option | Default | Description |
|
|
89
|
+
|--------|---------|-------------|
|
|
90
|
+
| `root` | *(required)* | Path to the source tree |
|
|
91
|
+
| `nav_title` | `API (<dirname>)` | Nav section heading |
|
|
92
|
+
| `output_dir` | `api/<dirname>` | Where generated pages go |
|
|
93
|
+
| `extensions` | `[".c", ".h"]` | File extensions to scan |
|
|
94
|
+
| `exclude` | `[]` | Glob patterns to skip |
|
|
95
|
+
| `clang_args` | `[]` | Extra flags, appended to global `clang_args` |
|
|
96
|
+
| `index` | `true` | Generate an overview page |
|
|
97
|
+
| `pages` | `[]` | Extra hand-written pages to include in the nav |
|
|
98
|
+
| `igt` | — | IGT test framework options ([see below](#test-documentation-igt-gpu-tools)) |
|
|
99
|
+
|
|
100
|
+
## Test documentation (IGT GPU Tools)
|
|
101
|
+
|
|
102
|
+
The plugin has built-in support for test source trees that use structured doc comments and test macros. While designed around [IGT GPU Tools](https://gitlab.freedesktop.org/drm/igt-gpu-tools) conventions, the approach works for any C test codebase that follows a similar comment structure.
|
|
103
|
+
|
|
104
|
+
### Enabling test mode
|
|
105
|
+
|
|
106
|
+
Add an `igt:` block to any source group:
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
sources:
|
|
110
|
+
- root: tests
|
|
111
|
+
nav_title: Tests
|
|
112
|
+
output_dir: api/tests
|
|
113
|
+
extensions: [".c"]
|
|
114
|
+
igt:
|
|
115
|
+
group_by: [category, mega_feature, sub_category, functionality]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
That's all you need. The presence of `igt:` enables test parsing for that source group.
|
|
119
|
+
|
|
120
|
+
### IGT GPU Tools options
|
|
121
|
+
|
|
122
|
+
| Option | Default | Description |
|
|
123
|
+
|--------|---------|-------------|
|
|
124
|
+
| `group_by` | `[]` | Metadata fields to generate "By …" index pages for |
|
|
125
|
+
| `fields` | same as `group_by` | Which metadata fields to show on each test page |
|
|
126
|
+
| `extract_steps` | `false` | Parse subtest code bodies for step-by-step tables |
|
|
127
|
+
|
|
128
|
+
### What it parses
|
|
129
|
+
|
|
130
|
+
**Structured doc comments** at file scope — either in a main `TEST:` block or standalone `SUBTEST:` blocks above functions:
|
|
131
|
+
|
|
132
|
+
```c
|
|
133
|
+
/**
|
|
134
|
+
* TEST: kms_addfb
|
|
135
|
+
* Category: Display
|
|
136
|
+
* Mega feature: KMS
|
|
137
|
+
* Sub-category: Framebuffer
|
|
138
|
+
* Description: Tests for the DRM framebuffer creation ioctl.
|
|
139
|
+
*
|
|
140
|
+
* SUBTEST: basic
|
|
141
|
+
* Description: Check if addfb2 works with a valid handle.
|
|
142
|
+
* Functionality: addfb
|
|
143
|
+
*/
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Standalone subtest blocks are also supported, placed above individual functions:
|
|
147
|
+
|
|
148
|
+
```c
|
|
149
|
+
/**
|
|
150
|
+
* SUBTEST: attach-debug-metadata
|
|
151
|
+
* Functionality: metadata
|
|
152
|
+
* Description:
|
|
153
|
+
* Read debug metadata when vm_bind has it attached.
|
|
154
|
+
*/
|
|
155
|
+
static void test_metadata_attach(int fd, unsigned int flags) { ... }
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Test macros** in code — `igt_subtest()`, `igt_describe()`, and `igt_subtest_with_dynamic()`:
|
|
159
|
+
|
|
160
|
+
```c
|
|
161
|
+
igt_describe("Check that invalid legacy set-property calls are "
|
|
162
|
+
"correctly rejected by the kernel.");
|
|
163
|
+
igt_subtest("invalid-properties-legacy") {
|
|
164
|
+
...
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Both sources are merged: subtests from doc comments and code are combined, with `igt_describe()` taking priority for descriptions, then standalone `SUBTEST:` blocks, then the main `TEST:` block.
|
|
169
|
+
|
|
170
|
+
Multi-line `igt_describe()` strings (concatenated across lines) are handled. Format-string subtests like `igt_subtest("%s")` are automatically excluded.
|
|
171
|
+
|
|
172
|
+
### Metadata fields
|
|
173
|
+
|
|
174
|
+
Any `Key: Value` pair in the doc comment becomes a metadata field. Common conventions:
|
|
175
|
+
|
|
176
|
+
| Field | Level | Typical values |
|
|
177
|
+
|-------|-------|----------------|
|
|
178
|
+
| `Category` | test | Core, Display, … |
|
|
179
|
+
| `Mega feature` | test | KMS, Memory Management, … |
|
|
180
|
+
| `Sub-category` | test | GEM, Framebuffer, … |
|
|
181
|
+
| `Functionality` | subtest | addfb, gem_create, … |
|
|
182
|
+
| `Description` | both | Free-form text (supports multi-line) |
|
|
183
|
+
|
|
184
|
+
Test-level fields (like Category) group all tests in a file. Subtest-level fields (like Functionality) group individual subtests and produce a different table layout on the "By …" pages.
|
|
185
|
+
|
|
186
|
+
### Generated pages
|
|
187
|
+
|
|
188
|
+
The nav sidebar shows:
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
Tests
|
|
192
|
+
Overview ← file table + A–Z symbol index
|
|
193
|
+
By Category ← tests grouped by Category field
|
|
194
|
+
By Mega Feature ← tests grouped by Mega Feature field
|
|
195
|
+
By Sub Category ← tests grouped by Sub-category field
|
|
196
|
+
By Functionality ← subtests grouped by Functionality field
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Each **"By …" page** groups tests under headings matching the field values. Under each value, every test gets its own subheading with a table of its subtests and descriptions.
|
|
200
|
+
|
|
201
|
+
Each **test page** shows a metadata table, the full subtest listing (with anchor links per subtest), and optionally step-by-step tables when `extract_steps: true`.
|
|
202
|
+
|
|
203
|
+
### Adapting for your own test framework
|
|
204
|
+
|
|
205
|
+
The `igt:` parser key specifically enables the IGT-style parser, but the comment format is generic enough for any C test suite. If your tests use `/** ... */` comments with structured `TEST:` / `SUBTEST:` blocks and key-value metadata, they will work as-is. You only need IGT-specific macros (`igt_subtest`, `igt_describe`) if you want code-level subtest discovery.
|
|
206
|
+
|
|
207
|
+
To use it with a custom test tree:
|
|
208
|
+
|
|
209
|
+
1. Add `/** TEST: my_test_name */` comments with any metadata fields you like.
|
|
210
|
+
2. Optionally add `/** SUBTEST: name */` blocks with per-subtest metadata.
|
|
211
|
+
3. Set `group_by` to whichever field names you used.
|
|
212
|
+
|
|
213
|
+
### Cross-referencing tests
|
|
214
|
+
|
|
215
|
+
Tests and subtests are registered in the symbol registry:
|
|
216
|
+
|
|
217
|
+
```markdown
|
|
218
|
+
See :test:`kms_addfb` for framebuffer tests.
|
|
219
|
+
The :subtest:`kms_addfb@basic` subtest covers the happy path.
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The `test@subtest` notation mirrors IGT's `--run-subtest` convention. Short-form `:subtest:`basic`` works if the subtest name is unique across all tests.
|
|
223
|
+
|
|
224
|
+
## Cross-references
|
|
225
|
+
|
|
226
|
+
The plugin builds a symbol registry at build time and resolves references across all pages — generated API pages and hand-written docs alike.
|
|
227
|
+
|
|
228
|
+
### reST roles in doc comments
|
|
229
|
+
|
|
230
|
+
Use reST roles (portable to Sphinx):
|
|
231
|
+
|
|
232
|
+
```c
|
|
233
|
+
/**
|
|
234
|
+
* Initialize the engine.
|
|
235
|
+
*
|
|
236
|
+
* Must be called before :func:`engine_run`. Configure with
|
|
237
|
+
* :struct:`engine_config` first.
|
|
238
|
+
*
|
|
239
|
+
* :param flags: Init flags.
|
|
240
|
+
* :returns: 0 on success.
|
|
241
|
+
*/
|
|
242
|
+
int engine_init(unsigned int flags);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Available roles: `:func:`, `:struct:`, `:union:`, `:enum:`, `:macro:`, `:type:`, `:var:`, `:const:`, `:member:`, `:class:`, `:file:`, `:test:`, `:subtest:`. Domain-qualified forms like `:c:func:` also work.
|
|
246
|
+
|
|
247
|
+
For struct members use dot notation: `:member:`engine_config.debug``. For files, use the bare filename if unique or qualify with the group: `:file:`core/engine.h``.
|
|
248
|
+
|
|
249
|
+
### reST roles in Markdown pages
|
|
250
|
+
|
|
251
|
+
The same roles work in hand-written Markdown:
|
|
252
|
+
|
|
253
|
+
```markdown
|
|
254
|
+
Call :func:`engine_init` with the appropriate flags, then pass
|
|
255
|
+
an :struct:`engine_config` to :func:`engine_run`.
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Auto-linking
|
|
259
|
+
|
|
260
|
+
When `auto_xref` is enabled (the default), backticked identifiers that match known symbols become links automatically:
|
|
261
|
+
|
|
262
|
+
```markdown
|
|
263
|
+
Call `engine_init()` first, then create an `engine_config` and
|
|
264
|
+
pass it to `engine_run()`.
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Trailing `()` signals a function reference. Bare backticked names link if they match a struct, enum, type, etc. Filenames with C/C++ extensions also auto-link. Unknown names stay as plain code.
|
|
268
|
+
|
|
269
|
+
## Rendering
|
|
270
|
+
|
|
271
|
+
**Parameter tables** — function parameters render as a table. When type information is available (from clang), a Type column is added with cross-reference links for struct/custom types.
|
|
272
|
+
|
|
273
|
+
**Pointer return types** — functions returning pointers (e.g. `char *get_name(...)`) render as "Pointer to `char`" rather than showing `*` in the name.
|
|
274
|
+
|
|
275
|
+
**Example sections** — if a doc comment contains `Example:`, the description and code render side-by-side, similar to the Stripe API documentation layout.
|
|
276
|
+
|
|
277
|
+
**Underscore-prefixed symbols** — functions with `_` or `__` prefix sort by the name without the prefix. `__engine_reset` sorts under **E**.
|
|
278
|
+
|
|
279
|
+
## gtk-doc migration
|
|
280
|
+
|
|
281
|
+
If your codebase uses gtk-doc markup:
|
|
282
|
+
|
|
283
|
+
```yaml
|
|
284
|
+
plugins:
|
|
285
|
+
- cdoc:
|
|
286
|
+
convert_gtkdoc: true
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
| gtk-doc | Converts to |
|
|
290
|
+
|---------|------------|
|
|
291
|
+
| `function_name()` | `:func:`function_name`` |
|
|
292
|
+
| `#TypeName` | `:type:`TypeName`` |
|
|
293
|
+
| `#Struct.field` | `:member:`Struct.field`` |
|
|
294
|
+
| `%CONSTANT` | `:const:`CONSTANT`` |
|
|
295
|
+
| `@param: desc` | `:param param: desc` |
|
|
296
|
+
| `Returns:` | `:returns:` |
|
|
297
|
+
| `\|[ code ]\|` | fenced code block |
|
|
298
|
+
|
|
299
|
+
Batch conversion CLI to permanently migrate source files:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
python -m mkdocs_cdoc.convert src/
|
|
303
|
+
python -m mkdocs_cdoc.convert src/ --dry-run
|
|
304
|
+
python -m mkdocs_cdoc.convert src/ --backup
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Inline directives
|
|
308
|
+
|
|
309
|
+
Pull specific symbols into hand-written pages:
|
|
310
|
+
|
|
311
|
+
```markdown
|
|
312
|
+
::: c:autofunction
|
|
313
|
+
:file: engine.h
|
|
314
|
+
:name: engine_init
|
|
315
|
+
|
|
316
|
+
::: c:autodoc
|
|
317
|
+
:file: uart.c
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Full directive list: `autodoc`, `autofunction`, `autostruct`, `autounion`, `autoenum`, `automacro`, `autovar`, `autotype`.
|
|
321
|
+
|
|
322
|
+
## Global config reference
|
|
323
|
+
|
|
324
|
+
| Option | Default | Description |
|
|
325
|
+
|--------|---------|-------------|
|
|
326
|
+
| `project_name` | `""` | Project name on the top-level overview page |
|
|
327
|
+
| `version_file` | `""` | File to extract version from |
|
|
328
|
+
| `sources` | `[]` | List of source group configs (see above) |
|
|
329
|
+
| `clang_args` | `[]` | Global clang flags (merged with per-group flags) |
|
|
330
|
+
| `convert_rst` | `true` | Convert reST markup to Markdown |
|
|
331
|
+
| `convert_gtkdoc` | `false` | Convert gtk-doc markup to reST at parse time |
|
|
332
|
+
| `auto_xref` | `true` | Auto-link backticked symbol names |
|
|
333
|
+
| `appendix_code_usages` | `false` | Append a "Referenced by" section to each symbol |
|
|
334
|
+
| `heading_level` | `2` | Heading depth for symbols |
|
|
335
|
+
| `members` | `true` | Show struct/union/enum members |
|
|
336
|
+
| `show_source_link` | `false` | Append `[source]` links |
|
|
337
|
+
| `source_uri` | `""` | Template: `https://github.com/you/repo/blob/main/{filename}#L{line}` |
|
|
338
|
+
| `fallback_parser` | `true` | Use regex parser when clang is unavailable |
|
|
339
|
+
| `language` | `"c"` | Source language (`c` or `cpp`) |
|
|
340
|
+
|
|
341
|
+
For single-source setups without `sources:`, these shortcuts are available: `source_root`, `autodoc_output_dir`, `autodoc_nav_title`, `autodoc_extensions`, `autodoc_exclude`, `autodoc_index`, `autodoc_pages`.
|
|
342
|
+
|
|
343
|
+
## Example: GTK-doc based project config
|
|
344
|
+
|
|
345
|
+
```yaml
|
|
346
|
+
plugins:
|
|
347
|
+
- cdoc:
|
|
348
|
+
project_name: my-project
|
|
349
|
+
version_file: meson.build
|
|
350
|
+
clang_args: ["-Ilib", "-Itests", "-Iinclude"]
|
|
351
|
+
|
|
352
|
+
sources:
|
|
353
|
+
- root: lib
|
|
354
|
+
nav_title: Core API
|
|
355
|
+
output_dir: reference_api/lib
|
|
356
|
+
|
|
357
|
+
- root: tests
|
|
358
|
+
nav_title: Tests
|
|
359
|
+
output_dir: reference_api/tests
|
|
360
|
+
extensions: [".c"]
|
|
361
|
+
|
|
362
|
+
convert_rst: true
|
|
363
|
+
convert_gtkdoc: true
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Credits
|
|
367
|
+
|
|
368
|
+
This project was inspired by the work of [Jani Nikula](https://github.com/jnikula) and the [Hawkmoth](https://github.com/jnikula/hawkmoth) project, which provides Sphinx-based autodoc for C. The core idea of extracting C doc comments through libclang originates there. mkdocs-cdoc adapts and extends that concept for the MkDocs ecosystem, adding multi-source-group navigation, cross-reference resolution, IGT GPU Tools test catalog generation, and gtk-doc migration tooling.
|
|
369
|
+
|
|
370
|
+
## License
|
|
371
|
+
|
|
372
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""
|
|
2
|
+
mkdocs-cdoc — C/C++ API Documentation for MkDocs.
|
|
3
|
+
|
|
4
|
+
Extracts documentation from C and C++ source comments and renders them
|
|
5
|
+
as browsable API reference pages in MkDocs, with cross-referencing,
|
|
6
|
+
symbol indexing, and IGT GPU Tools test catalog support.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Batch convert gtk-doc markup to reST in C/C++ doc comments.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python -m mkdocs_cdoc.convert src/
|
|
7
|
+
python -m mkdocs_cdoc.convert src/engine.h --dry-run
|
|
8
|
+
python -m mkdocs_cdoc.convert src/ --ext .c .h --backup
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import shutil
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
from .parser import gtkdoc_to_rst
|
|
18
|
+
|
|
19
|
+
_BLOCK_COMMENT_RE = re.compile(r"(/\*\*.*?\*/)", re.DOTALL)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def convert_file(path, dry_run=False, backup=False):
|
|
23
|
+
with open(path, "r", encoding="utf-8", errors="replace") as f:
|
|
24
|
+
original = f.read()
|
|
25
|
+
|
|
26
|
+
def convert_match(m):
|
|
27
|
+
full = m.group(1)
|
|
28
|
+
if not full.startswith("/**"):
|
|
29
|
+
return full
|
|
30
|
+
prefix = full[:3]
|
|
31
|
+
suffix = full[-2:]
|
|
32
|
+
inner = full[3:-2]
|
|
33
|
+
converted = gtkdoc_to_rst(inner)
|
|
34
|
+
return prefix + converted + suffix
|
|
35
|
+
|
|
36
|
+
result = _BLOCK_COMMENT_RE.sub(convert_match, original)
|
|
37
|
+
|
|
38
|
+
if result == original:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
if dry_run:
|
|
42
|
+
return True
|
|
43
|
+
|
|
44
|
+
if backup:
|
|
45
|
+
shutil.copy2(path, path + ".bak")
|
|
46
|
+
|
|
47
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
48
|
+
f.write(result)
|
|
49
|
+
return True
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def main():
|
|
53
|
+
p = argparse.ArgumentParser(description="Convert gtk-doc markup to reST in C/C++ doc comments")
|
|
54
|
+
p.add_argument("path", help="File or directory to convert")
|
|
55
|
+
p.add_argument(
|
|
56
|
+
"--ext",
|
|
57
|
+
nargs="+",
|
|
58
|
+
default=[".c", ".h", ".cpp", ".hpp"],
|
|
59
|
+
help="File extensions to process (default: .c .h .cpp .hpp)",
|
|
60
|
+
)
|
|
61
|
+
p.add_argument(
|
|
62
|
+
"--dry-run", action="store_true", help="Show what would change without modifying files"
|
|
63
|
+
)
|
|
64
|
+
p.add_argument("--backup", action="store_true", help="Create .bak files before modifying")
|
|
65
|
+
args = p.parse_args()
|
|
66
|
+
|
|
67
|
+
target = args.path
|
|
68
|
+
exts = set(e if e.startswith(".") else f".{e}" for e in args.ext)
|
|
69
|
+
|
|
70
|
+
files = []
|
|
71
|
+
if os.path.isfile(target):
|
|
72
|
+
files.append(target)
|
|
73
|
+
elif os.path.isdir(target):
|
|
74
|
+
for dirpath, _, fnames in os.walk(target):
|
|
75
|
+
for fn in sorted(fnames):
|
|
76
|
+
_, ext = os.path.splitext(fn)
|
|
77
|
+
if ext.lower() in exts:
|
|
78
|
+
files.append(os.path.join(dirpath, fn))
|
|
79
|
+
else:
|
|
80
|
+
print(f"error: {target} not found", file=sys.stderr)
|
|
81
|
+
sys.exit(1)
|
|
82
|
+
|
|
83
|
+
changed = 0
|
|
84
|
+
for fpath in files:
|
|
85
|
+
was_changed = convert_file(fpath, dry_run=args.dry_run, backup=args.backup)
|
|
86
|
+
if was_changed:
|
|
87
|
+
changed += 1
|
|
88
|
+
tag = "[dry-run] " if args.dry_run else ""
|
|
89
|
+
print(f"{tag}converted: {fpath}")
|
|
90
|
+
|
|
91
|
+
total = len(files)
|
|
92
|
+
print(f"\n{changed}/{total} files {'would be ' if args.dry_run else ''}modified")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if __name__ == "__main__":
|
|
96
|
+
main()
|