generated from 42cursus-youkim/project-template
-
Notifications
You must be signed in to change notification settings - Fork 1
/
create.py
executable file
·108 lines (76 loc) · 2.92 KB
/
create.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env python3
"""
create.py: create boilerplate for *.cpp, *.hpp, *.tpp
usage:
create.py [--help] [options] [-n | -N | --ns <N> ] <path>
options:
-h, --help show this help message and exit
-n use parent directory name as namespace
-N use nested directory names as namespace
--ns <N> choose namespace to use.
-s, --switch open created file on vscode.
-f, --force overwrite existing files.
-r <R>, --root <R> root of directory path [default: src]
"""
from pathlib import Path
from cpputil import run_docopt
def wrap_with(body: str, wrap: tuple[str, str], *, distance: int = 1) -> str:
nl = distance * "\n"
return f"{wrap[0]}{nl}{body}{nl}{wrap[1]}"
def wrap_header(body: str, path: Path) -> str:
guard = "_".join(path.parts).replace(".", "_").upper()
header = (
f"#ifndef {guard}\n" f"#define {guard}",
f"#endif // {guard}",
)
return wrap_with(body, header, distance=2)
def base_category_name(stem: str) -> str:
return stem.rsplit("_", maxsplit=1)[0]
def get_include(path: Path) -> str:
match path.suffix:
case ".hpp":
return ""
case ".tpp":
name = base_category_name(path.stem)
case ".cpp":
name = path.parent.stem.removeprefix("lib")
case _:
raise ValueError(f"Unknown file type: {path}")
return f"#include <{'/'.join(path.parent.parts)}/{name}.hpp>"
def get_nested_namespace(names: tuple[str]) -> str:
names = tuple(n.removeprefix("lib") for n in names)
begins = "\n".join([f"namespace {ns} {{" for ns in names])
ends = "\n".join([f"}} // namespace {ns}" for ns in reversed(names)])
return f"{begins}\n{ends}"
def save_text_to(text: str, path: Path) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(f"{text}\n")
print(text)
def create_text(path: Path, *, namespace: tuple[str] | None) -> str:
text = get_include(path)
if namespace:
text += f"\n\n{get_nested_namespace(namespace)}"
return text if path.suffix == ".cpp" else wrap_header(text, path)
def get_namespace(path: Path, args: dict[str, str]) -> tuple[str] | None:
if namespace := args["--ns"]:
return (namespace,)
elif args["-n"]:
return (path.parent.stem,)
elif args["-N"]:
return tuple(path.parent.parts)
def main():
args = run_docopt(__doc__)
# print(args)
path = Path(args["<path>"])
fullpath = Path(__file__).parent / args["--root"] / args["<path>"]
if not (args["--force"]) and fullpath.exists():
print("file already exists")
return
namespace = get_namespace(path, args)
text = create_text(path, namespace=namespace)
save_text_to(text, fullpath)
if args["--switch"]:
from subprocess import run
run(["code", str(fullpath)])
if __name__ == "__main__":
main()