main.dart 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'package:example/src/platform_menu.dart';
  4. import 'package:flutter/foundation.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter/services.dart';
  7. import 'package:flutter_pty/flutter_pty.dart';
  8. import 'package:xterm/xterm.dart';
  9. void main() {
  10. runApp(MyApp());
  11. }
  12. bool get isDesktop {
  13. if (kIsWeb) return false;
  14. return [
  15. TargetPlatform.windows,
  16. TargetPlatform.linux,
  17. TargetPlatform.macOS,
  18. ].contains(defaultTargetPlatform);
  19. }
  20. class MyApp extends StatelessWidget {
  21. @override
  22. Widget build(BuildContext context) {
  23. return MaterialApp(
  24. title: 'xterm.dart demo',
  25. debugShowCheckedModeBanner: false,
  26. home: AppPlatformMenu(child: Home()),
  27. // shortcuts: ,
  28. );
  29. }
  30. }
  31. class Home extends StatefulWidget {
  32. Home({super.key});
  33. @override
  34. // ignore: library_private_types_in_public_api
  35. _HomeState createState() => _HomeState();
  36. }
  37. class _HomeState extends State<Home> {
  38. final terminal = Terminal(
  39. maxLines: 10000,
  40. );
  41. final terminalController = TerminalController();
  42. late final Pty pty;
  43. @override
  44. void initState() {
  45. super.initState();
  46. WidgetsBinding.instance.endOfFrame.then(
  47. (_) {
  48. if (mounted) _startPty();
  49. },
  50. );
  51. }
  52. void _startPty() {
  53. pty = Pty.start(
  54. shell,
  55. columns: terminal.viewWidth,
  56. rows: terminal.viewHeight,
  57. );
  58. pty.output
  59. .cast<List<int>>()
  60. .transform(Utf8Decoder())
  61. .listen(terminal.write);
  62. pty.exitCode.then((code) {
  63. terminal.write('the process exited with exit code $code');
  64. });
  65. terminal.onOutput = (data) {
  66. pty.write(const Utf8Encoder().convert(data));
  67. };
  68. terminal.onResize = (w, h, pw, ph) {
  69. pty.resize(h, w);
  70. };
  71. }
  72. @override
  73. Widget build(BuildContext context) {
  74. return Scaffold(
  75. backgroundColor: Colors.transparent,
  76. body: SafeArea(
  77. child: TerminalView(
  78. terminal,
  79. controller: terminalController,
  80. autofocus: true,
  81. backgroundOpacity: 0.7,
  82. onSecondaryTapDown: (details, offset) async {
  83. final selection = terminalController.selection;
  84. if (selection != null) {
  85. final text = terminal.buffer.getText(selection);
  86. terminalController.clearSelection();
  87. await Clipboard.setData(ClipboardData(text: text));
  88. } else {
  89. final data = await Clipboard.getData('text/plain');
  90. final text = data?.text;
  91. if (text != null) {
  92. terminal.paste(text);
  93. }
  94. }
  95. },
  96. ),
  97. ),
  98. );
  99. }
  100. }
  101. String get shell {
  102. if (Platform.isMacOS || Platform.isLinux) {
  103. return Platform.environment['SHELL'] ?? 'bash';
  104. }
  105. if (Platform.isWindows) {
  106. return 'cmd.exe';
  107. }
  108. return 'sh';
  109. }