diff --git a/example/lib/main.dart b/example/lib/main.dart index 70b4519f..873f79b3 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:async'; - +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:xterm/flutter.dart'; import 'package:xterm/xterm.dart'; @@ -96,9 +97,19 @@ class _MyHomePageState extends State { Widget build(BuildContext context) { return Scaffold( body: SafeArea( - child: TerminalView( - terminal: terminal, - style: TerminalStyle(fontFamily: ['Cascadia Mono']), + child: Listener( + onPointerDown: (e) { + if (e.kind == PointerDeviceKind.mouse && e.buttons == kSecondaryMouseButton) { + final text = terminal.selectedText; + terminal.clearSelection(); + terminal.refresh(); + Clipboard.setData(ClipboardData(text: text)); + } + }, + child: TerminalView( + terminal: terminal, + style: TerminalStyle(fontFamily: ['Cascadia Mono']), + ), ), ), ); diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc index d38195aa..e71a16d2 100644 --- a/example/linux/flutter/generated_plugin_registrant.cc +++ b/example/linux/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h index 9bf74789..e0f0a47b 100644 --- a/example/linux/flutter/generated_plugin_registrant.h +++ b/example/linux/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake index 51436ae8..2e1de87a 100644 --- a/example/linux/flutter/generated_plugins.cmake +++ b/example/linux/flutter/generated_plugins.cmake @@ -5,6 +5,9 @@ list(APPEND FLUTTER_PLUGIN_LIST ) +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + set(PLUGIN_BUNDLED_LIBRARIES) foreach(plugin ${FLUTTER_PLUGIN_LIST}) @@ -13,3 +16,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST}) list(APPEND PLUGIN_BUNDLED_LIBRARIES $) list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/example/pubspec.lock b/example/pubspec.lock index df35f7b6..2d23a602 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,21 +7,21 @@ packages: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.3.1" asn1lib: dependency: transitive description: name: asn1lib url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.1.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -35,35 +35,28 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" + version: "1.2.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" convert: dependency: transitive description: name: convert url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.2" cupertino_icons: dependency: "direct main" description: @@ -77,7 +70,7 @@ packages: name: dart_console url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.2" dartssh2: dependency: "direct main" description: @@ -93,21 +86,21 @@ packages: name: equatable url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.5" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" ffi: dependency: transitive description: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "2.0.1" flutter: dependency: "direct main" description: flutter @@ -124,77 +117,84 @@ packages: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.13.4" + version: "0.13.5" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.1" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.0" js: dependency: transitive description: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.6.4" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.2" pinenacl: dependency: transitive description: name: pinenacl url: "https://pub.dartlang.org" source: hosted - version: "0.3.3" + version: "0.3.4" platform_info: dependency: transitive description: name: platform_info url: "https://pub.dartlang.org" source: hosted - version: "3.0.0-nullsafety.1" + version: "3.2.0" pointycastle: dependency: transitive description: name: pointycastle url: "https://pub.dartlang.org" source: hosted - version: "3.4.0" + version: "3.6.1" quiver: dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.1.0" sky_engine: dependency: transitive description: flutter @@ -206,7 +206,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -227,28 +227,28 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.8" + version: "0.4.12" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" validators: dependency: transitive description: @@ -262,21 +262,21 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.3.3" + version: "2.7.0" xterm: dependency: "direct main" description: path: ".." relative: true source: path - version: "2.5.0-pre" + version: "2.6.0" sdks: - dart: ">=2.14.0 <3.0.0" + dart: ">=2.17.0 <3.0.0" flutter: ">=2.0.0" diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake index 4d10c251..b93c4c30 100644 --- a/example/windows/flutter/generated_plugins.cmake +++ b/example/windows/flutter/generated_plugins.cmake @@ -5,6 +5,9 @@ list(APPEND FLUTTER_PLUGIN_LIST ) +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + set(PLUGIN_BUNDLED_LIBRARIES) foreach(plugin ${FLUTTER_PLUGIN_LIST}) @@ -13,3 +16,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST}) list(APPEND PLUGIN_BUNDLED_LIBRARIES $) list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/lib/frontend/input_listener.dart b/lib/frontend/input_listener.dart index ea97d7d0..62f13c49 100644 --- a/lib/frontend/input_listener.dart +++ b/lib/frontend/input_listener.dart @@ -75,7 +75,7 @@ class InputListenerState extends State if (!_didAutoFocus && widget.autofocus) { _didAutoFocus = true; - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { if (mounted) { FocusScope.of(context).autofocus(widget.focusNode); } @@ -217,7 +217,7 @@ class InputListenerState extends State } } -class TerminalTextInputClient extends TextInputClient { +class TerminalTextInputClient with TextInputClient { TerminalTextInputClient(this.onInput, this.onAction); final void Function(TextEditingValue) onInput; diff --git a/lib/frontend/terminal_view.dart b/lib/frontend/terminal_view.dart index d69392ba..d920e519 100644 --- a/lib/frontend/terminal_view.dart +++ b/lib/frontend/terminal_view.dart @@ -419,7 +419,7 @@ class _TerminalViewState extends State { } void onFocus(bool focused) { - SchedulerBinding.instance!.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) { widget.terminal.refresh(); }); } diff --git a/lib/terminal/terminal.dart b/lib/terminal/terminal.dart index 40e94b9e..4c6048ac 100644 --- a/lib/terminal/terminal.dart +++ b/lib/terminal/terminal.dart @@ -501,7 +501,7 @@ class Terminal } void selectWordOrRow(Position position) { - if (position.y > buffer.lines.length) { + if (position.y >= buffer.lines.length) { return; } @@ -558,25 +558,23 @@ class Terminal } final builder = StringBuffer(); + final yStart = max(_selection.start!.y, 0); + final yEnd = min(_selection.end!.y, buffer.height - 1); - for (var row = _selection.start!.y; row <= _selection.end!.y; row++) { - if (row >= buffer.height) { - break; - } - + for (var row = yStart; row <= yEnd; row++) { final line = buffer.lines[row]; var xStart = 0; var xEnd = viewWidth - 1; - if (row == _selection.start!.y) { - xStart = _selection.start!.x; + if (row == yStart) { + xStart = max(_selection.start!.x, 0); } else if (!line.isWrapped) { builder.write("\n"); } - if (row == _selection.end!.y) { - xEnd = _selection.end!.x; + if (row == yEnd) { + xEnd = min(_selection.end!.x, terminalWidth); } for (var col = xStart; col <= xEnd; col++) { diff --git a/pubspec.lock b/pubspec.lock index a62fd4be..246da480 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,191 +5,184 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "24.0.0" + version: "41.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "4.2.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.0" + version: "2.3.1" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.8.2" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.3.0" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.1.0" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.0" + version: "3.1.0" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.4" + version: "2.0.9" build_runner: dependency: "direct dev" description: name: build_runner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.2.0" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "7.1.0" + version: "7.2.3" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "5.1.0" + version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "8.1.2" + version: "8.4.0" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" - cli_util: - dependency: transitive - description: - name: cli_util - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.3" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.1.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.15.0" + version: "1.16.0" convert: dependency: "direct main" description: name: convert - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.0" + version: "3.0.2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.1" + version: "3.0.2" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.3" + version: "2.2.3" equatable: dependency: "direct main" description: name: equatable - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.2" + version: "2.0.3" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.0" + version: "1.3.0" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "6.1.2" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.0.1" flutter: dependency: "direct main" description: flutter @@ -204,163 +197,163 @@ packages: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.2" + version: "2.1.3" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.1" + version: "2.1.0" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.1.0" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.1" + version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.0.0" + version: "4.0.1" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "0.6.3" + version: "0.6.4" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.1.0" + version: "4.6.0" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.1" + version: "1.0.2" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.4" meta: dependency: "direct main" description: name: meta - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.7.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.0.2" mockito: dependency: "direct dev" description: name: mockito - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "5.0.15" + version: "5.2.0" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.0" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.11.1" + version: "1.8.1" platform_info: dependency: "direct main" description: name: platform_info - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.1.0" + version: "3.2.0" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.5.0" + version: "1.5.1" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.1.1" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.2.0" quiver: dependency: "direct main" description: name: quiver - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.0" + version: "3.1.0" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.0" + version: "1.3.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.1" + version: "1.0.2" sky_engine: dependency: transitive description: flutter @@ -370,100 +363,100 @@ packages: dependency: transitive description: name: source_gen - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.0" + version: "1.2.2" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "0.4.3" + version: "0.4.9" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.0" + version: "1.3.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.1.2" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.0.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.2.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted - version: "3.1.0" + version: "3.1.1" sdks: - dart: ">=2.14.0 <3.0.0" + dart: ">=2.17.0 <3.0.0" flutter: ">=2.0.0" diff --git a/test/terminal/terminal_selection_test.dart b/test/terminal/terminal_selection_test.dart new file mode 100644 index 00000000..9853cfab --- /dev/null +++ b/test/terminal/terminal_selection_test.dart @@ -0,0 +1,33 @@ +import 'dart:math' show max; +import 'package:flutter_test/flutter_test.dart'; +import 'package:xterm/mouse/position.dart'; +import 'package:xterm/xterm.dart'; + + +void main() async { + + group("Terminal selection test", () { + + const text = "" + "Hello World!\r\n" + "This is beautiful plugin!"; + final linesLength = text.split('\n').length; + final maxLengthInLine = text.split('\n').fold(0, (pre, e) => max(pre, e.length)); + + test("Select in normal range", () { + final terminal = Terminal(maxLines: 100); + terminal.write(text); + terminal.selection!.init(Position(0, 0)); + terminal.selection!.update(Position(maxLengthInLine, linesLength)); + expect(terminal.getSelectedText(), text.replaceAll('\r', '') + "\n"); + }); + + test("Select beyond the boundary", () { + final terminal = Terminal(maxLines: 100); + terminal.write(text); + terminal.selection!.init(Position(-3, -7)); + terminal.selection!.update(Position(maxLengthInLine + 8, linesLength)); + expect(terminal.getSelectedText(), text.replaceAll('\r', '') + "\n"); + }); + }); +} \ No newline at end of file