IncludeCPP 4.0.2__py3-none-any.whl → 4.2.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/CHANGELOG.md +175 -0
- includecpp/DOCUMENTATION.md +593 -0
- includecpp/__init__.py +1 -1
- includecpp/__init__.pyi +4 -1
- includecpp/cli/commands.py +698 -84
- includecpp/core/ai_integration.py +46 -13
- includecpp/core/cpp_api_extensions.pyi +350 -0
- includecpp/core/cssl/CSSL_DOCUMENTATION.md +186 -5
- includecpp/core/cssl/cssl_builtins.py +101 -4
- includecpp/core/cssl/cssl_languages.py +1757 -0
- includecpp/core/cssl/cssl_parser.py +429 -98
- includecpp/core/cssl/cssl_runtime.py +666 -51
- includecpp/core/cssl/cssl_syntax.py +88 -4
- includecpp/core/cssl/cssl_types.py +172 -1
- includecpp/core/cssl_bridge.py +194 -8
- includecpp/core/cssl_bridge.pyi +148 -10
- includecpp/generator/parser.cpp +121 -4
- includecpp/generator/parser.h +6 -0
- includecpp/vscode/cssl/package.json +43 -1
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +140 -17
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/METADATA +101 -1
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/RECORD +26 -22
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/WHEEL +0 -0
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/entry_points.txt +0 -0
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/licenses/LICENSE +0 -0
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/top_level.txt +0 -0
includecpp/cli/commands.py
CHANGED
|
@@ -152,113 +152,276 @@ def _render_readme_with_colors(readme_text):
|
|
|
152
152
|
click.echo(" " + stripped)
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
def
|
|
156
|
-
"""
|
|
155
|
+
def _get_changelog_path():
|
|
156
|
+
"""Get path to CHANGELOG.md file."""
|
|
157
|
+
# Try package location first
|
|
158
|
+
package_dir = Path(__file__).parent.parent
|
|
159
|
+
changelog_path = package_dir / 'CHANGELOG.md'
|
|
160
|
+
if changelog_path.exists():
|
|
161
|
+
return changelog_path
|
|
162
|
+
# Fallback to current directory
|
|
163
|
+
cwd_path = Path.cwd() / 'CHANGELOG.md'
|
|
164
|
+
if cwd_path.exists():
|
|
165
|
+
return cwd_path
|
|
166
|
+
return None
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _parse_changelog_entries(content: str) -> list:
|
|
170
|
+
"""Parse changelog into list of version entries.
|
|
171
|
+
|
|
172
|
+
Returns list of tuples: (version_header, content_lines)
|
|
173
|
+
"""
|
|
174
|
+
entries = []
|
|
175
|
+
lines = content.split('\n')
|
|
176
|
+
current_version = None
|
|
177
|
+
current_lines = []
|
|
178
|
+
|
|
179
|
+
for line in lines:
|
|
180
|
+
# Match version headers like "## v4.2.0 (2025-01-08)"
|
|
181
|
+
if line.startswith('## '):
|
|
182
|
+
# Save previous entry
|
|
183
|
+
if current_version:
|
|
184
|
+
entries.append((current_version, current_lines))
|
|
185
|
+
current_version = line[3:].strip()
|
|
186
|
+
current_lines = []
|
|
187
|
+
elif current_version:
|
|
188
|
+
current_lines.append(line)
|
|
189
|
+
|
|
190
|
+
# Save last entry
|
|
191
|
+
if current_version:
|
|
192
|
+
entries.append((current_version, current_lines))
|
|
193
|
+
|
|
194
|
+
return entries
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _show_changelog(count: int = 2, show_all: bool = False):
|
|
198
|
+
"""Display changelog from local CHANGELOG.md file.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
count: Number of version entries to show (default 2)
|
|
202
|
+
show_all: If True, show all entries
|
|
203
|
+
"""
|
|
157
204
|
_safe_echo("=" * 70)
|
|
158
205
|
_safe_echo("IncludeCPP Changelog", fg='cyan', bold=True)
|
|
159
206
|
_safe_echo("=" * 70)
|
|
160
207
|
_safe_echo("")
|
|
161
208
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
"https://pypi.org/pypi/IncludeCPP/json",
|
|
166
|
-
headers={"User-Agent": "IncludeCPP-CLI"}
|
|
167
|
-
)
|
|
168
|
-
with urllib.request.urlopen(req, timeout=15) as response:
|
|
169
|
-
raw_data = response.read().decode('utf-8')
|
|
170
|
-
|
|
171
|
-
data = json.loads(raw_data)
|
|
172
|
-
description = data.get('info', {}).get('description', '')
|
|
173
|
-
version = data.get('info', {}).get('version', 'unknown')
|
|
174
|
-
_safe_echo(" OK", fg='green')
|
|
209
|
+
changelog_path = _get_changelog_path()
|
|
210
|
+
if not changelog_path:
|
|
211
|
+
_safe_echo("CHANGELOG.md not found.", fg='yellow')
|
|
175
212
|
_safe_echo("")
|
|
213
|
+
_safe_echo("=" * 70)
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
try:
|
|
217
|
+
content = changelog_path.read_text(encoding='utf-8')
|
|
218
|
+
entries = _parse_changelog_entries(content)
|
|
176
219
|
|
|
177
|
-
if
|
|
178
|
-
_safe_echo(
|
|
220
|
+
if not entries:
|
|
221
|
+
_safe_echo("No changelog entries found.", fg='yellow')
|
|
179
222
|
_safe_echo("")
|
|
223
|
+
_safe_echo("=" * 70)
|
|
224
|
+
return
|
|
225
|
+
|
|
226
|
+
# Determine how many to show
|
|
227
|
+
if show_all:
|
|
228
|
+
entries_to_show = entries
|
|
229
|
+
else:
|
|
230
|
+
entries_to_show = entries[:count]
|
|
180
231
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
232
|
+
_safe_echo(f"Showing {len(entries_to_show)} of {len(entries)} releases", fg='bright_black')
|
|
233
|
+
_safe_echo("")
|
|
234
|
+
|
|
235
|
+
for version, lines in entries_to_show:
|
|
236
|
+
_safe_echo(version, fg='yellow', bold=True)
|
|
184
237
|
|
|
185
238
|
for line in lines:
|
|
186
|
-
|
|
187
|
-
|
|
239
|
+
stripped = line.strip()
|
|
240
|
+
if not stripped:
|
|
188
241
|
continue
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
242
|
+
elif stripped.startswith('### '):
|
|
243
|
+
_safe_echo(" " + stripped[4:], fg='cyan', bold=True)
|
|
244
|
+
elif stripped.startswith('- '):
|
|
245
|
+
_safe_echo(" " + stripped)
|
|
246
|
+
elif stripped.startswith('---'):
|
|
247
|
+
_safe_echo("")
|
|
248
|
+
else:
|
|
249
|
+
_safe_echo(" " + stripped)
|
|
250
|
+
|
|
251
|
+
_safe_echo("")
|
|
252
|
+
|
|
253
|
+
if not show_all and len(entries) > count:
|
|
254
|
+
_safe_echo(f"Use --changelog --all to see all {len(entries)} releases", fg='bright_black')
|
|
255
|
+
_safe_echo(f"Or --changelog --{len(entries)} to see specific count", fg='bright_black')
|
|
256
|
+
|
|
257
|
+
except Exception as e:
|
|
258
|
+
_safe_echo(f"Error reading changelog: {e}", fg='red', err=True)
|
|
259
|
+
|
|
260
|
+
_safe_echo("")
|
|
261
|
+
_safe_echo("=" * 70)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _get_doc_path():
|
|
265
|
+
"""Get path to DOCUMENTATION.md file."""
|
|
266
|
+
package_dir = Path(__file__).parent.parent
|
|
267
|
+
doc_path = package_dir / 'DOCUMENTATION.md'
|
|
268
|
+
if doc_path.exists():
|
|
269
|
+
return doc_path
|
|
270
|
+
# Fallback to current directory
|
|
271
|
+
cwd_path = Path.cwd() / 'DOCUMENTATION.md'
|
|
272
|
+
if cwd_path.exists():
|
|
273
|
+
return cwd_path
|
|
274
|
+
return None
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _show_doc(search_term: str = None):
|
|
278
|
+
"""Display documentation from local DOCUMENTATION.md file.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
search_term: Optional search term to filter content
|
|
282
|
+
"""
|
|
283
|
+
_safe_echo("=" * 70)
|
|
284
|
+
_safe_echo("IncludeCPP Documentation", fg='cyan', bold=True)
|
|
285
|
+
_safe_echo("=" * 70)
|
|
286
|
+
_safe_echo("")
|
|
287
|
+
|
|
288
|
+
doc_path = _get_doc_path()
|
|
289
|
+
if not doc_path:
|
|
290
|
+
_safe_echo("DOCUMENTATION.md not found.", fg='yellow')
|
|
291
|
+
_safe_echo("")
|
|
292
|
+
_safe_echo("=" * 70)
|
|
293
|
+
return
|
|
294
|
+
|
|
295
|
+
try:
|
|
296
|
+
content = doc_path.read_text(encoding='utf-8')
|
|
297
|
+
|
|
298
|
+
if search_term:
|
|
299
|
+
# Search mode - find matching sections
|
|
300
|
+
_safe_echo(f"Searching for: '{search_term}'", fg='green', bold=True)
|
|
301
|
+
_safe_echo("")
|
|
302
|
+
|
|
303
|
+
# Split into sections (## headers)
|
|
304
|
+
sections = re.split(r'(?=^## )', content, flags=re.MULTILINE)
|
|
305
|
+
|
|
306
|
+
# Find matching sections
|
|
307
|
+
matches = []
|
|
308
|
+
for section in sections:
|
|
309
|
+
if search_term.lower() in section.lower():
|
|
310
|
+
# Get section title
|
|
311
|
+
title_match = re.match(r'^## (.+)$', section, re.MULTILINE)
|
|
312
|
+
if title_match:
|
|
313
|
+
matches.append((title_match.group(1), section))
|
|
314
|
+
|
|
315
|
+
if matches:
|
|
316
|
+
_safe_echo(f"Found {len(matches)} matching section(s):", fg='green')
|
|
317
|
+
_safe_echo("")
|
|
318
|
+
|
|
319
|
+
for title, section_content in matches[:5]: # Limit to 5
|
|
320
|
+
_safe_echo(f"## {title}", fg='yellow', bold=True)
|
|
321
|
+
|
|
322
|
+
# Highlight search term
|
|
323
|
+
lines = section_content.split('\n')
|
|
324
|
+
for line in lines[:30]: # Limit lines per section
|
|
325
|
+
stripped = line.strip()
|
|
326
|
+
if not stripped or stripped.startswith('## '):
|
|
327
|
+
continue
|
|
328
|
+
|
|
329
|
+
# Highlight matches
|
|
330
|
+
if search_term.lower() in stripped.lower():
|
|
331
|
+
# Simple highlight - wrap matches
|
|
332
|
+
highlighted = re.sub(
|
|
333
|
+
f'({re.escape(search_term)})',
|
|
334
|
+
lambda m: click.style(m.group(1), fg='green', bold=True),
|
|
335
|
+
stripped,
|
|
336
|
+
flags=re.IGNORECASE
|
|
337
|
+
)
|
|
338
|
+
_safe_echo(" " + highlighted)
|
|
339
|
+
else:
|
|
340
|
+
_safe_echo(" " + stripped)
|
|
341
|
+
|
|
342
|
+
_safe_echo("")
|
|
343
|
+
_safe_echo("-" * 40)
|
|
344
|
+
_safe_echo("")
|
|
345
|
+
|
|
346
|
+
if len(matches) > 5:
|
|
347
|
+
_safe_echo(f"... and {len(matches) - 5} more sections", fg='bright_black')
|
|
203
348
|
else:
|
|
204
|
-
_safe_echo("No
|
|
349
|
+
_safe_echo(f"No matches found for '{search_term}'", fg='yellow')
|
|
350
|
+
_safe_echo("")
|
|
351
|
+
_safe_echo("Try searching for:")
|
|
352
|
+
_safe_echo(" - Commands: init, rebuild, plugin, auto")
|
|
353
|
+
_safe_echo(" - Features: CSSL, AI, CPPY, classes, functions")
|
|
354
|
+
_safe_echo(" - Syntax: $, @, <==, define, class")
|
|
205
355
|
else:
|
|
206
|
-
|
|
356
|
+
# Full documentation display
|
|
357
|
+
_safe_echo("+" + "=" * 68 + "+", fg='red', bold=True)
|
|
358
|
+
_safe_echo("| IMPORTANT: All C++ code MUST be in 'namespace includecpp { }' |", fg='red', bold=True)
|
|
359
|
+
_safe_echo("+" + "=" * 68 + "+", fg='red', bold=True)
|
|
360
|
+
_safe_echo("")
|
|
361
|
+
_render_readme_with_colors(content)
|
|
207
362
|
|
|
208
363
|
except Exception as e:
|
|
209
|
-
_safe_echo("
|
|
210
|
-
_safe_echo("")
|
|
211
|
-
_safe_echo("Could not fetch changelog: " + str(e), fg='red', err=True)
|
|
364
|
+
_safe_echo(f"Error reading documentation: {e}", fg='red', err=True)
|
|
212
365
|
|
|
213
366
|
_safe_echo("")
|
|
214
367
|
_safe_echo("=" * 70)
|
|
215
368
|
|
|
216
369
|
|
|
217
370
|
@click.group(invoke_without_command=True)
|
|
218
|
-
@click.option('--doc', '
|
|
219
|
-
@click.option('--changelog', 'show_changelog', is_flag=True, help='Show changelog
|
|
371
|
+
@click.option('--doc', 'doc_search', is_flag=False, flag_value='__SHOW_ALL__', default=None, help='Show documentation. Use --doc "term" to search.')
|
|
372
|
+
@click.option('--changelog', 'show_changelog', is_flag=True, help='Show changelog (last 2 releases by default)')
|
|
373
|
+
@click.option('--all', 'changelog_all', is_flag=True, help='Show all changelog entries (use with --changelog)')
|
|
374
|
+
@click.option('--1', 'changelog_1', is_flag=True, hidden=True)
|
|
375
|
+
@click.option('--2', 'changelog_2', is_flag=True, hidden=True)
|
|
376
|
+
@click.option('--3', 'changelog_3', is_flag=True, hidden=True)
|
|
377
|
+
@click.option('--4', 'changelog_4', is_flag=True, hidden=True)
|
|
378
|
+
@click.option('--5', 'changelog_5', is_flag=True, hidden=True)
|
|
379
|
+
@click.option('--6', 'changelog_6', is_flag=True, hidden=True)
|
|
380
|
+
@click.option('--7', 'changelog_7', is_flag=True, hidden=True)
|
|
381
|
+
@click.option('--8', 'changelog_8', is_flag=True, hidden=True)
|
|
382
|
+
@click.option('--9', 'changelog_9', is_flag=True, hidden=True)
|
|
383
|
+
@click.option('--10', 'changelog_10', is_flag=True, hidden=True)
|
|
220
384
|
@click.pass_context
|
|
221
|
-
def cli(ctx,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
_show_changelog()
|
|
225
|
-
ctx.exit(0)
|
|
226
|
-
if show_doc:
|
|
227
|
-
click.echo("=" * 70)
|
|
228
|
-
click.secho("IncludeCPP Documentation", fg='cyan', bold=True)
|
|
229
|
-
click.echo("=" * 70)
|
|
230
|
-
click.echo()
|
|
385
|
+
def cli(ctx, doc_search, show_changelog, changelog_all, changelog_1, changelog_2, changelog_3,
|
|
386
|
+
changelog_4, changelog_5, changelog_6, changelog_7, changelog_8, changelog_9, changelog_10):
|
|
387
|
+
"""IncludeCPP - C++ Performance in Python, Zero Hassle
|
|
231
388
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
)
|
|
238
|
-
with urllib.request.urlopen(req, timeout=15) as response:
|
|
239
|
-
raw_data = response.read().decode('utf-8')
|
|
240
|
-
|
|
241
|
-
data = json.loads(raw_data)
|
|
242
|
-
description = data.get('info', {}).get('description', '')
|
|
243
|
-
click.secho(" OK", fg='green')
|
|
244
|
-
click.echo()
|
|
245
|
-
|
|
246
|
-
if description:
|
|
247
|
-
click.secho("+" + "=" * 68 + "+", fg='red', bold=True)
|
|
248
|
-
click.secho("| IMPORTANT: All C++ code MUST be in 'namespace includecpp { }' |", fg='red', bold=True)
|
|
249
|
-
click.secho("| This is REQUIRED for IncludeCPP to work! |", fg='red', bold=True)
|
|
250
|
-
click.secho("+" + "=" * 68 + "+", fg='red', bold=True)
|
|
251
|
-
click.echo()
|
|
252
|
-
_render_readme_with_colors(description)
|
|
253
|
-
else:
|
|
254
|
-
click.secho("No documentation available.", fg='yellow')
|
|
389
|
+
\b
|
|
390
|
+
Documentation:
|
|
391
|
+
includecpp --doc Show full documentation
|
|
392
|
+
includecpp --doc "CSSL" Search documentation for "CSSL"
|
|
393
|
+
includecpp --doc "rebuild" Search documentation for "rebuild"
|
|
255
394
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
395
|
+
\b
|
|
396
|
+
Changelog:
|
|
397
|
+
includecpp --changelog Show last 2 releases
|
|
398
|
+
includecpp --changelog --all Show all releases
|
|
399
|
+
includecpp --changelog --5 Show last 5 releases
|
|
400
|
+
"""
|
|
401
|
+
# Handle changelog
|
|
402
|
+
if show_changelog:
|
|
403
|
+
# Determine count from --N flags
|
|
404
|
+
count = 2 # default
|
|
405
|
+
if changelog_all:
|
|
406
|
+
_show_changelog(show_all=True)
|
|
407
|
+
else:
|
|
408
|
+
if changelog_1: count = 1
|
|
409
|
+
elif changelog_2: count = 2
|
|
410
|
+
elif changelog_3: count = 3
|
|
411
|
+
elif changelog_4: count = 4
|
|
412
|
+
elif changelog_5: count = 5
|
|
413
|
+
elif changelog_6: count = 6
|
|
414
|
+
elif changelog_7: count = 7
|
|
415
|
+
elif changelog_8: count = 8
|
|
416
|
+
elif changelog_9: count = 9
|
|
417
|
+
elif changelog_10: count = 10
|
|
418
|
+
_show_changelog(count=count)
|
|
419
|
+
ctx.exit(0)
|
|
260
420
|
|
|
261
|
-
|
|
421
|
+
# Handle documentation - --doc or --doc "search"
|
|
422
|
+
if doc_search is not None:
|
|
423
|
+
search_term = None if doc_search == '__SHOW_ALL__' else doc_search
|
|
424
|
+
_show_doc(search_term)
|
|
262
425
|
ctx.exit(0)
|
|
263
426
|
|
|
264
427
|
# If no subcommand is given, show help
|
|
@@ -5199,7 +5362,7 @@ def ai_ask(question, module_name, files, all_modules, exclude, think_mode, think
|
|
|
5199
5362
|
verbose.phase('init', 'Setting up context')
|
|
5200
5363
|
verbose.detail('Question', question[:50] + '...' if len(question) > 50 else question)
|
|
5201
5364
|
verbose.detail('Mode', mode)
|
|
5202
|
-
verbose.detail('Model', ai_mgr.config.get('model', 'gpt-
|
|
5365
|
+
verbose.detail('Model', ai_mgr.config.get('model', 'gpt-4o'))
|
|
5203
5366
|
|
|
5204
5367
|
project_root = Path.cwd()
|
|
5205
5368
|
plugins_dir = project_root / "plugins"
|
|
@@ -5220,7 +5383,7 @@ def ai_ask(question, module_name, files, all_modules, exclude, think_mode, think
|
|
|
5220
5383
|
files=len(source_files) + len(plugin_files),
|
|
5221
5384
|
lines=total_lines,
|
|
5222
5385
|
tokens=total_lines * 4, # Approximate
|
|
5223
|
-
model=ai_mgr.config.get('model', 'gpt-
|
|
5386
|
+
model=ai_mgr.config.get('model', 'gpt-4o')
|
|
5224
5387
|
)
|
|
5225
5388
|
|
|
5226
5389
|
if use_websearch:
|
|
@@ -6456,7 +6619,7 @@ def _convert_with_ai(content: str, module_name: str, source_file,
|
|
|
6456
6619
|
)
|
|
6457
6620
|
|
|
6458
6621
|
if not success:
|
|
6459
|
-
ai_verbose.warning("AI conversion failed
|
|
6622
|
+
ai_verbose.warning(f"AI conversion failed: {response}")
|
|
6460
6623
|
ai_verbose.phase('fallback', 'Falling back to standard conversion')
|
|
6461
6624
|
ai_verbose.end(success=True, message="Fallback successful")
|
|
6462
6625
|
if to_cpp:
|
|
@@ -7919,6 +8082,457 @@ def cssl_vscode():
|
|
|
7919
8082
|
click.secho(f"Installation failed: {e}", fg='red')
|
|
7920
8083
|
|
|
7921
8084
|
|
|
8085
|
+
@cssl.command(name='sdk')
|
|
8086
|
+
@click.argument('lang', required=False, default=None)
|
|
8087
|
+
@click.option('--doc', is_flag=True, help='Show SDK documentation')
|
|
8088
|
+
def cssl_sdk(lang, doc):
|
|
8089
|
+
"""Generate SDK files for cross-language instance sharing.
|
|
8090
|
+
|
|
8091
|
+
\b
|
|
8092
|
+
Usage:
|
|
8093
|
+
includecpp cssl sdk cpp # Create C++ SDK in ./sdk/cpp/
|
|
8094
|
+
includecpp cssl sdk java # Create Java SDK in ./sdk/java/
|
|
8095
|
+
includecpp cssl sdk csharp # Create C# SDK in ./sdk/csharp/
|
|
8096
|
+
includecpp cssl sdk js # Create JavaScript SDK in ./sdk/javascript/
|
|
8097
|
+
includecpp cssl sdk all # Create all SDKs
|
|
8098
|
+
includecpp cssl sdk --doc # Show SDK documentation
|
|
8099
|
+
|
|
8100
|
+
\b
|
|
8101
|
+
Languages:
|
|
8102
|
+
cpp, c++ C++ header-only SDK
|
|
8103
|
+
java Java SDK (com.includecpp.CSSL)
|
|
8104
|
+
csharp, c# C# SDK (IncludeCPP.CSSL)
|
|
8105
|
+
js, javascript JavaScript/Node.js SDK
|
|
8106
|
+
all All languages
|
|
8107
|
+
|
|
8108
|
+
\b
|
|
8109
|
+
Cross-Language Instance Sharing:
|
|
8110
|
+
Share instances from any language and access them in CSSL using
|
|
8111
|
+
the lang$InstanceName syntax:
|
|
8112
|
+
|
|
8113
|
+
C++: CSSL::share("Engine", &engine); -> cpp$Engine
|
|
8114
|
+
Java: CSSL.share("Service", svc); -> java$Service
|
|
8115
|
+
C#: CSSL.Share("Handler", hdl); -> csharp$Handler
|
|
8116
|
+
JS: CSSL.share('Processor', proc); -> js$Processor
|
|
8117
|
+
"""
|
|
8118
|
+
from pathlib import Path as PathLib
|
|
8119
|
+
import shutil
|
|
8120
|
+
|
|
8121
|
+
# Show documentation if --doc flag is set
|
|
8122
|
+
if doc or lang == 'doc':
|
|
8123
|
+
_show_sdk_documentation()
|
|
8124
|
+
return
|
|
8125
|
+
|
|
8126
|
+
if lang is None:
|
|
8127
|
+
# Show help
|
|
8128
|
+
click.secho("CSSL Multi-Language SDK Generator", fg='cyan', bold=True)
|
|
8129
|
+
click.echo()
|
|
8130
|
+
click.echo("Usage:")
|
|
8131
|
+
click.echo(" includecpp cssl sdk <lang> Create SDK for language")
|
|
8132
|
+
click.echo(" includecpp cssl sdk --doc Show documentation")
|
|
8133
|
+
click.echo()
|
|
8134
|
+
click.echo("Languages:")
|
|
8135
|
+
click.echo(" cpp, c++ C++ header-only SDK")
|
|
8136
|
+
click.echo(" java Java SDK")
|
|
8137
|
+
click.echo(" csharp, c# C# SDK")
|
|
8138
|
+
click.echo(" js, javascript JavaScript SDK")
|
|
8139
|
+
click.echo(" all All SDKs")
|
|
8140
|
+
return
|
|
8141
|
+
|
|
8142
|
+
# Normalize language name
|
|
8143
|
+
lang_map = {
|
|
8144
|
+
'cpp': 'cpp', 'c++': 'cpp',
|
|
8145
|
+
'java': 'java',
|
|
8146
|
+
'csharp': 'csharp', 'c#': 'csharp', 'cs': 'csharp',
|
|
8147
|
+
'js': 'javascript', 'javascript': 'javascript',
|
|
8148
|
+
'all': 'all'
|
|
8149
|
+
}
|
|
8150
|
+
|
|
8151
|
+
normalized = lang_map.get(lang.lower())
|
|
8152
|
+
if normalized is None:
|
|
8153
|
+
click.secho(f"Unknown language: {lang}", fg='red')
|
|
8154
|
+
click.echo("Supported: cpp, java, csharp, js, all")
|
|
8155
|
+
return
|
|
8156
|
+
|
|
8157
|
+
# Find source SDK directory in package
|
|
8158
|
+
package_dir = PathLib(__file__).parent.parent
|
|
8159
|
+
source_sdk_dir = package_dir / 'sdk'
|
|
8160
|
+
|
|
8161
|
+
# Target SDK directory
|
|
8162
|
+
target_sdk_dir = PathLib.cwd() / 'sdk'
|
|
8163
|
+
|
|
8164
|
+
langs_to_create = ['cpp', 'java', 'csharp', 'javascript'] if normalized == 'all' else [normalized]
|
|
8165
|
+
|
|
8166
|
+
click.secho("Creating CSSL SDK files...", fg='cyan', bold=True)
|
|
8167
|
+
click.echo()
|
|
8168
|
+
|
|
8169
|
+
for lang_name in langs_to_create:
|
|
8170
|
+
_create_sdk_for_language(target_sdk_dir, lang_name)
|
|
8171
|
+
|
|
8172
|
+
click.echo()
|
|
8173
|
+
click.secho("SDK created successfully!", fg='green', bold=True)
|
|
8174
|
+
click.echo()
|
|
8175
|
+
click.echo("Next steps:")
|
|
8176
|
+
click.echo(" 1. Copy SDK file(s) to your project")
|
|
8177
|
+
click.echo(" 2. Import and use CSSL.share() in your code")
|
|
8178
|
+
click.echo(" 3. Access instances in CSSL via lang$InstanceName")
|
|
8179
|
+
click.echo()
|
|
8180
|
+
click.echo("Documentation: includecpp cssl sdk --doc")
|
|
8181
|
+
|
|
8182
|
+
|
|
8183
|
+
def _create_sdk_for_language(target_dir, lang_name):
|
|
8184
|
+
"""Create SDK files for a specific language."""
|
|
8185
|
+
from pathlib import Path as PathLib
|
|
8186
|
+
|
|
8187
|
+
# SDK content for each language
|
|
8188
|
+
sdk_content = {
|
|
8189
|
+
'cpp': _get_cpp_sdk_content(),
|
|
8190
|
+
'java': _get_java_sdk_content(),
|
|
8191
|
+
'csharp': _get_csharp_sdk_content(),
|
|
8192
|
+
'javascript': _get_js_sdk_content(),
|
|
8193
|
+
}
|
|
8194
|
+
|
|
8195
|
+
sdk_paths = {
|
|
8196
|
+
'cpp': ('cpp', 'includecpp.h'),
|
|
8197
|
+
'java': ('java/src/com/includecpp', 'CSSL.java'),
|
|
8198
|
+
'csharp': ('csharp', 'IncludeCPP.cs'),
|
|
8199
|
+
'javascript': ('javascript', 'includecpp.js'),
|
|
8200
|
+
}
|
|
8201
|
+
|
|
8202
|
+
subdir, filename = sdk_paths[lang_name]
|
|
8203
|
+
target_subdir = target_dir / subdir
|
|
8204
|
+
target_subdir.mkdir(parents=True, exist_ok=True)
|
|
8205
|
+
|
|
8206
|
+
target_file = target_subdir / filename
|
|
8207
|
+
target_file.write_text(sdk_content[lang_name], encoding='utf-8')
|
|
8208
|
+
|
|
8209
|
+
lang_display = {'cpp': 'C++', 'java': 'Java', 'csharp': 'C#', 'javascript': 'JavaScript'}
|
|
8210
|
+
click.echo(f" {lang_display[lang_name]}: {target_file}")
|
|
8211
|
+
|
|
8212
|
+
|
|
8213
|
+
def _get_cpp_sdk_content():
|
|
8214
|
+
return '''/**
|
|
8215
|
+
* IncludeCPP CSSL SDK for C++ (v4.2.0)
|
|
8216
|
+
* Cross-language instance sharing between C++ and CSSL.
|
|
8217
|
+
*
|
|
8218
|
+
* USAGE:
|
|
8219
|
+
* #include "includecpp.h"
|
|
8220
|
+
*
|
|
8221
|
+
* class Engine { public: int power = 100; };
|
|
8222
|
+
*
|
|
8223
|
+
* int main() {
|
|
8224
|
+
* Engine engine;
|
|
8225
|
+
* CSSL::share("Engine", &engine);
|
|
8226
|
+
* // In CSSL: cpp = libinclude("c++"); engine = cpp$Engine;
|
|
8227
|
+
* return 0;
|
|
8228
|
+
* }
|
|
8229
|
+
*/
|
|
8230
|
+
#pragma once
|
|
8231
|
+
#include <string>
|
|
8232
|
+
#include <any>
|
|
8233
|
+
#include <unordered_map>
|
|
8234
|
+
#include <vector>
|
|
8235
|
+
#include <mutex>
|
|
8236
|
+
|
|
8237
|
+
namespace includecpp { namespace cssl {
|
|
8238
|
+
class Registry {
|
|
8239
|
+
public:
|
|
8240
|
+
static Registry& instance() { static Registry r; return r; }
|
|
8241
|
+
void share(const std::string& n, std::any v) { std::lock_guard<std::mutex> l(_m); _i[n] = v; }
|
|
8242
|
+
template<typename T> void share(const std::string& n, T* p) { std::lock_guard<std::mutex> l(_m); _i[n] = static_cast<void*>(p); }
|
|
8243
|
+
std::any get(const std::string& n) { std::lock_guard<std::mutex> l(_m); auto it = _i.find(n); return it != _i.end() ? it->second : std::any{}; }
|
|
8244
|
+
template<typename T> T* get(const std::string& n) { std::lock_guard<std::mutex> l(_m); auto it = _i.find(n); if (it != _i.end()) try { return static_cast<T*>(std::any_cast<void*>(it->second)); } catch (...) {} return nullptr; }
|
|
8245
|
+
bool has(const std::string& n) { std::lock_guard<std::mutex> l(_m); return _i.count(n) > 0; }
|
|
8246
|
+
bool remove(const std::string& n) { std::lock_guard<std::mutex> l(_m); return _i.erase(n) > 0; }
|
|
8247
|
+
std::vector<std::string> list() { std::lock_guard<std::mutex> l(_m); std::vector<std::string> r; for (auto& p : _i) r.push_back(p.first); return r; }
|
|
8248
|
+
void clear() { std::lock_guard<std::mutex> l(_m); _i.clear(); }
|
|
8249
|
+
private:
|
|
8250
|
+
Registry() = default;
|
|
8251
|
+
std::unordered_map<std::string, std::any> _i;
|
|
8252
|
+
std::mutex _m;
|
|
8253
|
+
};
|
|
8254
|
+
}}
|
|
8255
|
+
|
|
8256
|
+
namespace CSSL {
|
|
8257
|
+
template<typename T> inline void share(const std::string& n, T* i) { includecpp::cssl::Registry::instance().share(n, i); }
|
|
8258
|
+
inline void share(const std::string& n, std::any v) { includecpp::cssl::Registry::instance().share(n, v); }
|
|
8259
|
+
template<typename T> inline T* get(const std::string& n) { return includecpp::cssl::Registry::instance().get<T>(n); }
|
|
8260
|
+
inline bool has(const std::string& n) { return includecpp::cssl::Registry::instance().has(n); }
|
|
8261
|
+
inline bool remove(const std::string& n) { return includecpp::cssl::Registry::instance().remove(n); }
|
|
8262
|
+
inline std::vector<std::string> list() { return includecpp::cssl::Registry::instance().list(); }
|
|
8263
|
+
inline void clear() { includecpp::cssl::Registry::instance().clear(); }
|
|
8264
|
+
}
|
|
8265
|
+
|
|
8266
|
+
#define CSSL_SHARE(name, instance) CSSL::share(#name, instance)
|
|
8267
|
+
#define CSSL_GET(type, name) CSSL::get<type>(#name)
|
|
8268
|
+
'''
|
|
8269
|
+
|
|
8270
|
+
|
|
8271
|
+
def _get_java_sdk_content():
|
|
8272
|
+
return '''/**
|
|
8273
|
+
* IncludeCPP CSSL SDK for Java (v4.2.0)
|
|
8274
|
+
* Cross-language instance sharing between Java and CSSL.
|
|
8275
|
+
*
|
|
8276
|
+
* USAGE:
|
|
8277
|
+
* import com.includecpp.CSSL;
|
|
8278
|
+
*
|
|
8279
|
+
* MyService service = new MyService();
|
|
8280
|
+
* CSSL.share("MyService", service);
|
|
8281
|
+
* // In CSSL: java = libinclude("java"); svc = java$MyService;
|
|
8282
|
+
*/
|
|
8283
|
+
package com.includecpp;
|
|
8284
|
+
|
|
8285
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
8286
|
+
import java.util.List;
|
|
8287
|
+
import java.util.ArrayList;
|
|
8288
|
+
|
|
8289
|
+
public class CSSL {
|
|
8290
|
+
private static final ConcurrentHashMap<String, Object> instances = new ConcurrentHashMap<>();
|
|
8291
|
+
|
|
8292
|
+
public static void share(String name, Object instance) { instances.put(name, instance); }
|
|
8293
|
+
@SuppressWarnings("unchecked")
|
|
8294
|
+
public static <T> T get(String name) { return (T) instances.get(name); }
|
|
8295
|
+
public static <T> T get(String name, Class<T> type) { Object o = instances.get(name); return type.isInstance(o) ? type.cast(o) : null; }
|
|
8296
|
+
public static boolean has(String name) { return instances.containsKey(name); }
|
|
8297
|
+
public static boolean remove(String name) { return instances.remove(name) != null; }
|
|
8298
|
+
public static List<String> list() { return new ArrayList<>(instances.keySet()); }
|
|
8299
|
+
public static void clear() { instances.clear(); }
|
|
8300
|
+
public static int size() { return instances.size(); }
|
|
8301
|
+
}
|
|
8302
|
+
'''
|
|
8303
|
+
|
|
8304
|
+
|
|
8305
|
+
def _get_csharp_sdk_content():
|
|
8306
|
+
return '''/**
|
|
8307
|
+
* IncludeCPP CSSL SDK for C# (v4.2.0)
|
|
8308
|
+
* Cross-language instance sharing between C# and CSSL.
|
|
8309
|
+
*
|
|
8310
|
+
* USAGE:
|
|
8311
|
+
* using IncludeCPP;
|
|
8312
|
+
*
|
|
8313
|
+
* var service = new MyService();
|
|
8314
|
+
* CSSL.Share("MyService", service);
|
|
8315
|
+
* // In CSSL: cs = libinclude("c#"); svc = cs$MyService;
|
|
8316
|
+
*/
|
|
8317
|
+
using System.Collections.Concurrent;
|
|
8318
|
+
using System.Collections.Generic;
|
|
8319
|
+
using System.Linq;
|
|
8320
|
+
|
|
8321
|
+
namespace IncludeCPP
|
|
8322
|
+
{
|
|
8323
|
+
public static class CSSL
|
|
8324
|
+
{
|
|
8325
|
+
private static readonly ConcurrentDictionary<string, object> _instances = new();
|
|
8326
|
+
|
|
8327
|
+
public static void Share(string name, object instance) => _instances[name] = instance;
|
|
8328
|
+
public static T Get<T>(string name) where T : class => _instances.TryGetValue(name, out var o) ? o as T : null;
|
|
8329
|
+
public static object Get(string name) => _instances.TryGetValue(name, out var o) ? o : null;
|
|
8330
|
+
public static bool Has(string name) => _instances.ContainsKey(name);
|
|
8331
|
+
public static bool Remove(string name) => _instances.TryRemove(name, out _);
|
|
8332
|
+
public static IReadOnlyList<string> List() => _instances.Keys.ToList().AsReadOnly();
|
|
8333
|
+
public static void Clear() => _instances.Clear();
|
|
8334
|
+
public static int Count => _instances.Count;
|
|
8335
|
+
}
|
|
8336
|
+
}
|
|
8337
|
+
'''
|
|
8338
|
+
|
|
8339
|
+
|
|
8340
|
+
def _get_js_sdk_content():
|
|
8341
|
+
return '''/**
|
|
8342
|
+
* IncludeCPP CSSL SDK for JavaScript (v4.2.0)
|
|
8343
|
+
* Cross-language instance sharing between JavaScript and CSSL.
|
|
8344
|
+
*
|
|
8345
|
+
* USAGE:
|
|
8346
|
+
* const { CSSL } = require('includecpp-cssl');
|
|
8347
|
+
* // or: import { CSSL } from 'includecpp-cssl';
|
|
8348
|
+
*
|
|
8349
|
+
* class DataProcessor { process(data) { return data.toUpperCase(); } }
|
|
8350
|
+
* CSSL.share('DataProcessor', new DataProcessor());
|
|
8351
|
+
* // In CSSL: js = libinclude("javascript"); proc = js$DataProcessor;
|
|
8352
|
+
*/
|
|
8353
|
+
const instances = new Map();
|
|
8354
|
+
|
|
8355
|
+
const CSSL = {
|
|
8356
|
+
share(name, instance) { instances.set(name, instance); },
|
|
8357
|
+
get(name) { return instances.get(name); },
|
|
8358
|
+
has(name) { return instances.has(name); },
|
|
8359
|
+
remove(name) { return instances.delete(name); },
|
|
8360
|
+
list() { return Array.from(instances.keys()); },
|
|
8361
|
+
clear() { instances.clear(); },
|
|
8362
|
+
get size() { return instances.size; }
|
|
8363
|
+
};
|
|
8364
|
+
|
|
8365
|
+
if (typeof module !== 'undefined') { module.exports = { CSSL }; module.exports.default = CSSL; }
|
|
8366
|
+
if (typeof window !== 'undefined') { window.CSSL = CSSL; }
|
|
8367
|
+
export { CSSL };
|
|
8368
|
+
export default CSSL;
|
|
8369
|
+
'''
|
|
8370
|
+
|
|
8371
|
+
|
|
8372
|
+
def _show_sdk_documentation():
|
|
8373
|
+
"""Show detailed SDK documentation."""
|
|
8374
|
+
click.secho("=" * 70, fg='cyan')
|
|
8375
|
+
click.secho(" CSSL Multi-Language SDK Documentation (v4.2.0)", fg='cyan', bold=True)
|
|
8376
|
+
click.secho("=" * 70, fg='cyan')
|
|
8377
|
+
click.echo()
|
|
8378
|
+
|
|
8379
|
+
click.secho("OVERVIEW", fg='yellow', bold=True)
|
|
8380
|
+
click.echo(" The CSSL SDK enables cross-language instance sharing between")
|
|
8381
|
+
click.echo(" C++, Java, C#, JavaScript and CSSL scripts.")
|
|
8382
|
+
click.echo()
|
|
8383
|
+
click.echo(" Share an instance from any language, then access it in CSSL")
|
|
8384
|
+
click.echo(" using the lang$InstanceName syntax.")
|
|
8385
|
+
click.echo()
|
|
8386
|
+
|
|
8387
|
+
click.secho("HOW IT WORKS", fg='yellow', bold=True)
|
|
8388
|
+
click.echo(" 1. In your language, call CSSL.share(name, instance)")
|
|
8389
|
+
click.echo(" 2. In CSSL, load language support with libinclude()")
|
|
8390
|
+
click.echo(" 3. Access instance via lang$InstanceName")
|
|
8391
|
+
click.echo()
|
|
8392
|
+
|
|
8393
|
+
click.secho("C++ USAGE", fg='green', bold=True)
|
|
8394
|
+
click.echo('''
|
|
8395
|
+
#include "includecpp.h"
|
|
8396
|
+
|
|
8397
|
+
class Engine {
|
|
8398
|
+
public:
|
|
8399
|
+
int power = 500;
|
|
8400
|
+
void start() { /* ... */ }
|
|
8401
|
+
};
|
|
8402
|
+
|
|
8403
|
+
int main() {
|
|
8404
|
+
Engine engine;
|
|
8405
|
+
CSSL::share("Engine", &engine);
|
|
8406
|
+
|
|
8407
|
+
// Alternative macro syntax:
|
|
8408
|
+
// CSSL_SHARE(Engine, &engine);
|
|
8409
|
+
|
|
8410
|
+
return 0;
|
|
8411
|
+
}
|
|
8412
|
+
|
|
8413
|
+
// In CSSL:
|
|
8414
|
+
// cpp = libinclude("c++");
|
|
8415
|
+
// engine = cpp$Engine;
|
|
8416
|
+
// printl(engine.power); // 500
|
|
8417
|
+
''')
|
|
8418
|
+
|
|
8419
|
+
click.secho("JAVA USAGE", fg='green', bold=True)
|
|
8420
|
+
click.echo('''
|
|
8421
|
+
import com.includecpp.CSSL;
|
|
8422
|
+
|
|
8423
|
+
public class Main {
|
|
8424
|
+
public static void main(String[] args) {
|
|
8425
|
+
MyService service = new MyService();
|
|
8426
|
+
CSSL.share("MyService", service);
|
|
8427
|
+
|
|
8428
|
+
// Check if exists
|
|
8429
|
+
if (CSSL.has("MyService")) {
|
|
8430
|
+
MyService s = CSSL.get("MyService", MyService.class);
|
|
8431
|
+
}
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
|
|
8435
|
+
// In CSSL:
|
|
8436
|
+
// java = libinclude("java");
|
|
8437
|
+
// service = java$MyService;
|
|
8438
|
+
// service.doSomething();
|
|
8439
|
+
''')
|
|
8440
|
+
|
|
8441
|
+
click.secho("C# USAGE", fg='green', bold=True)
|
|
8442
|
+
click.echo('''
|
|
8443
|
+
using IncludeCPP;
|
|
8444
|
+
|
|
8445
|
+
class Program {
|
|
8446
|
+
static void Main() {
|
|
8447
|
+
var handler = new DataHandler();
|
|
8448
|
+
CSSL.Share("DataHandler", handler);
|
|
8449
|
+
|
|
8450
|
+
// List all shared
|
|
8451
|
+
foreach (var name in CSSL.List()) {
|
|
8452
|
+
Console.WriteLine(name);
|
|
8453
|
+
}
|
|
8454
|
+
}
|
|
8455
|
+
}
|
|
8456
|
+
|
|
8457
|
+
// In CSSL:
|
|
8458
|
+
// cs = libinclude("c#");
|
|
8459
|
+
// handler = cs$DataHandler;
|
|
8460
|
+
// handler.Process(data);
|
|
8461
|
+
''')
|
|
8462
|
+
|
|
8463
|
+
click.secho("JAVASCRIPT USAGE", fg='green', bold=True)
|
|
8464
|
+
click.echo('''
|
|
8465
|
+
const { CSSL } = require('includecpp-cssl');
|
|
8466
|
+
// or: import { CSSL } from 'includecpp-cssl';
|
|
8467
|
+
|
|
8468
|
+
class DataProcessor {
|
|
8469
|
+
process(data) {
|
|
8470
|
+
return data.toUpperCase();
|
|
8471
|
+
}
|
|
8472
|
+
}
|
|
8473
|
+
|
|
8474
|
+
CSSL.share('DataProcessor', new DataProcessor());
|
|
8475
|
+
console.log(CSSL.list()); // ['DataProcessor']
|
|
8476
|
+
|
|
8477
|
+
// In CSSL:
|
|
8478
|
+
// js = libinclude("javascript");
|
|
8479
|
+
// processor = js$DataProcessor;
|
|
8480
|
+
// result = processor.process("hello");
|
|
8481
|
+
''')
|
|
8482
|
+
|
|
8483
|
+
click.secho("CSSL SIDE (Complete Example)", fg='green', bold=True)
|
|
8484
|
+
click.echo('''
|
|
8485
|
+
// Load language support
|
|
8486
|
+
cpp = libinclude("c++");
|
|
8487
|
+
java = libinclude("java");
|
|
8488
|
+
cs = libinclude("c#");
|
|
8489
|
+
js = libinclude("javascript");
|
|
8490
|
+
|
|
8491
|
+
// Access shared instances
|
|
8492
|
+
engine = cpp$Engine;
|
|
8493
|
+
service = java$MyService;
|
|
8494
|
+
handler = cs$DataHandler;
|
|
8495
|
+
processor = js$DataProcessor;
|
|
8496
|
+
|
|
8497
|
+
// Use them
|
|
8498
|
+
printl("Engine power: " + engine.power);
|
|
8499
|
+
service.doSomething();
|
|
8500
|
+
handler.Process(data);
|
|
8501
|
+
result = processor.process("hello");
|
|
8502
|
+
|
|
8503
|
+
// Cross-language inheritance
|
|
8504
|
+
class TurboEngine : extends cpp$Engine {
|
|
8505
|
+
int boost;
|
|
8506
|
+
|
|
8507
|
+
constr TurboEngine(int b) {
|
|
8508
|
+
this->boost = b;
|
|
8509
|
+
}
|
|
8510
|
+
}
|
|
8511
|
+
''')
|
|
8512
|
+
|
|
8513
|
+
click.secho("API REFERENCE", fg='yellow', bold=True)
|
|
8514
|
+
click.echo('''
|
|
8515
|
+
Method Description
|
|
8516
|
+
--------------- ------------------------------------------
|
|
8517
|
+
share(name, obj) Share an instance by name
|
|
8518
|
+
get(name) Get a shared instance
|
|
8519
|
+
has(name) Check if instance exists
|
|
8520
|
+
remove(name) Remove a shared instance
|
|
8521
|
+
list() Get all instance names
|
|
8522
|
+
clear() Clear all instances
|
|
8523
|
+
size/Count Number of shared instances
|
|
8524
|
+
''')
|
|
8525
|
+
|
|
8526
|
+
click.secho("GENERATE SDK FILES", fg='yellow', bold=True)
|
|
8527
|
+
click.echo('''
|
|
8528
|
+
includecpp cssl sdk cpp # C++ SDK
|
|
8529
|
+
includecpp cssl sdk java # Java SDK
|
|
8530
|
+
includecpp cssl sdk csharp # C# SDK
|
|
8531
|
+
includecpp cssl sdk js # JavaScript SDK
|
|
8532
|
+
includecpp cssl sdk all # All SDKs
|
|
8533
|
+
''')
|
|
8534
|
+
|
|
8535
|
+
|
|
7922
8536
|
# Register hidden cssl command group
|
|
7923
8537
|
cli.add_command(cssl)
|
|
7924
8538
|
|