terminal_view 0.1.0 copy "terminal_view: ^0.1.0" to clipboard
terminal_view: ^0.1.0 copied to clipboard

A fast terminal emulator widget for Flutter, with a VT100/xterm-compatible parser and a renderer built for mobile.

example/lib/main.dart

// The smallest useful terminal_view app: a terminal widget wired to a toy
// shell that runs in Dart. Swap _Shell for a PTY or an SSH channel and the
// rest of this file stays the same.

import 'package:flutter/material.dart';
import 'package:terminal_view/terminal_view.dart';

void main() => runApp(const DemoApp());

class DemoApp extends StatelessWidget {
  const DemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'terminal_view demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(),
      home: const TerminalPage(),
    );
  }
}

class TerminalPage extends StatefulWidget {
  const TerminalPage({super.key});

  @override
  State<TerminalPage> createState() => _TerminalPageState();
}

class _TerminalPageState extends State<TerminalPage> {
  final terminal = Terminal(maxLines: 10000);
  final controller = TerminalController();
  late final _Shell shell;

  @override
  void initState() {
    super.initState();
    shell = _Shell(terminal);
    // Whatever the user types arrives here.
    terminal.onOutput = shell.onInput;
    shell.start();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('terminal_view'),
        actions: [
          IconButton(
            tooltip: 'Copy selection',
            icon: const Icon(Icons.copy),
            onPressed: _copySelection,
          ),
        ],
      ),
      body: SafeArea(
        child: TerminalView(
          terminal,
          controller: controller,
          autofocus: true,
          padding: const EdgeInsets.all(8),
          textStyle: const TerminalStyle(fontSize: 13),
          blinkInterval: const Duration(milliseconds: 600),
        ),
      ),
    );
  }

  void _copySelection() {
    final selection = controller.selection;
    final text = selection == null ? null : terminal.buffer.getText(selection);
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(
          text == null || text.isEmpty
              ? 'Nothing selected. Long press the terminal to select.'
              : 'Selected ${text.length} characters',
        ),
      ),
    );
    controller.clearSelection();
  }
}

/// A toy shell. It echoes what is typed, edits the current line, and answers a
/// handful of commands, which is enough to show the terminal doing its job.
class _Shell {
  _Shell(this.terminal);

  final Terminal terminal;
  var _line = '';

  void start() {
    terminal.write(
      '\x1b[1;36mterminal_view\x1b[0m demo shell\r\n'
      'Type \x1b[1mhelp\x1b[0m for the list of commands.\r\n\r\n',
    );
    _prompt();
  }

  void onInput(String data) {
    for (final rune in data.runes) {
      switch (rune) {
        case 0x0d: // Enter
          terminal.write('\r\n');
          _execute(_line.trim());
          _line = '';
          _prompt();
        case 0x7f: // Backspace
          if (_line.isEmpty) break;
          _line = _line.substring(0, _line.length - 1);
          // Step back, overwrite with a space, step back again.
          terminal.write('\b \b');
        case 0x03: // Ctrl+C
          terminal.write('^C\r\n');
          _line = '';
          _prompt();
        default:
          if (rune < 0x20) break;
          final char = String.fromCharCode(rune);
          _line += char;
          terminal.write(char);
      }
    }
  }

  void _prompt() => terminal.write('\x1b[32m\$\x1b[0m ');

  void _execute(String command) {
    switch (command) {
      case '':
        return;
      case 'help':
        terminal.write(
          'help     this text\r\n'
          'colors   the 16 ANSI colors\r\n'
          'date     the current time\r\n'
          'clear    clear the screen\r\n',
        );
      case 'colors':
        for (var row = 0; row < 2; row++) {
          for (var column = 0; column < 8; column++) {
            final color = 30 + column + (row == 1 ? 60 : 0);
            terminal.write('\x1b[${color}m  ██  \x1b[0m');
          }
          terminal.write('\r\n');
        }
      case 'date':
        terminal.write('${DateTime.now()}\r\n');
      case 'clear':
        terminal.write('\x1b[2J\x1b[H');
      default:
        terminal.write('\x1b[31m$command: command not found\x1b[0m\r\n');
    }
  }
}
0
likes
0
points
0
downloads

Publisher

verified publishertermphin.dev

Weekly Downloads

A fast terminal emulator widget for Flutter, with a VT100/xterm-compatible parser and a renderer built for mobile.

Repository (GitHub)
View/report issues

Topics

#terminal #tty #console #ssh

License

unknown (license)

Dependencies

convert, equatable, flutter, meta, quiver, zmodem

More

Packages that depend on terminal_view