diff --git a/markitect/cli.py b/markitect/cli.py index acfed948..8846bcb4 100644 --- a/markitect/cli.py +++ b/markitect/cli.py @@ -1081,25 +1081,180 @@ def ast_query(config, file_path, jsonpath, format): sys.exit(1) +def _show_ast_subsystem_stats(config, format): + """Display AST subsystem statistics including cache and processing metrics.""" + try: + # Import dependencies + from .ast_cache import ASTCache + from .cache_service import CacheDirectoryService + + # Collect AST subsystem statistics + stats = {} + + # AST Cache information + try: + cache_service = CacheDirectoryService() + cache_stats = cache_service.get_cache_stats() + stats['ast_cache'] = { + 'directory': cache_stats.get('cache_directory', 'Unknown'), + 'total_files': cache_stats.get('total_files', 0), + 'cache_size_bytes': cache_stats.get('cache_size_bytes', 0), + 'cache_size_human': cache_stats.get('cache_size_human', '0 B'), + 'available': True + } + except Exception as e: + stats['ast_cache'] = { + 'available': False, + 'error': str(e) + } + + # Database statistics (files processed) + try: + db_manager = config.get('db_manager') + if db_manager: + # Get count of files in database (processed files) + conn = db_manager.get_connection() + cursor = conn.cursor() + cursor.execute("SELECT COUNT(*) FROM markdown_files") + total_files = cursor.fetchone()[0] + + # Get recent processing info + cursor.execute(""" + SELECT COUNT(*) FROM markdown_files + WHERE created_at >= datetime('now', '-7 days') + """) + recent_files = cursor.fetchone()[0] + + stats['processing'] = { + 'total_files_processed': total_files, + 'files_processed_last_7_days': recent_files, + 'database_available': True + } + else: + stats['processing'] = { + 'database_available': False, + 'message': 'Database not initialized' + } + except Exception as e: + stats['processing'] = { + 'database_available': False, + 'error': str(e) + } + + # System information + stats['system'] = { + 'ast_service_available': True, # If we got here, it's available + 'working_directory': os.getcwd(), + 'python_version': sys.version.split()[0] + } + + # Format output + if format == 'json': + click.echo(json.dumps(stats, indent=2)) + elif format == 'yaml': + click.echo(yaml.dump(stats, default_flow_style=False)) + elif format == 'simple': + # Simple key-value output + if stats['ast_cache']['available']: + cache = stats['ast_cache'] + click.echo(f"ast_cache_directory: {cache['directory']}") + click.echo(f"ast_cache_files: {cache['total_files']}") + click.echo(f"ast_cache_size: {cache['cache_size_human']}") + else: + click.echo(f"ast_cache_available: False") + + if stats['processing']['database_available']: + proc = stats['processing'] + click.echo(f"total_files_processed: {proc['total_files_processed']}") + click.echo(f"recent_files_processed: {proc['files_processed_last_7_days']}") + else: + click.echo("database_available: False") + + sys_info = stats['system'] + click.echo(f"working_directory: {sys_info['working_directory']}") + click.echo(f"python_version: {sys_info['python_version']}") + else: # table format (default) + click.echo("šŸ“Š AST Subsystem Statistics") + click.echo("=" * 50) + + # AST Cache section + click.echo("\nšŸ—ƒļø AST Cache:") + if stats['ast_cache']['available']: + cache = stats['ast_cache'] + click.echo(f" Directory: {cache['directory']}") + click.echo(f" Cached Files: {cache['total_files']}") + click.echo(f" Cache Size: {cache['cache_size_human']}") + if cache['total_files'] == 0: + click.echo(" Status: āš ļø No files cached yet") + else: + click.echo(f" Status: āœ… Active") + else: + click.echo(" Status: āŒ Unavailable") + if 'error' in stats['ast_cache']: + click.echo(f" Error: {stats['ast_cache']['error']}") + + # Processing section + click.echo("\nāš™ļø Processing Metrics:") + if stats['processing']['database_available']: + proc = stats['processing'] + click.echo(f" Total Files Processed: {proc['total_files_processed']}") + click.echo(f" Files Processed (Last 7 Days): {proc['files_processed_last_7_days']}") + if proc['total_files_processed'] == 0: + click.echo(" Status: āš ļø No files processed yet") + else: + click.echo(" Status: āœ… Active") + else: + click.echo(" Status: āŒ Database unavailable") + if 'error' in stats['processing']: + click.echo(f" Error: {stats['processing']['error']}") + elif 'message' in stats['processing']: + click.echo(f" Note: {stats['processing']['message']}") + + # System section + click.echo("\nšŸ–„ļø System Information:") + sys_info = stats['system'] + click.echo(f" AST Service: āœ… Available") + click.echo(f" Working Directory: {sys_info['working_directory']}") + click.echo(f" Python Version: {sys_info['python_version']}") + + except Exception as e: + click.echo(f"Error gathering AST subsystem statistics: {e}", err=True) + if config.get('verbose'): + import traceback + click.echo(traceback.format_exc(), err=True) + + @cli.command('ast-stats') -@click.argument('file_path', type=click.Path(exists=False)) +@click.argument('file_path', type=click.Path(exists=False), required=False) @click.option('--format', '-f', type=click.Choice(['table', 'json', 'yaml', 'simple']), default='table', help='Output format') @pass_config def ast_stats(config, file_path, format): """ - Show AST statistics (headings, links, etc.). + Show AST statistics for files or AST subsystem information. - Analyze markdown file structure and provide comprehensive statistics - about document elements, organization, and content patterns. + When called with a file: Analyze markdown file structure and provide + comprehensive statistics about document elements, organization, and content patterns. - FILE_PATH: Path to the markdown file to analyze + When called without a file: Show AST subsystem statistics including cache + information, processing metrics, and system status. + + FILE_PATH: Optional path to the markdown file to analyze Examples: - markitect ast-stats document.md + markitect ast-stats # Show AST subsystem statistics + markitect ast-stats document.md # Analyze specific file markitect ast-stats document.md --format json - markitect ast-stats document.md --format yaml """ try: + # If no file provided, show AST subsystem statistics + if not file_path: + if config.get('verbose'): + click.echo("Displaying AST subsystem statistics", err=True) + + _show_ast_subsystem_stats(config, format) + return + + # File-specific analysis (existing behavior) if config.get('verbose'): click.echo(f"Calculating statistics for: {file_path}", err=True)