@@ -412,6 +412,22 @@ def stats() -> None:
412412 status_logger .info (f"Total acronyms: { total :,} " )
413413
414414
415+ @acronym .command (name = "abbreviation-stats" )
416+ @handle_cli_errors
417+ def abbreviation_stats () -> None :
418+ """Show statistics about the learned abbreviations database."""
419+ status_logger = get_status_logger ()
420+
421+ acronym_cache = AcronymCache ()
422+ abbreviations = acronym_cache .export_all_abbreviations ()
423+ total = len (abbreviations )
424+
425+ if total == 0 :
426+ status_logger .info ("No abbreviations learned yet" )
427+ else :
428+ status_logger .info (f"Total learned abbreviations: { total :,} " )
429+
430+
415431@acronym .command (name = "list" )
416432@click .option ("--limit" , type = int , help = "Maximum number of entries to display" )
417433@click .option ("--offset" , type = int , default = 0 , help = "Number of entries to skip" )
@@ -450,7 +466,7 @@ def list_acronyms(limit: int | None, offset: int) -> None:
450466@click .argument ("output_file" , type = click .Path ())
451467@handle_cli_errors
452468def export (output_file : str ) -> None :
453- """Export the entire acronym database to a JSON file.
469+ """Export the entire acronym and abbreviation database to a JSON file.
454470
455471 Args:
456472 output_file: Path to the output JSON file.
@@ -459,16 +475,27 @@ def export(output_file: str) -> None:
459475 acronym_cache = AcronymCache ()
460476
461477 variants = acronym_cache .export_all_variants ()
478+ abbreviations = acronym_cache .export_all_abbreviations ()
479+
480+ dataset = {
481+ "acronyms" : variants ,
482+ "abbreviations" : abbreviations ,
483+ "metadata" : {
484+ "version" : "1.0" ,
485+ "type" : "aletheia-probe-venue-intelligence" ,
486+ },
487+ }
462488
463489 try :
464490 with open (output_file , "w" , encoding = "utf-8" ) as f :
465- json .dump (variants , f , indent = 2 , ensure_ascii = False )
491+ json .dump (dataset , f , indent = 2 , ensure_ascii = False )
466492
467493 status_logger .info (
468- f"Successfully exported { len (variants )} acronym variants to { output_file } "
494+ f"Successfully exported { len (variants )} acronym variants and "
495+ f"{ len (abbreviations )} learned abbreviations to { output_file } "
469496 )
470497 except Exception as e :
471- status_logger .error (f"Failed to export acronyms : { e } " )
498+ status_logger .error (f"Failed to export dataset : { e } " )
472499 raise click .ClickException (str (e )) from e
473500
474501
@@ -481,7 +508,9 @@ def export(output_file: str) -> None:
481508)
482509@handle_cli_errors
483510def import_acronyms (input_file : str , merge : bool ) -> None :
484- """Import acronyms from a JSON file.
511+ """Import acronyms and abbreviations from a JSON file.
512+
513+ Supports both unified dataset format and legacy list-only format.
485514
486515 Args:
487516 input_file: Path to the input JSON file.
@@ -492,44 +521,69 @@ def import_acronyms(input_file: str, merge: bool) -> None:
492521
493522 try :
494523 with open (input_file , encoding = "utf-8" ) as f :
495- variants = json .load (f )
496-
497- if not isinstance (variants , list ):
498- raise ValueError ("Input file must contain a JSON list of variants" )
499-
500- status_logger .info (f"Read { len (variants )} variants from { input_file } " )
524+ data = json .load (f )
525+
526+ variants = []
527+ abbreviations = []
528+
529+ # Detect format
530+ if isinstance (data , list ):
531+ # Legacy format: list of variants
532+ variants = data
533+ status_logger .info (f"Detected legacy format with { len (variants )} variants" )
534+ elif isinstance (data , dict ):
535+ # Unified format
536+ variants = data .get ("acronyms" , [])
537+ abbreviations = data .get ("abbreviations" , [])
538+ status_logger .info (
539+ f"Detected unified format with { len (variants )} variants and "
540+ f"{ len (abbreviations )} abbreviations"
541+ )
542+ else :
543+ raise ValueError ("Input file must contain a JSON list or object" )
501544
502545 if not merge :
503546 if click .confirm (
504- "This will clear existing acronyms before importing. Continue?" ,
547+ "This will clear existing data before importing. Continue?" ,
505548 abort = True ,
506549 ):
507550 acronym_cache .clear_acronym_database ()
551+ acronym_cache .clear_learned_abbreviations ()
508552
509- count = acronym_cache .import_variants (variants , merge = True )
553+ variant_count = acronym_cache .import_variants (variants , merge = True )
554+ abbrev_count = acronym_cache .import_abbreviations (abbreviations , merge = True )
510555
511- status_logger .info (f"Successfully imported { count } acronym variants" )
556+ status_logger .info (
557+ f"Successfully imported { variant_count } acronym variants and "
558+ f"{ abbrev_count } learned abbreviations"
559+ )
512560
513561 except Exception as e :
514- status_logger .error (f"Failed to import acronyms : { e } " )
562+ status_logger .error (f"Failed to import dataset : { e } " )
515563 raise click .ClickException (str (e )) from e
516564
517565
518566@acronym .command ()
519567@click .option ("--confirm" , is_flag = True , help = "Skip confirmation prompt" )
568+ @click .option (
569+ "--include-abbreviations" , is_flag = True , help = "Also clear learned abbreviations"
570+ )
520571@handle_cli_errors
521- def clear (confirm : bool ) -> None :
522- """Clear all entries from the acronym database.
572+ def clear (confirm : bool , include_abbreviations : bool ) -> None :
573+ """Clear entries from the acronym database.
523574
524575 Args:
525576 confirm: Whether to skip the confirmation prompt.
577+ include_abbreviations: Whether to also clear learned abbreviations.
526578 """
527579 status_logger = get_status_logger ()
528580
581+ msg = "This will delete all conference acronym mappings."
582+ if include_abbreviations :
583+ msg = "This will delete all acronym mappings AND learned abbreviations."
584+
529585 if not confirm :
530- click .confirm (
531- "This will delete all conference acronym mappings. Continue?" , abort = True
532- )
586+ click .confirm (f"{ msg } Continue?" , abort = True )
533587
534588 acronym_cache = AcronymCache ()
535589 count = acronym_cache .clear_acronym_database ()
@@ -539,6 +593,13 @@ def clear(confirm: bool) -> None:
539593 else :
540594 status_logger .info (f"Cleared { count :,} acronym mapping(s)." )
541595
596+ if include_abbreviations :
597+ abbrev_count = acronym_cache .clear_learned_abbreviations ()
598+ if abbrev_count == 0 :
599+ status_logger .info ("Learned abbreviations database is already empty." )
600+ else :
601+ status_logger .info (f"Cleared { abbrev_count :,} learned abbreviation(s)." )
602+
542603
543604@acronym .command ()
544605@click .argument ("acronym" )
0 commit comments