cppgolf 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.
- cppgolf-0.1.0/PKG-INFO +97 -0
- cppgolf-0.1.0/README.md +70 -0
- cppgolf-0.1.0/cppgolf/__init__.py +46 -0
- cppgolf-0.1.0/cppgolf/__main__.py +148 -0
- cppgolf-0.1.0/cppgolf/golf_rename.py +452 -0
- cppgolf-0.1.0/cppgolf/merge.py +68 -0
- cppgolf-0.1.0/cppgolf/strip_comments.py +62 -0
- cppgolf-0.1.0/cppgolf/transforms.py +99 -0
- cppgolf-0.1.0/cppgolf/whitespace.py +127 -0
- cppgolf-0.1.0/cppgolf.egg-info/PKG-INFO +97 -0
- cppgolf-0.1.0/cppgolf.egg-info/SOURCES.txt +15 -0
- cppgolf-0.1.0/cppgolf.egg-info/dependency_links.txt +1 -0
- cppgolf-0.1.0/cppgolf.egg-info/entry_points.txt +2 -0
- cppgolf-0.1.0/cppgolf.egg-info/requires.txt +7 -0
- cppgolf-0.1.0/cppgolf.egg-info/top_level.txt +1 -0
- cppgolf-0.1.0/pyproject.toml +47 -0
- cppgolf-0.1.0/setup.cfg +4 -0
cppgolf-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cppgolf
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: C++ multi-file merge & code golf / minifier tool
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/yourname/cppgolf
|
|
7
|
+
Project-URL: Issues, https://github.com/yourname/cppgolf/issues
|
|
8
|
+
Keywords: cpp,c++,golf,minify,code-golf,competitive-programming
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
18
|
+
Classifier: Topic :: Text Processing :: Filters
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: tree-sitter>=0.25
|
|
22
|
+
Requires-Dist: tree-sitter-cpp>=0.23
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build; extra == "dev"
|
|
25
|
+
Requires-Dist: twine; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest; extra == "dev"
|
|
27
|
+
|
|
28
|
+
# CPPGolf
|
|
29
|
+
|
|
30
|
+
C++ 多文件合并 + 代码高尔夫(压缩)工具,专为竞技编程场景设计。
|
|
31
|
+
|
|
32
|
+
## 安装
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install cppgolf
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## CLI 用法
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
cppgolf solution.cpp # 输出到 stdout
|
|
42
|
+
cppgolf solution.cpp -o golf.cpp # 输出到文件
|
|
43
|
+
cppgolf solution.cpp -I include/ -o out.cpp
|
|
44
|
+
cppgolf solution.cpp --rename # 符号压缩
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 选项
|
|
48
|
+
|
|
49
|
+
| 选项 | 说明 |
|
|
50
|
+
|------|------|
|
|
51
|
+
| `-o FILE` | 输出文件(默认 stdout) |
|
|
52
|
+
| `-I DIR` | 追加 include 搜索目录(可多次) |
|
|
53
|
+
| `--no-merge` | 跳过 `#include "..."` 内联 |
|
|
54
|
+
| `--no-strip-comments` | 保留注释 |
|
|
55
|
+
| `--no-compress-ws` | 保留空白格式 |
|
|
56
|
+
| `--no-std-ns` | 不添加 `using namespace std` |
|
|
57
|
+
| `--no-typedefs` | 不添加 `ll`/`ld` 等类型宏 |
|
|
58
|
+
| `--keep-main-return` | 保留 `return 0;` |
|
|
59
|
+
| `--keep-endl` | 保留 `endl` |
|
|
60
|
+
| `--keep-inline` | 保留 `inline` 关键字 |
|
|
61
|
+
| `--aggressive` | 去除单语句 if/for/while 花括号 |
|
|
62
|
+
| `--shortcuts` | 高频 cout/cin → `#define` 缩写 |
|
|
63
|
+
| `--rename` | 变量/成员名压缩为 a/b/aa/… |
|
|
64
|
+
| `--stats` | 显示压缩率统计 |
|
|
65
|
+
|
|
66
|
+
## Python API
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from cppgolf import process
|
|
70
|
+
from pathlib import Path
|
|
71
|
+
|
|
72
|
+
result = process(
|
|
73
|
+
Path("solution.cpp"),
|
|
74
|
+
include_dirs=[], # 额外的 #include 搜索目录
|
|
75
|
+
rename_symbols=True,
|
|
76
|
+
)
|
|
77
|
+
print(result)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
也可单独使用各 pass:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from cppgolf import strip_comments, compress_whitespace, golf_rename_symbols
|
|
84
|
+
|
|
85
|
+
code = open("a.cpp").read()
|
|
86
|
+
code = strip_comments(code)
|
|
87
|
+
code = golf_rename_symbols(code)
|
|
88
|
+
code = compress_whitespace(code)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 功能说明
|
|
92
|
+
|
|
93
|
+
- **合并**:递归内联 `#include "..."` 本地头文件,去除 include guard / `#pragma once`,系统头去重
|
|
94
|
+
- **去注释**:状态机感知字符串,支持 `//`、`/* */`、原始字符串 `R"(...)"`
|
|
95
|
+
- **语义压缩**:`std::` 消除、`long long→ll` 宏、`endl→"\n"`、去 `return 0;`、去 `inline`
|
|
96
|
+
- **空白压缩**:token 级最小化,代码压为单行,预处理行保留换行
|
|
97
|
+
- **符号重命名**:tree-sitter AST 驱动,仅重命名用户自定义变量/参数/成员名,不碰函数名/类型名/命名空间
|
cppgolf-0.1.0/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# CPPGolf
|
|
2
|
+
|
|
3
|
+
C++ 多文件合并 + 代码高尔夫(压缩)工具,专为竞技编程场景设计。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install cppgolf
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## CLI 用法
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cppgolf solution.cpp # 输出到 stdout
|
|
15
|
+
cppgolf solution.cpp -o golf.cpp # 输出到文件
|
|
16
|
+
cppgolf solution.cpp -I include/ -o out.cpp
|
|
17
|
+
cppgolf solution.cpp --rename # 符号压缩
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 选项
|
|
21
|
+
|
|
22
|
+
| 选项 | 说明 |
|
|
23
|
+
|------|------|
|
|
24
|
+
| `-o FILE` | 输出文件(默认 stdout) |
|
|
25
|
+
| `-I DIR` | 追加 include 搜索目录(可多次) |
|
|
26
|
+
| `--no-merge` | 跳过 `#include "..."` 内联 |
|
|
27
|
+
| `--no-strip-comments` | 保留注释 |
|
|
28
|
+
| `--no-compress-ws` | 保留空白格式 |
|
|
29
|
+
| `--no-std-ns` | 不添加 `using namespace std` |
|
|
30
|
+
| `--no-typedefs` | 不添加 `ll`/`ld` 等类型宏 |
|
|
31
|
+
| `--keep-main-return` | 保留 `return 0;` |
|
|
32
|
+
| `--keep-endl` | 保留 `endl` |
|
|
33
|
+
| `--keep-inline` | 保留 `inline` 关键字 |
|
|
34
|
+
| `--aggressive` | 去除单语句 if/for/while 花括号 |
|
|
35
|
+
| `--shortcuts` | 高频 cout/cin → `#define` 缩写 |
|
|
36
|
+
| `--rename` | 变量/成员名压缩为 a/b/aa/… |
|
|
37
|
+
| `--stats` | 显示压缩率统计 |
|
|
38
|
+
|
|
39
|
+
## Python API
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from cppgolf import process
|
|
43
|
+
from pathlib import Path
|
|
44
|
+
|
|
45
|
+
result = process(
|
|
46
|
+
Path("solution.cpp"),
|
|
47
|
+
include_dirs=[], # 额外的 #include 搜索目录
|
|
48
|
+
rename_symbols=True,
|
|
49
|
+
)
|
|
50
|
+
print(result)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
也可单独使用各 pass:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from cppgolf import strip_comments, compress_whitespace, golf_rename_symbols
|
|
57
|
+
|
|
58
|
+
code = open("a.cpp").read()
|
|
59
|
+
code = strip_comments(code)
|
|
60
|
+
code = golf_rename_symbols(code)
|
|
61
|
+
code = compress_whitespace(code)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 功能说明
|
|
65
|
+
|
|
66
|
+
- **合并**:递归内联 `#include "..."` 本地头文件,去除 include guard / `#pragma once`,系统头去重
|
|
67
|
+
- **去注释**:状态机感知字符串,支持 `//`、`/* */`、原始字符串 `R"(...)"`
|
|
68
|
+
- **语义压缩**:`std::` 消除、`long long→ll` 宏、`endl→"\n"`、去 `return 0;`、去 `inline`
|
|
69
|
+
- **空白压缩**:token 级最小化,代码压为单行,预处理行保留换行
|
|
70
|
+
- **符号重命名**:tree-sitter AST 驱动,仅重命名用户自定义变量/参数/成员名,不碰函数名/类型名/命名空间
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cppgolf — C++ multi-file merge & code golf tool
|
|
3
|
+
|
|
4
|
+
公开 API:
|
|
5
|
+
process(input_file, include_dirs, **options) -> str
|
|
6
|
+
golf_rename_symbols(code) -> str
|
|
7
|
+
strip_comments(code) -> str
|
|
8
|
+
merge_files(filepath, include_dirs, visited, sys_includes) -> str
|
|
9
|
+
compress_whitespace(code) -> str
|
|
10
|
+
golf_std_namespace / golf_typedefs / golf_endl_to_newline /
|
|
11
|
+
golf_remove_main_return / golf_remove_inline /
|
|
12
|
+
golf_braces_single_stmt / golf_define_shortcuts
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from .strip_comments import strip_comments
|
|
16
|
+
from .merge import merge_files, strip_include_guard
|
|
17
|
+
from .whitespace import compress_whitespace
|
|
18
|
+
from .transforms import (
|
|
19
|
+
golf_std_namespace,
|
|
20
|
+
golf_typedefs,
|
|
21
|
+
golf_remove_main_return,
|
|
22
|
+
golf_endl_to_newline,
|
|
23
|
+
golf_remove_inline,
|
|
24
|
+
golf_braces_single_stmt,
|
|
25
|
+
golf_define_shortcuts,
|
|
26
|
+
)
|
|
27
|
+
from .golf_rename import golf_rename_symbols
|
|
28
|
+
from .__main__ import process
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"process",
|
|
32
|
+
"strip_comments",
|
|
33
|
+
"merge_files",
|
|
34
|
+
"strip_include_guard",
|
|
35
|
+
"compress_whitespace",
|
|
36
|
+
"golf_std_namespace",
|
|
37
|
+
"golf_typedefs",
|
|
38
|
+
"golf_remove_main_return",
|
|
39
|
+
"golf_endl_to_newline",
|
|
40
|
+
"golf_remove_inline",
|
|
41
|
+
"golf_braces_single_stmt",
|
|
42
|
+
"golf_define_shortcuts",
|
|
43
|
+
"golf_rename_symbols",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""cppgolf.__main__ — CLI 入口,支持 python -m cppgolf 和 cppgolf 命令"""
|
|
2
|
+
import sys
|
|
3
|
+
import argparse
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .strip_comments import strip_comments
|
|
7
|
+
from .merge import merge_files
|
|
8
|
+
from .whitespace import compress_whitespace
|
|
9
|
+
from .transforms import (
|
|
10
|
+
golf_std_namespace, golf_typedefs, golf_remove_main_return,
|
|
11
|
+
golf_endl_to_newline, golf_remove_inline,
|
|
12
|
+
golf_braces_single_stmt, golf_define_shortcuts,
|
|
13
|
+
)
|
|
14
|
+
from .golf_rename import golf_rename_symbols
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def process(
|
|
18
|
+
input_file: Path,
|
|
19
|
+
include_dirs: list,
|
|
20
|
+
*,
|
|
21
|
+
no_merge: bool = False,
|
|
22
|
+
no_strip_comments: bool = False,
|
|
23
|
+
no_compress_ws: bool = False,
|
|
24
|
+
no_std_ns: bool = False,
|
|
25
|
+
no_typedefs: bool = False,
|
|
26
|
+
keep_main_return: bool = False,
|
|
27
|
+
keep_endl: bool = False,
|
|
28
|
+
keep_inline: bool = False,
|
|
29
|
+
aggressive: bool = False,
|
|
30
|
+
define_shortcuts: bool = False,
|
|
31
|
+
rename_symbols: bool = False,
|
|
32
|
+
) -> str:
|
|
33
|
+
sys_includes: list = []
|
|
34
|
+
visited: set = set()
|
|
35
|
+
|
|
36
|
+
if not no_merge:
|
|
37
|
+
merged = merge_files(input_file, list(include_dirs), visited, sys_includes)
|
|
38
|
+
code = ''.join(sys_includes) + merged
|
|
39
|
+
else:
|
|
40
|
+
code = input_file.read_text(encoding='utf-8-sig', errors='replace')
|
|
41
|
+
|
|
42
|
+
if not no_strip_comments:
|
|
43
|
+
code = strip_comments(code)
|
|
44
|
+
|
|
45
|
+
if not keep_endl:
|
|
46
|
+
code = golf_endl_to_newline(code)
|
|
47
|
+
if not no_std_ns:
|
|
48
|
+
code = golf_std_namespace(code)
|
|
49
|
+
if not no_typedefs:
|
|
50
|
+
code = golf_typedefs(code)
|
|
51
|
+
if not keep_main_return:
|
|
52
|
+
code = golf_remove_main_return(code)
|
|
53
|
+
if not keep_inline:
|
|
54
|
+
code = golf_remove_inline(code)
|
|
55
|
+
if aggressive:
|
|
56
|
+
code = golf_braces_single_stmt(code)
|
|
57
|
+
if define_shortcuts:
|
|
58
|
+
code = golf_define_shortcuts(code)
|
|
59
|
+
if rename_symbols:
|
|
60
|
+
code = golf_rename_symbols(code)
|
|
61
|
+
|
|
62
|
+
if not no_compress_ws:
|
|
63
|
+
code = compress_whitespace(code)
|
|
64
|
+
|
|
65
|
+
return code.strip() + '\n'
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
69
|
+
p = argparse.ArgumentParser(
|
|
70
|
+
prog='cppgolf',
|
|
71
|
+
description='C++ 多文件合并 + 代码高尔夫工具',
|
|
72
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
73
|
+
epilog="""示例:
|
|
74
|
+
cppgolf solution.cpp
|
|
75
|
+
cppgolf solution.cpp -o golf.cpp
|
|
76
|
+
cppgolf solution.cpp -I include/ --rename --stats
|
|
77
|
+
""",
|
|
78
|
+
)
|
|
79
|
+
p.add_argument('input', type=Path, help='入口 C++ 文件')
|
|
80
|
+
p.add_argument('-o', '--output', type=Path, default=None, help='输出文件(默认 stdout)')
|
|
81
|
+
p.add_argument('-I', '--include', dest='include_dirs', action='append',
|
|
82
|
+
type=Path, default=[], metavar='DIR', help='追加 include 目录(可多次)')
|
|
83
|
+
|
|
84
|
+
g = p.add_argument_group('功能开关(默认全部开启)')
|
|
85
|
+
g.add_argument('--no-merge', action='store_true', help='跳过多文件合并')
|
|
86
|
+
g.add_argument('--no-strip-comments', action='store_true', help='保留注释')
|
|
87
|
+
g.add_argument('--no-compress-ws', action='store_true', help='保留空白格式')
|
|
88
|
+
g.add_argument('--no-std-ns', action='store_true', help='不添加 using namespace std')
|
|
89
|
+
g.add_argument('--no-typedefs', action='store_true', help='不添加 ll/ld 等类型宏')
|
|
90
|
+
g.add_argument('--keep-main-return', action='store_true', help='保留 main 末尾 return 0')
|
|
91
|
+
g.add_argument('--keep-endl', action='store_true', help='保留 endl')
|
|
92
|
+
g.add_argument('--keep-inline', action='store_true', help='保留 inline 关键字')
|
|
93
|
+
|
|
94
|
+
g2 = p.add_argument_group('激进优化(有风险,默认关闭)')
|
|
95
|
+
g2.add_argument('--aggressive', action='store_true',
|
|
96
|
+
help='单语句 if/for/while 去花括号')
|
|
97
|
+
g2.add_argument('--shortcuts', dest='define_shortcuts', action='store_true',
|
|
98
|
+
help='高频 cout/cin 用 #define 缩写')
|
|
99
|
+
g2.add_argument('--rename', dest='rename_symbols', action='store_true',
|
|
100
|
+
help='将用户变量/成员名压缩为短名(需要 tree-sitter-cpp)')
|
|
101
|
+
|
|
102
|
+
p.add_argument('--stats', action='store_true', help='显示压缩率统计')
|
|
103
|
+
return p
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def main():
|
|
107
|
+
parser = build_parser()
|
|
108
|
+
args = parser.parse_args()
|
|
109
|
+
|
|
110
|
+
if not args.input.exists():
|
|
111
|
+
print(f'错误:文件不存在 —— {args.input}', file=sys.stderr)
|
|
112
|
+
sys.exit(1)
|
|
113
|
+
|
|
114
|
+
original_size = args.input.stat().st_size
|
|
115
|
+
result = process(
|
|
116
|
+
args.input, args.include_dirs,
|
|
117
|
+
no_merge=args.no_merge,
|
|
118
|
+
no_strip_comments=args.no_strip_comments,
|
|
119
|
+
no_compress_ws=args.no_compress_ws,
|
|
120
|
+
no_std_ns=args.no_std_ns,
|
|
121
|
+
no_typedefs=args.no_typedefs,
|
|
122
|
+
keep_main_return=args.keep_main_return,
|
|
123
|
+
keep_endl=args.keep_endl,
|
|
124
|
+
keep_inline=args.keep_inline,
|
|
125
|
+
aggressive=args.aggressive,
|
|
126
|
+
define_shortcuts=args.define_shortcuts,
|
|
127
|
+
rename_symbols=args.rename_symbols,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def print_stats(final_size: int):
|
|
131
|
+
ratio = (1 - final_size / original_size) * 100 if original_size else 0
|
|
132
|
+
print(f'[统计] 原始:{original_size} B → 高尔夫后:{final_size} B (压缩 {ratio:.1f}%)',
|
|
133
|
+
file=sys.stderr)
|
|
134
|
+
|
|
135
|
+
if args.output:
|
|
136
|
+
args.output.write_text(result, encoding='utf-8')
|
|
137
|
+
if args.stats:
|
|
138
|
+
print_stats(args.output.stat().st_size)
|
|
139
|
+
else:
|
|
140
|
+
print(f'已写入:{args.output}', file=sys.stderr)
|
|
141
|
+
else:
|
|
142
|
+
if args.stats:
|
|
143
|
+
print_stats(len(result.encode('utf-8')))
|
|
144
|
+
sys.stdout.write(result)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
if __name__ == '__main__':
|
|
148
|
+
main()
|