main.dart 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import 'dart:io';
  2. import 'package:flutter/material.dart';
  3. import 'package:pocketpy/pocketpy.dart' as pkpy;
  4. void main() {
  5. runApp(const MaterialApp(home: MyApp()));
  6. }
  7. class MyApp extends StatefulWidget {
  8. const MyApp({super.key});
  9. @override
  10. State<MyApp> createState() => _MyAppState();
  11. }
  12. class _MyAppState extends State<MyApp> {
  13. late final pkpy.VM vm;
  14. late final pkpy.REPL repl;
  15. bool needMoreLines = false;
  16. final TextEditingController _controller = TextEditingController();
  17. final StringBuffer buffer = StringBuffer();
  18. @override
  19. void initState() {
  20. super.initState();
  21. // create a pocketpy virtual machine
  22. vm = pkpy.VM();
  23. // create a REPL
  24. repl = pkpy.REPL(vm);
  25. WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  26. refresh();
  27. });
  28. }
  29. void addMessage(String text) {
  30. setState(() {
  31. buffer.write(text);
  32. });
  33. }
  34. void submitCode() {
  35. var text = _controller.text;
  36. _controller.clear();
  37. setState(() {
  38. buffer.write(needMoreLines ? '... $text' : '>>> $text\n');
  39. });
  40. if (text == "exit()") exit(0);
  41. needMoreLines = repl.input(text) == 0;
  42. refresh();
  43. }
  44. void refresh() {
  45. // ignore: no_leading_underscores_for_local_identifiers
  46. var _o = vm.read_output();
  47. if (_o.stdout.isNotEmpty) buffer.write(_o.stdout);
  48. if (_o.stderr.isNotEmpty) buffer.write(_o.stderr);
  49. setState(() {});
  50. }
  51. @override
  52. Widget build(BuildContext context) {
  53. var style = const TextStyle(fontSize: 16);
  54. return Scaffold(
  55. appBar: AppBar(
  56. title: const Text('Demo'),
  57. ),
  58. body: Padding(
  59. padding: const EdgeInsets.all(8.0),
  60. child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
  61. Expanded(
  62. child: SingleChildScrollView(
  63. reverse: true,
  64. child: Text(
  65. buffer.toString(),
  66. style: style,
  67. textAlign: TextAlign.left,
  68. ),
  69. ),
  70. ),
  71. const SizedBox(
  72. height: 16,
  73. ),
  74. SizedBox(
  75. height: 50,
  76. child: TextFormField(
  77. controller: _controller,
  78. style: style,
  79. maxLines: 1,
  80. decoration: const InputDecoration(
  81. border: OutlineInputBorder(),
  82. hintText: 'Enter Python code',
  83. ),
  84. ),
  85. ),
  86. Container(
  87. height: 60,
  88. alignment: Alignment.centerRight,
  89. child: MaterialButton(
  90. onPressed: submitCode,
  91. color: Colors.blue,
  92. textColor: Colors.white,
  93. child: const Text('Run')),
  94. ),
  95. ]),
  96. ),
  97. );
  98. }
  99. }