Skip to content

Commit 718c52a

Browse files
committed
Documentation megacommit
- Add auto-gen'd docstrings for many ImGui enums - Parse docstrings from imgui.h oneline comments - Add slimgui_add_stub which adds docstrings to stubgen output
1 parent 35c602a commit 718c52a

15 files changed

+3570
-629
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
build/
2+
dist/
23
.venv/

CMakeLists.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ set(Python_EXECUTABLE ".venv/Scripts/python.exe")
22
cmake_minimum_required(VERSION 3.15...3.27)
33
project(slimgui LANGUAGES CXX)
44

5+
# Extended stubgen for slimgui
6+
include(slimgui_stubgen.cmake)
7+
58
# Try to import all Python components potentially needed by nanobind
69
find_package(Python 3.8
710
REQUIRED COMPONENTS Interpreter Development.Module
@@ -33,7 +36,7 @@ nanobind_add_module(slimgui_ext
3336
src/c/imgui/imgui_widgets.cpp
3437
)
3538

36-
nanobind_add_stub(
39+
slimgui_add_stub(
3740
slimgui_ext_stub
3841
MODULE slimgui_ext
3942
OUTPUT "${CMAKE_SOURCE_DIR}/src/slimgui/slimgui_ext.pyi"

README.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ python3 -m venv .venv
2121
. .venv/bin/activate
2222
pip install git+https://github.com/wjakob/nanobind 'scikit-build-core[pyproject]' click glfw pyopengl numpy requests
2323
pip install --no-build-isolation -ve .
24-
python gen/gen_nb.py > src/im_enums.inl
24+
python gen/gen_nb_enums.py > src/im_enums.inl
2525
```
2626

2727
Windows:
@@ -31,7 +31,13 @@ python3 -m venv .venv
3131
.venv\Scripts\activate.bat
3232
pip install git+https://github.com/wjakob/nanobind scikit-build-core[pyproject] click glfw pyopengl numpy
3333
pip install --no-build-isolation -ve .
34-
python gen\gen_nb.py > src\im_enums.inl
34+
python gen\gen_nb_enums.py > src\im_enums.inl
35+
```
36+
37+
### Doc build with filewatching
38+
39+
```
40+
npx nodemon -w gen -w docs/template.html -w docs/apiref.md -x python gen/build_docs.py --pyi-file src/slimgui/slimgui_ext.pyi --output docs/apiref.html docs/apiref.md
3541
```
3642

3743
## Cimgui outputs for some API generation

docs/apiref.md

+476
Large diffs are not rendered by default.

docs/template.html

+217
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
<!DOCTYPE html>
2+
<html lang="en" dir="ltr">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<title>$title$</title>
7+
<meta property="og:title" content="$title$">
8+
<meta property="og:description" content="$subtitle$">
9+
10+
<style type='text/css'>
11+
12+
:root {
13+
--func-vert-padding: 0.5em;
14+
}
15+
16+
span.smallcaps{font-variant: small-caps;}
17+
span.underline{text-decoration: underline;}
18+
div.column{display: inline-block; vertical-align: top; width: 50%;}
19+
20+
body {
21+
font-family: 'Segoe UI', sans-serif;
22+
color: #000;
23+
line-height: 1.5;
24+
}
25+
26+
.tocstyle nav {
27+
display: table;
28+
padding: .4em 2em .5em 0;
29+
margin-top: 1em;
30+
background-color: #f6f8fa;
31+
border: 1px solid DarkSlateGray;
32+
}
33+
header {
34+
margin-top: 0;
35+
margin-bottom: 0;
36+
padding-top: 0;
37+
padding-bottom: 0;
38+
}
39+
40+
header h1 {
41+
font-size: 2em;
42+
margin-top: 1em;
43+
margin-bottom: 0.5em;
44+
font-weight: 600;
45+
color: #333;
46+
}
47+
48+
h1 {
49+
font-family: 'Segoe UI', sans-serif;
50+
line-height: 1.2;
51+
font-size: 3em;
52+
margin-top: 0em;
53+
margin-bottom: 0em;
54+
}
55+
h2, h3, h4, h5, h6 {
56+
font-family: 'Segoe UI', sans-serif;
57+
font-weight: 600;
58+
margin-bottom: 0.1em;
59+
color: DarkSlateGray;
60+
}
61+
62+
h2 {
63+
margin-top: 0.5em;
64+
margin-bottom: 0.5em;
65+
padding-top: 0;
66+
}
67+
68+
h2, h3 { border-bottom: 1px solid #ccc; }
69+
p {
70+
margin-left: 0px;
71+
margin-right: 0px;
72+
margin-top: 0.75em;
73+
margin-bottom: 0.75em;
74+
}
75+
76+
.max-width {
77+
margin: 1em;
78+
}
79+
80+
@media screen and (min-width: 680px) {
81+
.max-width {
82+
margin-left: auto;
83+
margin-right: auto;
84+
margin-top: 20px;
85+
margin-bottom: 20px;
86+
max-width: 800px;
87+
}
88+
}
89+
90+
.pixelated {
91+
image-rendering: pixelated;
92+
}
93+
94+
strong {
95+
font-weight: 600;
96+
}
97+
98+
.title { text-align: center; }
99+
100+
.subtitle {
101+
font-size: 1.25em;
102+
margin-top: 0px;
103+
padding-top: 0px;
104+
padding-bottom: 1em;
105+
margin-bottom: 1em;
106+
border-bottom: 1px solid #ccc;
107+
color: #444;
108+
}
109+
110+
.centered { text-align: center; }
111+
112+
.spaced {
113+
margin: 2em 0;
114+
}
115+
.no-bottom-margin {
116+
margin-bottom: 0;
117+
}
118+
.top-lined {
119+
padding-top: 2em;
120+
border-top: 1px solid #000;
121+
}
122+
.bottom-lined {
123+
padding-bottom: 2em;
124+
border-bottom: 1px solid #888;
125+
}
126+
127+
.permalinked {
128+
color: #222;
129+
text-decoration: none;
130+
}
131+
.permalinked:hover,
132+
.permalinked:focus {
133+
text-decoration: underline;
134+
}
135+
.flattr-note {
136+
vertical-align: top;
137+
}
138+
139+
pre {
140+
font-family: 'Consolas', monospace, sans-serif;
141+
font-size: 10pt;
142+
font-weight: normal;
143+
background-color: #f6f8fa;
144+
border-radius: 3px;
145+
padding: 6px;
146+
line-height: 1.2;
147+
overflow-x:auto;
148+
white-space: pre-wrap;
149+
}
150+
151+
code {
152+
font-family: 'Consolas', monospace, sans-serif;
153+
font-size: 11pt;
154+
font-weight: normal;
155+
line-height: 1.3;
156+
white-space: pre;
157+
}
158+
159+
/* Styles for API reference */
160+
div.apifunc {
161+
margin-bottom: 1.0em;
162+
}
163+
164+
.apifunc p {
165+
margin-top: 0;
166+
margin-bottom: 0;
167+
margin-left: 2em;
168+
font-size: 11pt;
169+
}
170+
171+
.apifunc pre {
172+
color: #000;
173+
margin-top: 0.3em;
174+
margin-bottom: 0.3em;
175+
}
176+
177+
.apifunc code {
178+
font-size: 11pt;
179+
color: #555;
180+
}
181+
182+
.apifunc code span.keyword {
183+
color: #444;
184+
}
185+
186+
.apifunc code span.func_name {
187+
color: #000;
188+
font-weight: bold;
189+
}
190+
191+
.apifunc code span.arg_name {
192+
color: #000;
193+
}
194+
195+
196+
</style>
197+
<link href="https://fonts.googleapis.com/css?family=Montserrat|Segoe+UI" rel="stylesheet">
198+
</head>
199+
200+
<body class='max-width'>
201+
<header id='title-block-header'>
202+
<h1>$title$ documentation</h1>
203+
<p class='subtitle'>$subtitle$</p>
204+
</header>
205+
206+
$if(toc)$
207+
<h2 style='border-bottom: 0; padding-bottom: 0;'>Table of contents</h2>
208+
<div class="tocstyle">
209+
<nav id="$idprefix$TOC">
210+
$table-of-contents$
211+
</nav></div>
212+
$endif$
213+
214+
$body$
215+
</body>
216+
217+
</html>

gen/amend_func_docs.py

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
2+
import argparse
3+
import re
4+
5+
import gen_utils
6+
7+
def parse_func_line_comments(header_path: str) -> dict[str, str | None]:
8+
with open(header_path, "rt", encoding="utf-8") as f:
9+
lines = f.readlines()
10+
11+
func_line_comments: dict[str, str | None] = {}
12+
for line in lines:
13+
line = line.rstrip()
14+
# IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window.
15+
if (m := re.match(r"^\s*IMGUI_API.* (\w+)\(.*;(.*)", line)) is not None:
16+
comment = None
17+
func_name = gen_utils.camel_to_snake(m.group(1))
18+
trail = m.group(2)
19+
if (pos := trail.find('//')) != -1:
20+
comment = trail[pos+2:].lstrip(' \t')
21+
func_line_comments[func_name] = comment
22+
return func_line_comments
23+
24+
25+
def main():
26+
parser = argparse.ArgumentParser(description="Extract doc comments from imgui.h")
27+
parser.add_argument('--imgui-h', type=str, default='src/c/imgui/imgui.h')
28+
parser.add_argument('--pyi-file', type=str, default='src/slimgui/slimgui_ext.pyi')
29+
parser.add_argument('-o', dest='output', type=str, help="If not specified, output to stdout. Otherwise, write to this file. Output can be the same as input.")
30+
args = parser.parse_args()
31+
32+
syms = parse_func_line_comments(args.imgui_h)
33+
34+
out_lines = []
35+
with open(args.pyi_file, "rt", encoding="utf-8") as f:
36+
for line in f.readlines():
37+
line = line.rstrip()
38+
39+
if (m := re.match(r"^def (\w+)\(", line)) is not None:
40+
line = re.sub(r': ...$', ':', line)
41+
42+
out_lines.append(line)
43+
func_name = m.group(1)
44+
if (comment := syms.get(func_name)) is not None:
45+
comment = comment.strip()
46+
if comment == '"':
47+
comment = '' # remove spurious double quotes
48+
comment = comment.replace('"', '\\"')
49+
if comment != '':
50+
out_lines.append(f' """{comment}"""')
51+
out_lines.append(' ...\n')
52+
else:
53+
out_lines.append(line)
54+
55+
if args.output is not None:
56+
with open(args.output, "wt", encoding="utf-8") as f:
57+
f.write('\n'.join(out_lines))
58+
else:
59+
print('\n'.join(out_lines))
60+
61+
if __name__ == "__main__":
62+
main()

0 commit comments

Comments
 (0)