99import json
1010from pathlib import Path
1111from rich .console import Console
12+ from rich .table import Table
13+ from rich .panel import Panel
14+ from rich .syntax import Syntax
15+ from rich .progress import Progress , SpinnerColumn , TextColumn
16+ from rich import box
1217
1318from . import (
1419 generate_from_analysis ,
@@ -30,6 +35,10 @@ class CLIError(Exception):
3035 pass
3136
3237
38+ # Initialize rich console
39+ console = Console ()
40+
41+
3342def add_codegen_args (parser : argparse .ArgumentParser ):
3443 """Add code generation arguments to existing CLI parser."""
3544
@@ -171,10 +180,10 @@ def handle_codegen_command(args: argparse.Namespace) -> int:
171180 return _generate_and_output (json_data , language , config , args )
172181
173182 except CLIError as e :
174- print (f"Error: { e } " , file = sys . stderr )
183+ console . print (f"[red]✗ Error:[/red] { e } " )
175184 return 1
176185 except Exception as e :
177- print (f"Unexpected error: { e } " , file = sys . stderr )
186+ console . print (f"[red]✗ Unexpected error:[/red] { e } " )
178187 return 1
179188
180189
@@ -292,14 +301,13 @@ def _handle_codegen_subcommand(args: argparse.Namespace) -> int:
292301
293302 # Require language for generation
294303 if not args .language :
295- print ("Error: --language is required for code generation" , file = sys . stderr )
304+ console . print ("[red]✗[/red] --language is required for code generation" )
296305 return 1
297306
298307 # Require input
299308 if not (args .file or args .url or args .stdin ):
300- print (
301- "Error: Input source required (file, --url, or --stdin)" ,
302- file = sys .stderr ,
309+ console .print (
310+ "[red]✗[/red] Input source required (file, --url, or --stdin)"
303311 )
304312 return 1
305313
@@ -319,7 +327,7 @@ def _handle_codegen_subcommand(args: argparse.Namespace) -> int:
319327 return _generate_and_output (json_data , args .language , config , args )
320328
321329 except Exception as e :
322- print (f"Error: { e } " , file = sys . stderr )
330+ console . print (f"[red]✗ Error:[/red] { e } " )
323331 return 1
324332
325333
@@ -329,60 +337,129 @@ def _list_languages() -> int:
329337 language_info = list_all_language_info ()
330338
331339 if not language_info :
332- print ("No code generators available" )
340+ console . print ("[yellow]⚠️ No code generators available[/yellow] " )
333341 return 0
334342
335- print ("Supported languages:" )
336- print ()
343+ # Create a rich table
344+ table = Table (
345+ title = "📋 Supported Languages" , box = box .ROUNDED , title_style = "bold cyan"
346+ )
347+
348+ table .add_column ("Language" , style = "bold green" , no_wrap = True )
349+ table .add_column ("Extension" , style = "cyan" )
350+ table .add_column ("Generator Class" , style = "dim" )
351+ table .add_column ("Aliases" , style = "blue" )
337352
338353 for lang_name , info in sorted (language_info .items ()):
339- print (f" { lang_name } " )
340- print (f" Extension: { info ['file_extension' ]} " )
341- print (f" Class: { info ['class' ]} " )
342- if info ["aliases" ]:
343- print (f" Aliases: { ', ' .join (info ['aliases' ])} " )
344- print ()
354+ aliases = (
355+ ", " .join (info ["aliases" ]) if info ["aliases" ] else "[dim]none[/dim]"
356+ )
357+
358+ table .add_row (
359+ f"🔧 { lang_name } " , info ["file_extension" ], info ["class" ], aliases
360+ )
361+
362+ console .print ()
363+ console .print (table )
364+ console .print ()
365+
366+ # Add usage hint
367+ console .print (
368+ Panel (
369+ "[bold]Usage:[/bold] json_explorer [dim]input.json[/dim] --generate [cyan]LANGUAGE[/cyan]\n "
370+ "[bold]Info:[/bold] json_explorer codegen --language-info [cyan]LANGUAGE[/cyan]" ,
371+ title = "💡 Quick Start" ,
372+ border_style = "blue" ,
373+ )
374+ )
345375
346376 return 0
347377
348378 except Exception as e :
349- print (f"Error listing languages: { e } " , file = sys . stderr )
379+ console . print (f"[red]✗ Error listing languages:[/red] { e } " )
350380 return 1
351381
352382
353383def _show_language_info (language : str ) -> int :
354384 """Show detailed information about a specific language."""
355385 try :
356386 if not _validate_language (language , silent = True ):
357- print (f"Error: Language '{ language } ' is not supported" , file = sys . stderr )
358- print ("Use --list-languages to see available options" , file = sys . stderr )
387+ console . print (f"[red]✗ Language '{ language } ' is not supported[/red]" )
388+ console . print ("[dim] Use --list-languages to see available options[/dim]" )
359389 return 1
360390
361391 info = get_language_info (language )
362392
363- print (f"Language: { info ['name' ]} " )
364- print (f"File extension: { info ['file_extension' ]} " )
365- print (f"Generator class: { info ['class' ]} " )
366- print (f"Module: { info ['module' ]} " )
393+ # Create main info panel
394+ info_text = f"""[bold]Language:[/bold] { info ['name' ]}
395+ [bold]File Extension:[/bold] { info ['file_extension' ]}
396+ [bold]Generator Class:[/bold] { info ['class' ]}
397+ [bold]Module:[/bold] { info ['module' ]} """
367398
368399 if info ["aliases" ]:
369- print (f"Aliases: { ', ' .join (info ['aliases' ])} " )
400+ info_text += f"\n [bold]Aliases:[/bold] { ', ' .join (info ['aliases' ])} "
401+
402+ console .print ()
403+ console .print (
404+ Panel (
405+ info_text ,
406+ title = f"🔧 { info ['name' ].title ()} Generator" ,
407+ border_style = "green" ,
408+ )
409+ )
370410
371- # Try to get a sample generator to show default config
411+ # Try to get configuration details
372412 try :
373413 generator = get_generator (language )
374- print (f"\n Default configuration:" )
375- print (f" Package name: { generator .config .package_name } " )
376- print (f" Indent size: { generator .config .indent_size } " )
377- print (f" Generate JSON tags: { generator .config .generate_json_tags } " )
378- print (f" Add comments: { generator .config .add_comments } " )
414+
415+ # Create configuration table
416+ config_table = Table (
417+ title = "⚙️ Default Configuration" ,
418+ box = box .SIMPLE ,
419+ show_header = True ,
420+ header_style = "bold cyan" ,
421+ )
422+
423+ config_table .add_column ("Setting" , style = "bold" )
424+ config_table .add_column ("Value" , style = "green" )
425+
426+ config_table .add_row ("Package Name" , str (generator .config .package_name ))
427+ config_table .add_row ("Indent Size" , str (generator .config .indent_size ))
428+ config_table .add_row (
429+ "Generate JSON Tags" , str (generator .config .generate_json_tags )
430+ )
431+ config_table .add_row ("Add Comments" , str (generator .config .add_comments ))
432+ config_table .add_row (
433+ "JSON Tag Omitempty" , str (generator .config .json_tag_omitempty )
434+ )
435+
436+ console .print ()
437+ console .print (config_table )
438+
379439 except Exception :
380- pass
440+ console .print (
441+ "\n [yellow]⚠️ Could not retrieve configuration details[/yellow]"
442+ )
443+
444+ # Add examples panel
445+ examples_text = f"""Generate basic structure:
446+ [cyan]json_explorer codegen --language { language } data.json[/cyan]
447+
448+ Generate to file:
449+ [cyan]json_explorer codegen -l { language } -o output{ info ['file_extension' ]} data.json[/cyan]
450+
451+ Custom package name:
452+ [cyan]json_explorer codegen -l { language } --package mypackage data.json[/cyan]"""
453+
454+ console .print ()
455+ console .print (
456+ Panel (examples_text , title = "💡 Usage Examples" , border_style = "blue" )
457+ )
381458
382459 return 0
383460
384461 except Exception as e :
385- print (f"Error getting language info: { e } " , file = sys . stderr )
462+ console . print (f"[red]✗ Error getting language info:[/red] { e } " )
386463 return 1
387464
388465
@@ -391,8 +468,8 @@ def _validate_language(language: str, silent: bool = False) -> bool:
391468 supported = list_supported_languages ()
392469 if language .lower () not in [lang .lower () for lang in supported ]:
393470 if not silent :
394- print (f"Error: Unsupported language '{ language } '" , file = sys . stderr )
395- print (f"Supported languages: { ', ' .join (supported )} " , file = sys . stderr )
471+ console . print (f"[red]✗ Unsupported language '{ language } '[/red]" )
472+ console . print (f"[dim] Supported languages: { ', ' .join (supported )} [/dim]" )
396473 return False
397474 return True
398475
@@ -408,10 +485,10 @@ def _get_input_data(args: argparse.Namespace):
408485 # Try to read from stdin
409486 return json .load (sys .stdin )
410487 except json .JSONDecodeError as e :
411- print (f"Error: Invalid JSON input: { e } " , file = sys . stderr )
488+ console . print (f"[red]✗ Invalid JSON input:[/red] { e } " )
412489 return None
413490 except Exception as e :
414- print (f"Error: Failed to load input: { e } " , file = sys . stderr )
491+ console . print (f"[red]✗ Failed to load input:[/red] { e } " )
415492 return None
416493
417494
@@ -531,55 +608,97 @@ def _build_subcommand_config(args: argparse.Namespace) -> GeneratorConfig:
531608def _generate_and_output (
532609 json_data , language : str , config : GeneratorConfig , args : argparse .Namespace
533610) -> int :
534- """Generate code and handle output."""
611+ """Generate code and handle output with rich formatting ."""
535612 try :
536- # Analyze JSON
537- analysis = analyze_json (json_data )
613+ # Show analysis progress
614+ with Progress (
615+ SpinnerColumn (),
616+ TextColumn ("[progress.description]{task.description}" ),
617+ console = console ,
618+ ) as progress :
619+
620+ # Analyze JSON
621+ analyze_task = progress .add_task (
622+ "[cyan]Analyzing JSON structure..." , total = None
623+ )
624+ analysis = analyze_json (json_data )
625+ progress .remove_task (analyze_task )
538626
539- # Generate code
540- root_name = getattr (args , "root_name" , "Root" )
541- result = generate_from_analysis (analysis , language , config , root_name )
627+ # Generate code
628+ gen_task = progress .add_task (
629+ f"[green]Generating { language } code..." , total = None
630+ )
631+ root_name = getattr (args , "root_name" , "Root" )
632+ result = generate_from_analysis (analysis , language , config , root_name )
633+ progress .remove_task (gen_task )
542634
543635 if not result .success :
544- print (
545- f"Error: Code generation failed: { result .error_message } " ,
546- file = sys .stderr ,
636+ console .print (
637+ f"[red]✗ Code generation failed:[/red] { result .error_message } "
547638 )
548639 if hasattr (result , "exception" ) and result .exception :
549- print (f"Details: { result .exception } " , file = sys . stderr )
640+ console . print (f"[dim] Details: { result .exception } [/dim]" )
550641 return 1
551642
552- # Show warnings
553- if result .warnings :
554- for warning in result .warnings :
555- print (f"Warning: { warning } " , file = sys .stderr )
556-
557643 # Output code
558644 output_file = getattr (args , "output" , None )
559645 if output_file :
560646 try :
561647 output_path = Path (output_file )
562648 output_path .write_text (result .code , encoding = "utf-8" )
563- print (f"Generated { language } code saved to { output_path } " )
649+ console .print (
650+ f"[green]✓[/green] Generated { language } code saved to [cyan]{ output_path } [/cyan]"
651+ )
564652 except IOError as e :
565- print (f"Error: Failed to write to { output_path } : { e } " , file = sys . stderr )
653+ console . print (f"[red]✗ Failed to write to { output_path } :[/red] { e } " )
566654 return 1
567655 else :
568- print (result .code )
656+ top_border = "═" * 40
657+ console .print (
658+ f"[green]{ top_border } 📄 Generated { language .title ()} Code { top_border } [/green]\n "
659+ )
660+ # Display code with syntax highlighting
661+ try :
662+ syntax = Syntax (result .code , language , theme = "monokai" )
663+ console .print (syntax )
664+
665+ except Exception :
666+ # Fallback to plain text if syntax highlighting fails
667+ console .print (result .code )
668+ console .print (f"\n [green]{ top_border } { top_border } { top_border } [/green]" )
569669
570670 # Show metadata if verbose
571671 if hasattr (args , "verbose" ) and args .verbose and result .metadata :
572- print (f"\n Generation metadata:" , file = sys .stderr )
672+ metadata_table = Table (
673+ title = "📊 Generation Metadata" ,
674+ box = box .SIMPLE ,
675+ show_header = True ,
676+ header_style = "bold cyan" ,
677+ )
678+
679+ metadata_table .add_column ("Property" , style = "bold" )
680+ metadata_table .add_column ("Value" , style = "green" )
681+
573682 for key , value in result .metadata .items ():
574- print (f" { key } : { value } " , file = sys .stderr )
683+ metadata_table .add_row (key .replace ("_" , " " ).title (), str (value ))
684+
685+ console .print ()
686+ console .print (metadata_table )
687+
688+ # Show warnings with rich formatting
689+ if result .warnings :
690+ console .print ("\n [yellow]⚠️ Warnings:[/yellow]" )
691+ for warning in result .warnings :
692+ console .print (f" [yellow]•[/yellow] { warning } " )
693+ console .print ()
575694
576695 return 0
577696
578697 except GeneratorError as e :
579- print (f"Error: { e } " , file = sys . stderr )
698+ console . print (f"[red]✗[/red] { e } " )
580699 return 1
581700 except Exception as e :
582- print (f"Error: Unexpected failure: { e } " , file = sys . stderr )
701+ console . print (f"[red]✗ Unexpected failure:[/red] { e } " )
583702 return 1
584703
585704
0 commit comments