xterm.dart

repository·master·Indexed 20 days ago

https://github.com/terminalstudio/xterm.dart

A high-performance terminal emulator for Flutter applications supporting mobile and desktop platforms. It features 60fps rendering, wide character support (CJK, emojis), and provides the Terminal class for state management and TerminalView for rendering. The library includes support for alternative buffers, custom keyboard shortcuts, and a TerminalController for managing text selection and visual highlights.

Tokens
5.4K
Snippets
22
Records
27
Agent score
70%

What's inside xterm.dart

  1. Quickstart: Create and display a terminal

    master

    To implement a basic terminal, follow these steps:

    1. Initialize a Terminal instance.
    2. (Optional) Set an onOutput callback to handle user input/interaction.
    3. Use TerminalView from package:xterm/flutter.dart to render the terminal in your Flutter widget tree.
    4. Use terminal.write() to send text to the terminal buffer.
    import 'package:xterm/xterm.dart';
    import 'package:xterm/flutter.dart';
    
    // 1. Create the terminal
    final terminal = Terminal();
    
    // 2. Listen to user interaction
    terminal.onOutput = (output) {
      print('output: $output');
    };
    
    // 3. In your Widget build method:
    // child: TerminalView(terminal),
    
    // 4. Write to the terminal
    terminal.write('Hello, world!');
  2. Customize the iOS launch screen assets

    master

    To change the image displayed during the app's launch on iOS, you can either replace the image files directly in the project directory or use Xcode.

    Option 1: Direct File Replacement Replace the existing image files within the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory with your own assets.

    Option 2: Using Xcode

    1. Open the iOS workspace using the command: open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  3. Manage terminal UI state with TerminalController

    master

    The TerminalController is a ChangeNotifier used to manage terminal interactions, including text selection, pointer inputs, and visual highlights. It allows you to programmatically control how the terminal responds to user input and how it displays state changes.

    Key capabilities:

    • Selection Management: Control whether text selection follows SelectionMode.line or SelectionMode.block and manually set or clear selections.
    • Pointer Input Control: Configure which PointerInput types (e.g., tap, drag) are sent to the terminal and toggle whether pointer inputs are suspended entirely.
    • Visual Highlights: Create temporary colored highlights over specific cell ranges.

    When the controller's state changes, it calls notifyListeners(), allowing your Flutter widgets to rebuild accordingly.

    final controller = TerminalController(
      selectionMode: SelectionMode.line,
      pointerInputs: const PointerInputs({PointerInput.tap}),
    );
  4. Access terminal state and buffers

    master

    The Terminal class provides access to its internal state and buffers:

    • viewWidth / viewHeight: The current dimensions of the visible viewport.
    • buffer: The currently active buffer (either mainBuffer or altBuffer).
    • mainBuffer: The primary buffer used for standard output.
    • altBuffer: The alternative buffer (often used by programs like vim or less to provide a full-screen interface).
    • isUsingAltBuffer: Boolean indicating if the terminal is currently using the alternative buffer.
    • lines: An IndexAwareCircularBuffer of BufferLine objects representing the active buffer's content.
    • cursor: Returns the current CursorStyle (color, blink, etc.).
  5. Use SuggestionPortal to display command suggestions

    master

    The SuggestionPortal widget is used to display a suggestion or autocompletion popup near a specific location (typically the terminal cursor). It uses a SuggestionPortalController to manage the popup's visibility and position.

    To use it:

    1. Create a SuggestionPortalController.
    2. Wrap your terminal/input widget with SuggestionPortal.
    3. Provide an overlayBuilder that returns the widget you want to show as a suggestion (e.g., a list of completions).
    4. When the cursor moves or a suggestion is needed, call controller.update(rect) where rect is the bounding box of the cursor.
    // 1. Create the controller
    final suggestionController = SuggestionPortalController();
    
    // 2. In your widget tree
    SuggestionPortal(
      controller: suggestionController,
      // The widget to show when suggestions are active
      overlayBuilder: (context) => MySuggestionListWidget(),
      // The actual terminal/input widget
      child: MyTerminalWidget(
        onCursorMove: (rect) {
          // 3. Update the portal position when the cursor moves
          suggestionController.update(rect);
        },
      ),
      // Optional: spacing configuration
      padding: const EdgeInsets.all(8),
      cursorMargin: const EdgeInsets.all(4),
    )
  6. Initialize and configure the Terminal class

    master

    The Terminal class is the primary interface for interacting with command line applications. It manages the terminal state, buffers, and translates escape sequences into updates. You can configure it via its constructor to handle specific events like bell rings, title changes, or outputting data to an underlying program.

    Key configuration options include:

    • maxLines: The maximum number of lines in the scrollback buffer.
    • onOutput: A callback triggered when the terminal needs to send data (from user input or paste) to the underlying application.
    • onResize: A callback triggered when the terminal dimensions change.
    • onTitleChange: A callback for window title updates.
    • onBell: A callback for terminal bell requests.
    • platform: Sets the TerminalTargetPlatform (e.g., for OS-specific behaviors).
    • reflowEnabled: Whether to perform text reflow when the viewport size changes (defaults to true).
    final terminal = Terminal(
      maxLines: 2000,
      onOutput: (data) {
        // Send this data to your shell or process
        myProcess.write(data);
      },
      onResize: (width, height, pixelWidth, pixelHeight) {
        // Update your UI layout
      },
      onTitleChange: (title) {
        print('New window title: $title');
      },
    );
  7. Use TerminalView for Flutter rendering

    master

    To display the terminal in a Flutter application, wrap the Terminal instance in a TerminalView widget. This widget is provided by package:xterm/flutter.dart and handles the rendering of the terminal buffer at 60fps.

    import 'package:xterm/flutter.dart';
    
    // Inside a build method
    TerminalView(terminal)
  8. Use the Terminal.onOutput callback

    master

    The onOutput property of the Terminal class is a callback that triggers when the user interacts with the terminal. This is where you should process input, such as sending keystrokes to a shell or a remote server.

    terminal.onOutput = (output) {
      // Handle the output string here
      print('output: $output');
    };
  9. Configure SuggestionPortal layout and margins

    master

    The SuggestionPortal widget provides two properties to control the spacing of the suggestion popup:

    • padding: The minimum space between the suggestion popup and the screen edges.
    • cursorMargin: The minimum space between the suggestion popup and the cursor. Currently, only the top and bottom values of this EdgeInsets are utilized to determine if the popup should appear above or below the cursor.
  10. Write data to the terminal via ZModemMux

    master

    Use terminalWrite(String input) to send text to the underlying connection.

    If a ZModem session is currently active, the data will be buffered and sent as part of the ZModem protocol state. If no ZModem session is active, the string is encoded as UTF-8 and written directly to the stdin sink.

    mux.terminalWrite('hello world\r\n');
  11. Configure pointer inputs and suspension

    master

    Use TerminalController to filter or disable mouse/pointer interactions sent to the terminal.

    • setPointerInputs(PointerInputs pointerInput): Defines the set of allowed PointerInput types.
    • setSuspendPointerInput(bool suspend): A master toggle to stop all pointer events from being sent to the terminal.
    // Only allow taps
    controller.setPointerInputs(const PointerInputs({PointerInput.tap}));
    
    // Disable all pointer input
    controller.setSuspendPointerInput(true);