code2logic 1.0.34__tar.gz → 1.0.36__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.
- {code2logic-1.0.34 → code2logic-1.0.36}/PKG-INFO +1 -1
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/__init__.py +1 -1
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/cli.py +129 -80
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/function_logic.py +24 -7
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/toon_format.py +64 -6
- {code2logic-1.0.34 → code2logic-1.0.36}/pyproject.toml +1 -1
- {code2logic-1.0.34 → code2logic-1.0.36}/LICENSE +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/README.md +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/__main__.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/adaptive.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/analyzer.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/base.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/benchmark.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/benchmarks/__init__.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/benchmarks/common.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/benchmarks/results.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/benchmarks/runner.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/chunked_reproduction.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/code_review.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/config.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/core/__init__.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/dependency.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/errors.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/file_formats.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/formats/__init__.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/generators.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/gherkin.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/integrations/__init__.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/intent.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/llm/__init__.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/llm.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/llm_clients.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/llm_clients_new.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/llm_profiler.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/logicml.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/markdown_format.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/mcp_server.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/metrics.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/models.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/parsers.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/project_comparison.md +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/project_reproducer.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/prompts.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/py.typed +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/quality.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/refactor.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/reproducer.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/reproduction.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/schemas/__init__.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/schemas/json_schema.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/schemas/logicml_schema.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/schemas/markdown_schema.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/schemas/yaml_schema.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/shared_utils.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/similarity.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/terminal.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/tools/__init__.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/universal.py +0 -0
- {code2logic-1.0.34 → code2logic-1.0.36}/code2logic/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2logic
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.36
|
|
4
4
|
Summary: Code2Logic - Source code to logical representation converter for LLM analysis, featuring Tree-sitter parsing, dependency graph analysis, and multi-language support.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -605,8 +605,9 @@ code2logic [path] [options]
|
|
|
605
605
|
help='Detail level - columns to include (default: standard)'
|
|
606
606
|
)
|
|
607
607
|
parser.add_argument(
|
|
608
|
-
'-o', '--output',
|
|
609
|
-
|
|
608
|
+
'-o', '--output-dir',
|
|
609
|
+
dest='output_dir',
|
|
610
|
+
help='Output directory for all generated files. If specified, files are saved instead of stdout. File names are derived from --name and format flags: {name}.{format}, {name}.functions.{ext}, {name}.{format}-schema.json'
|
|
610
611
|
)
|
|
611
612
|
parser.add_argument(
|
|
612
613
|
'--name',
|
|
@@ -643,7 +644,29 @@ code2logic [path] [options]
|
|
|
643
644
|
parser.add_argument(
|
|
644
645
|
'--with-schema',
|
|
645
646
|
action='store_true',
|
|
646
|
-
help='Generate JSON schema alongside output'
|
|
647
|
+
help='Generate JSON schema file alongside output (uses project name for filename)'
|
|
648
|
+
)
|
|
649
|
+
parser.add_argument(
|
|
650
|
+
'--stdout',
|
|
651
|
+
action='store_true',
|
|
652
|
+
help='Write all output to stdout instead of files (including schema and function-logic). Useful for piping.'
|
|
653
|
+
)
|
|
654
|
+
parser.add_argument(
|
|
655
|
+
'--no-repeat-module',
|
|
656
|
+
action='store_true',
|
|
657
|
+
dest='no_repeat_module',
|
|
658
|
+
help='Reduce repeated directory prefixes in TOON outputs by using ./file for consecutive entries in the same folder (applies to function-logic TOON and TOON module lists).'
|
|
659
|
+
)
|
|
660
|
+
parser.add_argument(
|
|
661
|
+
'--no-repeat-name',
|
|
662
|
+
action='store_true',
|
|
663
|
+
dest='no_repeat_module',
|
|
664
|
+
help=argparse.SUPPRESS
|
|
665
|
+
)
|
|
666
|
+
parser.add_argument(
|
|
667
|
+
'--no-repeat-details',
|
|
668
|
+
action='store_true',
|
|
669
|
+
help='Reduce repeated directory prefixes in function-logic TOON section function_details by using ./file for consecutive entries in the same folder.'
|
|
647
670
|
)
|
|
648
671
|
parser.add_argument(
|
|
649
672
|
'--no-install',
|
|
@@ -856,23 +879,34 @@ code2logic [path] [options]
|
|
|
856
879
|
# Get project name: CLI arg > env var > default
|
|
857
880
|
project_name = args.project_name if args.project_name else config.get_project_name()
|
|
858
881
|
|
|
859
|
-
# Determine
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
882
|
+
# Determine output mode:
|
|
883
|
+
# - --stdout: all requested output to stdout (with section markers)
|
|
884
|
+
# - -o ./dir with --function-logic or --with-schema: only generate flagged files
|
|
885
|
+
# - -o ./dir without aux flags: generate main file only
|
|
886
|
+
# - no -o: main to stdout (auxiliary files require explicit path)
|
|
887
|
+
use_stdout = args.stdout
|
|
888
|
+
output_dir = args.output_dir
|
|
889
|
+
|
|
890
|
+
# When using output_dir with aux flags, only generate those files (not main)
|
|
891
|
+
has_aux_flags = args.function_logic or args.with_schema
|
|
892
|
+
generate_main = not has_aux_flags or use_stdout
|
|
893
|
+
|
|
894
|
+
# Build output paths based on output_dir
|
|
895
|
+
ext_map = {
|
|
896
|
+
'markdown': 'md',
|
|
897
|
+
'compact': 'txt',
|
|
898
|
+
'json': 'json',
|
|
899
|
+
'yaml': 'yaml',
|
|
900
|
+
'hybrid': 'yaml',
|
|
901
|
+
'csv': 'csv',
|
|
902
|
+
'gherkin': 'feature',
|
|
903
|
+
'toon': 'toon',
|
|
904
|
+
'logicml': 'logicml',
|
|
905
|
+
}
|
|
906
|
+
ext = ext_map.get(args.format, args.format)
|
|
907
|
+
main_output_path = None
|
|
908
|
+
if output_dir and generate_main:
|
|
909
|
+
main_output_path = os.path.join(output_dir, f"{project_name}.{ext}")
|
|
876
910
|
|
|
877
911
|
# Generate output
|
|
878
912
|
if args.verbose:
|
|
@@ -913,16 +947,19 @@ code2logic [path] [options]
|
|
|
913
947
|
schema = generator.generate_schema('hybrid')
|
|
914
948
|
else:
|
|
915
949
|
schema = generator.generate_schema('compact' if compact else 'full')
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
f.
|
|
924
|
-
|
|
925
|
-
|
|
950
|
+
|
|
951
|
+
if use_stdout:
|
|
952
|
+
# Write to stdout with section marker
|
|
953
|
+
print(f"\n=== SCHEMA ===")
|
|
954
|
+
print(schema)
|
|
955
|
+
elif output_dir:
|
|
956
|
+
# Write to file in output directory
|
|
957
|
+
schema_path = os.path.join(output_dir, f"{project_name}.yaml-schema.json")
|
|
958
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
959
|
+
with open(schema_path, 'w', encoding='utf-8') as f:
|
|
960
|
+
f.write(schema)
|
|
961
|
+
if args.verbose:
|
|
962
|
+
log.success(f"Schema written to: {schema_path}")
|
|
926
963
|
|
|
927
964
|
elif args.format == 'toon':
|
|
928
965
|
generator = TOONGenerator()
|
|
@@ -941,22 +978,29 @@ code2logic [path] [options]
|
|
|
941
978
|
'standard': 'standard',
|
|
942
979
|
'full': 'full',
|
|
943
980
|
}
|
|
944
|
-
output = generator.generate(
|
|
981
|
+
output = generator.generate(
|
|
982
|
+
project,
|
|
983
|
+
detail=detail_map.get(args.detail, 'standard'),
|
|
984
|
+
no_repeat_name=args.no_repeat_module,
|
|
985
|
+
)
|
|
945
986
|
|
|
946
987
|
# Generate schema if requested
|
|
947
988
|
if args.with_schema:
|
|
948
989
|
schema_type = 'ultra_compact' if use_ultra_compact else 'standard'
|
|
949
990
|
schema = generator.generate_schema(schema_type)
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
f.
|
|
958
|
-
|
|
959
|
-
|
|
991
|
+
|
|
992
|
+
if use_stdout:
|
|
993
|
+
# Write to stdout with section marker
|
|
994
|
+
print(f"\n=== SCHEMA ===")
|
|
995
|
+
print(schema)
|
|
996
|
+
elif output_dir:
|
|
997
|
+
# Write to file in output directory
|
|
998
|
+
schema_path = os.path.join(output_dir, f"{project_name}.toon-schema.json")
|
|
999
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
1000
|
+
with open(schema_path, 'w', encoding='utf-8') as f:
|
|
1001
|
+
f.write(schema)
|
|
1002
|
+
if args.verbose:
|
|
1003
|
+
log.success(f"Schema written to: {schema_path}")
|
|
960
1004
|
|
|
961
1005
|
elif args.format == 'logicml':
|
|
962
1006
|
generator = LogicMLGenerator()
|
|
@@ -970,21 +1014,16 @@ code2logic [path] [options]
|
|
|
970
1014
|
if args.function_logic:
|
|
971
1015
|
logic_gen = FunctionLogicGenerator()
|
|
972
1016
|
|
|
973
|
-
#
|
|
1017
|
+
# Determine path for function logic file
|
|
974
1018
|
if args.function_logic == 'auto':
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
if base.endswith('.c2l'):
|
|
980
|
-
base = base[:-4]
|
|
981
|
-
ext = effective_output.rsplit('.', 1)[-1] if '.' in effective_output else 'logicml'
|
|
982
|
-
logic_path = f"{base}.functions.{ext}"
|
|
1019
|
+
if output_dir:
|
|
1020
|
+
# Use output directory with project name
|
|
1021
|
+
logic_ext = ext_map.get(args.format, 'logicml')
|
|
1022
|
+
logic_path = os.path.join(output_dir, f"{project_name}.functions.{logic_ext}")
|
|
983
1023
|
else:
|
|
984
|
-
#
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
logic_path = f"{project_name}.functions.{ext}"
|
|
1024
|
+
# No output dir - use project name in current directory
|
|
1025
|
+
logic_ext = ext_map.get(args.format, 'logicml')
|
|
1026
|
+
logic_path = f"{project_name}.functions.{logic_ext}"
|
|
988
1027
|
else:
|
|
989
1028
|
logic_path = str(args.function_logic)
|
|
990
1029
|
|
|
@@ -994,17 +1033,26 @@ code2logic [path] [options]
|
|
|
994
1033
|
elif lower.endswith(('.yaml', '.yml')):
|
|
995
1034
|
logic_out = logic_gen.generate_yaml(project, detail=args.detail)
|
|
996
1035
|
elif lower.endswith('.toon'):
|
|
997
|
-
logic_out = logic_gen.generate_toon(
|
|
1036
|
+
logic_out = logic_gen.generate_toon(
|
|
1037
|
+
project,
|
|
1038
|
+
detail=args.detail,
|
|
1039
|
+
no_repeat_name=args.no_repeat_module,
|
|
1040
|
+
no_repeat_details=args.no_repeat_details,
|
|
1041
|
+
)
|
|
998
1042
|
else:
|
|
999
1043
|
logic_out = logic_gen.generate(project, detail=args.detail)
|
|
1000
1044
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1045
|
+
if use_stdout:
|
|
1046
|
+
# Write to stdout with section marker
|
|
1047
|
+
print(f"\n=== FUNCTION_LOGIC ===")
|
|
1048
|
+
print(logic_out)
|
|
1049
|
+
elif output_dir:
|
|
1050
|
+
# Write to file in output directory
|
|
1051
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
1052
|
+
with open(logic_path, 'w', encoding='utf-8') as f:
|
|
1053
|
+
f.write(logic_out)
|
|
1054
|
+
if args.verbose:
|
|
1055
|
+
log.success(f"Function logic written to: {logic_path}")
|
|
1008
1056
|
|
|
1009
1057
|
gen_time = time.time() - gen_start
|
|
1010
1058
|
|
|
@@ -1015,25 +1063,26 @@ code2logic [path] [options]
|
|
|
1015
1063
|
log.stats("Size", f"{output_size:,} chars (~{tokens_approx:,} tokens)")
|
|
1016
1064
|
log.stats("Lines", output.count('\n') + 1)
|
|
1017
1065
|
|
|
1018
|
-
# Write output
|
|
1019
|
-
if
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
os.makedirs(
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
print(output, flush=True)
|
|
1031
|
-
except BrokenPipeError:
|
|
1066
|
+
# Write main output (only if generate_main is True)
|
|
1067
|
+
if generate_main:
|
|
1068
|
+
if output_dir:
|
|
1069
|
+
# Write to file in output directory
|
|
1070
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
1071
|
+
with open(main_output_path, 'w', encoding='utf-8') as f:
|
|
1072
|
+
f.write(output)
|
|
1073
|
+
if args.verbose:
|
|
1074
|
+
log.success(f"Output written to: {main_output_path}")
|
|
1075
|
+
else:
|
|
1076
|
+
# Write to stdout
|
|
1077
|
+
if not args.quiet:
|
|
1032
1078
|
try:
|
|
1033
|
-
|
|
1034
|
-
except
|
|
1035
|
-
|
|
1036
|
-
|
|
1079
|
+
print(output, flush=True)
|
|
1080
|
+
except BrokenPipeError:
|
|
1081
|
+
try:
|
|
1082
|
+
sys.stdout.close()
|
|
1083
|
+
except Exception:
|
|
1084
|
+
pass
|
|
1085
|
+
os._exit(0)
|
|
1037
1086
|
|
|
1038
1087
|
# Final summary
|
|
1039
1088
|
if args.verbose:
|
|
@@ -59,7 +59,13 @@ class FunctionLogicGenerator:
|
|
|
59
59
|
return self.generate(project, detail)
|
|
60
60
|
return yaml.dump(data, default_flow_style=False, allow_unicode=True, sort_keys=False, width=120)
|
|
61
61
|
|
|
62
|
-
def generate_toon(
|
|
62
|
+
def generate_toon(
|
|
63
|
+
self,
|
|
64
|
+
project: ProjectInfo,
|
|
65
|
+
detail: str = 'full',
|
|
66
|
+
no_repeat_name: bool = False,
|
|
67
|
+
no_repeat_details: bool = False,
|
|
68
|
+
) -> str:
|
|
63
69
|
if detail == 'detailed':
|
|
64
70
|
detail = 'full'
|
|
65
71
|
toon = TOONGenerator()
|
|
@@ -73,21 +79,33 @@ class FunctionLogicGenerator:
|
|
|
73
79
|
|
|
74
80
|
modules = list(project.modules or [])
|
|
75
81
|
lines.append(f"modules[{len(modules)}]{{path{dm}lang{dm}items}}:")
|
|
82
|
+
prev_dir: str | None = None
|
|
76
83
|
for m in modules:
|
|
77
84
|
items = self._module_items(m)
|
|
78
|
-
|
|
85
|
+
if no_repeat_name:
|
|
86
|
+
compressed_path, prev_dir = toon._compress_module_path(m.path, prev_dir)
|
|
87
|
+
path_out = compressed_path
|
|
88
|
+
else:
|
|
89
|
+
path_out = m.path
|
|
90
|
+
lines.append(f" {toon._quote(path_out)}{delim}{toon._short_lang(m.language)}{delim}{len(items)}")
|
|
79
91
|
|
|
80
92
|
lines.append("")
|
|
81
93
|
lines.append("function_details:")
|
|
82
94
|
|
|
95
|
+
prev_dir = None
|
|
83
96
|
for m in modules:
|
|
84
97
|
items = self._module_items(m)
|
|
85
98
|
if not items:
|
|
86
99
|
continue
|
|
87
100
|
|
|
88
|
-
|
|
101
|
+
if no_repeat_details:
|
|
102
|
+
compressed_path, prev_dir = toon._compress_module_path(m.path, prev_dir)
|
|
103
|
+
details_key = compressed_path
|
|
104
|
+
else:
|
|
105
|
+
details_key = m.path
|
|
106
|
+
lines.append(f" {toon._quote(details_key)}:")
|
|
89
107
|
|
|
90
|
-
header = f"name{dm}kind{dm}sig{dm}
|
|
108
|
+
header = f"line{dm}name{dm}kind{dm}sig{dm}async{dm}cc"
|
|
91
109
|
if detail in ('standard', 'full'):
|
|
92
110
|
header += f"{dm}does"
|
|
93
111
|
if detail == 'full':
|
|
@@ -97,15 +115,14 @@ class FunctionLogicGenerator:
|
|
|
97
115
|
|
|
98
116
|
for kind, qname, func in items:
|
|
99
117
|
sig = self._build_sig(func, include_async_prefix=False, language=m.language)
|
|
100
|
-
loc = self._build_loc(func)
|
|
101
118
|
is_async = 'true' if getattr(func, 'is_async', False) else 'false'
|
|
119
|
+
start_line = str(getattr(func, 'start_line', 0) or 0)
|
|
102
120
|
row = [
|
|
121
|
+
start_line,
|
|
103
122
|
toon._quote(qname),
|
|
104
123
|
toon._quote(kind),
|
|
105
124
|
toon._quote(sig),
|
|
106
|
-
toon._quote(loc),
|
|
107
125
|
is_async,
|
|
108
|
-
str(getattr(func, 'lines', 0) or 0),
|
|
109
126
|
str(getattr(func, 'complexity', 1) or 1),
|
|
110
127
|
]
|
|
111
128
|
|
|
@@ -33,6 +33,37 @@ class TOONGenerator:
|
|
|
33
33
|
SPECIAL_CHARS = re.compile(r'[:\"\\\[\]\{\}\n\t\r,]')
|
|
34
34
|
LOOKS_LIKE_LITERAL = re.compile(r'^(true|false|null|-?\d+\.?\d*([eE][+-]?\d+)?|-)$')
|
|
35
35
|
|
|
36
|
+
LANGUAGE_ABBREVIATIONS = {
|
|
37
|
+
'python': 'py',
|
|
38
|
+
'javascript': 'js',
|
|
39
|
+
'typescript': 'ts',
|
|
40
|
+
'tsx': 'tsx',
|
|
41
|
+
'jsx': 'jsx',
|
|
42
|
+
'java': 'java',
|
|
43
|
+
'kotlin': 'kt',
|
|
44
|
+
'go': 'go',
|
|
45
|
+
'rust': 'rs',
|
|
46
|
+
'c': 'c',
|
|
47
|
+
'cpp': 'cpp',
|
|
48
|
+
'c++': 'cpp',
|
|
49
|
+
'csharp': 'cs',
|
|
50
|
+
'c#': 'cs',
|
|
51
|
+
'php': 'php',
|
|
52
|
+
'ruby': 'rb',
|
|
53
|
+
'swift': 'swift',
|
|
54
|
+
'scala': 'scala',
|
|
55
|
+
'bash': 'sh',
|
|
56
|
+
'shell': 'sh',
|
|
57
|
+
'sql': 'sql',
|
|
58
|
+
'yaml': 'yaml',
|
|
59
|
+
'json': 'json',
|
|
60
|
+
'toml': 'toml',
|
|
61
|
+
'markdown': 'md',
|
|
62
|
+
'html': 'html',
|
|
63
|
+
'css': 'css',
|
|
64
|
+
'dockerfile': 'docker',
|
|
65
|
+
}
|
|
66
|
+
|
|
36
67
|
def __init__(self, delimiter: str = ',', use_tabs: bool = False):
|
|
37
68
|
"""
|
|
38
69
|
Initialize TOON generator.
|
|
@@ -46,7 +77,27 @@ class TOONGenerator:
|
|
|
46
77
|
# parsers/LLMs can read them. Use comma-separated headers regardless of row delimiter.
|
|
47
78
|
self.delim_marker = ','
|
|
48
79
|
|
|
49
|
-
def
|
|
80
|
+
def _short_lang(self, lang: str) -> str:
|
|
81
|
+
lang_norm = (lang or '').strip().lower()
|
|
82
|
+
return self.LANGUAGE_ABBREVIATIONS.get(lang_norm, lang)
|
|
83
|
+
|
|
84
|
+
def _compress_module_path(self, path: str, prev_dir: str | None) -> tuple[str, str]:
|
|
85
|
+
"""Compress repeated directory prefixes for module summary tables.
|
|
86
|
+
|
|
87
|
+
If consecutive modules are in the same directory, emit './<basename>' instead
|
|
88
|
+
of repeating '<dir>/<basename>'. The first entry for a directory stays as the
|
|
89
|
+
full path.
|
|
90
|
+
"""
|
|
91
|
+
p = (path or '')
|
|
92
|
+
if '/' not in p:
|
|
93
|
+
return p, ''
|
|
94
|
+
|
|
95
|
+
cur_dir, base = p.rsplit('/', 1)
|
|
96
|
+
if prev_dir is not None and cur_dir == prev_dir:
|
|
97
|
+
return f"./{base}", cur_dir
|
|
98
|
+
return p, cur_dir
|
|
99
|
+
|
|
100
|
+
def generate(self, project: ProjectInfo, detail: str = 'standard', no_repeat_name: bool = False) -> str:
|
|
50
101
|
"""
|
|
51
102
|
Generate TOON format from ProjectInfo.
|
|
52
103
|
|
|
@@ -71,26 +122,33 @@ class TOONGenerator:
|
|
|
71
122
|
|
|
72
123
|
# Languages as primitive array
|
|
73
124
|
if project.languages:
|
|
74
|
-
lang_items = [f"{k}:{v}" for k, v in project.languages.items()]
|
|
125
|
+
lang_items = [f"{self._short_lang(k)}:{v}" for k, v in project.languages.items()]
|
|
75
126
|
lines.append(f" languages[{len(lang_items)}]: {self.delimiter.join(lang_items)}")
|
|
76
127
|
|
|
77
128
|
# Modules - tabular format for efficiency
|
|
78
129
|
if project.modules:
|
|
79
130
|
lines.append("")
|
|
80
|
-
lines.extend(self._generate_modules(project.modules, detail))
|
|
131
|
+
lines.extend(self._generate_modules(project.modules, detail, no_repeat_name=no_repeat_name))
|
|
81
132
|
|
|
82
133
|
return '\n'.join(lines)
|
|
83
134
|
|
|
84
|
-
def _generate_modules(self, modules: List[ModuleInfo], detail: str) -> List[str]:
|
|
135
|
+
def _generate_modules(self, modules: List[ModuleInfo], detail: str, no_repeat_name: bool = False) -> List[str]:
|
|
85
136
|
"""Generate modules section."""
|
|
86
137
|
lines = []
|
|
87
138
|
|
|
88
139
|
# Module summary as tabular array
|
|
89
140
|
lines.append(f"modules[{len(modules)}]{{path{self.delim_marker}lang{self.delim_marker}lines{self.delim_marker}kb}}:")
|
|
141
|
+
prev_dir: str | None = None
|
|
90
142
|
for m in modules:
|
|
91
|
-
|
|
143
|
+
if no_repeat_name:
|
|
144
|
+
path_out, prev_dir = self._compress_module_path(m.path, prev_dir)
|
|
145
|
+
else:
|
|
146
|
+
path_out = m.path
|
|
147
|
+
path = self._quote(path_out)
|
|
92
148
|
kb = round((getattr(m, 'file_bytes', 0) or 0) / 1024, 1)
|
|
93
|
-
lines.append(
|
|
149
|
+
lines.append(
|
|
150
|
+
f" {path}{self.delimiter}{self._short_lang(m.language)}{self.delimiter}{m.lines_code}{self.delimiter}{kb}"
|
|
151
|
+
)
|
|
94
152
|
|
|
95
153
|
# Detailed module info
|
|
96
154
|
if detail in ('standard', 'full'):
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "code2logic"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.36"
|
|
8
8
|
description = "Code2Logic - Source code to logical representation converter for LLM analysis, featuring Tree-sitter parsing, dependency graph analysis, and multi-language support."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|