code_formatter_package 1.0.0
code_formatter_package: ^1.0.0 copied to clipboard
A Flutter package for formatting and splitting Dart code into widgets.
// ignore_for_file: avoid_print
import 'package:code_formatter_package/code_formatter_package.dart';
import 'package:flutter/material.dart';
/// Example code containing multiple widgets to be split
const String sampleCode = '''
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/// A simple home screen widget
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
backgroundColor: Colors.blue,
),
body: const Center(
child: Text(
'Welcome to Home Screen!',
style: TextStyle(fontSize: 24),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
);
}
}
/// A profile screen with state management
class ProfileScreen extends StatefulWidget {
final String userId;
const ProfileScreen({super.key, required this.userId});
@override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
bool _isLoading = true;
String _userName = '';
@override
void initState() {
super.initState();
_loadUserData();
}
Future<void> _loadUserData() async {
await Future.delayed(const Duration(seconds: 1));
setState(() {
_userName = 'John Doe';
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
if (_isLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
appBar: AppBar(title: Text('Profile: \$_userName')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircleAvatar(
radius: 50,
child: Icon(Icons.person, size: 50),
),
const SizedBox(height: 16),
Text(
_userName,
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
Text('User ID: \${widget.userId}'),
],
),
),
);
}
}
/// A settings screen widget
class SettingsScreen extends StatelessWidget {
const SettingsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Settings')),
body: ListView(
children: const [
ListTile(
leading: Icon(Icons.notifications),
title: Text('Notifications'),
trailing: Icon(Icons.chevron_right),
),
ListTile(
leading: Icon(Icons.security),
title: Text('Privacy'),
trailing: Icon(Icons.chevron_right),
),
ListTile(
leading: Icon(Icons.help),
title: Text('Help & Support'),
trailing: Icon(Icons.chevron_right),
),
],
),
);
}
}
''';
void main() {
runApp(const ExampleApp());
}
/// Example Flutter app demonstrating the code formatter package
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Code Formatter Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const FormatterDemoScreen(),
);
}
}
/// Demo screen showing various ways to use the formatter
class FormatterDemoScreen extends StatefulWidget {
const FormatterDemoScreen({super.key});
@override
State<FormatterDemoScreen> createState() => _FormatterDemoScreenState();
}
class _FormatterDemoScreenState extends State<FormatterDemoScreen> {
String _status = 'Ready to format';
List<ExtractedWidget> _extractedWidgets = [];
bool _isProcessing = false;
@override
void initState() {
super.initState();
// Example: Initialize formatter when app starts
_previewWidgets();
}
/// Preview widgets without saving to files
void _previewWidgets() {
final widgets = CodeFormatter.previewWidgets(sampleCode);
setState(() {
_extractedWidgets = widgets;
_status = 'Found ${widgets.length} widgets (preview mode)';
});
}
/// Format code and save to files
Future<void> _formatAndSave() async {
setState(() {
_isProcessing = true;
_status = 'Processing...';
});
// Example 1: Basic formatting with default config
final result = CodeFormatter.formatCode(sampleCode);
if (result.success) {
setState(() {
_extractedWidgets = result.widgets;
_status = 'Successfully saved ${result.widgets.length} widgets!';
});
// Show where files were saved
for (final widget in result.widgets) {
print('Saved: ${widget.className} -> ${widget.savedPath}');
}
// Check for warnings
if (result.warnings.isNotEmpty) {
print('Warnings:');
for (final warning in result.warnings) {
print(' - $warning');
}
}
} else {
setState(() {
_status = 'Error: ${result.errorMessage}';
});
// Handle specific error types
switch (result.errorType) {
case CodeFormatterErrorType.noWidgetsFound:
print('No widgets found in the code');
break;
case CodeFormatterErrorType.parseError:
print('Failed to parse the code');
break;
default:
print('Error: ${result.errorMessage}');
}
}
setState(() {
_isProcessing = false;
});
}
/// Format with custom configuration
Future<void> _formatWithCustomConfig() async {
setState(() {
_isProcessing = true;
_status = 'Processing with custom config...';
});
final result = CodeFormatter.formatCode(
sampleCode,
config: const FormatterConfig(
outputDir: 'lib/custom_widgets',
useClassNameAsFileName: true,
includeFlutterImports: true,
includeHeaderComment: true,
overwriteExisting: true,
),
);
setState(() {
_isProcessing = false;
if (result.success) {
_extractedWidgets = result.widgets;
_status = 'Custom format: ${result.widgets.length} widgets saved!';
} else {
_status = 'Error: ${result.errorMessage}';
}
});
}
/// Format with custom file names
Future<void> _formatWithCustomNames() async {
setState(() {
_isProcessing = true;
_status = 'Processing with custom names...';
});
final result = CodeFormatter.formatCode(
sampleCode,
config: const FormatterConfig(
outputDir: 'lib/named_widgets',
customNames: ['main_home', 'user_profile', 'app_settings'],
),
);
setState(() {
_isProcessing = false;
if (result.success) {
_extractedWidgets = result.widgets;
_status = 'Named format: ${result.widgets.length} widgets saved!';
} else {
_status = 'Error: ${result.errorMessage}';
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Code Formatter Demo'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Status card
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Status',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
Text(_status),
if (_isProcessing)
const Padding(
padding: EdgeInsets.only(top: 8.0),
child: LinearProgressIndicator(),
),
],
),
),
),
const SizedBox(height: 16),
// Action buttons
Wrap(
spacing: 8,
runSpacing: 8,
children: [
ElevatedButton.icon(
onPressed: _isProcessing ? null : _previewWidgets,
icon: const Icon(Icons.visibility),
label: const Text('Preview'),
),
ElevatedButton.icon(
onPressed: _isProcessing ? null : _formatAndSave,
icon: const Icon(Icons.save),
label: const Text('Format & Save'),
),
ElevatedButton.icon(
onPressed: _isProcessing ? null : _formatWithCustomConfig,
icon: const Icon(Icons.settings),
label: const Text('Custom Config'),
),
ElevatedButton.icon(
onPressed: _isProcessing ? null : _formatWithCustomNames,
icon: const Icon(Icons.edit),
label: const Text('Custom Names'),
),
],
),
const SizedBox(height: 16),
// Extracted widgets list
Text(
'Extracted Widgets (${_extractedWidgets.length})',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
Expanded(
child: ListView.builder(
itemCount: _extractedWidgets.length,
itemBuilder: (context, index) {
final widget = _extractedWidgets[index];
return Card(
child: ListTile(
leading: Icon(
widget.isStateful ? Icons.sync : Icons.widgets,
color: widget.isStateful ? Colors.orange : Colors.blue,
),
title: Text(widget.className),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.isStateful
? 'StatefulWidget'
: 'StatelessWidget',
),
if (widget.savedPath != null)
Text(
'Saved: ${widget.savedPath}',
style: Theme.of(context).textTheme.bodySmall,
),
if (widget.associatedClasses.isNotEmpty)
Text(
'Associated: ${widget.associatedClasses.join(", ")}',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
isThreeLine: true,
),
);
},
),
),
],
),
),
);
}
}
// =============================================================================
// Additional Examples (for documentation purposes)
// =============================================================================
/// Example: Format a file from disk
void exampleFormatFile() {
final result = CodeFormatter.formatFile(
'lib/screens/large_screen.dart',
config: const FormatterConfig(
outputDir: 'lib/widgets',
),
);
if (result.success) {
print('Formatted ${result.widgets.length} widgets from file');
}
}
/// Example: Async file formatting
Future<void> exampleAsyncFormat() async {
final result = await CodeFormatter.formatFileAsync(
'lib/screens/async_screen.dart',
);
if (result.success) {
for (final widget in result.widgets) {
print('${widget.className}: ${widget.savedPath}');
}
}
}
/// Example: Using initializeFormatter with callback
class InitializerExample extends StatefulWidget {
const InitializerExample({super.key});
@override
State<InitializerExample> createState() => _InitializerExampleState();
}
class _InitializerExampleState extends State<InitializerExample> {
String _message = 'Initializing...';
@override
void initState() {
super.initState();
// This runs after the first frame
CodeFormatter.initializeFormatter(
'lib/screens/home.dart',
config: const FormatterConfig(
outputDir: 'lib/generated',
),
onComplete: (result) {
setState(() {
if (result.success) {
_message = 'Formatted ${result.widgets.length} widgets!';
} else {
_message = 'Error: ${result.errorMessage}';
}
});
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text(_message)),
);
}
}
/// Example: Error handling
void exampleErrorHandling() {
final result = CodeFormatter.formatFile('nonexistent_file.dart');
if (!result.success) {
switch (result.errorType) {
case CodeFormatterErrorType.fileNotFound:
print('The file does not exist');
break;
case CodeFormatterErrorType.parseError:
print('Could not parse the Dart code');
break;
case CodeFormatterErrorType.noWidgetsFound:
print('No StatelessWidget or StatefulWidget classes found');
break;
case CodeFormatterErrorType.directoryCreationError:
print('Could not create output directory');
break;
case CodeFormatterErrorType.fileWriteError:
print('Could not write to output file');
break;
case CodeFormatterErrorType.invalidInput:
print('Invalid input provided');
break;
case CodeFormatterErrorType.unknown:
case null:
print('Unknown error: ${result.errorMessage}');
break;
}
}
// Always check warnings even on success
for (final warning in result.warnings) {
print('Warning: $warning');
}
}