main.dart 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. repl.input(text);
  42. needMoreLines = repl.last_input_result() == 0;
  43. refresh();
  44. }
  45. void refresh() {
  46. // ignore: no_leading_underscores_for_local_identifiers
  47. var _o = vm.read_output();
  48. if (_o.stdout.isNotEmpty) buffer.write(_o.stdout);
  49. if (_o.stderr.isNotEmpty) buffer.write(_o.stderr);
  50. setState(() {});
  51. }
  52. @override
  53. Widget build(BuildContext context) {
  54. var style = const TextStyle(fontSize: 16);
  55. return Scaffold(
  56. appBar: AppBar(
  57. title: const Text('Demo'),
  58. ),
  59. body: Padding(
  60. padding: const EdgeInsets.all(8.0),
  61. child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
  62. Expanded(
  63. child: SingleChildScrollView(
  64. reverse: true,
  65. child: Text(
  66. buffer.toString(),
  67. style: style,
  68. textAlign: TextAlign.left,
  69. ),
  70. ),
  71. ),
  72. const SizedBox(
  73. height: 16,
  74. ),
  75. SizedBox(
  76. height: 50,
  77. child: TextFormField(
  78. controller: _controller,
  79. style: style,
  80. maxLines: 1,
  81. decoration: const InputDecoration(
  82. border: OutlineInputBorder(),
  83. hintText: 'Enter Python code',
  84. ),
  85. ),
  86. ),
  87. Container(
  88. height: 60,
  89. alignment: Alignment.centerRight,
  90. child: MaterialButton(
  91. onPressed: submitCode,
  92. color: Colors.blue,
  93. textColor: Colors.white,
  94. child: const Text('Run')),
  95. ),
  96. ]),
  97. ),
  98. );
  99. }
  100. }