IncludeCPP 3.3.11__py3-none-any.whl → 3.4.2__py3-none-any.whl
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.
- includecpp/__init__.py +4 -3
- includecpp/cli/commands.py +665 -62
- includecpp/core/ai_integration.py +69 -34
- includecpp/core/cppy_converter.py +570 -31
- includecpp/core/cssl/__init__.py +40 -0
- includecpp/core/cssl/cssl_builtins.py +1693 -0
- includecpp/core/cssl/cssl_events.py +621 -0
- includecpp/core/cssl/cssl_modules.py +2803 -0
- includecpp/core/cssl/cssl_parser.py +1493 -0
- includecpp/core/cssl/cssl_runtime.py +1549 -0
- includecpp/core/cssl/cssl_syntax.py +488 -0
- includecpp/core/cssl/cssl_types.py +390 -0
- includecpp/core/cssl_bridge.py +132 -0
- includecpp/core/error_formatter.py +50 -19
- includecpp/core/project_ui.py +3370 -0
- includecpp/core/settings_ui.py +127 -48
- includecpp/generator/parser.cpp +81 -0
- {includecpp-3.3.11.dist-info → includecpp-3.4.2.dist-info}/METADATA +160 -18
- includecpp-3.4.2.dist-info/RECORD +40 -0
- includecpp-3.3.11.dist-info/RECORD +0 -30
- {includecpp-3.3.11.dist-info → includecpp-3.4.2.dist-info}/WHEEL +0 -0
- {includecpp-3.3.11.dist-info → includecpp-3.4.2.dist-info}/entry_points.txt +0 -0
- {includecpp-3.3.11.dist-info → includecpp-3.4.2.dist-info}/licenses/LICENSE +0 -0
- {includecpp-3.3.11.dist-info → includecpp-3.4.2.dist-info}/top_level.txt +0 -0
includecpp/core/settings_ui.py
CHANGED
|
@@ -5,7 +5,8 @@ from pathlib import Path
|
|
|
5
5
|
try:
|
|
6
6
|
from PyQt6.QtWidgets import (
|
|
7
7
|
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
|
8
|
-
QPushButton, QLineEdit, QCheckBox, QComboBox, QFrame
|
|
8
|
+
QPushButton, QLineEdit, QCheckBox, QComboBox, QFrame,
|
|
9
|
+
QScrollArea
|
|
9
10
|
)
|
|
10
11
|
from PyQt6.QtCore import Qt
|
|
11
12
|
from PyQt6.QtGui import QFont
|
|
@@ -14,6 +15,18 @@ except ImportError:
|
|
|
14
15
|
PYQT_AVAILABLE = False
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def is_experimental_enabled() -> bool:
|
|
19
|
+
"""Check if experimental features are enabled globally."""
|
|
20
|
+
config_path = Path.home() / '.includecpp' / '.secret'
|
|
21
|
+
if config_path.exists():
|
|
22
|
+
try:
|
|
23
|
+
config = json.loads(config_path.read_text(encoding='utf-8'))
|
|
24
|
+
return config.get('experimental_features', False)
|
|
25
|
+
except Exception:
|
|
26
|
+
pass
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
|
|
17
30
|
class SettingsWidget(QWidget):
|
|
18
31
|
def __init__(self):
|
|
19
32
|
super().__init__()
|
|
@@ -25,24 +38,26 @@ class SettingsWidget(QWidget):
|
|
|
25
38
|
def _load_config(self):
|
|
26
39
|
if self.config_path.exists():
|
|
27
40
|
try:
|
|
28
|
-
return json.loads(self.config_path.read_text())
|
|
29
|
-
except:
|
|
41
|
+
return json.loads(self.config_path.read_text(encoding='utf-8'))
|
|
42
|
+
except Exception:
|
|
30
43
|
pass
|
|
31
44
|
return {}
|
|
32
45
|
|
|
33
46
|
def _save_config(self):
|
|
34
47
|
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
35
|
-
self.config_path.write_text(json.dumps(self.config, indent=2))
|
|
48
|
+
self.config_path.write_text(json.dumps(self.config, indent=2), encoding='utf-8')
|
|
36
49
|
|
|
37
50
|
def _setup_ui(self):
|
|
38
51
|
self.setWindowTitle('IncludeCPP Settings')
|
|
39
|
-
self.setFixedSize(
|
|
52
|
+
self.setFixedSize(360, 580)
|
|
40
53
|
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
|
41
54
|
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
|
42
55
|
|
|
56
|
+
# Main container with background
|
|
43
57
|
main = QWidget(self)
|
|
44
|
-
main.setGeometry(0, 0,
|
|
45
|
-
|
|
58
|
+
main.setGeometry(0, 0, 360, 580)
|
|
59
|
+
|
|
60
|
+
base_style = '''
|
|
46
61
|
QWidget {
|
|
47
62
|
background-color: #1a1a1a;
|
|
48
63
|
border-radius: 12px;
|
|
@@ -51,15 +66,16 @@ class SettingsWidget(QWidget):
|
|
|
51
66
|
QLabel {
|
|
52
67
|
color: #e0e0e0;
|
|
53
68
|
font-size: 12px;
|
|
69
|
+
background-color: transparent;
|
|
54
70
|
}
|
|
55
71
|
QLineEdit {
|
|
56
72
|
background-color: #2d2d2d;
|
|
57
73
|
border: 1px solid #3d3d3d;
|
|
58
74
|
border-radius: 6px;
|
|
59
|
-
padding: 10px
|
|
75
|
+
padding: 8px 10px;
|
|
60
76
|
color: #e0e0e0;
|
|
61
|
-
font-size:
|
|
62
|
-
min-height:
|
|
77
|
+
font-size: 12px;
|
|
78
|
+
min-height: 14px;
|
|
63
79
|
}
|
|
64
80
|
QLineEdit:focus {
|
|
65
81
|
border: 1px solid #4a9eff;
|
|
@@ -68,9 +84,9 @@ class SettingsWidget(QWidget):
|
|
|
68
84
|
background-color: #2d2d2d;
|
|
69
85
|
border: 1px solid #3d3d3d;
|
|
70
86
|
border-radius: 6px;
|
|
71
|
-
padding:
|
|
87
|
+
padding: 8px 16px;
|
|
72
88
|
color: #e0e0e0;
|
|
73
|
-
font-size:
|
|
89
|
+
font-size: 12px;
|
|
74
90
|
}
|
|
75
91
|
QPushButton:hover {
|
|
76
92
|
background-color: #3d3d3d;
|
|
@@ -80,11 +96,12 @@ class SettingsWidget(QWidget):
|
|
|
80
96
|
}
|
|
81
97
|
QCheckBox {
|
|
82
98
|
color: #e0e0e0;
|
|
83
|
-
font-size:
|
|
99
|
+
font-size: 12px;
|
|
100
|
+
background-color: transparent;
|
|
84
101
|
}
|
|
85
102
|
QCheckBox::indicator {
|
|
86
|
-
width:
|
|
87
|
-
height:
|
|
103
|
+
width: 16px;
|
|
104
|
+
height: 16px;
|
|
88
105
|
border-radius: 4px;
|
|
89
106
|
background-color: #2d2d2d;
|
|
90
107
|
border: 1px solid #3d3d3d;
|
|
@@ -96,10 +113,10 @@ class SettingsWidget(QWidget):
|
|
|
96
113
|
background-color: #2d2d2d;
|
|
97
114
|
border: 1px solid #3d3d3d;
|
|
98
115
|
border-radius: 6px;
|
|
99
|
-
padding: 10px
|
|
116
|
+
padding: 8px 10px;
|
|
100
117
|
color: #e0e0e0;
|
|
101
|
-
font-size:
|
|
102
|
-
min-height:
|
|
118
|
+
font-size: 12px;
|
|
119
|
+
min-height: 14px;
|
|
103
120
|
}
|
|
104
121
|
QComboBox::drop-down {
|
|
105
122
|
border: none;
|
|
@@ -110,76 +127,131 @@ class SettingsWidget(QWidget):
|
|
|
110
127
|
color: #e0e0e0;
|
|
111
128
|
selection-background-color: #4a9eff;
|
|
112
129
|
}
|
|
113
|
-
|
|
130
|
+
QScrollArea {
|
|
131
|
+
background-color: transparent;
|
|
132
|
+
border: none;
|
|
133
|
+
}
|
|
134
|
+
QScrollBar:vertical {
|
|
135
|
+
background-color: #2d2d2d;
|
|
136
|
+
width: 8px;
|
|
137
|
+
border-radius: 4px;
|
|
138
|
+
}
|
|
139
|
+
QScrollBar::handle:vertical {
|
|
140
|
+
background-color: #4a4a4a;
|
|
141
|
+
border-radius: 4px;
|
|
142
|
+
min-height: 20px;
|
|
143
|
+
}
|
|
144
|
+
QScrollBar::handle:vertical:hover {
|
|
145
|
+
background-color: #5a5a5a;
|
|
146
|
+
}
|
|
147
|
+
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
|
|
148
|
+
height: 0px;
|
|
149
|
+
}
|
|
150
|
+
'''
|
|
151
|
+
main.setStyleSheet(base_style)
|
|
114
152
|
|
|
115
|
-
layout
|
|
116
|
-
|
|
117
|
-
|
|
153
|
+
# Main layout for the container
|
|
154
|
+
main_layout = QVBoxLayout(main)
|
|
155
|
+
main_layout.setContentsMargins(16, 16, 16, 16)
|
|
156
|
+
main_layout.setSpacing(8)
|
|
118
157
|
|
|
158
|
+
# Header (fixed, not scrollable)
|
|
119
159
|
header = QHBoxLayout()
|
|
120
|
-
title = QLabel('IncludeCPP')
|
|
121
|
-
title.setFont(QFont('Segoe UI',
|
|
122
|
-
title.setStyleSheet('color: #4a9eff;')
|
|
160
|
+
title = QLabel('IncludeCPP Settings')
|
|
161
|
+
title.setFont(QFont('Segoe UI', 13, QFont.Weight.Bold))
|
|
162
|
+
title.setStyleSheet('color: #4a9eff; background-color: transparent;')
|
|
123
163
|
header.addWidget(title)
|
|
124
164
|
header.addStretch()
|
|
125
165
|
close_btn = QPushButton('×')
|
|
126
166
|
close_btn.setFixedSize(24, 24)
|
|
127
|
-
close_btn.setStyleSheet('font-size:
|
|
167
|
+
close_btn.setStyleSheet('font-size: 16px; border-radius: 12px;')
|
|
128
168
|
close_btn.clicked.connect(self.close)
|
|
129
169
|
header.addWidget(close_btn)
|
|
130
|
-
|
|
170
|
+
main_layout.addLayout(header)
|
|
171
|
+
|
|
172
|
+
self._add_separator(main_layout)
|
|
131
173
|
|
|
132
|
-
|
|
174
|
+
# Scroll area for content
|
|
175
|
+
scroll = QScrollArea()
|
|
176
|
+
scroll.setWidgetResizable(True)
|
|
177
|
+
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
178
|
+
scroll.setStyleSheet('QScrollArea { background-color: transparent; border: none; }')
|
|
133
179
|
|
|
180
|
+
# Content widget inside scroll area
|
|
181
|
+
content = QWidget()
|
|
182
|
+
content.setStyleSheet('background-color: transparent;')
|
|
183
|
+
content_layout = QVBoxLayout(content)
|
|
184
|
+
content_layout.setContentsMargins(0, 0, 8, 0)
|
|
185
|
+
content_layout.setSpacing(10)
|
|
186
|
+
|
|
187
|
+
# --- Experimental Features Section ---
|
|
188
|
+
exp_label = QLabel('Experimental')
|
|
189
|
+
exp_label.setFont(QFont('Segoe UI', 10, QFont.Weight.Bold))
|
|
190
|
+
exp_label.setStyleSheet('color: #ff9800; background-color: transparent;')
|
|
191
|
+
content_layout.addWidget(exp_label)
|
|
192
|
+
|
|
193
|
+
self.experimental_enabled = QCheckBox('Enable Experimental Features')
|
|
194
|
+
self.experimental_enabled.setToolTip('Enables AI and CPPY commands (may contain bugs)')
|
|
195
|
+
content_layout.addWidget(self.experimental_enabled)
|
|
196
|
+
|
|
197
|
+
self._add_separator(content_layout)
|
|
198
|
+
|
|
199
|
+
# --- AI Configuration Section ---
|
|
134
200
|
ai_label = QLabel('AI Configuration')
|
|
135
|
-
ai_label.setFont(QFont('Segoe UI',
|
|
136
|
-
|
|
201
|
+
ai_label.setFont(QFont('Segoe UI', 10, QFont.Weight.Bold))
|
|
202
|
+
content_layout.addWidget(ai_label)
|
|
137
203
|
|
|
138
204
|
self.ai_enabled = QCheckBox('Enable AI Features')
|
|
139
|
-
|
|
205
|
+
content_layout.addWidget(self.ai_enabled)
|
|
140
206
|
|
|
141
|
-
|
|
207
|
+
content_layout.addWidget(QLabel('OpenAI API Key'))
|
|
142
208
|
self.api_key = QLineEdit()
|
|
143
209
|
self.api_key.setEchoMode(QLineEdit.EchoMode.Password)
|
|
144
210
|
self.api_key.setPlaceholderText('sk-...')
|
|
145
|
-
|
|
211
|
+
content_layout.addWidget(self.api_key)
|
|
146
212
|
|
|
147
|
-
|
|
213
|
+
content_layout.addWidget(QLabel('Model'))
|
|
148
214
|
self.model = QComboBox()
|
|
149
215
|
self.model.addItems(['gpt-5', 'gpt-5-nano', 'gpt-4o', 'gpt-4-turbo', 'gpt-3.5-turbo'])
|
|
150
|
-
|
|
216
|
+
content_layout.addWidget(self.model)
|
|
151
217
|
|
|
152
|
-
self._add_separator(
|
|
218
|
+
self._add_separator(content_layout)
|
|
153
219
|
|
|
220
|
+
# --- API Tokens Section ---
|
|
154
221
|
tokens_label = QLabel('API Tokens')
|
|
155
|
-
tokens_label.setFont(QFont('Segoe UI',
|
|
156
|
-
|
|
222
|
+
tokens_label.setFont(QFont('Segoe UI', 10, QFont.Weight.Bold))
|
|
223
|
+
content_layout.addWidget(tokens_label)
|
|
157
224
|
|
|
158
|
-
|
|
225
|
+
content_layout.addWidget(QLabel('Brave Search API'))
|
|
159
226
|
self.brave_key = QLineEdit()
|
|
160
227
|
self.brave_key.setEchoMode(QLineEdit.EchoMode.Password)
|
|
161
228
|
self.brave_key.setPlaceholderText('Token for --websearch')
|
|
162
|
-
|
|
229
|
+
content_layout.addWidget(self.brave_key)
|
|
163
230
|
|
|
164
|
-
self._add_separator(
|
|
231
|
+
self._add_separator(content_layout)
|
|
165
232
|
|
|
233
|
+
# --- Usage Limits Section ---
|
|
166
234
|
limits_label = QLabel('Usage Limits')
|
|
167
|
-
limits_label.setFont(QFont('Segoe UI',
|
|
168
|
-
|
|
235
|
+
limits_label.setFont(QFont('Segoe UI', 10, QFont.Weight.Bold))
|
|
236
|
+
content_layout.addWidget(limits_label)
|
|
169
237
|
|
|
170
|
-
|
|
238
|
+
content_layout.addWidget(QLabel('Daily Token Limit'))
|
|
171
239
|
self.daily_limit = QLineEdit()
|
|
172
240
|
self.daily_limit.setPlaceholderText('220000')
|
|
173
|
-
|
|
241
|
+
content_layout.addWidget(self.daily_limit)
|
|
242
|
+
|
|
243
|
+
content_layout.addStretch()
|
|
174
244
|
|
|
175
|
-
|
|
245
|
+
scroll.setWidget(content)
|
|
246
|
+
main_layout.addWidget(scroll)
|
|
176
247
|
|
|
248
|
+
# Save button (fixed at bottom)
|
|
177
249
|
btn_layout = QHBoxLayout()
|
|
178
250
|
save_btn = QPushButton('Save')
|
|
179
|
-
save_btn.setStyleSheet('background-color: #4a9eff;')
|
|
251
|
+
save_btn.setStyleSheet('background-color: #4a9eff; font-weight: bold;')
|
|
180
252
|
save_btn.clicked.connect(self._save)
|
|
181
253
|
btn_layout.addWidget(save_btn)
|
|
182
|
-
|
|
254
|
+
main_layout.addLayout(btn_layout)
|
|
183
255
|
|
|
184
256
|
self._drag_pos = None
|
|
185
257
|
|
|
@@ -190,6 +262,9 @@ class SettingsWidget(QWidget):
|
|
|
190
262
|
layout.addWidget(line)
|
|
191
263
|
|
|
192
264
|
def _load_values(self):
|
|
265
|
+
# Experimental features
|
|
266
|
+
self.experimental_enabled.setChecked(self.config.get('experimental_features', False))
|
|
267
|
+
# AI settings
|
|
193
268
|
self.ai_enabled.setChecked(self.config.get('enabled', False))
|
|
194
269
|
api = self.config.get('api_key', '')
|
|
195
270
|
if api:
|
|
@@ -205,10 +280,14 @@ class SettingsWidget(QWidget):
|
|
|
205
280
|
self.daily_limit.setText(str(daily_limit))
|
|
206
281
|
|
|
207
282
|
def _save(self):
|
|
283
|
+
# Experimental features
|
|
284
|
+
self.config['experimental_features'] = self.experimental_enabled.isChecked()
|
|
285
|
+
# AI settings
|
|
208
286
|
self.config['enabled'] = self.ai_enabled.isChecked()
|
|
209
287
|
api = self.api_key.text().strip()
|
|
210
288
|
if api:
|
|
211
289
|
self.config['api_key'] = api
|
|
290
|
+
# Only update model if user explicitly changed it (preserve existing if combo unchanged)
|
|
212
291
|
self.config['model'] = self.model.currentText()
|
|
213
292
|
brave = self.brave_key.text().strip()
|
|
214
293
|
if brave:
|
includecpp/generator/parser.cpp
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include <functional>
|
|
9
9
|
#include <filesystem>
|
|
10
10
|
#include <iterator>
|
|
11
|
+
#include <set>
|
|
11
12
|
|
|
12
13
|
int API::main(int argc, char* argv[]) {
|
|
13
14
|
if (argc < 5) {
|
|
@@ -489,6 +490,27 @@ ModuleDescriptor API::parse_cp_file(const std::string& filepath) {
|
|
|
489
490
|
sig.param_types.push_back(parts[i]);
|
|
490
491
|
}
|
|
491
492
|
|
|
493
|
+
// v3.3.22: Also populate parameters for display in get command
|
|
494
|
+
for (size_t i = 0; i < sig.param_types.size(); ++i) {
|
|
495
|
+
ParameterInfo param;
|
|
496
|
+
std::string type_str = sig.param_types[i];
|
|
497
|
+
param.type = type_str;
|
|
498
|
+
param.name = "arg" + std::to_string(i + 1);
|
|
499
|
+
// Check for const
|
|
500
|
+
if (type_str.find("const ") != std::string::npos) {
|
|
501
|
+
param.is_const = true;
|
|
502
|
+
}
|
|
503
|
+
// Check for reference
|
|
504
|
+
if (!type_str.empty() && type_str.back() == '&') {
|
|
505
|
+
param.is_reference = true;
|
|
506
|
+
}
|
|
507
|
+
// Check for pointer
|
|
508
|
+
if (!type_str.empty() && type_str.back() == '*') {
|
|
509
|
+
param.is_pointer = true;
|
|
510
|
+
}
|
|
511
|
+
sig.parameters.push_back(param);
|
|
512
|
+
}
|
|
513
|
+
|
|
492
514
|
cb.method_signatures.push_back(sig);
|
|
493
515
|
// Also add to legacy methods list for backward compatibility
|
|
494
516
|
cb.methods.push_back(sig.name);
|
|
@@ -678,6 +700,47 @@ ModuleDescriptor API::parse_cp_file(const std::string& filepath) {
|
|
|
678
700
|
validate_namespace_includecpp(desc.source_path, desc.module_name);
|
|
679
701
|
}
|
|
680
702
|
|
|
703
|
+
// v3.4.1: Auto-detect header from #include directives in source file
|
|
704
|
+
if (!desc.has_header && !desc.source_path.empty()) {
|
|
705
|
+
std::ifstream source_file(desc.source_path);
|
|
706
|
+
if (source_file.is_open()) {
|
|
707
|
+
std::string line;
|
|
708
|
+
std::regex include_regex(R"(^\s*#include\s*"([^"]+\.h(?:pp)?)")");
|
|
709
|
+
std::smatch match;
|
|
710
|
+
|
|
711
|
+
while (std::getline(source_file, line)) {
|
|
712
|
+
if (std::regex_search(line, match, include_regex)) {
|
|
713
|
+
std::string header_name = match[1].str();
|
|
714
|
+
// Skip standard headers and pybind11 headers
|
|
715
|
+
if (header_name.find("pybind11") == std::string::npos &&
|
|
716
|
+
header_name.find("std") == std::string::npos) {
|
|
717
|
+
// Found a local header - construct the path
|
|
718
|
+
std::filesystem::path source_path(desc.source_path);
|
|
719
|
+
std::filesystem::path header_path = source_path.parent_path() / header_name;
|
|
720
|
+
|
|
721
|
+
// Check if the header file exists
|
|
722
|
+
if (std::filesystem::exists(header_path)) {
|
|
723
|
+
desc.header_path = header_path.string();
|
|
724
|
+
desc.has_header = true;
|
|
725
|
+
std::cout << "NOTE: Auto-detected header for '" << desc.module_name
|
|
726
|
+
<< "': " << desc.header_path << std::endl;
|
|
727
|
+
break;
|
|
728
|
+
}
|
|
729
|
+
// Also try in include/ subdirectory
|
|
730
|
+
header_path = source_path.parent_path().parent_path() / "include" / header_name;
|
|
731
|
+
if (std::filesystem::exists(header_path)) {
|
|
732
|
+
desc.header_path = header_path.string();
|
|
733
|
+
desc.has_header = true;
|
|
734
|
+
std::cout << "NOTE: Auto-detected header for '" << desc.module_name
|
|
735
|
+
<< "': " << desc.header_path << std::endl;
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
681
744
|
return desc;
|
|
682
745
|
}
|
|
683
746
|
|
|
@@ -901,6 +964,11 @@ std::string API::generate_pybind11_code(const std::vector<ModuleDescriptor>& mod
|
|
|
901
964
|
code << "#include <pybind11/complex.h>\n";
|
|
902
965
|
code << "#include <pybind11/chrono.h>\n\n";
|
|
903
966
|
|
|
967
|
+
// v3.3.22: Track included headers to prevent duplicates
|
|
968
|
+
std::set<std::string> included_headers;
|
|
969
|
+
std::vector<std::string> ordered_includes;
|
|
970
|
+
|
|
971
|
+
// First pass: collect all headers and detect dependencies
|
|
904
972
|
for (const auto& mod : modules) {
|
|
905
973
|
std::string include_path;
|
|
906
974
|
if (mod.has_header) {
|
|
@@ -912,6 +980,19 @@ std::string API::generate_pybind11_code(const std::vector<ModuleDescriptor>& mod
|
|
|
912
980
|
<< "' has no separate header, including source file: "
|
|
913
981
|
<< include_path << std::endl;
|
|
914
982
|
}
|
|
983
|
+
|
|
984
|
+
// Skip if already included
|
|
985
|
+
if (included_headers.find(include_path) != included_headers.end()) {
|
|
986
|
+
std::cout << "NOTE: Skipping duplicate include: " << include_path << std::endl;
|
|
987
|
+
continue;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
included_headers.insert(include_path);
|
|
991
|
+
ordered_includes.push_back(include_path);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// Generate includes (duplicates already filtered)
|
|
995
|
+
for (const auto& include_path : ordered_includes) {
|
|
915
996
|
code << "#include \"" << include_path << "\"\n";
|
|
916
997
|
}
|
|
917
998
|
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: IncludeCPP
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.2
|
|
4
4
|
Summary: Professional C++ Python bindings with type-generic templates, pystubs and native threading
|
|
5
|
-
Home-page: https://github.com/
|
|
6
|
-
Author:
|
|
7
|
-
Author-email:
|
|
5
|
+
Home-page: https://github.com/liliassg/IncludeCPP
|
|
6
|
+
Author: Lilias Hatterscheidt
|
|
7
|
+
Author-email: lilias@includecpp.dev
|
|
8
8
|
License: MIT
|
|
9
|
-
Project-URL:
|
|
10
|
-
Project-URL:
|
|
11
|
-
Project-URL: Repository, https://github.com/includecpp/includecpp
|
|
12
|
-
Project-URL: Bug Tracker, https://github.com/includecpp/includecpp/issues
|
|
9
|
+
Project-URL: Repository, https://github.com/liliassg/IncludeCPP
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/liliasg/IncludeCPP/issues
|
|
13
11
|
Keywords: c++,python,bindings,pybind11,template,performance,threading
|
|
14
12
|
Classifier: Development Status :: 4 - Beta
|
|
15
13
|
Classifier: Intended Audience :: Developers
|
|
16
14
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
-
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
20
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
20
|
Classifier: Programming Language :: C++
|
|
24
21
|
Classifier: License :: OSI Approved :: MIT License
|
|
25
22
|
Classifier: Operating System :: OS Independent
|
|
@@ -30,7 +27,7 @@ Requires-Dist: pybind11>=2.11.0
|
|
|
30
27
|
Requires-Dist: click>=8.0.0
|
|
31
28
|
Requires-Dist: typing-extensions>=4.0.0
|
|
32
29
|
Requires-Dist: requests>=2.28.0
|
|
33
|
-
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
34
31
|
Dynamic: home-page
|
|
35
32
|
Dynamic: license-file
|
|
36
33
|
Dynamic: requires-python
|
|
@@ -604,8 +601,159 @@ Options:
|
|
|
604
601
|
- pybind11 (installed automatically)
|
|
605
602
|
- CMake (for build generation)
|
|
606
603
|
|
|
604
|
+
# Experimental Features
|
|
605
|
+
|
|
606
|
+
The following features are **experimental** and may contain bugs:
|
|
607
|
+
|
|
608
|
+
- `includecpp ai` - AI-powered code assistance
|
|
609
|
+
- `includecpp cppy` - Python to C++ code conversion
|
|
610
|
+
|
|
611
|
+
These commands are **hidden by default**. To enable them:
|
|
612
|
+
|
|
613
|
+
```bash
|
|
614
|
+
includecpp settings
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
Then check **"Enable Experimental Features"** and save.
|
|
618
|
+
|
|
619
|
+
**Warning:** Experimental features are under active development and may:
|
|
620
|
+
- Produce incorrect output
|
|
621
|
+
- Have breaking changes between versions
|
|
622
|
+
- Be removed or significantly changed
|
|
623
|
+
|
|
624
|
+
Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCPP/issues
|
|
625
|
+
|
|
607
626
|
# Changelog
|
|
608
627
|
|
|
628
|
+
## v3.4.2
|
|
629
|
+
- **New Feature: `exec` Command**
|
|
630
|
+
- Interactive REPL for quick code testing without creating files
|
|
631
|
+
- `includecpp exec py` - Python REPL with IncludeCPP support
|
|
632
|
+
- `includecpp exec cpp` - C++ REPL with auto-compilation
|
|
633
|
+
- Auto-import modules: `includecpp exec py mymodule`
|
|
634
|
+
- Auto-import from plugins: `includecpp exec py plugins/math.cp`
|
|
635
|
+
- Import all modules: `includecpp exec py --all`
|
|
636
|
+
- Enter code line by line, press ENTER on empty line to execute
|
|
637
|
+
|
|
638
|
+
## v3.4.1
|
|
639
|
+
- **Bug Fixes:**
|
|
640
|
+
- fix command: Fixed false positives for unused variables (sum, memory_) using word-boundary matching
|
|
641
|
+
- CPPY: C++ reserved words (double, int, void, etc.) now properly escaped as Python identifiers
|
|
642
|
+
- CPPY: C++ STL functions (accumulate, find, sort, reverse) properly converted to Python equivalents
|
|
643
|
+
- CPPY: Member variables with trailing underscore (memory_) now get self. prefix
|
|
644
|
+
- CPPY: Private class members now detected for self. prefix conversion
|
|
645
|
+
- Plugin: Auto-detect header files from #include directives in source files
|
|
646
|
+
|
|
647
|
+
## v3.4.0
|
|
648
|
+
- **CodeMaker Major Update:**
|
|
649
|
+
- New Source node type with 8 connection ports for code generation
|
|
650
|
+
- Smart code generation: Source nodes generate Python/Plugin files with all connected nodes included
|
|
651
|
+
- Right-click on Source node: "Create Python" creates .py in project root
|
|
652
|
+
- Right-click on Source node: "Create Plugin" creates .cp, .h, .cpp in plugins/ and include/
|
|
653
|
+
- Code options hidden after file generation (prevents duplicates)
|
|
654
|
+
- Enhanced description display with background rect in node body
|
|
655
|
+
- Arrow key navigation to pan the canvas
|
|
656
|
+
- New toolbar buttons: Align H, Align V, Auto-Arrange
|
|
657
|
+
- Quick-add buttons: +Source, +Class, +Function
|
|
658
|
+
- Properties Panel on the right side for editing selected nodes
|
|
659
|
+
- Auto-arrange algorithm for grid layout
|
|
660
|
+
- Align horizontal/vertical for selected nodes
|
|
661
|
+
- **Bug Fixes:**
|
|
662
|
+
- Changelog encoding fixes for Windows console
|
|
663
|
+
- CPPY C++ keyword escaping (double, int, etc.)
|
|
664
|
+
- CPPY C++ to Python syntax conversion improvements
|
|
665
|
+
- CPPY self. prefix for member variables
|
|
666
|
+
- Plugin auto-header detection from #include
|
|
667
|
+
|
|
668
|
+
## v3.3.21
|
|
669
|
+
- **Encoding Fixes:**
|
|
670
|
+
- Replaced Unicode arrow characters with ASCII in changelog (Windows console compatibility)
|
|
671
|
+
|
|
672
|
+
## v3.3.20
|
|
673
|
+
- **Bug Fixes:**
|
|
674
|
+
- Fixed `QPoint.toPoint()` AttributeError in rubber band selection
|
|
675
|
+
- Added UTF-8 encoding to all file read/write operations for cross-platform compatibility
|
|
676
|
+
- Fixed bare `except:` clauses to proper `except Exception:` in settings_ui.py
|
|
677
|
+
|
|
678
|
+
## v3.3.19
|
|
679
|
+
- **PyQt6 Import Fix:**
|
|
680
|
+
- Fixed silent import failure that caused "PyQt6 not installed" error even when installed
|
|
681
|
+
- Moved `QUndoStack`, `QUndoCommand`, `QShortcut` from QtWidgets to QtGui (correct location in PyQt6)
|
|
682
|
+
|
|
683
|
+
## v3.3.18
|
|
684
|
+
- **CodeMaker Visual Editor (Experimental):**
|
|
685
|
+
- Complete rewrite of `project` command with professional-grade UI
|
|
686
|
+
- 24 node types across 5 categories (Code Structures, Functions, Data, Organization, Flow)
|
|
687
|
+
- Undo/redo system with full command history
|
|
688
|
+
- Multi-selection with rubber band and Ctrl+Click
|
|
689
|
+
- Copy/paste/duplicate with Ctrl+C/V/D shortcuts
|
|
690
|
+
- Node grouping with Ctrl+G
|
|
691
|
+
- Code generation for C++ (header/source) and Python
|
|
692
|
+
- Search and filter nodes by name and type
|
|
693
|
+
- Export to PNG/SVG with transparency support
|
|
694
|
+
- Categorized right-click context menus
|
|
695
|
+
- Toolbar with common actions
|
|
696
|
+
- Cross-platform font detection (Windows/macOS/Linux)
|
|
697
|
+
- DPI-aware scaling for high-resolution displays
|
|
698
|
+
- **Experimental Feature Gating:**
|
|
699
|
+
- `project` command now requires "Enable Experimental Features" in settings
|
|
700
|
+
- Consistent gating with `ai` and `cppy` commands
|
|
701
|
+
|
|
702
|
+
## v3.3.16-3.3.17
|
|
703
|
+
- **QPen Bug Fixes:**
|
|
704
|
+
- Fixed 3 instances of `setPen(Qt.PenStyle.NoPen)` to `setPen(QPen(Qt.PenStyle.NoPen))`
|
|
705
|
+
- Proper QPen construction for PyQt6 compatibility
|
|
706
|
+
|
|
707
|
+
## v3.3.15
|
|
708
|
+
- **CPPY Converter Major Fixes:**
|
|
709
|
+
- Functions returning container now get `std::vector<T>` return type (e.g., shuffle_list)
|
|
710
|
+
- `max(items)` / `min(items)` now correctly uses `std::max_element` / `std::min_element`
|
|
711
|
+
- Template element parameters (`value`, `item`) now use `const T&` instead of `double`
|
|
712
|
+
- Explicit template instantiations now include correct return types and all parameters
|
|
713
|
+
- Python docstrings now become C++ comments instead of dangling string literals
|
|
714
|
+
- **Unicode Fallback System:**
|
|
715
|
+
- AI progress indicators use ASCII fallbacks on Windows terminals
|
|
716
|
+
- Fixed encoding errors in changelog display
|
|
717
|
+
|
|
718
|
+
## v3.3.14
|
|
719
|
+
- **Experimental Features System:**
|
|
720
|
+
- AI and CPPY commands now hidden by default
|
|
721
|
+
- Enable via Settings UI: "Enable Experimental Features" checkbox
|
|
722
|
+
- Warning about potential bugs documented in README
|
|
723
|
+
- **Settings UI Improvements:**
|
|
724
|
+
- Added scrollable content area to prevent layout squashing
|
|
725
|
+
- New "Experimental" section with orange header
|
|
726
|
+
- Better spacing and styling for all elements
|
|
727
|
+
- Preserved existing config values on save
|
|
728
|
+
|
|
729
|
+
## v3.3.13
|
|
730
|
+
- **Template Support for Generic Functions:**
|
|
731
|
+
- Generic container parameters now generate proper C++ templates
|
|
732
|
+
- `template<typename T> T getChoice(const std::vector<T>& choices)` instead of invalid `std::vector<auto>`
|
|
733
|
+
- Automatic explicit template instantiations for int, double, std::string
|
|
734
|
+
- **AI Conversion - No pybind11:**
|
|
735
|
+
- AI no longer generates pybind11 code - IncludeCPP handles bindings automatically
|
|
736
|
+
- Clean C++ output in `namespace includecpp`
|
|
737
|
+
- User runs `includecpp plugin` separately to generate bindings
|
|
738
|
+
- **AI Context - Dynamic README:**
|
|
739
|
+
- AI now loads README.md dynamically for accurate IncludeCPP documentation
|
|
740
|
+
- Better understanding of IncludeCPP workflow and patterns
|
|
741
|
+
|
|
742
|
+
## v3.3.12
|
|
743
|
+
- **Smart Type Inference:**
|
|
744
|
+
- Parameter types now inferred from common naming patterns (start/end -> int, name/path -> string, etc.)
|
|
745
|
+
- Variable type tracking throughout conversion for accurate string detection
|
|
746
|
+
- Loop variable types inferred from iterables (enumerate, for loops)
|
|
747
|
+
- **String Conversion Fix:**
|
|
748
|
+
- No more `std::to_string()` on already-string variables in f-strings
|
|
749
|
+
- `_is_string_expr()` method for comprehensive string type detection
|
|
750
|
+
- String variables detected by name, type tracking, and method calls
|
|
751
|
+
- **AI Conversion Improvements:**
|
|
752
|
+
- Explicit file extension enforcement (.cpp NOT .cp, .h NOT .hpp)
|
|
753
|
+
- Better --no-h flag handling with clear AI instructions
|
|
754
|
+
- AI can request clarification on unconvertible modules (tkinter, pygame, etc.)
|
|
755
|
+
- User prompted for input when AI needs guidance
|
|
756
|
+
|
|
609
757
|
## v3.3.11
|
|
610
758
|
- **CPPY Converter Improvements:**
|
|
611
759
|
- Added `_safe_arg()` and `_safe_get()` for robust bounds checking on all args
|
|
@@ -655,13 +803,7 @@ Options:
|
|
|
655
803
|
- Fixed duplicate file output in `cppy convert --ai`
|
|
656
804
|
- Plugin command now skips inline and underscore-prefixed functions
|
|
657
805
|
|
|
658
|
-
## v3.3.7
|
|
659
|
-
- Fixed AI knowledge: Now properly documents `SOURCE() && HEADER()` syntax for .cp files
|
|
660
|
-
- AI generates correct .cp format with `&& HEADER()` when creating both .cpp and .h files
|
|
661
|
-
- `cppy convert --ai --no-h` now properly instructs AI to skip header generation
|
|
662
|
-
- Fixed verbose output error in changes_summary method
|
|
663
|
-
|
|
664
806
|
|
|
665
807
|
---
|
|
666
808
|
|
|
667
|
-
MIT License | v3.
|
|
809
|
+
MIT License | v3.4.2 | [GitHub](https://github.com/liliassg/IncludeCPP)
|