1515import time
1616import logging
1717import json
18+ import signal
1819from datetime import datetime
1920
2021from . import __version__
@@ -509,6 +510,11 @@ def main():
509510 """Main CLI entry point."""
510511 cli_start = time .time ()
511512
513+ try :
514+ signal .signal (signal .SIGPIPE , signal .SIG_DFL )
515+ except Exception :
516+ pass
517+
512518 if len (sys .argv ) > 1 and sys .argv [1 ] == 'llm' :
513519 _code2logic_llm_cli (sys .argv [2 :])
514520 return
@@ -524,12 +530,17 @@ def main():
524530 code2logic /path/to/project -f yaml # YAML (human-readable)
525531 code2logic /path/to/project -f json --flat # Flat JSON (for comparisons)
526532 code2logic /path/to/project -f compact # Ultra-compact text
533+ code2logic /path/to/project -f logicml # LogicML (compressed, reproduction-oriented)
534+ code2logic /path/to/project -f toon # TOON (token-oriented tabular format)
527535
528536Output formats (token efficiency):
529537 csv - Best for LLM (~20K tokens/100 files) - flat table
530538 compact - Good for LLM (~25K tokens/100 files) - minimal text
531539 json - Standard (~35K tokens/100 files) - nested/flat
532540 yaml - Readable (~35K tokens/100 files) - nested/flat
541+ logicml - Compressed (best compression) - reproduction-oriented
542+ toon - Token-oriented (~JSON-size, more LLM-friendly) - tabular arrays
543+ gherkin - Behavioral scenarios - good for minimal implementations
533544 markdown - Documentation (~55K tokens/100 files)
534545
535546Detail levels (columns in csv/json/yaml):
@@ -538,6 +549,39 @@ def main():
538549 full - + calls, lines, complexity, hash (16 columns)
539550'''
540551 )
552+
553+ def _maybe_print_pretty_help () -> bool :
554+ """Print colorized help as markdown when appropriate.
555+
556+ Returns True if help was printed and the CLI should exit early.
557+ """
558+ force_pretty = os .environ .get ("CODE2LOGIC_PRETTY_HELP" ) == "1" or bool (os .environ .get ("FORCE_COLOR" ))
559+ if not force_pretty :
560+ if not hasattr (sys .stdout , "isatty" ) or not sys .stdout .isatty ():
561+ return False
562+ try :
563+ from .terminal import render
564+ except Exception :
565+ return False
566+
567+ help_md = f"""# code2logic
568+
569+ Convert source code to logical representation for LLM analysis.
570+
571+ ## Usage
572+
573+ ```bash
574+ code2logic [path] [options]
575+ ```
576+
577+ ## Help
578+
579+ ```text
580+ { parser .format_help ().rstrip ()}
581+ ```
582+ """
583+ render .markdown (help_md )
584+ return True
541585
542586 parser .add_argument (
543587 'path' ,
@@ -547,13 +591,13 @@ def main():
547591 )
548592 parser .add_argument (
549593 '-f' , '--format' ,
550- choices = ['markdown' , 'compact' , 'json' , 'yaml' , 'csv' , 'gherkin' ],
594+ choices = ['markdown' , 'compact' , 'json' , 'yaml' , 'csv' , 'gherkin' , 'toon' , 'logicml' ],
551595 default = 'markdown' ,
552596 help = 'Output format (default: markdown)'
553597 )
554598 parser .add_argument (
555599 '-d' , '--detail' ,
556- choices = ['minimal' , 'standard' , 'full' ],
600+ choices = ['minimal' , 'standard' , 'full' , 'detailed' ],
557601 default = 'standard' ,
558602 help = 'Detail level - columns to include (default: standard)'
559603 )
@@ -617,7 +661,15 @@ def main():
617661 help = 'Show saved LLM profiles'
618662 )
619663
664+ if len (sys .argv ) == 1 or any (a in ("-h" , "--help" ) for a in sys .argv [1 :]):
665+ if not _maybe_print_pretty_help ():
666+ parser .print_help ()
667+ return
668+
620669 args = parser .parse_args ()
670+
671+ if args .detail == 'detailed' :
672+ args .detail = 'full'
621673
622674 # Initialize logger
623675 log = Logger (verbose = args .verbose , debug = args .debug )
@@ -642,6 +694,8 @@ def main():
642694 YAMLGenerator , CSVGenerator
643695 )
644696 from .gherkin import GherkinGenerator
697+ from .toon_format import TOONGenerator
698+ from .logicml import LogicMLGenerator
645699
646700 # Status check
647701 if args .status :
@@ -705,9 +759,10 @@ def main():
705759
706760 # Path is required for analysis
707761 if args .path is None :
708- print ("Error: path is required" , file = sys .stderr )
709- parser .print_help ()
710- sys .exit (1 )
762+ # Keep behavior consistent with --help
763+ if not _maybe_print_pretty_help ():
764+ parser .print_help ()
765+ return
711766
712767 # Validate path
713768 if not os .path .exists (args .path ):
@@ -774,6 +829,20 @@ def main():
774829 elif args .format == 'gherkin' :
775830 generator = GherkinGenerator ()
776831 output = generator .generate (project , detail = args .detail )
832+
833+ elif args .format == 'toon' :
834+ generator = TOONGenerator ()
835+ detail_map = {
836+ 'minimal' : 'compact' ,
837+ 'standard' : 'standard' ,
838+ 'full' : 'full' ,
839+ }
840+ output = generator .generate (project , detail = detail_map .get (args .detail , 'standard' ))
841+
842+ elif args .format == 'logicml' :
843+ generator = LogicMLGenerator ()
844+ spec = generator .generate (project , detail = args .detail )
845+ output = spec .content
777846
778847 gen_time = time .time () - gen_start
779848
@@ -792,7 +861,14 @@ def main():
792861 log .success (f"Output written to: { args .output } " )
793862 else :
794863 if not args .quiet :
795- print (output )
864+ try :
865+ print (output , flush = True )
866+ except BrokenPipeError :
867+ try :
868+ sys .stdout .close ()
869+ except Exception :
870+ pass
871+ os ._exit (0 )
796872
797873 # Final summary
798874 if args .verbose :
0 commit comments