xuty před 4 roky
rodič
revize
a6e36ffc52

+ 17 - 15
lib/buffer/buffer.dart

@@ -19,12 +19,12 @@ class Buffer {
 
   int _cursorX = 0;
   int _cursorY = 0;
-  int _savedCursorX;
-  int _savedCursorY;
+  int? _savedCursorX;
+  int? _savedCursorY;
   int _scrollLinesFromBottom = 0;
-  int _marginTop;
-  int _marginBottom;
-  CellAttr _savedCellAttr;
+  late int _marginTop;
+  late int _marginBottom;
+  CellAttr? _savedCellAttr;
 
   int get cursorX => _cursorX.clamp(0, terminal.viewWidth - 1);
   int get cursorY => _cursorY;
@@ -230,8 +230,9 @@ class Buffer {
 
     if (_cursorY >= terminal.viewHeight - 1) {
       lines.add(BufferLine());
-      if (terminal.maxLines != null && lines.length > terminal.maxLines) {
-        lines.removeRange(0, lines.length - terminal.maxLines);
+      final maxLines = terminal.maxLines;
+      if (maxLines != null && lines.length > maxLines) {
+        lines.removeRange(0, lines.length - maxLines);
       }
     } else {
       moveCursorY(1);
@@ -247,12 +248,12 @@ class Buffer {
     }
   }
 
-  Cell getCell(int col, int row) {
+  Cell? getCell(int col, int row) {
     final rawRow = convertViewLineToRawLine(row);
     return getRawCell(col, rawRow);
   }
 
-  Cell getRawCell(int col, int rawRow) {
+  Cell? getRawCell(int col, int rawRow) {
     if (col < 0 || rawRow < 0 || rawRow >= lines.length) {
       return null;
     }
@@ -265,7 +266,7 @@ class Buffer {
     return line.getCell(col);
   }
 
-  Cell getCellUnderCursor() {
+  Cell? getCellUnderCursor() {
     return getCell(cursorX, cursorY);
   }
 
@@ -347,15 +348,15 @@ class Buffer {
 
   void restoreCursor() {
     if (_savedCellAttr != null) {
-      terminal.cellAttr.use(_savedCellAttr);
+      terminal.cellAttr.use(_savedCellAttr!);
     }
 
     if (_savedCursorX != null) {
-      _cursorX = _savedCursorX;
+      _cursorX = _savedCursorX!;
     }
 
     if (_savedCursorY != null) {
-      _cursorY = _savedCursorY;
+      _cursorY = _savedCursorY!;
     }
 
     charset.restore();
@@ -426,8 +427,9 @@ class Buffer {
       final newLine = BufferLine();
       lines.insert(index, newLine);
 
-      if (terminal.maxLines != null && lines.length > terminal.maxLines) {
-        lines.removeRange(0, lines.length - terminal.maxLines);
+      final maxLines = terminal.maxLines;
+      if (maxLines != null && lines.length > maxLines) {
+        lines.removeRange(0, lines.length - maxLines);
       }
     } else {
       final bottom = convertViewLineToRawLine(marginBottom);

+ 1 - 1
lib/buffer/buffer_line.dart

@@ -39,7 +39,7 @@ class BufferLine {
     return _cells[index];
   }
 
-  void removeRange(int start, [int end]) {
+  void removeRange(int start, [int? end]) {
     start = start.clamp(0, _cells.length);
     end ??= _cells.length;
     end = end.clamp(start, _cells.length);

+ 2 - 2
lib/buffer/cell.dart

@@ -3,9 +3,9 @@ import 'package:xterm/buffer/cell_attr.dart';
 class Cell {
   Cell({this.codePoint, this.width = 1, this.attr});
 
-  int codePoint;
+  int? codePoint;
   int width;
-  CellAttr attr;
+  CellAttr? attr;
 
   void setCodePoint(int codePoint) {
     this.codePoint = codePoint;

+ 12 - 12
lib/buffer/cell_attr.dart

@@ -24,8 +24,8 @@ class CellAttr {
           invisible,
         );
 
-  final TerminalColor fgColor;
-  final TerminalColor bgColor;
+  final TerminalColor? fgColor;
+  final TerminalColor? bgColor;
   final bool bold;
   final bool faint;
   final bool italic;
@@ -77,15 +77,15 @@ class CellAttr {
   // }
 
   CellAttr copyWith({
-    TerminalColor fgColor,
-    TerminalColor bgColor,
-    bool bold,
-    bool faint,
-    bool italic,
-    bool underline,
-    bool blink,
-    bool inverse,
-    bool invisible,
+    TerminalColor? fgColor,
+    TerminalColor? bgColor,
+    bool? bold,
+    bool? faint,
+    bool? italic,
+    bool? underline,
+    bool? blink,
+    bool? inverse,
+    bool? invisible,
   }) {
     return CellAttr(
       fgColor: fgColor ?? this.fgColor,
@@ -106,7 +106,7 @@ class CellAttrTemplate {
     reset();
   }
 
-  CellAttr _attr;
+  late CellAttr _attr;
 
   set fgColor(TerminalColor value) {
     _attr = _attr.copyWith(fgColor: value);

+ 6 - 6
lib/frontend/char_size.dart

@@ -1,11 +1,11 @@
 class CellSize {
   CellSize({
-    this.charWidth,
-    this.charHeight,
-    this.letterSpacing,
-    this.lineSpacing,
-    this.cellWidth,
-    this.cellHeight,
+    required this.charWidth,
+    required this.charHeight,
+    required this.letterSpacing,
+    required this.lineSpacing,
+    required this.cellWidth,
+    required this.cellHeight,
   });
 
   final double charWidth;

+ 1 - 1
lib/frontend/input_behavior.dart

@@ -11,7 +11,7 @@ abstract class InputBehavior {
 
   void onKeyStroke(RawKeyEvent event, Terminal terminal);
 
-  TextEditingValue onTextEdit(TextEditingValue value, Terminal terminal);
+  TextEditingValue? onTextEdit(TextEditingValue value, Terminal terminal);
 
   void onAction(TextInputAction action, Terminal terminal);
 }

+ 1 - 1
lib/frontend/input_behavior_default.dart

@@ -32,7 +32,7 @@ class InputBehaviorDefault extends InputBehavior {
   }
 
   @override
-  TextEditingValue onTextEdit(TextEditingValue value, Terminal terminal) {
+  TextEditingValue? onTextEdit(TextEditingValue value, Terminal terminal) {
     terminal.onInput(value.text);
     if (value == TextEditingValue.empty) {
       return null;

+ 25 - 25
lib/frontend/input_listener.dart

@@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
 import 'package:meta/meta.dart';
 
 typedef KeyStrokeHandler = void Function(RawKeyEvent);
-typedef InputHandler = TextEditingValue Function(TextEditingValue);
+typedef InputHandler = TextEditingValue? Function(TextEditingValue);
 typedef ActionHandler = void Function(TextInputAction);
 typedef FocusHandler = void Function(bool);
 
@@ -15,11 +15,11 @@ abstract class InputListenerController {
 
 class InputListener extends StatefulWidget {
   InputListener({
-    @required this.child,
-    @required this.onKeyStroke,
-    @required this.onTextInput,
-    @required this.onAction,
-    @required this.focusNode,
+    required this.child,
+    required this.onKeyStroke,
+    required this.onTextInput,
+    required this.onAction,
+    required this.focusNode,
     this.onFocus,
     this.autofocus = false,
     this.listenKeyStroke = true,
@@ -31,7 +31,7 @@ class InputListener extends StatefulWidget {
   final InputHandler onTextInput;
   final KeyStrokeHandler onKeyStroke;
   final ActionHandler onAction;
-  final FocusHandler onFocus;
+  final FocusHandler? onFocus;
   final bool autofocus;
   final FocusNode focusNode;
   final bool listenKeyStroke;
@@ -41,15 +41,15 @@ class InputListener extends StatefulWidget {
   @override
   InputListenerState createState() => InputListenerState();
 
-  static InputListenerController of(BuildContext context) {
+  static InputListenerController? of(BuildContext context) {
     return context.findAncestorStateOfType<InputListenerState>();
   }
 }
 
 class InputListenerState extends State<InputListener>
     implements InputListenerController {
-  TextInputConnection _conn;
-  FocusAttachment _focusAttachment;
+  TextInputConnection? _conn;
+  FocusAttachment? _focusAttachment;
   bool _didAutoFocus = false;
 
   @override
@@ -65,7 +65,7 @@ class InputListenerState extends State<InputListener>
 
     if (!_didAutoFocus && widget.autofocus) {
       _didAutoFocus = true;
-      SchedulerBinding.instance.addPostFrameCallback((_) {
+      SchedulerBinding.instance!.addPostFrameCallback((_) {
         if (mounted) {
           FocusScope.of(context).autofocus(widget.focusNode);
         }
@@ -75,7 +75,7 @@ class InputListenerState extends State<InputListener>
 
   bool get _shouldCreateInputConnection => kIsWeb || !widget.readOnly;
 
-  bool get _hasInputConnection => _conn != null && _conn.attached;
+  bool get _hasInputConnection => _conn != null && _conn!.attached;
 
   @override
   void didUpdateWidget(InputListener oldWidget) {
@@ -100,12 +100,12 @@ class InputListenerState extends State<InputListener>
   @override
   void dispose() {
     super.dispose();
-    _focusAttachment.detach();
+    _focusAttachment?.detach();
   }
 
   @override
   Widget build(BuildContext context) {
-    _focusAttachment.reparent();
+    _focusAttachment?.reparent();
 
     if (widget.listenKeyStroke) {
       return RawKeyboardListener(
@@ -134,7 +134,7 @@ class InputListenerState extends State<InputListener>
 
   void onFocusChange() {
     if (widget.onFocus != null) {
-      widget.onFocus(widget.focusNode.hasFocus);
+      widget.onFocus?.call(widget.focusNode.hasFocus);
     }
 
     openOrCloseInputConnectionIfNeeded();
@@ -154,28 +154,28 @@ class InputListenerState extends State<InputListener>
     }
 
     if (_hasInputConnection) {
-      _conn.show();
+      _conn!.show();
     } else {
       final config = TextInputConfiguration();
       final client = TerminalTextInputClient(onInput, onAction);
       _conn = TextInput.attach(client, config);
 
-      _conn.show();
+      _conn!.show();
 
       final dx = 0.0;
       final dy = 0.0;
-      _conn.setEditableSizeAndTransform(
+      _conn!.setEditableSizeAndTransform(
         Size(10, 10),
         Matrix4.translationValues(dx, dy, 0.0),
       );
 
-      _conn.setEditingState(widget.initEditingState);
+      _conn!.setEditingState(widget.initEditingState);
     }
   }
 
   void closeInputConnectionIfNeeded() {
-    if (_conn != null && _conn.attached) {
-      _conn.close();
+    if (_conn != null && _conn!.attached) {
+      _conn!.close();
       _conn = null;
     }
   }
@@ -189,7 +189,7 @@ class InputListenerState extends State<InputListener>
   }
 
   void onAction(TextInputAction action) {
-    widget?.onAction(action);
+    widget.onAction(action);
   }
 }
 
@@ -199,13 +199,13 @@ class TerminalTextInputClient extends TextInputClient {
   final void Function(TextEditingValue) onInput;
   final ActionHandler onAction;
 
-  TextEditingValue _savedValue;
+  TextEditingValue? _savedValue;
 
-  TextEditingValue get currentTextEditingValue {
+  TextEditingValue? get currentTextEditingValue {
     return _savedValue;
   }
 
-  AutofillScope get currentAutofillScope {
+  AutofillScope? get currentAutofillScope {
     return null;
   }
 

+ 1 - 1
lib/frontend/input_map.dart

@@ -282,6 +282,6 @@ final _idKeyMap = {
   // LogicalKeyboardKey.returnKey.keyId: TerminalKey.returnKey,
 };
 
-TerminalKey inputMap(LogicalKeyboardKey key) {
+TerminalKey? inputMap(LogicalKeyboardKey key) {
   return _idKeyMap[key.keyId];
 }

+ 4 - 1
lib/frontend/mouse_listener.dart

@@ -4,7 +4,10 @@ import 'package:flutter/widgets.dart';
 typedef ScrollHandler = void Function(Offset);
 
 class MouseListener extends StatelessWidget {
-  MouseListener({this.child, this.onScroll});
+  MouseListener({
+    required this.child,
+    required this.onScroll,
+  });
 
   final Widget child;
   final ScrollHandler onScroll;

+ 2 - 2
lib/frontend/oscillator.dart

@@ -10,7 +10,7 @@ class Oscillator with Observable {
   final Duration duration;
 
   var _value = true;
-  Timer _timer;
+  Timer? _timer;
 
   void _onOscillation(_) {
     _value = !_value;
@@ -27,7 +27,7 @@ class Oscillator with Observable {
   }
 
   void stop() {
-    _timer.cancel();
+    _timer?.cancel();
     _timer = null;
   }
 }

+ 47 - 47
lib/frontend/terminal_view.dart

@@ -24,27 +24,28 @@ typedef ResizeHandler = void Function(int width, int height);
 
 class TerminalView extends StatefulWidget {
   TerminalView({
-    Key key,
-    @required this.terminal,
+    Key? key,
+    required this.terminal,
     this.onResize,
     this.style = const TerminalStyle(),
-    FocusNode focusNode,
+    this.opacity = 1.0,
+    FocusNode? focusNode,
     this.autofocus = false,
-    ScrollController scrollController,
-    InputBehavior inputBehavior,
-  })  : assert(terminal != null),
-        focusNode = focusNode ?? FocusNode(),
+    ScrollController? scrollController,
+    InputBehavior? inputBehavior,
+  })  : focusNode = focusNode ?? FocusNode(),
         scrollController = scrollController ?? ScrollController(),
         inputBehavior = inputBehavior ?? InputBehaviors.platform,
         super(key: key ?? ValueKey(terminal));
 
   final Terminal terminal;
-  final ResizeHandler onResize;
+  final ResizeHandler? onResize;
   final FocusNode focusNode;
   final bool autofocus;
   final ScrollController scrollController;
 
   final TerminalStyle style;
+  final double opacity;
 
   final InputBehavior inputBehavior;
 
@@ -54,7 +55,7 @@ class TerminalView extends StatefulWidget {
     final text = Text(
       testString,
       style: (style.textStyleProvider != null)
-          ? style.textStyleProvider(
+          ? style.textStyleProvider!(
               fontSize: style.fontSize,
             )
           : TextStyle(
@@ -93,10 +94,10 @@ class _TerminalViewState extends State<TerminalView> {
     return widget.focusNode.hasFocus;
   }
 
-  int _lastTerminalWidth;
-  int _lastTerminalHeight;
-  CellSize _cellSize;
-  ViewportOffset _offset;
+  int? _lastTerminalWidth;
+  int? _lastTerminalHeight;
+  late CellSize _cellSize;
+  late ViewportOffset _offset;
 
   var _minScrollExtent = 0.0;
   var _maxScrollExtent = 0.0;
@@ -195,7 +196,7 @@ class _TerminalViewState extends State<TerminalView> {
       dragStartBehavior: DragStartBehavior.down,
       onTapDown: (detail) {
         if (widget.terminal.selection.isEmpty) {
-          InputListener.of(context).requestKeyboard();
+          InputListener.of(context)!.requestKeyboard();
         } else {
           widget.terminal.selection.clear();
         }
@@ -218,7 +219,8 @@ class _TerminalViewState extends State<TerminalView> {
       },
       child: Container(
         constraints: BoxConstraints.expand(),
-        color: Color(widget.terminal.theme.background.value),
+        color: Color(widget.terminal.theme.background.value)
+            .withOpacity(widget.opacity),
         child: CustomPaint(
           painter: TerminalPainter(
             terminal: widget.terminal,
@@ -253,11 +255,9 @@ class _TerminalViewState extends State<TerminalView> {
 
       // print('($termWidth, $termHeight)');
 
-      if (widget.onResize != null) {
-        widget.onResize(termWidth, termHeight);
-      }
+      widget.onResize?.call(termWidth, termHeight);
 
-      SchedulerBinding.instance.addPostFrameCallback((_) {
+      SchedulerBinding.instance!.addPostFrameCallback((_) {
         widget.terminal.resize(termWidth, termHeight);
       });
 
@@ -267,7 +267,7 @@ class _TerminalViewState extends State<TerminalView> {
     }
   }
 
-  TextEditingValue onInput(TextEditingValue value) {
+  TextEditingValue? onInput(TextEditingValue value) {
     return widget.inputBehavior.onTextEdit(value, widget.terminal);
   }
 
@@ -277,7 +277,7 @@ class _TerminalViewState extends State<TerminalView> {
   }
 
   void onFocus(bool focused) {
-    SchedulerBinding.instance.addPostFrameCallback((_) {
+    SchedulerBinding.instance!.addPostFrameCallback((_) {
       widget.terminal.refresh();
     });
   }
@@ -295,11 +295,11 @@ class _TerminalViewState extends State<TerminalView> {
 
 class TerminalPainter extends CustomPainter {
   TerminalPainter({
-    this.terminal,
-    this.view,
-    this.oscillator,
-    this.focused,
-    this.charSize,
+    required this.terminal,
+    required this.view,
+    required this.oscillator,
+    required this.focused,
+    required this.charSize,
   });
 
   final Terminal terminal;
@@ -334,8 +334,9 @@ class TerminalPainter extends CustomPainter {
 
       for (var i = 0; i < cellCount; i++) {
         final cell = line.getCell(i);
+        final attr = cell.attr;
 
-        if (cell.attr == null || cell.width == 0) {
+        if (attr == null || cell.width == 0) {
           continue;
         }
 
@@ -343,8 +344,7 @@ class TerminalPainter extends CustomPainter {
         final effectWidth = charSize.cellWidth * cell.width + 1;
         final effectHeight = charSize.cellHeight + 1;
 
-        final bgColor =
-            cell.attr.inverse ? cell.attr.fgColor : cell.attr.bgColor;
+        final bgColor = attr.inverse ? attr.fgColor : attr.bgColor;
 
         if (bgColor == null) {
           continue;
@@ -415,50 +415,50 @@ class TerminalPainter extends CustomPainter {
   }
 
   void paintCell(Canvas canvas, Cell cell, double offsetX, double offsetY) {
-    if (cell.codePoint == null || cell.attr.invisible) {
+    final attr = cell.attr!;
+
+    if (cell.codePoint == null || attr.invisible) {
       return;
     }
 
-    final cellColor = cell.attr.inverse
-        ? cell.attr.bgColor ?? terminal.theme.background
-        : cell.attr.fgColor ?? terminal.theme.foreground;
+    final cellColor = attr.inverse
+        ? attr.bgColor ?? terminal.theme.background
+        : attr.fgColor ?? terminal.theme.foreground;
 
     var color = Color(cellColor.value);
 
-    if (cell.attr.faint) {
+    if (attr.faint) {
       color = color.withOpacity(0.5);
     }
 
     final style = (view.style.textStyleProvider != null)
-        ? view.style.textStyleProvider(
+        ? view.style.textStyleProvider!(
             color: color,
-            fontWeight: cell.attr.bold ? FontWeight.bold : FontWeight.normal,
-            fontStyle: cell.attr.italic ? FontStyle.italic : FontStyle.normal,
+            fontWeight: attr.bold ? FontWeight.bold : FontWeight.normal,
+            fontStyle: attr.italic ? FontStyle.italic : FontStyle.normal,
             fontSize: view.style.fontSize,
-            decoration: cell.attr.underline
-                ? TextDecoration.underline
-                : TextDecoration.none,
+            decoration:
+                attr.underline ? TextDecoration.underline : TextDecoration.none,
           )
         : TextStyle(
             color: color,
-            fontWeight: cell.attr.bold ? FontWeight.bold : FontWeight.normal,
-            fontStyle: cell.attr.italic ? FontStyle.italic : FontStyle.normal,
+            fontWeight: attr.bold ? FontWeight.bold : FontWeight.normal,
+            fontStyle: attr.italic ? FontStyle.italic : FontStyle.normal,
             fontSize: view.style.fontSize,
-            decoration: cell.attr.underline
-                ? TextDecoration.underline
-                : TextDecoration.none,
+            decoration:
+                attr.underline ? TextDecoration.underline : TextDecoration.none,
             fontFamily: 'monospace',
             fontFamilyFallback: view.style.fontFamily);
 
     final span = TextSpan(
-      text: String.fromCharCode(cell.codePoint),
+      text: String.fromCharCode(cell.codePoint!),
       // text: codePointCache.getOrConstruct(cell.codePoint),
       style: style,
     );
 
     // final tp = textLayoutCache.getOrPerformLayout(span);
     final tp = textLayoutCacheV2.getOrPerformLayout(
-        span, hashValues(cell.codePoint, cell.attr));
+        span, hashValues(cell.codePoint, attr));
 
     tp.paint(canvas, Offset(offsetX, offsetY));
   }

+ 3 - 4
lib/input/keytab/keytab.dart

@@ -1,4 +1,3 @@
-import 'package:meta/meta.dart';
 import 'package:xterm/input/keytab/keytab_default.dart';
 import 'package:xterm/input/keytab/keytab_parse.dart';
 import 'package:xterm/input/keytab/keytab_record.dart';
@@ -6,8 +5,8 @@ import 'package:xterm/input/keytab/keytab_token.dart';
 
 class Keytab {
   Keytab({
-    @required this.name,
-    @required this.records,
+    required this.name,
+    required this.records,
   });
 
   factory Keytab.parse(String source) {
@@ -20,7 +19,7 @@ class Keytab {
     return Keytab.parse(kDefaultKeytab);
   }
 
-  final String name;
+  final String? name;
   final List<KeytabRecord> records;
 
   @override

+ 1 - 1
lib/input/keytab/keytab_escape.dart

@@ -12,7 +12,7 @@ String keytabUnescape(String str) {
 
   final hexPattern = RegExp(r'\\x([0-9a-fA-F][0-9a-fA-F])');
   str = str.replaceAllMapped(hexPattern, (match) {
-    final hexString = match.group(1);
+    final hexString = match.group(1)!;
     final hexValue = int.parse(hexString, radix: 16);
     return String.fromCharCode(hexValue);
   });

+ 25 - 25
lib/input/keytab/keytab_parse.dart

@@ -14,32 +14,32 @@ class TokensReader {
 
   bool get done => _pos > tokens.length - 1;
 
-  KeytabToken take() {
+  KeytabToken? take() {
     final result = peek();
     _pos += 1;
     return result;
   }
 
-  KeytabToken peek() {
+  KeytabToken? peek() {
     if (done) return null;
     return tokens[_pos];
   }
 }
 
 class KeytabParser {
-  String _name;
+  String? _name;
   final _records = <KeytabRecord>[];
 
   void addTokens(List<KeytabToken> tokens) {
     final reader = TokensReader(tokens);
 
     while (!reader.done) {
-      if (reader.peek().type == KeytabTokenType.keyboard) {
+      if (reader.peek()!.type == KeytabTokenType.keyboard) {
         _parseName(reader);
         continue;
       }
 
-      if (reader.peek().type == KeytabTokenType.keyDefine) {
+      if (reader.peek()!.type == KeytabTokenType.keyDefine) {
         _parseKeyDefine(reader);
         continue;
       }
@@ -53,11 +53,11 @@ class KeytabParser {
   }
 
   void _parseName(TokensReader reader) {
-    if (reader.take().type != KeytabTokenType.keyboard) {
+    if (reader.take()!.type != KeytabTokenType.keyboard) {
       throw ParseError();
     }
 
-    final name = reader.take();
+    final name = reader.take()!;
     if (name.type != KeytabTokenType.input) {
       throw ParseError();
     }
@@ -66,11 +66,11 @@ class KeytabParser {
   }
 
   void _parseKeyDefine(TokensReader reader) {
-    if (reader.take().type != KeytabTokenType.keyDefine) {
+    if (reader.take()!.type != KeytabTokenType.keyDefine) {
       throw ParseError();
     }
 
-    final keyName = reader.take();
+    final keyName = reader.take()!;
 
     if (keyName.type != KeytabTokenType.keyName) {
       throw ParseError();
@@ -81,20 +81,20 @@ class KeytabParser {
       throw ParseError();
     }
 
-    bool alt;
-    bool ctrl;
-    bool shift;
-    bool anyModifier;
-    bool ansi;
-    bool appScreen;
-    bool keyPad;
-    bool appCursorKeys;
-    bool appKeyPad;
-    bool newLine;
-
-    while (reader.peek().type == KeytabTokenType.modeStatus) {
+    bool? alt;
+    bool? ctrl;
+    bool? shift;
+    bool? anyModifier;
+    bool? ansi;
+    bool? appScreen;
+    bool? keyPad;
+    bool? appCursorKeys;
+    bool? appKeyPad;
+    bool? newLine;
+
+    while (reader.peek()!.type == KeytabTokenType.modeStatus) {
       bool modeStatus;
-      switch (reader.take().value) {
+      switch (reader.take()!.value) {
         case '+':
           modeStatus = true;
           break;
@@ -106,7 +106,7 @@ class KeytabParser {
       }
 
       final mode = reader.take();
-      if (mode.type != KeytabTokenType.mode) {
+      if (mode!.type != KeytabTokenType.mode) {
         throw ParseError();
       }
 
@@ -146,11 +146,11 @@ class KeytabParser {
       }
     }
 
-    if (reader.take().type != KeytabTokenType.colon) {
+    if (reader.take()!.type != KeytabTokenType.colon) {
       throw ParseError();
     }
 
-    final actionToken = reader.take();
+    final actionToken = reader.take()!;
     KeytabAction action;
     if (actionToken.type == KeytabTokenType.input) {
       action = KeytabAction(KeytabActionType.input, actionToken.value);

+ 33 - 33
lib/input/keytab/keytab_record.dart

@@ -27,35 +27,35 @@ class KeytabAction {
 
 class KeytabRecord {
   KeytabRecord({
-    @required this.qtKeyName,
-    @required this.key,
-    @required this.action,
-    @required this.alt,
-    @required this.ctrl,
-    @required this.shift,
-    @required this.anyModifier,
-    @required this.ansi,
-    @required this.appScreen,
-    @required this.keyPad,
-    @required this.appCursorKeys,
-    @required this.appKeyPad,
-    @required this.newLine,
+    required this.qtKeyName,
+    required this.key,
+    required this.action,
+    required this.alt,
+    required this.ctrl,
+    required this.shift,
+    required this.anyModifier,
+    required this.ansi,
+    required this.appScreen,
+    required this.keyPad,
+    required this.appCursorKeys,
+    required this.appKeyPad,
+    required this.newLine,
   });
 
   String qtKeyName;
   TerminalKey key;
   KeytabAction action;
 
-  bool alt;
-  bool ctrl;
-  bool shift;
-  bool anyModifier;
-  bool ansi;
-  bool appScreen;
-  bool keyPad;
-  bool appCursorKeys;
-  bool appKeyPad;
-  bool newLine;
+  bool? alt;
+  bool? ctrl;
+  bool? shift;
+  bool? anyModifier;
+  bool? ansi;
+  bool? appScreen;
+  bool? keyPad;
+  bool? appCursorKeys;
+  bool? appKeyPad;
+  bool? newLine;
 
   @override
   String toString() {
@@ -63,43 +63,43 @@ class KeytabRecord {
     buffer.write('$qtKeyName ');
 
     if (alt != null) {
-      buffer.write(modeStatus(alt, 'Alt'));
+      buffer.write(modeStatus(alt!, 'Alt'));
     }
 
     if (ctrl != null) {
-      buffer.write(modeStatus(ctrl, 'Control'));
+      buffer.write(modeStatus(ctrl!, 'Control'));
     }
 
     if (shift != null) {
-      buffer.write(modeStatus(shift, 'Shift'));
+      buffer.write(modeStatus(shift!, 'Shift'));
     }
 
     if (anyModifier != null) {
-      buffer.write(modeStatus(anyModifier, 'AnyMod'));
+      buffer.write(modeStatus(anyModifier!, 'AnyMod'));
     }
 
     if (ansi != null) {
-      buffer.write(modeStatus(ansi, 'Ansi'));
+      buffer.write(modeStatus(ansi!, 'Ansi'));
     }
 
     if (appScreen != null) {
-      buffer.write(modeStatus(appScreen, 'AppScreen'));
+      buffer.write(modeStatus(appScreen!, 'AppScreen'));
     }
 
     if (keyPad != null) {
-      buffer.write(modeStatus(keyPad, 'KeyPad'));
+      buffer.write(modeStatus(keyPad!, 'KeyPad'));
     }
 
     if (appCursorKeys != null) {
-      buffer.write(modeStatus(appCursorKeys, 'AppCuKeys'));
+      buffer.write(modeStatus(appCursorKeys!, 'AppCuKeys'));
     }
 
     if (appKeyPad != null) {
-      buffer.write(modeStatus(appKeyPad, 'AppKeyPad'));
+      buffer.write(modeStatus(appKeyPad!, 'AppKeyPad'));
     }
 
     if (newLine != null) {
-      buffer.write(modeStatus(newLine, 'NewLine'));
+      buffer.write(modeStatus(newLine!, 'NewLine'));
     }
 
     buffer.write(' : $action');

+ 3 - 3
lib/input/keytab/keytab_token.dart

@@ -32,13 +32,13 @@ class LineReader {
 
   bool get done => _pos > line.length - 1;
 
-  String take([int count = 1]) {
+  String? take([int count = 1]) {
     final result = peek(count);
     _pos += count;
     return result;
   }
 
-  String peek([int count = 1]) {
+  String? peek([int count = 1]) {
     if (done) return null;
     final end = min(_pos + count, line.length);
     final result = line.substring(_pos, end);
@@ -142,7 +142,7 @@ Iterable<KeytabToken> _parseKeyDefine(String line) sync* {
   reader.skipWhitespace();
 
   while (reader.peek() == '+' || reader.peek() == '-') {
-    final modeStatus = reader.take();
+    final modeStatus = reader.take()!;
     yield KeytabToken(KeytabTokenType.modeStatus, modeStatus);
     final mode = reader.readString();
     yield KeytabToken(KeytabTokenType.mode, mode);

+ 9 - 8
lib/mouse/selection.dart

@@ -1,12 +1,12 @@
 import 'package:xterm/mouse/position.dart';
 
 class Selection {
-  Position _start;
-  Position _end;
+  Position? _start;
+  Position? _end;
   var _endFixed = false;
 
-  Position get start => _start;
-  Position get end => _end;
+  Position? get start => _start;
+  Position? get end => _end;
 
   void init(Position position) {
     _start = position;
@@ -15,16 +15,17 @@ class Selection {
   }
 
   void update(Position position) {
-    if (_start == null) {
+    final start = _start;
+    if (start == null) {
       return;
     }
 
-    if (position.isBefore(_start) && !_endFixed) {
+    if (position.isBefore(start) && !_endFixed) {
       _endFixed = true;
       _end = _start;
     }
 
-    if (position.isAfter(_start) && _endFixed) {
+    if (position.isAfter(start) && _endFixed) {
       _endFixed = false;
       _start = _end;
     }
@@ -49,7 +50,7 @@ class Selection {
       return false;
     }
 
-    return _start.isBeforeOrSame(position) && _end.isAfterOrSame(position);
+    return _start!.isBeforeOrSame(position) && _end!.isAfterOrSame(position);
   }
 
   bool get isEmpty {

+ 1 - 1
lib/terminal/ansi.dart

@@ -42,7 +42,7 @@ final _ansiHandlers = <String, AnsiHandler>{
 
 AnsiHandler _voidHandler(int sequenceLength) {
   return (queue, terminal) {
-    return queue.take(sequenceLength);
+    queue.take(sequenceLength);
   };
 }
 

+ 1 - 1
lib/terminal/charset.dart

@@ -91,5 +91,5 @@ int decSpecGraphicsTranslator(int codePoint) {
     return codePoint;
   }
 
-  return decSpecGraphics[codePoint] ?? decSpecGraphics;
+  return decSpecGraphics[codePoint] ?? codePoint;
 }

+ 9 - 5
lib/terminal/csi.dart

@@ -38,9 +38,9 @@ final _csiHandlers = <int, CsiSequenceHandler>{
 
 class CSI {
   CSI({
-    this.params,
-    this.finalByte,
-    this.intermediates,
+    required this.params,
+    required this.finalByte,
+    required this.intermediates,
   });
 
   final List<String> params;
@@ -53,11 +53,11 @@ class CSI {
   }
 }
 
-CSI _parseCsi(Queue<int> queue) {
+CSI? _parseCsi(Queue<int> queue) {
   final paramBuffer = StringBuffer();
   final intermediates = <int>[];
 
-  while (true) {
+  while (queue.isNotEmpty) {
     // TODO: handle special case when queue is empty as this time.
 
     final char = queue.removeFirst();
@@ -89,6 +89,10 @@ CSI _parseCsi(Queue<int> queue) {
 void csiHandler(Queue<int> queue, Terminal terminal) {
   final csi = _parseCsi(queue);
 
+  if (csi == null) {
+    return;
+  }
+
   terminal.debug.onCsi(csi);
 
   final handler = _csiHandlers[csi.finalByte];

+ 1 - 1
lib/terminal/platform.dart

@@ -1,5 +1,5 @@
 class PlatformBehavior {
-  const PlatformBehavior({this.oscTerminators});
+  const PlatformBehavior({required this.oscTerminators});
 
   final Set<int> oscTerminators;
 }

+ 1 - 1
lib/terminal/sgr.dart

@@ -347,5 +347,5 @@ TerminalColor parse8BitSgrColour(int colNum, Terminal terminal) {
     return TerminalColor.fromARGB(0xff, r, g, b);
   }
 
-  return TerminalColor(grayscaleColors[colNum.clamp(232, 255)]);
+  return TerminalColor(grayscaleColors[colNum.clamp(232, 255)]!);
 }

+ 64 - 20
lib/terminal/terminal.dart

@@ -24,15 +24,20 @@ typedef BellHandler = void Function();
 typedef TitleChangeHandler = void Function(String);
 typedef IconChangeHandler = void Function(String);
 
+void _defaultInputHandler(String _) {}
+void _defaultBellHandler() {}
+void _defaultTitleHandler(String _) {}
+void _defaultIconHandler(String _) {}
+
 class Terminal with Observable {
   Terminal({
-    this.onInput,
-    this.onBell,
-    this.onTitleChange,
-    this.onIconChange,
+    this.onInput = _defaultInputHandler,
+    this.onBell = _defaultBellHandler,
+    this.onTitleChange = _defaultTitleHandler,
+    this.onIconChange = _defaultIconHandler,
     this.platform = PlatformBehaviors.unix,
     this.theme = TerminalThemes.defaultTheme,
-    int maxLines,
+    int? maxLines,
   }) {
     _maxLines = maxLines;
 
@@ -55,10 +60,10 @@ class Terminal with Observable {
     }
   }
 
-  int _maxLines;
-  int get maxLines {
+  int? _maxLines;
+  int? get maxLines {
     if (_maxLines == null) return null;
-    return max(viewHeight, _maxLines);
+    return max(viewHeight, _maxLines!);
   }
 
   int _viewWidth = 80;
@@ -70,14 +75,45 @@ class Terminal with Observable {
   int get visibleHeight => min(_viewHeight, buffer.height);
   int get invisibleHeight => buffer.height - visibleHeight;
 
-  bool _originMode = false;
-  bool _replaceMode = false;
+  /// Insert/Replace Mode (IRM)
+  /// 
+  /// The terminal displays received characters at the cursor position.
+  /// Insert/Replace mode determines how the terminal adds characters to the
+  /// screen. Insert mode displays the new character and moves previously
+  /// displayed characters to the right. Replace mode adds characters by
+  /// replacing the character at the cursor position. 
+  ///
+  /// You can set or reset insert/replace mode as follows.
+  bool _replaceMode = true;
+
+
   bool _lineFeed = true;
   bool _screenMode = false; // DECSCNM (black on white background)
   bool _autoWrapMode = true;
   bool _bracketedPasteMode = false;
 
+  /// DECOM – Origin Mode (DEC Private)
+  ///
+  /// This is a private parameter applicable to set mode (SM) and reset mode
+  /// (RM) control sequences. The reset state causes the origin to be at the
+  /// upper-left character position on the screen. Line and column numbers are,
+  /// therefore, independent of current margin settings. The cursor may be
+  /// positioned outside the margins with a cursor position (CUP) or horizontal
+  /// and vertical position (HVP) control.
+  ///
+  /// The set state causes the origin to be at the upper-left character position
+  /// within the margins. Line and column numbers are therefore relative to the
+  /// current margin settings. The cursor is not allowed to be positioned
+  /// outside the margins.
+  ///
+  /// The cursor is moved to the new home position when this mode is set or
+  /// reset.
+  ///
+  /// Lines and columns are numbered consecutively, with the origin being line
+  /// 1, column 1.
   bool get originMode => _originMode;
+  bool _originMode = false;
+
   bool get lineFeed => _lineFeed;
   bool get newLineMode => !_lineFeed;
   bool get bracketedPasteMode => _bracketedPasteMode;
@@ -90,9 +126,9 @@ class Terminal with Observable {
   bool get applicationCursorKeys => _applicationCursorKeys;
   bool get blinkingCursor => _blinkingCursor;
 
-  Buffer _buffer;
-  Buffer _mainBuffer;
-  Buffer _altBuffer;
+  late Buffer _buffer;
+  late Buffer _mainBuffer;
+  late Buffer _altBuffer;
 
   /// Queue of input characters. addLast() to add, removeFirst() to consume.
   final _queue = Queue<int>();
@@ -130,6 +166,11 @@ class Terminal with Observable {
     _processInput();
   }
 
+  void writeBytes(Iterable<int> data) async {
+    _queue.addAll(data);
+    _processInput();
+  }
+
   void writeChar(int codePoint) {
     _queue.addLast(codePoint);
     _processInput();
@@ -270,6 +311,9 @@ class Terminal with Observable {
   }) {
     debug.onMsg(key);
 
+    // keep a local reference to bypass nnbd checks.
+    final onInput = this.onInput;
+
     if (onInput == null) {
       return;
     }
@@ -346,14 +390,14 @@ class Terminal with Observable {
     }
   }
 
-  String getSelectedText() {
+  String? getSelectedText() {
     if (selection.isEmpty) {
-      return '';
+      return null;
     }
 
     final builder = StringBuffer();
 
-    for (var row = selection.start.y; row <= selection.end.y; row++) {
+    for (var row = selection.start!.y; row <= selection.end!.y; row++) {
       if (row >= buffer.height) {
         break;
       }
@@ -363,14 +407,14 @@ class Terminal with Observable {
       var xStart = 0;
       var xEnd = viewWidth - 1;
 
-      if (row == selection.start.y) {
-        xStart = selection.start.x;
+      if (row == selection.start!.y) {
+        xStart = selection.start!.x;
       } else if (!line.isWrapped) {
         builder.write("\n");
       }
 
-      if (row == selection.end.y) {
-        xEnd = selection.end.x;
+      if (row == selection.end!.y) {
+        xEnd = selection.end!.x;
       }
 
       for (var col = xStart; col <= xEnd; col++) {

+ 3 - 1
lib/theme/terminal_style.dart

@@ -24,6 +24,8 @@ class TerminalStyle {
     'Arial',
     'Droid Sans Fallback',
     'sans-serif',
+    'Cascadia Mono',
+    'Arial Unicode MS',
   ];
 
   const TerminalStyle({
@@ -38,7 +40,7 @@ class TerminalStyle {
   final double fontSize;
   final double fontWidthScaleFactor;
   final double fontHeightScaleFactor;
-  final TextStyleProvider textStyleProvider;
+  final TextStyleProvider? textStyleProvider;
 }
 
 typedef TextStyleProvider = Function({

+ 20 - 21
lib/theme/terminal_theme.dart

@@ -1,28 +1,27 @@
-import 'package:meta/meta.dart';
 import 'package:xterm/theme/terminal_color.dart';
 
 class TerminalTheme {
   const TerminalTheme({
-    @required this.cursor,
-    @required this.selection,
-    @required this.foreground,
-    @required this.background,
-    @required this.black,
-    @required this.white,
-    @required this.red,
-    @required this.green,
-    @required this.yellow,
-    @required this.blue,
-    @required this.magenta,
-    @required this.cyan,
-    @required this.brightBlack,
-    @required this.brightRed,
-    @required this.brightGreen,
-    @required this.brightYellow,
-    @required this.brightBlue,
-    @required this.brightMagenta,
-    @required this.brightCyan,
-    @required this.brightWhite,
+    required this.cursor,
+    required this.selection,
+    required this.foreground,
+    required this.background,
+    required this.black,
+    required this.white,
+    required this.red,
+    required this.green,
+    required this.yellow,
+    required this.blue,
+    required this.magenta,
+    required this.cyan,
+    required this.brightBlack,
+    required this.brightRed,
+    required this.brightGreen,
+    required this.brightYellow,
+    required this.brightBlue,
+    required this.brightMagenta,
+    required this.brightCyan,
+    required this.brightWhite,
   });
 
   final TerminalColor cursor;

+ 23 - 20
lib/utli/hash_values.dart

@@ -5,7 +5,7 @@ class _HashEnd {
 const _HashEnd _hashEnd = _HashEnd();
 
 class _Jenkins {
-  static int combine(int hash, Object o) {
+  static int combine(int hash, Object? o) {
     assert(o is! Iterable);
     hash = 0x1fffffff & (hash + o.hashCode);
     hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
@@ -19,25 +19,28 @@ class _Jenkins {
   }
 }
 
-int hashValues(Object arg01, Object arg02,
-    [Object arg03 = _hashEnd,
-    Object arg04 = _hashEnd,
-    Object arg05 = _hashEnd,
-    Object arg06 = _hashEnd,
-    Object arg07 = _hashEnd,
-    Object arg08 = _hashEnd,
-    Object arg09 = _hashEnd,
-    Object arg10 = _hashEnd,
-    Object arg11 = _hashEnd,
-    Object arg12 = _hashEnd,
-    Object arg13 = _hashEnd,
-    Object arg14 = _hashEnd,
-    Object arg15 = _hashEnd,
-    Object arg16 = _hashEnd,
-    Object arg17 = _hashEnd,
-    Object arg18 = _hashEnd,
-    Object arg19 = _hashEnd,
-    Object arg20 = _hashEnd]) {
+int hashValues(
+  Object? arg01,
+  Object? arg02, [
+  Object? arg03 = _hashEnd,
+  Object? arg04 = _hashEnd,
+  Object? arg05 = _hashEnd,
+  Object? arg06 = _hashEnd,
+  Object? arg07 = _hashEnd,
+  Object? arg08 = _hashEnd,
+  Object? arg09 = _hashEnd,
+  Object? arg10 = _hashEnd,
+  Object? arg11 = _hashEnd,
+  Object? arg12 = _hashEnd,
+  Object? arg13 = _hashEnd,
+  Object? arg14 = _hashEnd,
+  Object? arg15 = _hashEnd,
+  Object? arg16 = _hashEnd,
+  Object? arg17 = _hashEnd,
+  Object? arg18 = _hashEnd,
+  Object? arg19 = _hashEnd,
+  Object? arg20 = _hashEnd,
+]) {
   int result = 0;
   result = _Jenkins.combine(result, arg01);
   result = _Jenkins.combine(result, arg02);

+ 16 - 17
lib/utli/unicode_v11.dart

@@ -457,7 +457,22 @@ const HIGH_WIDE = [
   [0x30000, 0x3FFFD]
 ];
 
-Uint8List table;
+final table = buildTable();
+
+Uint8List buildTable() {
+  final table = Uint8List(65536);
+  table.fillRange(0, table.length, 1);
+  table[0] = 0;
+  table.fillRange(1, 32, 0);
+  table.fillRange(0x7f, 0xa0, 0);
+  for (var r = 0; r < BMP_COMBINING.length; ++r) {
+    table.fillRange(BMP_COMBINING[r][0], BMP_COMBINING[r][1] + 1, 0);
+  }
+  for (var r = 0; r < BMP_WIDE.length; ++r) {
+    table.fillRange(BMP_WIDE[r][0], BMP_WIDE[r][1] + 1, 2);
+  }
+  return table;
+}
 
 bool bisearch(int ucs, List<List<int>> data) {
   var min = 0;
@@ -482,22 +497,6 @@ bool bisearch(int ucs, List<List<int>> data) {
 class UnicodeV11 {
   final version = '11';
 
-  UnicodeV11() {
-    if (table == null) {
-      table = Uint8List(65536);
-      table.fillRange(0, table.length, 1);
-      table[0] = 0;
-      table.fillRange(1, 32, 0);
-      table.fillRange(0x7f, 0xa0, 0);
-      for (var r = 0; r < BMP_COMBINING.length; ++r) {
-        table.fillRange(BMP_COMBINING[r][0], BMP_COMBINING[r][1] + 1, 0);
-      }
-      for (var r = 0; r < BMP_WIDE.length; ++r) {
-        table.fillRange(BMP_WIDE[r][0], BMP_WIDE[r][1] + 1, 2);
-      }
-    }
-  }
-
   int wcwidth(int codePoint) {
     if (codePoint < 32) return 0;
     if (codePoint < 127) return 1;

+ 24 - 24
pubspec.lock

@@ -2,61 +2,61 @@
 # See https://dart.dev/tools/pub/glossary#lockfile
 packages:
   async:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.5.0-nullsafety"
+    version: "2.5.0"
   boolean_selector:
     dependency: transitive
     description:
       name: boolean_selector
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.0-nullsafety"
+    version: "2.1.0"
   characters:
     dependency: transitive
     description:
       name: characters
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0-nullsafety.2"
+    version: "1.1.0"
   charcode:
     dependency: transitive
     description:
       name: charcode
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0-nullsafety"
+    version: "1.2.0"
   clock:
     dependency: transitive
     description:
       name: clock
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0-nullsafety"
+    version: "1.1.0"
   collection:
     dependency: transitive
     description:
       name: collection
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.15.0-nullsafety.2"
+    version: "1.15.0"
   convert:
     dependency: "direct main"
     description:
       name: convert
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.1"
+    version: "3.0.0"
   fake_async:
     dependency: transitive
     description:
       name: fake_async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0-nullsafety"
+    version: "1.2.0"
   flutter:
     dependency: "direct main"
     description: flutter
@@ -73,35 +73,35 @@ packages:
       name: matcher
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.12.10-nullsafety"
+    version: "0.12.10"
   meta:
     dependency: "direct main"
     description:
       name: meta
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0-nullsafety.2"
+    version: "1.3.0"
   path:
     dependency: transitive
     description:
       name: path
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.0-nullsafety"
+    version: "1.8.0"
   platform_info:
     dependency: "direct main"
     description:
       name: platform_info
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.0.1"
+    version: "3.0.0-nullsafety.1"
   quiver:
     dependency: "direct main"
     description:
       name: quiver
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.3"
+    version: "3.0.0"
   sky_engine:
     dependency: transitive
     description: flutter
@@ -113,56 +113,56 @@ packages:
       name: source_span
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.0-nullsafety.2"
+    version: "1.8.0"
   stack_trace:
     dependency: transitive
     description:
       name: stack_trace
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.10.0-nullsafety"
+    version: "1.10.0"
   stream_channel:
     dependency: transitive
     description:
       name: stream_channel
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.0-nullsafety"
+    version: "2.1.0"
   string_scanner:
     dependency: transitive
     description:
       name: string_scanner
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0-nullsafety"
+    version: "1.1.0"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0-nullsafety"
+    version: "1.2.0"
   test_api:
     dependency: transitive
     description:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.2.19-nullsafety"
+    version: "0.2.19"
   typed_data:
     dependency: transitive
     description:
       name: typed_data
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0-nullsafety.2"
+    version: "1.3.0"
   vector_math:
     dependency: transitive
     description:
       name: vector_math
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.0-nullsafety.2"
+    version: "2.1.0"
 sdks:
-  dart: ">=2.10.0-0.0.dev <2.10.0"
-  flutter: ">=1.17.0 <2.0.0"
+  dart: ">=2.12.0-0.0 <3.0.0"
+  flutter: ">=1.22.0"

+ 6 - 7
pubspec.yaml

@@ -1,18 +1,17 @@
 name: xterm
 description: xterm.dart is a fast and fully-featured terminal emulator for Flutter applications, with support for mobile and desktop platforms.
-version: 1.3.0
+version: 2.0.0
 homepage: https://github.com/TerminalStudio/xterm.dart
 
 environment:
-  sdk: ">=2.7.0 <3.0.0"
+  sdk: ">=2.12.0-0 <3.0.0"
   flutter: ">=1.22.0"
 
 dependencies:
-  convert: ^2.1.1
-  async: ^2.4.1
-  meta: ^1.1.8
-  quiver: ^2.1.3
-  platform_info: ^2.0.1
+  convert: ^3.0.0
+  meta: ^1.3.0
+  quiver: ^3.0.0-nullsafety.1
+  platform_info: ^3.0.0-nullsafety.1
   flutter:
     sdk: flutter