diff --git a/bin/xterm_bench.dart b/bin/xterm_bench.dart index e8cf66d3..32c841f5 100644 --- a/bin/xterm_bench.dart +++ b/bin/xterm_bench.dart @@ -1,4 +1,4 @@ -import 'package:xterm/src/terminal.dart'; +import 'package:xterm_core/xterm_core.dart'; void main(List args) async { final lines = 1000; diff --git a/example/macos/Podfile b/example/macos/Podfile index c795730d..b52666a1 100644 --- a/example/macos/Podfile +++ b/example/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.14' +platform :osx, '10.15' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index 6d2dbc33..ec75a5e2 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -14,9 +14,9 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral SPEC CHECKSUMS: - flutter_pty: 41b6f848ade294be726a6b94cdd4a67c3bc52f59 - FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + flutter_pty: 1e360feaf8b1a213d2d50da3c076005b8eef1eee + FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 -PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 +PODFILE CHECKSUM: 9ebaf0ce3d369aaa26a9ea0e159195ed94724cf3 -COCOAPODS: 1.15.0 +COCOAPODS: 1.16.2 diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 28438dca..b02adc49 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -557,7 +557,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -639,7 +639,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -689,7 +689,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15368ecc..ac78810c 100644 --- a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -59,6 +59,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/example/macos/Runner/AppDelegate.swift b/example/macos/Runner/AppDelegate.swift index d53ef643..b3c17614 100644 --- a/example/macos/Runner/AppDelegate.swift +++ b/example/macos/Runner/AppDelegate.swift @@ -1,9 +1,13 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/example/pubspec.lock b/example/pubspec.lock index 25262108..47869e45 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -77,26 +77,26 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.1" convert: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" ffi: dependency: transitive description: @@ -276,26 +276,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.2" lints: dependency: "direct dev" description: @@ -308,26 +308,26 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.17.0" package_config: dependency: transitive description: @@ -340,10 +340,10 @@ packages: dependency: "direct main" description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" petitparser: dependency: transitive description: @@ -420,7 +420,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: @@ -433,18 +433,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: @@ -465,10 +465,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.7" typed_data: dependency: transitive description: @@ -489,10 +489,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -531,7 +531,16 @@ packages: path: ".." relative: true source: path - version: "3.6.1-pre" + version: "4.0.0" + xterm_core: + dependency: transitive + description: + path: "." + ref: HEAD + resolved-ref: a9f4d54c36890d349e673a46b8e638239914d0d0 + url: "https://github.com/isegal/xterm_core.dart" + source: git + version: "4.0.0" yaml: dependency: transitive description: @@ -549,5 +558,5 @@ packages: source: hosted version: "0.0.6" sdks: - dart: ">=3.3.0-279.1.beta <4.0.0" - flutter: ">=3.10.0" + dart: ">=3.8.0-0 <4.0.0" + flutter: ">=3.19.0" diff --git a/lib/core.dart b/lib/core.dart deleted file mode 100644 index ffe7f1cc..00000000 --- a/lib/core.dart +++ /dev/null @@ -1,22 +0,0 @@ -export 'src/core/buffer/buffer.dart'; -export 'src/core/buffer/cell_flags.dart'; -export 'src/core/buffer/cell_offset.dart'; -export 'src/core/buffer/line.dart'; -export 'src/core/buffer/range.dart'; -export 'src/core/buffer/range_block.dart'; -export 'src/core/buffer/range_line.dart'; -export 'src/core/buffer/segment.dart'; -export 'src/core/cell.dart'; -export 'src/core/color.dart'; -export 'src/core/cursor.dart'; -export 'src/core/escape/handler.dart'; -export 'src/core/escape/parser.dart'; -export 'src/core/input/handler.dart'; -export 'src/core/input/keys.dart'; -export 'src/core/mouse/button.dart'; -export 'src/core/mouse/button_state.dart'; -export 'src/core/mouse/handler.dart'; -export 'src/core/mouse/mode.dart'; -export 'src/core/platform.dart'; -export 'src/core/state.dart'; -export 'src/terminal.dart'; diff --git a/lib/src/base/disposable.dart b/lib/src/base/disposable.dart deleted file mode 100644 index c6dc023c..00000000 --- a/lib/src/base/disposable.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:xterm/src/base/event.dart'; - -mixin Disposable { - final _disposables = []; - - bool get disposed => _disposed; - bool _disposed = false; - - Event get onDisposed => _onDisposed.event; - final _onDisposed = EventEmitter(); - - void register(Disposable disposable) { - assert(!_disposed); - _disposables.add(disposable); - } - - void registerCallback(void Function() callback) { - assert(!_disposed); - _disposables.add(_DisposeCallback(callback)); - } - - void dispose() { - _disposed = true; - for (final disposable in _disposables) { - disposable.dispose(); - } - _onDisposed.emit(null); - } -} - -class _DisposeCallback with Disposable { - final void Function() callback; - - _DisposeCallback(this.callback); - - @override - void dispose() { - super.dispose(); - callback(); - } -} diff --git a/lib/src/base/event.dart b/lib/src/base/event.dart deleted file mode 100644 index 3987332e..00000000 --- a/lib/src/base/event.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:xterm/src/base/disposable.dart'; - -typedef EventListener = void Function(T event); - -class Event { - final EventEmitter emitter; - - Event(this.emitter); - - void call(EventListener listener) { - emitter(listener); - } -} - -class EventEmitter { - final _listeners = >[]; - - EventSubscription call(EventListener listener) { - _listeners.add(listener); - return EventSubscription(this, listener); - } - - void emit(T event) { - for (final listener in _listeners) { - listener(event); - } - } - - Event get event => Event(this); -} - -class EventSubscription with Disposable { - final EventEmitter emitter; - final EventListener listener; - - EventSubscription(this.emitter, this.listener); - - @override - void dispose() { - emitter._listeners.remove(listener); - } -} diff --git a/lib/src/base/observable.dart b/lib/src/base/observable.dart deleted file mode 100644 index ac2b78a5..00000000 --- a/lib/src/base/observable.dart +++ /dev/null @@ -1,17 +0,0 @@ -mixin Observable { - final listeners = {}; - - void addListener(void Function() listener) { - listeners.add(listener); - } - - void removeListener(void Function() listener) { - listeners.remove(listener); - } - - void notifyListeners() { - for (var listener in listeners) { - listener(); - } - } -} diff --git a/lib/src/core/buffer/buffer.dart b/lib/src/core/buffer/buffer.dart deleted file mode 100644 index 10789382..00000000 --- a/lib/src/core/buffer/buffer.dart +++ /dev/null @@ -1,604 +0,0 @@ -import 'dart:math' show max, min; - -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/buffer/line.dart'; -import 'package:xterm/src/core/buffer/range_line.dart'; -import 'package:xterm/src/core/buffer/range.dart'; -import 'package:xterm/src/core/charset.dart'; -import 'package:xterm/src/core/cursor.dart'; -import 'package:xterm/src/core/reflow.dart'; -import 'package:xterm/src/core/state.dart'; -import 'package:xterm/src/utils/circular_buffer.dart'; -import 'package:xterm/src/utils/unicode_v11.dart'; - -class Buffer { - final TerminalState terminal; - - final int maxLines; - - final bool isAltBuffer; - - /// Characters that break selection when calling [getWordBoundary]. If null, - /// defaults to [defaultWordSeparators]. - final Set? wordSeparators; - - Buffer( - this.terminal, { - required this.maxLines, - required this.isAltBuffer, - this.wordSeparators, - }) { - for (int i = 0; i < terminal.viewHeight; i++) { - lines.push(_newEmptyLine()); - } - - resetVerticalMargins(); - } - - int _cursorX = 0; - - int _cursorY = 0; - - late int _marginTop; - - late int _marginBottom; - - var _savedCursorX = 0; - - var _savedCursorY = 0; - - final _savedCursorStyle = CursorStyle(); - - final charset = Charset(); - - /// Width of the viewport in columns. Also the index of the last column. - int get viewWidth => terminal.viewWidth; - - /// Height of the viewport in rows. Also the index of the last line. - int get viewHeight => terminal.viewHeight; - - /// lines of the buffer. the length of [lines] should always be equal or - /// greater than [viewHeight]. - late final lines = IndexAwareCircularBuffer(maxLines); - - /// Total number of lines in the buffer. Always equal or greater than - /// [viewHeight]. - int get height => lines.length; - - /// Horizontal position of the cursor relative to the top-left cornor of the - /// screen, starting from 0. - int get cursorX => _cursorX.clamp(0, terminal.viewWidth - 1); - - /// Vertical position of the cursor relative to the top-left cornor of the - /// screen, starting from 0. - int get cursorY => _cursorY; - - /// Index of the first line in the scroll region. - int get marginTop => _marginTop; - - /// Index of the last line in the scroll region. - int get marginBottom => _marginBottom; - - /// The number of lines above the viewport. - int get scrollBack => height - viewHeight; - - /// Vertical position of the cursor relative to the top of the buffer, - /// starting from 0. - int get absoluteCursorY => _cursorY + scrollBack; - - /// Absolute index of the first line in the scroll region. - int get absoluteMarginTop => _marginTop + scrollBack; - - /// Absolute index of the last line in the scroll region. - int get absoluteMarginBottom => _marginBottom + scrollBack; - - /// Writes data to the _terminal. Terminal sequences or special characters are - /// not interpreted and directly added to the buffer. - /// - /// See also: [Terminal.write] - void write(String text) { - for (var char in text.runes) { - writeChar(char); - } - } - - /// Writes a single character to the _terminal. Escape sequences or special - /// characters are not interpreted and directly added to the buffer. - /// - /// See also: [Terminal.writeChar] - void writeChar(int codePoint) { - codePoint = charset.translate(codePoint); - - final cellWidth = unicodeV11.wcwidth(codePoint); - if (_cursorX >= terminal.viewWidth) { - index(); - setCursorX(0); - if (terminal.autoWrapMode) { - currentLine.isWrapped = true; - } - } - - final line = currentLine; - line.setCell(_cursorX, codePoint, cellWidth, terminal.cursor); - - if (_cursorX < viewWidth) { - _cursorX++; - } - - if (cellWidth == 2) { - writeChar(0); - } - } - - /// The line at the current cursor position. - BufferLine get currentLine { - return lines[absoluteCursorY]; - } - - void backspace() { - if (_cursorX == 0 && currentLine.isWrapped) { - currentLine.isWrapped = false; - moveCursor(viewWidth - 1, -1); - } else if (_cursorX == viewWidth) { - moveCursor(-2, 0); - } else { - moveCursor(-1, 0); - } - } - - /// Erases the viewport from the cursor position to the end of the buffer, - /// including the cursor position. - void eraseDisplayFromCursor() { - eraseLineFromCursor(); - - for (var i = absoluteCursorY + 1; i < height; i++) { - final line = lines[i]; - line.isWrapped = false; - line.eraseRange(0, viewWidth, terminal.cursor); - } - } - - /// Erases the viewport from the top-left corner to the cursor, including the - /// cursor. - void eraseDisplayToCursor() { - eraseLineToCursor(); - - for (var i = 0; i < _cursorY; i++) { - final line = lines[i + scrollBack]; - line.isWrapped = false; - line.eraseRange(0, viewWidth, terminal.cursor); - } - } - - /// Erases the whole viewport. - void eraseDisplay() { - for (var i = 0; i < viewHeight; i++) { - final line = lines[i + scrollBack]; - line.isWrapped = false; - line.eraseRange(0, viewWidth, terminal.cursor); - } - } - - /// Erases the line from the cursor to the end of the line, including the - /// cursor position. - void eraseLineFromCursor() { - currentLine.isWrapped = false; - currentLine.eraseRange(_cursorX, viewWidth, terminal.cursor); - } - - /// Erases the line from the start of the line to the cursor, including the - /// cursor. - void eraseLineToCursor() { - currentLine.isWrapped = false; - currentLine.eraseRange(0, _cursorX, terminal.cursor); - } - - /// Erases the line at the current cursor position. - void eraseLine() { - currentLine.isWrapped = false; - currentLine.eraseRange(0, viewWidth, terminal.cursor); - } - - /// Erases [count] cells starting at the cursor position. - void eraseChars(int count) { - final start = _cursorX; - currentLine.eraseRange(start, start + count, terminal.cursor); - } - - void scrollDown(int lines) { - for (var i = absoluteMarginBottom; i >= absoluteMarginTop; i--) { - if (i >= absoluteMarginTop + lines) { - this.lines[i] = this.lines[i - lines]; - } else { - this.lines[i] = _newEmptyLine(); - } - } - } - - void scrollUp(int lines) { - for (var i = absoluteMarginTop; i <= absoluteMarginBottom; i++) { - if (i <= absoluteMarginBottom - lines) { - this.lines[i] = this.lines[i + lines]; - } else { - this.lines[i] = _newEmptyLine(); - } - } - } - - /// https://vt100.net/docs/vt100-ug/chapter3.html#IND IND – Index - /// - /// ESC D - /// - /// [index] causes the active position to move downward one line without - /// changing the column position. If the active position is at the bottom - /// margin, a scroll up is performed. - void index() { - if (isInVerticalMargin) { - if (_cursorY == _marginBottom) { - if (marginTop == 0 && !isAltBuffer) { - lines.insert(absoluteMarginBottom + 1, _newEmptyLine()); - } else { - scrollUp(1); - } - } else { - moveCursorY(1); - } - return; - } - - // the cursor is not in the scrollable region - if (_cursorY >= viewHeight - 1) { - // we are at the bottom - if (isAltBuffer) { - scrollUp(1); - } else { - lines.push(_newEmptyLine()); - } - } else { - // there're still lines so we simply move cursor down. - moveCursorY(1); - } - } - - void lineFeed() { - index(); - if (terminal.lineFeedMode) { - setCursorX(0); - } - } - - /// https://terminalguide.namepad.de/seq/a_esc_cm/ - void reverseIndex() { - if (isInVerticalMargin) { - if (_cursorY == _marginTop) { - scrollDown(1); - } else { - moveCursorY(-1); - } - } else { - moveCursorY(-1); - } - } - - void cursorGoForward() { - _cursorX = min(_cursorX + 1, viewWidth); - } - - void setCursorX(int cursorX) { - _cursorX = cursorX.clamp(0, viewWidth - 1); - } - - void setCursorY(int cursorY) { - _cursorY = cursorY.clamp(0, viewHeight - 1); - } - - void moveCursorX(int offset) { - setCursorX(_cursorX + offset); - } - - void moveCursorY(int offset) { - setCursorY(_cursorY + offset); - } - - void setCursor(int cursorX, int cursorY) { - var maxCursorY = viewHeight - 1; - - if (terminal.originMode) { - cursorY += _marginTop; - maxCursorY = _marginBottom; - } - - _cursorX = cursorX.clamp(0, viewWidth - 1); - _cursorY = cursorY.clamp(0, maxCursorY); - } - - void moveCursor(int offsetX, int offsetY) { - final cursorX = _cursorX + offsetX; - final cursorY = _cursorY + offsetY; - setCursor(cursorX, cursorY); - } - - /// Save cursor position, charmap and text attributes. - void saveCursor() { - _savedCursorX = _cursorX; - _savedCursorY = _cursorY; - _savedCursorStyle.foreground = terminal.cursor.foreground; - _savedCursorStyle.background = terminal.cursor.background; - _savedCursorStyle.attrs = terminal.cursor.attrs; - charset.save(); - } - - /// Restore cursor position, charmap and text attributes. - void restoreCursor() { - _cursorX = _savedCursorX; - _cursorY = _savedCursorY; - terminal.cursor.foreground = _savedCursorStyle.foreground; - terminal.cursor.background = _savedCursorStyle.background; - terminal.cursor.attrs = _savedCursorStyle.attrs; - charset.restore(); - } - - /// Sets the vertical scrolling margin to [top] and [bottom]. - /// Both values must be between 0 and [viewHeight] - 1. - void setVerticalMargins(int top, int bottom) { - _marginTop = top.clamp(0, viewHeight - 1); - _marginBottom = bottom.clamp(0, viewHeight - 1); - - _marginTop = min(_marginTop, _marginBottom); - _marginBottom = max(_marginTop, _marginBottom); - } - - bool get isInVerticalMargin { - return _cursorY >= _marginTop && _cursorY <= _marginBottom; - } - - void resetVerticalMargins() { - setVerticalMargins(0, viewHeight - 1); - } - - void deleteChars(int count) { - final start = _cursorX.clamp(0, viewWidth); - count = min(count, viewWidth - start); - currentLine.removeCells(start, count, terminal.cursor); - } - - /// Remove all lines above the top of the viewport. - void clearScrollback() { - if (height <= viewHeight) { - return; - } - - lines.trimStart(scrollBack); - } - - /// Clears the viewport and scrollback buffer. Then fill with empty lines. - void clear() { - lines.clear(); - for (int i = 0; i < viewHeight; i++) { - lines.push(_newEmptyLine()); - } - } - - void insertBlankChars(int count) { - currentLine.insertCells(_cursorX, count, terminal.cursor); - } - - void insertLines(int count) { - if (!isInVerticalMargin) { - return; - } - - setCursorX(0); - - // Number of lines from the cursor to the bottom of the scrollable region - // including the cursor itself. - final linesBelow = absoluteMarginBottom - absoluteCursorY + 1; - - // Number of empty lines to insert. - final linesToInsert = min(count, linesBelow); - - // Number of lines to move up. - final linesToMove = linesBelow - linesToInsert; - - for (var i = 0; i < linesToMove; i++) { - final index = absoluteMarginBottom - i; - lines[index] = lines.swap(index - linesToInsert, _newEmptyLine()); - } - - for (var i = linesToMove; i < linesToInsert; i++) { - lines[absoluteCursorY + i] = _newEmptyLine(); - } - } - - /// Remove [count] lines starting at the current cursor position. Lines below - /// the removed lines are shifted up. This only affects the scrollable region. - /// Lines outside the scrollable region are not affected. - void deleteLines(int count) { - if (!isInVerticalMargin) { - return; - } - - setCursorX(0); - - count = min(count, absoluteMarginBottom - absoluteCursorY + 1); - - final linesToMove = absoluteMarginBottom - absoluteCursorY + 1 - count; - - for (var i = 0; i < linesToMove; i++) { - final index = absoluteCursorY + i; - lines[index] = lines[index + count]; - } - - for (var i = 0; i < count; i++) { - lines[absoluteMarginBottom - i] = _newEmptyLine(); - } - } - - void resize(int oldWidth, int oldHeight, int newWidth, int newHeight) { - // 1. Adjust the height. - if (newHeight > oldHeight) { - // Grow larger - for (var i = 0; i < newHeight - oldHeight; i++) { - if (newHeight > lines.length) { - lines.push(_newEmptyLine(newWidth)); - } else { - _cursorY++; - } - } - } else { - // Shrink smaller - for (var i = 0; i < oldHeight - newHeight; i++) { - if (_cursorY > newHeight - 1) { - _cursorY--; - } else { - lines.pop(); - } - } - } - - // Ensure cursor is within the screen. - _cursorX = _cursorX.clamp(0, newWidth - 1); - _cursorY = _cursorY.clamp(0, newHeight - 1); - - // 2. Adjust the width. - if (newWidth != oldWidth) { - if (terminal.reflowEnabled && !isAltBuffer) { - final reflowResult = reflow(lines, oldWidth, newWidth); - - while (reflowResult.length < newHeight) { - reflowResult.add(_newEmptyLine(newWidth)); - } - - lines.replaceWith(reflowResult); - } else { - lines.forEach((item) => item.resize(newWidth)); - } - } - } - - /// Create a new [CellAnchor] at the specified [x] and [y] coordinates. - CellAnchor createAnchor(int x, int y) { - return lines[y].createAnchor(x); - } - - /// Create a new [CellAnchor] at the specified [x] and [y] coordinates. - CellAnchor createAnchorFromOffset(CellOffset offset) { - return lines[offset.y].createAnchor(offset.x); - } - - CellAnchor createAnchorFromCursor() { - return createAnchor(cursorX, absoluteCursorY); - } - - /// Create a new empty [BufferLine] with the current [viewWidth] if [width] - /// is not specified. - BufferLine _newEmptyLine([int? width]) { - final line = BufferLine(width ?? viewWidth); - return line; - } - - static final defaultWordSeparators = { - 0, - r' '.codeUnitAt(0), - r'.'.codeUnitAt(0), - r':'.codeUnitAt(0), - r'-'.codeUnitAt(0), - r'\'.codeUnitAt(0), - r'"'.codeUnitAt(0), - r'*'.codeUnitAt(0), - r'+'.codeUnitAt(0), - r'/'.codeUnitAt(0), - r'\'.codeUnitAt(0), - }; - - BufferRangeLine? getWordBoundary(CellOffset position) { - var separators = wordSeparators ?? defaultWordSeparators; - if (position.y >= lines.length) { - return null; - } - - var line = lines[position.y]; - var start = position.x; - var end = position.x; - - do { - if (start == 0) { - break; - } - final char = line.getCodePoint(start - 1); - if (separators.contains(char)) { - break; - } - start--; - } while (true); - - do { - if (end >= viewWidth) { - break; - } - final char = line.getCodePoint(end); - if (separators.contains(char)) { - break; - } - end++; - } while (true); - - if (start == end) { - return null; - } - - return BufferRangeLine( - CellOffset(start, position.y), - CellOffset(end, position.y), - ); - } - - /// Get the plain text content of the buffer including the scrollback. - /// Accepts an optional [range] to get a specific part of the buffer. - String getText([BufferRange? range]) { - range ??= BufferRangeLine( - CellOffset(0, 0), - CellOffset(viewWidth - 1, height - 1), - ); - - range = range.normalized; - - final builder = StringBuffer(); - - for (var segment in range.toSegments()) { - if (segment.line < 0 || segment.line >= height) { - continue; - } - final line = lines[segment.line]; - if (!(segment.line == range.begin.y || - segment.line == 0 || - line.isWrapped)) { - builder.write("\n"); - } - builder.write(line.getText(segment.start, segment.end)); - } - - return builder.toString(); - } - - /// Returns a debug representation of the buffer. - @override - String toString() { - final builder = StringBuffer(); - final lineNumberLength = lines.length.toString().length; - - for (var i = 0; i < lines.length; i++) { - final line = lines[i]; - - builder.write('${i.toString().padLeft(lineNumberLength)}: |${lines[i]}|'); - - if (line.isWrapped) { - builder.write(' (⏎)'); - } - - builder.write('\n'); - } - - return builder.toString(); - } -} diff --git a/lib/src/core/buffer/cell_flags.dart b/lib/src/core/buffer/cell_flags.dart deleted file mode 100644 index 97c5b8aa..00000000 --- a/lib/src/core/buffer/cell_flags.dart +++ /dev/null @@ -1,9 +0,0 @@ -abstract class CellFlags { - static const bold = 1 << 0; - static const faint = 1 << 1; - static const italic = 1 << 2; - static const underline = 1 << 3; - static const blink = 1 << 4; - static const inverse = 1 << 5; - static const invisible = 1 << 6; -} diff --git a/lib/src/core/buffer/cell_offset.dart b/lib/src/core/buffer/cell_offset.dart deleted file mode 100644 index 36eb426f..00000000 --- a/lib/src/core/buffer/cell_offset.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'package:xterm/src/core/buffer/range.dart'; - -class CellOffset { - final int x; - - final int y; - - const CellOffset(this.x, this.y); - - bool isEqual(CellOffset other) { - return other.x == x && other.y == y; - } - - bool isBefore(CellOffset other) { - return y < other.y || (y == other.y && x < other.x); - } - - bool isAfter(CellOffset other) { - return y > other.y || (y == other.y && x > other.x); - } - - bool isBeforeOrSame(CellOffset other) { - return y < other.y || (y == other.y && x <= other.x); - } - - bool isAfterOrSame(CellOffset other) { - return y > other.y || (y == other.y && x >= other.x); - } - - bool isAtSameRow(CellOffset other) { - return y == other.y; - } - - bool isAtSameColumn(CellOffset other) { - return x == other.x; - } - - bool isWithin(BufferRange range) { - return range.contains(this); - } - - @override - String toString() => 'CellOffset($x, $y)'; - - @override - int get hashCode => x.hashCode ^ y.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is CellOffset && - runtimeType == other.runtimeType && - x == other.x && - y == other.y; -} diff --git a/lib/src/core/buffer/line.dart b/lib/src/core/buffer/line.dart deleted file mode 100644 index 6e72114d..00000000 --- a/lib/src/core/buffer/line.dart +++ /dev/null @@ -1,418 +0,0 @@ -import 'dart:math' show min; -import 'dart:typed_data'; - -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/cell.dart'; -import 'package:xterm/src/core/cursor.dart'; -import 'package:xterm/src/utils/circular_buffer.dart'; -import 'package:xterm/src/utils/unicode_v11.dart'; - -const _cellSize = 4; - -const _cellForeground = 0; - -const _cellBackground = 1; - -const _cellAttributes = 2; - -const _cellContent = 3; - -class BufferLine with IndexedItem { - BufferLine( - this._length, { - this.isWrapped = false, - }) : _data = Uint32List(_calcCapacity(_length) * _cellSize); - - int _length; - - Uint32List _data; - - Uint32List get data => _data; - - var isWrapped = false; - - int get length => _length; - - final _anchors = []; - - List get anchors => _anchors; - - int getForeground(int index) { - return _data[index * _cellSize + _cellForeground]; - } - - int getBackground(int index) { - return _data[index * _cellSize + _cellBackground]; - } - - int getAttributes(int index) { - return _data[index * _cellSize + _cellAttributes]; - } - - int getContent(int index) { - return _data[index * _cellSize + _cellContent]; - } - - int getCodePoint(int index) { - return _data[index * _cellSize + _cellContent] & CellContent.codepointMask; - } - - int getWidth(int index) { - return _data[index * _cellSize + _cellContent] >> CellContent.widthShift; - } - - void getCellData(int index, CellData cellData) { - final offset = index * _cellSize; - cellData.foreground = _data[offset + _cellForeground]; - cellData.background = _data[offset + _cellBackground]; - cellData.flags = _data[offset + _cellAttributes]; - cellData.content = _data[offset + _cellContent]; - } - - CellData createCellData(int index) { - final cellData = CellData.empty(); - final offset = index * _cellSize; - _data[offset + _cellForeground] = cellData.foreground; - _data[offset + _cellBackground] = cellData.background; - _data[offset + _cellAttributes] = cellData.flags; - _data[offset + _cellContent] = cellData.content; - return cellData; - } - - void setForeground(int index, int value) { - _data[index * _cellSize + _cellForeground] = value; - } - - void setBackground(int index, int value) { - _data[index * _cellSize + _cellBackground] = value; - } - - void setAttributes(int index, int value) { - _data[index * _cellSize + _cellAttributes] = value; - } - - void setContent(int index, int value) { - _data[index * _cellSize + _cellContent] = value; - } - - void setCodePoint(int index, int char) { - final width = unicodeV11.wcwidth(char); - setContent(index, char | (width << CellContent.widthShift)); - } - - void setCell(int index, int char, int witdh, CursorStyle style) { - final offset = index * _cellSize; - _data[offset + _cellForeground] = style.foreground; - _data[offset + _cellBackground] = style.background; - _data[offset + _cellAttributes] = style.attrs; - _data[offset + _cellContent] = char | (witdh << CellContent.widthShift); - } - - void setCellData(int index, CellData cellData) { - final offset = index * _cellSize; - _data[offset + _cellForeground] = cellData.foreground; - _data[offset + _cellBackground] = cellData.background; - _data[offset + _cellAttributes] = cellData.flags; - _data[offset + _cellContent] = cellData.content; - } - - void eraseCell(int index, CursorStyle style) { - final offset = index * _cellSize; - _data[offset + _cellForeground] = style.foreground; - _data[offset + _cellBackground] = style.background; - _data[offset + _cellAttributes] = style.attrs; - _data[offset + _cellContent] = 0; - } - - void resetCell(int index) { - final offset = index * _cellSize; - _data[offset + _cellForeground] = 0; - _data[offset + _cellBackground] = 0; - _data[offset + _cellAttributes] = 0; - _data[offset + _cellContent] = 0; - } - - /// Erase cells whose index satisfies [start] <= index < [end]. Erased cells - /// are filled with [style]. - void eraseRange(int start, int end, CursorStyle style) { - // reset cell one to the left if start is second cell of a wide char - if (start > 0 && getWidth(start - 1) == 2) { - eraseCell(start - 1, style); - } - - // reset cell one to the right if end is second cell of a wide char - if (end < _length && getWidth(end - 1) == 2) { - eraseCell(end - 1, style); - } - - end = min(end, _length); - for (var i = start; i < end; i++) { - eraseCell(i, style); - } - } - - /// Remove [count] cells starting at [start]. Cells that are empty after the - /// removal are filled with [style]. - void removeCells(int start, int count, [CursorStyle? style]) { - assert(start >= 0 && start < _length); - assert(count >= 0 && start + count <= _length); - - style ??= CursorStyle.empty; - - if (start + count < _length) { - final moveStart = start * _cellSize; - final moveEnd = (_length - count) * _cellSize; - final moveOffset = count * _cellSize; - for (var i = moveStart; i < moveEnd; i++) { - _data[i] = _data[i + moveOffset]; - } - } - - for (var i = _length - count; i < _length; i++) { - eraseCell(i, style); - } - - if (start > 0 && getWidth(start - 1) == 2) { - eraseCell(start - 1, style); - } - - // Update anchors, remove anchors that are inside the removed range. - for (var i = 0; i < _anchors.length; i++) { - final anchor = _anchors[i]; - if (anchor.x >= start) { - if (anchor.x < start + count) { - anchor.dispose(); - } else { - anchor.reposition(anchor.x - count); - } - } - } - } - - /// Inserts [count] cells at [start]. New cells are initialized with [style]. - void insertCells(int start, int count, [CursorStyle? style]) { - style ??= CursorStyle.empty; - - if (start > 0 && getWidth(start - 1) == 2) { - eraseCell(start - 1, style); - } - - if (start + count < _length) { - final moveStart = start * _cellSize; - final moveEnd = (_length - count) * _cellSize; - final moveOffset = count * _cellSize; - for (var i = moveEnd - 1; i >= moveStart; i--) { - _data[i + moveOffset] = _data[i]; - } - } - - final end = min(start + count, _length); - for (var i = start; i < end; i++) { - eraseCell(i, style); - } - - if (getWidth(_length - 1) == 2) { - eraseCell(_length - 1, style); - } - - // Update anchors, move anchors that are after the inserted range. - for (var i = 0; i < _anchors.length; i++) { - final anchor = _anchors[i]; - if (anchor.x >= start + count) { - anchor.reposition(anchor.x + count); - - // Remove anchors that are now outside the buffer. - if (anchor.x >= _length) { - anchor.dispose(); - } - } - } - } - - void resize(int length) { - assert(length >= 0); - - if (length == _length) { - return; - } - - if (length > _length) { - final newBufferSize = _calcCapacity(length) * _cellSize; - - if (newBufferSize > _data.length) { - final newBuffer = Uint32List(newBufferSize); - newBuffer.setRange(0, _data.length, _data); - _data = newBuffer; - } - } - - _length = length; - - for (var i = 0; i < _anchors.length; i++) { - final anchor = _anchors[i]; - if (anchor.x > _length) { - anchor.reposition(_length); - } - } - } - - /// Returns the offset of the last cell that has content from the start of - /// the line. - int getTrimmedLength([int? cols]) { - final maxCols = _data.length ~/ _cellSize; - - if (cols == null || cols > maxCols) { - cols = maxCols; - } - - if (cols <= 0) { - return 0; - } - - for (var i = cols - 1; i >= 0; i--) { - var codePoint = getCodePoint(i); - - if (codePoint != 0) { - // we are at the last cell in this line that has content. - // the length of this line is the index of this cell + 1 - // the only exception is that if that last cell is wider - // than 1 then we have to add the diff - final lastCellWidth = getWidth(i); - return i + lastCellWidth; - } - } - return 0; - } - - /// Copies [len] cells from [src] starting at [srcCol] to [dstCol] at this - /// line. - void copyFrom(BufferLine src, int srcCol, int dstCol, int len) { - resize(dstCol + len); - - // data.setRange( - // dstCol * _cellSize, - // (dstCol + len) * _cellSize, - // Uint32List.sublistView(src.data, srcCol * _cellSize, len * _cellSize), - // ); - - var srcOffset = srcCol * _cellSize; - var dstOffset = dstCol * _cellSize; - - for (var i = 0; i < len * _cellSize; i++) { - _data[dstOffset++] = src._data[srcOffset++]; - } - } - - static int _calcCapacity(int length) { - assert(length >= 0); - - var capacity = 64; - - if (length < 256) { - while (capacity < length) { - capacity *= 2; - } - } else { - capacity = 256; - while (capacity < length) { - capacity += 32; - } - } - - return capacity; - } - - String getText([int? from, int? to]) { - if (from == null || from < 0) { - from = 0; - } - - if (to == null || to > _length) { - to = _length; - } - - final builder = StringBuffer(); - for (var i = from; i < to; i++) { - final codePoint = getCodePoint(i); - final width = getWidth(i); - if (codePoint != 0 && i + width <= to) { - builder.writeCharCode(codePoint); - } - } - - return builder.toString(); - } - - CellAnchor createAnchor(int offset) { - final anchor = CellAnchor(offset, owner: this); - _anchors.add(anchor); - return anchor; - } - - void dispose() { - for (final anchor in _anchors) { - anchor.dispose(); - } - } - - @override - String toString() { - return getText(); - } -} - -/// A handle to a cell in a [BufferLine] that can be used to track the location -/// of the cell. Anchors are guaranteed to be stable, retaining their relative -/// position to each other after mutations to the buffer. -class CellAnchor { - CellAnchor(int offset, {BufferLine? owner}) - : _offset = offset, - _owner = owner; - - int _offset; - - int get x { - return _offset; - } - - int get y { - assert(attached); - return _owner!.index; - } - - CellOffset get offset { - assert(attached); - return CellOffset(_offset, _owner!.index); - } - - BufferLine? _owner; - - BufferLine? get line => _owner; - - bool get attached => _owner?.attached ?? false; - - void reparent(BufferLine owner, int offset) { - _owner?._anchors.remove(this); - _owner = owner; - _owner?._anchors.add(this); - _offset = offset; - } - - void reposition(int offset) { - _offset = offset; - } - - void dispose() { - _owner?._anchors.remove(this); - _owner = null; - } - - @override - String toString() { - if (attached) { - return 'CellAnchor($x, $y)'; - } else { - return 'CellAnchor($x, detached)'; - } - } -} diff --git a/lib/src/core/buffer/range.dart b/lib/src/core/buffer/range.dart deleted file mode 100644 index 2401f15f..00000000 --- a/lib/src/core/buffer/range.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/buffer/segment.dart'; - -abstract class BufferRange { - final CellOffset begin; - - final CellOffset end; - - const BufferRange(this.begin, this.end); - - BufferRange.collapsed(this.begin) : end = begin; - - bool get isNormalized { - return begin.isBefore(end) || begin.isEqual(end); - } - - bool get isCollapsed { - return begin.isEqual(end); - } - - BufferRange get normalized; - - /// Convert this range to segments of single lines. - Iterable toSegments(); - - /// Returns true if the given[position] is within this range. - bool contains(CellOffset position); - - /// Returns the smallest range that contains both this range and the given - /// [range]. - BufferRange merge(BufferRange range); - - /// Returns the smallest range that contains both this range and the given - /// [position]. - BufferRange extend(CellOffset position); - - @override - operator ==(Object other) { - if (identical(this, other)) { - return true; - } - - if (other is! BufferRange) { - return false; - } - - return begin == other.begin && end == other.end; - } - - @override - int get hashCode => begin.hashCode ^ end.hashCode; - - @override - String toString() => 'Range($begin, $end)'; -} diff --git a/lib/src/core/buffer/range_block.dart b/lib/src/core/buffer/range_block.dart deleted file mode 100644 index 33c18365..00000000 --- a/lib/src/core/buffer/range_block.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'dart:math'; - -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/buffer/range.dart'; -import 'package:xterm/src/core/buffer/segment.dart'; - -class BufferRangeBlock extends BufferRange { - BufferRangeBlock(super.begin, super.end); - - BufferRangeBlock.collapsed(super.begin) : super.collapsed(); - - @override - bool get isNormalized { - // A block range is normalized if begin is the top left corner of the range - // and end the bottom right corner. - return (begin.isBefore(end) && begin.x <= end.x) || begin.isEqual(end); - } - - @override - BufferRangeBlock get normalized { - if (isNormalized) { - return this; - } - // Determine new normalized begin and end offset, such that begin is the - // top left corner and end is the bottom right corner of the block. - final normalBegin = CellOffset(min(begin.x, end.x), min(begin.y, end.y)); - final normalEnd = CellOffset(max(begin.x, end.x), max(begin.y, end.y)); - return BufferRangeBlock(normalBegin, normalEnd); - } - - @override - Iterable toSegments() sync* { - var begin = this.begin; - var end = this.end; - - if (!isNormalized) { - end = this.begin; - begin = this.end; - } - - final startX = min(begin.x, end.x); - final endX = max(begin.x, end.x); - for (var i = begin.y; i <= end.y; i++) { - yield BufferSegment(this, i, startX, endX); - } - } - - @override - bool contains(CellOffset position) { - var begin = this.begin; - var end = this.end; - - if (!isNormalized) { - end = this.begin; - begin = this.end; - } - if (!(begin.y <= position.y && position.y <= end.y)) { - return false; - } - - final startX = min(begin.x, end.x); - final endX = max(begin.x, end.x); - return startX <= position.x && position.x <= endX; - } - - @override - BufferRangeBlock merge(BufferRange range) { - // Enlarge the block such that both borders of the range - // are within the selected block. - return extend(range.begin).extend(range.end); - } - - @override - BufferRangeBlock extend(CellOffset position) { - // If the position is within the block, there is nothing to do. - if (contains(position)) { - return this; - } - // Otherwise normalize the block and push the borders outside up to - // the position to which the block has to extended. - final normal = normalized; - final extendBegin = CellOffset( - min(normal.begin.x, position.x), - min(normal.begin.y, position.y), - ); - final extendEnd = CellOffset( - max(normal.end.x, position.x), - max(normal.end.y, position.y), - ); - return BufferRangeBlock(extendBegin, extendEnd); - } - - @override - operator ==(Object other) { - if (identical(this, other)) { - return true; - } - - if (other is! BufferRangeBlock) { - return false; - } - - return begin == other.begin && end == other.end; - } - - @override - int get hashCode => begin.hashCode ^ end.hashCode; - - @override - String toString() => 'Block Range($begin, $end)'; -} diff --git a/lib/src/core/buffer/range_line.dart b/lib/src/core/buffer/range_line.dart deleted file mode 100644 index 83218eb9..00000000 --- a/lib/src/core/buffer/range_line.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/buffer/range.dart'; -import 'package:xterm/src/core/buffer/segment.dart'; - -class BufferRangeLine extends BufferRange { - BufferRangeLine(super.begin, super.end); - - BufferRangeLine.collapsed(super.begin) : super.collapsed(); - - @override - BufferRangeLine get normalized { - return isNormalized ? this : BufferRangeLine(end, begin); - } - - @override - Iterable toSegments() sync* { - final self = normalized; - for (var i = self.begin.y; i <= self.end.y; i++) { - var startX = i == self.begin.y ? self.begin.x : null; - var endX = i == self.end.y ? self.end.x : null; - yield BufferSegment(this, i, startX, endX); - } - } - - @override - bool contains(CellOffset position) { - final self = normalized; - return self.begin.isBeforeOrSame(position) && - self.end.isAfterOrSame(position); - } - - @override - BufferRangeLine merge(BufferRange range) { - final self = normalized; - final begin = self.begin.isBefore(range.begin) ? self.begin : range.begin; - final end = self.end.isAfter(range.end) ? self.end : range.end; - return BufferRangeLine(begin, end); - } - - @override - BufferRangeLine extend(CellOffset position) { - final self = normalized; - final begin = self.begin.isAfter(position) ? position : self.begin; - final end = self.end.isBefore(position) ? position : self.end; - return BufferRangeLine(begin, end); - } - - @override - operator ==(Object other) { - if (identical(this, other)) { - return true; - } - - if (other is! BufferRangeLine) { - return false; - } - - return begin == other.begin && end == other.end; - } - - @override - int get hashCode => begin.hashCode ^ end.hashCode; - - @override - String toString() => 'Line Range($begin, $end)'; -} diff --git a/lib/src/core/buffer/segment.dart b/lib/src/core/buffer/segment.dart deleted file mode 100644 index 9314ab6c..00000000 --- a/lib/src/core/buffer/segment.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/buffer/range.dart'; - -/// A BufferSegment represents a range within a line. -class BufferSegment { - /// The range that this segment belongs to. - final BufferRange range; - - /// The line that this segment resides on. - final int line; - - /// The start position of this segment. [null] means the start of the line. - final int? start; - - /// The end position of this segment. [null] means the end of the line. - /// Should be greater than or equal to [start]. - final int? end; - - const BufferSegment(this.range, this.line, this.start, this.end) - : assert((start != null && end != null) ? start <= end : true); - - bool isWithin(CellOffset position) { - if (position.y != line) { - return false; - } - - if (start != null && position.x < start!) { - return false; - } - - if (end != null && position.x > end!) { - return false; - } - - return true; - } - - @override - String toString() { - final start = this.start != null ? this.start.toString() : 'start'; - final end = this.end != null ? this.end.toString() : 'end'; - return 'Segment($line, $start -> $end)'; - } - - @override - int get hashCode => - range.hashCode ^ line.hashCode ^ start.hashCode ^ end.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is BufferSegment && - runtimeType == other.runtimeType && - range == other.range && - line == other.line && - start == other.start && - end == other.end; -} diff --git a/lib/src/core/cell.dart b/lib/src/core/cell.dart deleted file mode 100644 index c52039ff..00000000 --- a/lib/src/core/cell.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:xterm/src/utils/hash_values.dart'; - -class CellData { - CellData({ - required this.foreground, - required this.background, - required this.flags, - required this.content, - }); - - factory CellData.empty() { - return CellData( - foreground: 0, - background: 0, - flags: 0, - content: 0, - ); - } - - int foreground; - - int background; - - int flags; - - int content; - - int getHash() { - return hashValues(foreground, background, flags, content); - } - - @override - String toString() { - return 'CellData{foreground: $foreground, background: $background, flags: $flags, content: $content}'; - } -} - -abstract class CellAttr { - static const bold = 1 << 0; - static const faint = 1 << 1; - static const italic = 1 << 2; - static const underline = 1 << 3; - static const blink = 1 << 4; - static const inverse = 1 << 5; - static const invisible = 1 << 6; - static const strikethrough = 1 << 7; -} - -abstract class CellColor { - static const valueMask = 0xFFFFFF; - - static const typeShift = 25; - static const typeMask = 3 << typeShift; - - static const normal = 0 << typeShift; - static const named = 1 << typeShift; - static const palette = 2 << typeShift; - static const rgb = 3 << typeShift; -} - -abstract class CellContent { - static const codepointMask = 0x1fffff; - - static const widthShift = 22; - // static const widthMask = 3 << widthShift; -} diff --git a/lib/src/core/charset.dart b/lib/src/core/charset.dart deleted file mode 100644 index 3659810a..00000000 --- a/lib/src/core/charset.dart +++ /dev/null @@ -1,95 +0,0 @@ -typedef CharsetTranslator = int Function(int); - -final _charsets = { - '0'.codeUnitAt(0): decSpecGraphicsTranslator, - 'B'.codeUnitAt(0): asciiTranslator, -}; - -class Charset { - var _charsetMap = {}; - var _currentIndex = 0; - - var _savedCharsetMap = {}; - var _savedIndex = 0; - - var _cached = asciiTranslator; - - void _updateCache() { - _cached = _charsetMap[_currentIndex] ?? asciiTranslator; - } - - int translate(int codePoint) { - return _cached(codePoint); - } - - void designate(int index, int name) { - final charset = _charsets[name]; - if (charset != null) { - _charsetMap[index] = charset; - _updateCache(); - } - } - - void use(int index) { - _currentIndex = index; - _updateCache(); - } - - void save() { - _savedCharsetMap = Map.from(_charsetMap); - _savedIndex = _currentIndex; - } - - void restore() { - _charsetMap = _savedCharsetMap; - _currentIndex = _savedIndex; - _updateCache(); - } -} - -const decSpecGraphics = { - 0x5f: 0x00A0, // NO-BREAK SPACE - 0x60: 0x25C6, // BLACK DIAMOND - 0x61: 0x2592, // MEDIUM SHADE - 0x62: 0x2409, // SYMBOL FOR HORIZONTAL TABULATION - 0x63: 0x240C, // SYMBOL FOR FORM FEED - 0x64: 0x240D, // SYMBOL FOR CARRIAGE RETURN - 0x65: 0x240A, // SYMBOL FOR LINE FEED - 0x66: 0x00B0, // DEGREE SIGN - 0x67: 0x00B1, // PLUS-MINUS SIGN - 0x68: 0x2424, // SYMBOL FOR NEWLINE - 0x69: 0x240B, // SYMBOL FOR VERTICAL TABULATION - 0x6a: 0x2518, // BOX DRAWINGS LIGHT UP AND LEFT - 0x6b: 0x2510, // BOX DRAWINGS LIGHT DOWN AND LEFT - 0x6c: 0x250C, // BOX DRAWINGS LIGHT DOWN AND RIGHT - 0x6d: 0x2514, // BOX DRAWINGS LIGHT UP AND RIGHT - 0x6e: 0x253C, // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - 0x6f: 0x23BA, // HORIZONTAL SCAN LINE-1 - 0x70: 0x23BB, // HORIZONTAL SCAN LINE-3 - 0x71: 0x2500, // BOX DRAWINGS LIGHT HORIZONTAL - 0x72: 0x23BC, // HORIZONTAL SCAN LINE-7 - 0x73: 0x23BD, // HORIZONTAL SCAN LINE-9 - 0x74: 0x251C, // BOX DRAWINGS LIGHT VERTICAL AND RIGHT - 0x75: 0x2524, // BOX DRAWINGS LIGHT VERTICAL AND LEFT - 0x76: 0x2534, // BOX DRAWINGS LIGHT UP AND HORIZONTAL - 0x77: 0x252C, // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - 0x78: 0x2502, // BOX DRAWINGS LIGHT VERTICAL - 0x79: 0x2264, // LESS-THAN OR EQUAL TO - 0x7a: 0x2265, // GREATER-THAN OR EQUAL TO - 0x7b: 0x03C0, // GREEK SMALL LETTER PI - 0x7c: 0x2260, // NOT EQUAL TO - 0x7d: 0x00A3, // POUND SIGN - 0x7e: 0x00B7, // MIDDLE DOT -}; - -int asciiTranslator(int codePoint) { - return codePoint; -} - -int decSpecGraphicsTranslator(int codePoint) { - if (codePoint >= 127) { - return codePoint; - } - - return decSpecGraphics[codePoint] ?? codePoint; -} diff --git a/lib/src/core/color.dart b/lib/src/core/color.dart deleted file mode 100644 index 716219c3..00000000 --- a/lib/src/core/color.dart +++ /dev/null @@ -1,19 +0,0 @@ -abstract class NamedColor { - static const black = 0; - static const red = 1; - static const green = 2; - static const yellow = 3; - static const blue = 4; - static const magenta = 5; - static const cyan = 6; - static const white = 7; - - static const brightBlack = 8; - static const brightRed = 9; - static const brightGreen = 10; - static const brightYellow = 11; - static const brightBlue = 12; - static const brightMagenta = 13; - static const brightCyan = 14; - static const brightWhite = 15; -} diff --git a/lib/src/core/cursor.dart b/lib/src/core/cursor.dart deleted file mode 100644 index ce08610d..00000000 --- a/lib/src/core/cursor.dart +++ /dev/null @@ -1,137 +0,0 @@ -import 'package:xterm/src/core/cell.dart'; - -class CursorStyle { - int foreground; - - int background; - - int attrs; - - CursorStyle({this.foreground = 0, this.background = 0, this.attrs = 0}); - - static final empty = CursorStyle(); - - void setBold() { - attrs |= CellAttr.bold; - } - - void setFaint() { - attrs |= CellAttr.faint; - } - - void setItalic() { - attrs |= CellAttr.italic; - } - - void setUnderline() { - attrs |= CellAttr.underline; - } - - void setBlink() { - attrs |= CellAttr.blink; - } - - void setInverse() { - attrs |= CellAttr.inverse; - } - - void setInvisible() { - attrs |= CellAttr.invisible; - } - - void setStrikethrough() { - attrs |= CellAttr.strikethrough; - } - - void unsetBold() { - attrs &= ~CellAttr.bold; - } - - void unsetFaint() { - attrs &= ~CellAttr.faint; - } - - void unsetItalic() { - attrs &= ~CellAttr.italic; - } - - void unsetUnderline() { - attrs &= ~CellAttr.underline; - } - - void unsetBlink() { - attrs &= ~CellAttr.blink; - } - - void unsetInverse() { - attrs &= ~CellAttr.inverse; - } - - void unsetInvisible() { - attrs &= ~CellAttr.invisible; - } - - void unsetStrikethrough() { - attrs &= ~CellAttr.strikethrough; - } - - bool get isBold => (attrs & CellAttr.bold) != 0; - - bool get isFaint => (attrs & CellAttr.faint) != 0; - - bool get isItalis => (attrs & CellAttr.italic) != 0; - - bool get isUnderline => (attrs & CellAttr.underline) != 0; - - bool get isBlink => (attrs & CellAttr.blink) != 0; - - bool get isInverse => (attrs & CellAttr.inverse) != 0; - - bool get isInvisible => (attrs & CellAttr.invisible) != 0; - - void setForegroundColor16(int color) { - foreground = color | CellColor.named; - } - - void setForegroundColor256(int color) { - foreground = color | CellColor.palette; - } - - void setForegroundColorRgb(int r, int g, int b) { - foreground = (r << 16) | (g << 8) | b | CellColor.rgb; - } - - void resetForegroundColor() { - foreground = 0; // | CellColor.normal; - } - - void setBackgroundColor16(int color) { - background = color | CellColor.named; - } - - void setBackgroundColor256(int color) { - background = color | CellColor.palette; - } - - void setBackgroundColorRgb(int r, int g, int b) { - background = (r << 16) | (g << 8) | b | CellColor.rgb; - } - - void resetBackgroundColor() { - background = 0; // | CellColor.normal; - } - - void reset() { - foreground = 0; - background = 0; - attrs = 0; - } -} - -class CursorPosition { - int x; - - int y; - - CursorPosition(this.x, this.y); -} diff --git a/lib/src/core/escape/emitter.dart b/lib/src/core/escape/emitter.dart deleted file mode 100644 index faf5d401..00000000 --- a/lib/src/core/escape/emitter.dart +++ /dev/null @@ -1,33 +0,0 @@ -class EscapeEmitter { - const EscapeEmitter(); - - String primaryDeviceAttributes() { - return '\x1b[?1;2c'; - } - - String secondaryDeviceAttributes() { - const model = 0; - const version = 0; - return '\x1b[>$model;$version;0c'; - } - - String tertiaryDeviceAttributes() { - return '\x1bP!|00000000\x1b\\'; - } - - String operatingStatus() { - return '\x1b[0n'; - } - - String cursorPosition(int x, int y) { - return '\x1b[$y;${x}R'; - } - - String bracketedPaste(String text) { - return '\x1b[200~$text\x1b[201~'; - } - - String size(int rows, int cols) { - return '\x1b[8;$rows;${cols}t'; - } -} diff --git a/lib/src/core/escape/handler.dart b/lib/src/core/escape/handler.dart deleted file mode 100644 index 166fb485..00000000 --- a/lib/src/core/escape/handler.dart +++ /dev/null @@ -1,215 +0,0 @@ -import 'package:xterm/src/core/mouse/mode.dart'; - -abstract class EscapeHandler { - void writeChar(int char); - - /* SBC */ - - void bell(); - - void backspaceReturn(); - - void tab(); - - void lineFeed(); - - void carriageReturn(); - - void shiftOut(); - - void shiftIn(); - - void unknownSBC(int char); - - /* ANSI sequence */ - - void saveCursor(); - - void restoreCursor(); - - void index(); - - void nextLine(); - - void setTapStop(); - - void reverseIndex(); - - void designateCharset(int charset, int name); - - void unkownEscape(int char); - - /* CSI */ - - void repeatPreviousCharacter(int n); - - void setCursor(int x, int y); - - void setCursorX(int x); - - void setCursorY(int y); - - void sendPrimaryDeviceAttributes(); - - void clearTabStopUnderCursor(); - - void clearAllTabStops(); - - void moveCursorX(int offset); - - void moveCursorY(int n); - - void sendSecondaryDeviceAttributes(); - - void sendTertiaryDeviceAttributes(); - - void sendOperatingStatus(); - - void sendCursorPosition(); - - void setMargins(int i, [int? bottom]); - - void cursorNextLine(int amount); - - void cursorPrecedingLine(int amount); - - void eraseDisplayBelow(); - - void eraseDisplayAbove(); - - void eraseDisplay(); - - void eraseScrollbackOnly(); - - void eraseLineRight(); - - void eraseLineLeft(); - - void eraseLine(); - - void insertLines(int amount); - - void deleteLines(int amount); - - void deleteChars(int amount); - - void scrollUp(int amount); - - void scrollDown(int amount); - - void eraseChars(int amount); - - void insertBlankChars(int amount); - - void unknownCSI(int finalByte); - - /* Modes */ - - void setInsertMode(bool enabled); - - void setLineFeedMode(bool enabled); - - void setUnknownMode(int mode, bool enabled); - - /* DEC Private modes */ - - void setCursorKeysMode(bool enabled); - - void setReverseDisplayMode(bool enabled); - - void setOriginMode(bool enabled); - - void setColumnMode(bool enabled); - - void setAutoWrapMode(bool enabled); - - void setMouseMode(MouseMode mode); - - void setCursorBlinkMode(bool enabled); - - void setCursorVisibleMode(bool enabled); - - void useAltBuffer(); - - void useMainBuffer(); - - void clearAltBuffer(); - - void setAppKeypadMode(bool enabled); - - void setReportFocusMode(bool enabled); - - void setMouseReportMode(MouseReportMode mode); - - void setAltBufferMouseScrollMode(bool enabled); - - void setBracketedPasteMode(bool enabled); - - void setUnknownDecMode(int mode, bool enabled); - - void resize(int cols, int rows); - - void sendSize(); - - /* Select Graphic Rendition (SGR) */ - - void resetCursorStyle(); - - void setCursorBold(); - - void setCursorFaint(); - - void setCursorItalic(); - - void setCursorUnderline(); - - void setCursorBlink(); - - void setCursorInverse(); - - void setCursorInvisible(); - - void setCursorStrikethrough(); - - void unsetCursorBold(); - - void unsetCursorFaint(); - - void unsetCursorItalic(); - - void unsetCursorUnderline(); - - void unsetCursorBlink(); - - void unsetCursorInverse(); - - void unsetCursorInvisible(); - - void unsetCursorStrikethrough(); - - void setForegroundColor16(int color); - - void setForegroundColor256(int index); - - void setForegroundColorRgb(int r, int g, int b); - - void resetForeground(); - - void setBackgroundColor16(int color); - - void setBackgroundColor256(int index); - - void setBackgroundColorRgb(int r, int g, int b); - - void resetBackground(); - - void unsupportedStyle(int param); - - /* OSC */ - - void setTitle(String name); - - void setIconName(String name); - - void unknownOSC(String code, List args); -} diff --git a/lib/src/core/escape/parser.dart b/lib/src/core/escape/parser.dart deleted file mode 100644 index 0c7e74a9..00000000 --- a/lib/src/core/escape/parser.dart +++ /dev/null @@ -1,1154 +0,0 @@ -import 'package:xterm/src/core/color.dart'; -import 'package:xterm/src/core/mouse/mode.dart'; -import 'package:xterm/src/core/escape/handler.dart'; -import 'package:xterm/src/utils/ascii.dart'; -import 'package:xterm/src/utils/byte_consumer.dart'; -import 'package:xterm/src/utils/char_code.dart'; -import 'package:xterm/src/utils/lookup_table.dart'; - -/// [EscapeParser] translates control characters and escape sequences into -/// function calls that the terminal can handle. -/// -/// Design goals: -/// * Zero object allocation during processing. -/// * No internal state. Same input will always produce same output. -class EscapeParser { - final EscapeHandler handler; - - EscapeParser(this.handler); - - final _queue = ByteConsumer(); - - /// Start of sequence or character being processed. Useful for debugging. - var tokenBegin = 0; - - /// End of sequence or character being processed. Useful for debugging. - int get tokenEnd => _queue.totalConsumed; - - void write(String chunk) { - _queue.unrefConsumedBlocks(); - _queue.add(chunk); - _process(); - } - - void _process() { - while (_queue.isNotEmpty) { - tokenBegin = _queue.totalConsumed; - final char = _queue.consume(); - - if (char == Ascii.ESC) { - final processed = _processEscape(); - if (!processed) { - _queue.rollback(tokenEnd - tokenBegin); - return; - } - } else { - _processChar(char); - } - } - } - - void _processChar(int char) { - if (char > _sbcHandlers.maxIndex) { - handler.writeChar(char); - return; - } - - final sbcHandler = _sbcHandlers[char]; - if (sbcHandler == null) { - handler.unkownEscape(char); - return; - } - - sbcHandler(); - } - - /// Processes a sequence of characters that starts with an escape character. - /// Returns [true] if the sequence was processed, [false] if it was not. - bool _processEscape() { - if (_queue.isEmpty) return false; - - final escapeChar = _queue.consume(); - final escapeHandler = _escHandlers[escapeChar]; - - if (escapeHandler == null) { - handler.unkownEscape(escapeChar); - return true; - } - - return escapeHandler(); - } - - late final _sbcHandlers = FastLookupTable<_SbcHandler>({ - 0x07: handler.bell, - 0x08: handler.backspaceReturn, - 0x09: handler.tab, - 0x0a: handler.lineFeed, - 0x0b: handler.lineFeed, - 0x0c: handler.lineFeed, - 0x0d: handler.carriageReturn, - 0x0e: handler.shiftOut, - 0x0f: handler.shiftIn, - }); - - late final _escHandlers = FastLookupTable<_EscHandler>({ - '['.charCode: _escHandleCSI, - ']'.charCode: _escHandleOSC, - '7'.charCode: _escHandleSaveCursor, - '8'.charCode: _escHandleRestoreCursor, - 'D'.charCode: _escHandleIndex, - 'E'.charCode: _escHandleNextLine, - 'H'.charCode: _escHandleTabSet, - 'M'.charCode: _escHandleReverseIndex, - // 'P'.charCode: _unsupportedHandler, // Sixel - // 'c'.charCode: _unsupportedHandler, - // '#'.charCode: _unsupportedHandler, - '('.charCode: _escHandleDesignateCharset0, // SCS - G0 - ')'.charCode: _escHandleDesignateCharset1, // SCS - G1 - // '*'.charCode: _voidHandler(1), // TODO: G2 (vt220) - // '+'.charCode: _voidHandler(1), // TODO: G3 (vt220) - '>'.charCode: _escHandleResetAppKeypadMode, // TODO: Normal Keypad - '='.charCode: _escHandleSetAppKeypadMode, // TODO: Application Keypad - }); - - /// `ESC 7` Save Cursor (DECSC) - /// - /// https://terminalguide.namepad.de/seq/a_esc_a7/ - bool _escHandleSaveCursor() { - handler.saveCursor(); - return true; - } - - /// `ESC 8` Restore Cursor (DECRC) - /// - /// https://terminalguide.namepad.de/seq/a_esc_a8/ - bool _escHandleRestoreCursor() { - handler.restoreCursor(); - return true; - } - - /// `ESC D` Index (IND) - /// - /// https://terminalguide.namepad.de/seq/a_esc_cd/ - bool _escHandleIndex() { - handler.index(); - return true; - } - - /// `ESC E` Next Line (NEL) - /// - /// https://terminalguide.namepad.de/seq/a_esc_ce/ - bool _escHandleNextLine() { - handler.nextLine(); - return true; - } - - /// `ESC H` Horizontal Tab Set (HTS) - /// - /// https://terminalguide.namepad.de/seq/a_esc_ch/ - bool _escHandleTabSet() { - handler.setTapStop(); - return true; - } - - /// `ESC M` Reverse Index (RI) - /// - /// https://terminalguide.namepad.de/seq/a_esc_cm/ - bool _escHandleReverseIndex() { - handler.reverseIndex(); - return true; - } - - bool _escHandleDesignateCharset0() { - if (_queue.isEmpty) return false; - int name = _queue.consume(); - handler.designateCharset(0, name); - return true; - } - - bool _escHandleDesignateCharset1() { - if (_queue.isEmpty) return false; - int name = _queue.consume(); - handler.designateCharset(1, name); - return true; - } - - /// `ESC >` Reset Application Keypad Mode (DECKPNM) - /// - /// https://terminalguide.namepad.de/seq/a_esc_x3c_greater_than/ - bool _escHandleSetAppKeypadMode() { - handler.setAppKeypadMode(true); - return true; - } - - /// `ESC =` Set Application Keypad Mode (DECKPAM) - /// - /// https://terminalguide.namepad.de/seq/a_esc_x3d_equals/ - bool _escHandleResetAppKeypadMode() { - handler.setAppKeypadMode(false); - return true; - } - - bool _escHandleCSI() { - final consumed = _consumeCsi(); - if (!consumed) return false; - - final csiHandler = _csiHandlers[_csi.finalByte]; - - if (csiHandler == null) { - handler.unknownCSI(_csi.finalByte); - } else { - csiHandler(); - } - - return true; - } - - /// The last parsed [_Csi]. This is a mutable singletion by design to reduce - /// object allocations. - final _csi = _Csi(finalByte: 0, params: []); - - /// Parse a CSI from the head of the queue. Return false if the CSI isn't - /// complete. After a CSI is successfully parsed, [_csi] is updated. - bool _consumeCsi() { - if (_queue.isEmpty) { - return false; - } - - _csi.params.clear(); - - // test whether the csi is a `CSI ? Ps ...` or `CSI Ps ...` - final prefix = _queue.peek(); - if (prefix >= Ascii.colon && prefix <= Ascii.questionMark) { - _csi.prefix = prefix; - _queue.consume(); - } else { - _csi.prefix = null; - } - - var param = 0; - var hasParam = false; - while (true) { - // The sequence isn't completed, just ignore it. - if (_queue.isEmpty) { - return false; - } - - final char = _queue.consume(); - - if (char == Ascii.semicolon) { - if (hasParam) { - _csi.params.add(param); - } - param = 0; - continue; - } - - if (char >= Ascii.num0 && char <= Ascii.num9) { - hasParam = true; - param *= 10; - param += char - Ascii.num0; - continue; - } - - if (char > Ascii.NULL && char < Ascii.num0) { - // intermediates.add(char); - continue; - } - - if (char >= Ascii.atSign && char <= Ascii.tilde) { - if (hasParam) { - _csi.params.add(param); - } - - _csi.finalByte = char; - return true; - } - } - } - - late final _csiHandlers = FastLookupTable<_CsiHandler>({ - // 'a'.codeUnitAt(0): _csiHandleCursorHorizontalRelative, - 'b'.codeUnitAt(0): _csiHandleRepeatPreviousCharacter, - 'c'.codeUnitAt(0): _csiHandleSendDeviceAttributes, - 'd'.codeUnitAt(0): _csiHandleLinePositionAbsolute, - 'f'.codeUnitAt(0): _csiHandleCursorPosition, - 'g'.codeUnitAt(0): _csiHandelClearTabStop, - 'h'.codeUnitAt(0): _csiHandleMode, - 'l'.codeUnitAt(0): _csiHandleMode, - 'm'.codeUnitAt(0): _csiHandleSgr, - 'n'.codeUnitAt(0): _csiHandleDeviceStatusReport, - 'r'.codeUnitAt(0): _csiHandleSetMargins, - 't'.codeUnitAt(0): _csiWindowManipulation, - 'A'.codeUnitAt(0): _csiHandleCursorUp, - 'B'.codeUnitAt(0): _csiHandleCursorDown, - 'C'.codeUnitAt(0): _csiHandleCursorForward, - 'D'.codeUnitAt(0): _csiHandleCursorBackward, - 'E'.codeUnitAt(0): _csiHandleCursorNextLine, - 'F'.codeUnitAt(0): _csiHandleCursorPrecedingLine, - 'G'.codeUnitAt(0): _csiHandleCursorHorizontalAbsolute, - 'H'.codeUnitAt(0): _csiHandleCursorPosition, - 'J'.codeUnitAt(0): _csiHandleEraseDisplay, - 'K'.codeUnitAt(0): _csiHandleEraseLine, - 'L'.codeUnitAt(0): _csiHandleInsertLines, - 'M'.codeUnitAt(0): _csiHandleDeleteLines, - 'P'.codeUnitAt(0): _csiHandleDelete, - 'S'.codeUnitAt(0): _csiHandleScrollUp, - 'T'.codeUnitAt(0): _csiHandleScrollDown, - 'X'.codeUnitAt(0): _csiHandleEraseCharacters, - '@'.codeUnitAt(0): _csiHandleInsertBlankCharacters, - }); - - /// `ESC [ Ps a` Cursor Horizontal Position Relative (HPR) - /// - /// https://terminalguide.namepad.de/seq/csi_sa/ - // void _csiHandleCursorHorizontalRelative() { - // if (_csi.params.isEmpty) { - // handler.cursorHorizontal(1); - // } else { - // handler.cursorHorizontal(_csi.params[0]); - // } - // } - - /// `ESC [ Ps b` Repeat Previous Character (REP) - /// - /// https://terminalguide.namepad.de/seq/csi_sb/ - void _csiHandleRepeatPreviousCharacter() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - if (amount == 0) amount = 1; - } - - handler.repeatPreviousCharacter(amount); - } - - /// `ESC [ Ps c` Device Attributes (DA) - /// - /// https://terminalguide.namepad.de/seq/csi_sc/ - void _csiHandleSendDeviceAttributes() { - switch (_csi.prefix) { - case Ascii.greaterThan: - return handler.sendSecondaryDeviceAttributes(); - case Ascii.equal: - return handler.sendTertiaryDeviceAttributes(); - default: - handler.sendPrimaryDeviceAttributes(); - } - } - - /// `ESC [ Ps d` Cursor Vertical Position Absolute (VPA) - /// - /// https://terminalguide.namepad.de/seq/csi_sd/ - void _csiHandleLinePositionAbsolute() { - var y = 1; - - if (_csi.params.isNotEmpty) { - y = _csi.params[0]; - } - - handler.setCursorY(y - 1); - } - - /// `ESC [ Ps ; Ps f` Alias: Set Cursor Position - /// - /// https://terminalguide.namepad.de/seq/csi_sf/ - void _csiHandleCursorPosition() { - var row = 1; - var col = 1; - - if (_csi.params.length == 2) { - row = _csi.params[0]; - col = _csi.params[1]; - } - - handler.setCursor(col - 1, row - 1); - } - - /// `ESC [ Ps g` Tab Clear (TBC) - /// - /// https://terminalguide.namepad.de/seq/csi_sg/ - void _csiHandelClearTabStop() { - var cmd = 0; - - if (_csi.params.length == 1) { - cmd = _csi.params[0]; - } - - switch (cmd) { - case 0: - return handler.clearTabStopUnderCursor(); - default: - return handler.clearAllTabStops(); - } - } - - /// - `ESC [ [ Pm ] h Set Mode (SM)` https://terminalguide.namepad.de/seq/csi_sm/ - /// - `ESC [ ? [ Pm ] h` Set Mode (?) (SM) https://terminalguide.namepad.de/seq/csi_sh__p/ - /// - `ESC [ [ Pm ] l` Reset Mode (RM) https://terminalguide.namepad.de/seq/csi_rm/ - /// - `ESC [ ? [ Pm ] l` Reset Mode (?) (RM) https://terminalguide.namepad.de/seq/csi_sl__p/ - void _csiHandleMode() { - final isEnabled = _csi.finalByte == Ascii.h; - - final isDecModes = _csi.prefix == Ascii.questionMark; - - if (isDecModes) { - for (var mode in _csi.params) { - _setDecMode(mode, isEnabled); - } - } else { - for (var mode in _csi.params) { - _setMode(mode, isEnabled); - } - } - } - - /// `ESC [ [ Ps ] m` Select Graphic Rendition (SGR) - /// - /// https://terminalguide.namepad.de/seq/csi_sm/ - void _csiHandleSgr() { - final params = _csi.params; - - if (params.isEmpty) { - return handler.resetCursorStyle(); - } - - // This is a workaround for a bug in the analyzer. - // ignore: dead_code - for (var i = 0; i < _csi.params.length; i++) { - final param = params[i]; - switch (param) { - case 0: - handler.resetCursorStyle(); - continue; - case 1: - handler.setCursorBold(); - continue; - case 2: - handler.setCursorFaint(); - continue; - case 3: - handler.setCursorItalic(); - continue; - case 4: - handler.setCursorUnderline(); - continue; - case 5: - handler.setCursorBlink(); - continue; - case 7: - handler.setCursorInverse(); - continue; - case 8: - handler.setCursorInvisible(); - continue; - case 9: - handler.setCursorStrikethrough(); - continue; - - case 21: - handler.unsetCursorBold(); - continue; - case 22: - handler.unsetCursorFaint(); - continue; - case 23: - handler.unsetCursorItalic(); - continue; - case 24: - handler.unsetCursorUnderline(); - continue; - case 25: - handler.unsetCursorBlink(); - continue; - case 27: - handler.unsetCursorInverse(); - continue; - case 28: - handler.unsetCursorInvisible(); - continue; - case 29: - handler.unsetCursorStrikethrough(); - continue; - - case 30: - handler.setForegroundColor16(NamedColor.black); - continue; - case 31: - handler.setForegroundColor16(NamedColor.red); - continue; - case 32: - handler.setForegroundColor16(NamedColor.green); - continue; - case 33: - handler.setForegroundColor16(NamedColor.yellow); - continue; - case 34: - handler.setForegroundColor16(NamedColor.blue); - continue; - case 35: - handler.setForegroundColor16(NamedColor.magenta); - continue; - case 36: - handler.setForegroundColor16(NamedColor.cyan); - continue; - case 37: - handler.setForegroundColor16(NamedColor.white); - continue; - case 38: - final mode = params[i + 1]; - switch (mode) { - case 2: - final r = params[i + 2]; - final g = params[i + 3]; - final b = params[i + 4]; - handler.setForegroundColorRgb(r, g, b); - i += 4; - break; - case 5: - final index = params[i + 2]; - handler.setForegroundColor256(index); - i += 2; - break; - } - continue; - case 39: - handler.resetForeground(); - continue; - - case 40: - handler.setBackgroundColor16(NamedColor.black); - continue; - case 41: - handler.setBackgroundColor16(NamedColor.red); - continue; - case 42: - handler.setBackgroundColor16(NamedColor.green); - continue; - case 43: - handler.setBackgroundColor16(NamedColor.yellow); - continue; - case 44: - handler.setBackgroundColor16(NamedColor.blue); - continue; - case 45: - handler.setBackgroundColor16(NamedColor.magenta); - continue; - case 46: - handler.setBackgroundColor16(NamedColor.cyan); - continue; - case 47: - handler.setBackgroundColor16(NamedColor.white); - continue; - case 48: - final mode = params[i + 1]; - switch (mode) { - case 2: - final r = params[i + 2]; - final g = params[i + 3]; - final b = params[i + 4]; - handler.setBackgroundColorRgb(r, g, b); - i += 4; - break; - case 5: - final index = params[i + 2]; - handler.setBackgroundColor256(index); - i += 2; - break; - } - continue; - case 49: - handler.resetBackground(); - continue; - - case 90: - handler.setForegroundColor16(NamedColor.brightBlack); - continue; - case 91: - handler.setForegroundColor16(NamedColor.brightRed); - continue; - case 92: - handler.setForegroundColor16(NamedColor.brightGreen); - continue; - case 93: - handler.setForegroundColor16(NamedColor.brightYellow); - continue; - case 94: - handler.setForegroundColor16(NamedColor.brightBlue); - continue; - case 95: - handler.setForegroundColor16(NamedColor.brightMagenta); - continue; - case 96: - handler.setForegroundColor16(NamedColor.brightCyan); - continue; - case 97: - handler.setForegroundColor16(NamedColor.brightWhite); - continue; - - case 100: - handler.setBackgroundColor16(NamedColor.brightBlack); - continue; - case 101: - handler.setBackgroundColor16(NamedColor.brightRed); - continue; - case 102: - handler.setBackgroundColor16(NamedColor.brightGreen); - continue; - case 103: - handler.setBackgroundColor16(NamedColor.brightYellow); - continue; - case 104: - handler.setBackgroundColor16(NamedColor.brightBlue); - continue; - case 105: - handler.setBackgroundColor16(NamedColor.brightMagenta); - continue; - case 106: - handler.setBackgroundColor16(NamedColor.brightCyan); - continue; - case 107: - handler.setBackgroundColor16(NamedColor.brightWhite); - continue; - - default: - handler.unsupportedStyle(param); - continue; - } - } - } - - /// `ESC [ Ps n` Device Status Report [Dispatch] (DSR) - /// - /// https://terminalguide.namepad.de/seq/csi_sn/ - void _csiHandleDeviceStatusReport() { - if (_csi.params.isEmpty) return; - - switch (_csi.params[0]) { - case 5: - return handler.sendOperatingStatus(); - case 6: - return handler.sendCursorPosition(); - } - } - - /// `ESC [ Ps ; Ps r` Set Top and Bottom Margins (DECSTBM) - /// - /// https://terminalguide.namepad.de/seq/csi_sr/ - void _csiHandleSetMargins() { - var top = 1; - int? bottom; - - if (_csi.params.length > 2) return; - - if (_csi.params.isNotEmpty) { - top = _csi.params[0]; - - if (_csi.params.length == 2) { - bottom = _csi.params[1] - 1; - } - } - - handler.setMargins(top - 1, bottom); - } - - /// `ESC [ Ps t` Window operations [DISPATCH] - /// - /// https://terminalguide.namepad.de/seq/csi_st/ - void _csiWindowManipulation() { - // The sequence needs at least one parameter. - if (_csi.params.isEmpty) { - return; - } - // Most the commands in this group are either of the scope of this package, - // or should be disabled for security risks. - switch (_csi.params.first) { - // Window handling is currently not in the scope of the package. - case 1: // Restore Terminal Window (show window if minimized) - case 2: // Minimize Terminal Window - case 3: // Set Terminal Window Position - case 4: // Set Terminal Window Size in Pixels - case 5: // Raise Terminal Window - case 6: // Lower Terminal Window - case 7: // Refresh/Redraw Terminal Window - return; - case 8: // Set Terminal Window Size (in characters) - // This CSI contains 2 more parameters: width and height. - if (_csi.params.length != 3) { - return; - } - final rows = _csi.params[1]; - final cols = _csi.params[2]; - handler.resize(cols, rows); - return; - // Window handling is currently no in the scope of the package. - case 9: // Maximize Terminal Window - case 10: // Alias: Maximize Terminal Window - case 11: // Report Terminal Window State - case 13: // Report Terminal Window Position - case 14: // Report Terminal Window Size in Pixels - case 15: // Report Screen Size in Pixels - case 16: // Report Cell Size in Pixels - return; - case 18: // Report Terminal Size (in characters) - handler.sendSize(); - return; - // Screen handling is currently no in the scope of the package. - case 19: // Report Screen Size (in characters) - // Disabled as these can a security risk. - case 20: // Get Icon Title - case 21: // Get Terminal Title - // Not implemented. - case 22: // Push Terminal Title - case 23: // Pop Terminal Title - return; - // Unknown CSI. - default: - return; - } - } - - /// `ESC [ Ps A` Cursor Up (CUU) - /// - /// https://terminalguide.namepad.de/seq/csi_ca/ - void _csiHandleCursorUp() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - if (amount == 0) amount = 1; - } - - handler.moveCursorY(-amount); - } - - /// `ESC [ Ps B` Cursor Down (CUD) - /// - /// https://terminalguide.namepad.de/seq/csi_cb/ - void _csiHandleCursorDown() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - if (amount == 0) amount = 1; - } - - handler.moveCursorY(amount); - } - - /// `ESC [ Ps C` Cursor Right (CUF) - /// - /// Cursor Right (CUF) - void _csiHandleCursorForward() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - if (amount == 0) amount = 1; - } - - handler.moveCursorX(amount); - } - - /// `ESC [ Ps D` Cursor Left (CUB) - /// - /// https://terminalguide.namepad.de/seq/csi_cd/ - void _csiHandleCursorBackward() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - if (amount == 0) amount = 1; - } - - handler.moveCursorX(-amount); - } - - /// `ESC [ Ps E` Cursor Next Line (CNL) - /// - /// https://terminalguide.namepad.de/seq/csi_ce/ - void _csiHandleCursorNextLine() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - if (amount == 0) amount = 1; - } - - handler.cursorNextLine(amount); - } - - /// `ESC [ Ps F` Cursor Previous Line (CPL) - /// - /// https://terminalguide.namepad.de/seq/csi_cf/ - void _csiHandleCursorPrecedingLine() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - if (amount == 0) amount = 1; - } - - handler.cursorPrecedingLine(amount); - } - - void _csiHandleCursorHorizontalAbsolute() { - var x = 1; - - if (_csi.params.isNotEmpty) { - x = _csi.params[0]; - if (x == 0) x = 1; - } - - handler.setCursorX(x - 1); - } - - /// ESC [ Ps J Erase Display [Dispatch] (ED) - /// - /// https://terminalguide.namepad.de/seq/csi_cj/ - void _csiHandleEraseDisplay() { - var cmd = 0; - - if (_csi.params.length == 1) { - cmd = _csi.params[0]; - } - - switch (cmd) { - case 0: - return handler.eraseDisplayBelow(); - case 1: - return handler.eraseDisplayAbove(); - case 2: - return handler.eraseDisplay(); - case 3: - return handler.eraseScrollbackOnly(); - } - } - - /// `ESC [ Ps K` Erase Line [Dispatch] (EL) - /// - /// https://terminalguide.namepad.de/seq/csi_ck/ - void _csiHandleEraseLine() { - var cmd = 0; - - if (_csi.params.length == 1) { - cmd = _csi.params[0]; - } - - switch (cmd) { - case 0: - return handler.eraseLineRight(); - case 1: - return handler.eraseLineLeft(); - case 2: - return handler.eraseLine(); - } - } - - /// `ESC [ Ps L` Insert Line (IL) - /// - /// https://terminalguide.namepad.de/seq/csi_cl/ - void _csiHandleInsertLines() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - } - - handler.insertLines(amount); - } - - /// ESC [ Ps M Delete Line (DL) - /// - /// https://terminalguide.namepad.de/seq/csi_cm/ - void _csiHandleDeleteLines() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - } - - handler.deleteLines(amount); - } - - /// ESC [ Ps P Delete Character (DCH) - /// - /// https://terminalguide.namepad.de/seq/csi_cp/ - void _csiHandleDelete() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - } - - handler.deleteChars(amount); - } - - /// `ESC [ Ps S` Scroll Up (SU) - /// - /// https://terminalguide.namepad.de/seq/csi_cs/ - void _csiHandleScrollUp() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - } - - handler.scrollUp(amount); - } - - /// `ESC [ Ps T `Scroll Down (SD) - /// - /// https://terminalguide.namepad.de/seq/csi_ct_1param/ - void _csiHandleScrollDown() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - } - - handler.scrollDown(amount); - } - - /// `ESC [ Ps X` Erase Character (ECH) - /// - /// https://terminalguide.namepad.de/seq/csi_cx/ - void _csiHandleEraseCharacters() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - } - - handler.eraseChars(amount); - } - - /// `ESC [ Ps @` Insert Blanks (ICH) - /// - /// https://terminalguide.namepad.de/seq/csi_x40_at/ - /// - /// Inserts amount spaces at current cursor position moving existing cell - /// contents to the right. The contents of the amount right-most columns in - /// the scroll region are lost. The cursor position is not changed. - void _csiHandleInsertBlankCharacters() { - var amount = 1; - - if (_csi.params.isNotEmpty) { - amount = _csi.params[0]; - } - - handler.insertBlankChars(amount); - } - - void _setMode(int mode, bool enabled) { - switch (mode) { - case 4: - return handler.setInsertMode(enabled); - case 20: - return handler.setLineFeedMode(enabled); - default: - return handler.setUnknownMode(mode, enabled); - } - } - - void _setDecMode(int mode, bool enabled) { - switch (mode) { - case 1: - return handler.setCursorKeysMode(enabled); - case 3: - return handler.setColumnMode(enabled); - case 5: - return handler.setReverseDisplayMode(enabled); - case 6: - return handler.setOriginMode(enabled); - case 7: - return handler.setAutoWrapMode(enabled); - case 9: - return enabled - ? handler.setMouseMode(MouseMode.clickOnly) - : handler.setMouseMode(MouseMode.none); - case 12: - case 13: - return handler.setCursorBlinkMode(enabled); - case 25: - return handler.setCursorVisibleMode(enabled); - case 47: - if (enabled) { - return handler.useAltBuffer(); - } else { - return handler.useMainBuffer(); - } - case 66: - return handler.setAppKeypadMode(enabled); - case 1000: - case 10061000: - return enabled - ? handler.setMouseMode(MouseMode.upDownScroll) - : handler.setMouseMode(MouseMode.none); - case 1001: - return enabled - ? handler.setMouseMode(MouseMode.upDownScroll) - : handler.setMouseMode(MouseMode.none); - case 1002: - return enabled - ? handler.setMouseMode(MouseMode.upDownScrollDrag) - : handler.setMouseMode(MouseMode.none); - case 1003: - return enabled - ? handler.setMouseMode(MouseMode.upDownScrollMove) - : handler.setMouseMode(MouseMode.none); - case 1004: - return handler.setReportFocusMode(enabled); - case 1005: - return enabled - ? handler.setMouseReportMode(MouseReportMode.utf) - : handler.setMouseReportMode(MouseReportMode.normal); - case 1006: - return enabled - ? handler.setMouseReportMode(MouseReportMode.sgr) - : handler.setMouseReportMode(MouseReportMode.normal); - case 1007: - return handler.setAltBufferMouseScrollMode(enabled); - case 1015: - return enabled - ? handler.setMouseReportMode(MouseReportMode.urxvt) - : handler.setMouseReportMode(MouseReportMode.normal); - case 1047: - if (enabled) { - handler.useAltBuffer(); - } else { - handler.clearAltBuffer(); - handler.useMainBuffer(); - } - return; - case 1048: - if (enabled) { - return handler.saveCursor(); - } else { - return handler.restoreCursor(); - } - case 1049: - if (enabled) { - handler.saveCursor(); - handler.clearAltBuffer(); - handler.useAltBuffer(); - } else { - handler.useMainBuffer(); - } - return; - case 2004: - return handler.setBracketedPasteMode(enabled); - default: - return handler.setUnknownDecMode(mode, enabled); - } - } - - /// Parse a OSC sequence from the queue. Returns true if a sequence was - /// found and handled. - bool _escHandleOSC() { - final consumed = _consumeOsc(); - if (!consumed) { - return false; - } - - if (_osc.isEmpty) { - return true; - } - - // Common OSCs - if (_osc.length >= 2) { - final ps = _osc[0]; - final pt = _osc[1]; - - switch (ps) { - case '0': - handler.setTitle(pt); - handler.setIconName(pt); - return true; - case '1': - handler.setIconName(pt); - return true; - case '2': - handler.setTitle(pt); - return true; - } - } - - // Private extensions - handler.unknownOSC(_osc[0], _osc.sublist(1)); - - return true; - } - - final _osc = []; - - bool _consumeOsc() { - _osc.clear(); - final param = StringBuffer(); - - while (true) { - if (_queue.isEmpty) { - return false; - } - - final char = _queue.consume(); - - // OSC terminates with BEL - if (char == Ascii.BEL) { - _osc.add(param.toString()); - return true; - } - - /// OSC terminates with ST - if (char == Ascii.ESC) { - if (_queue.isEmpty) { - return false; - } - - if (_queue.consume() == Ascii.backslash) { - _osc.add(param.toString()); - } - - return true; - } - - /// Parse next parameter - if (char == Ascii.semicolon) { - _osc.add(param.toString()); - param.clear(); - continue; - } - - param.writeCharCode(char); - } - } -} - -class _Csi { - _Csi({ - required this.params, - required this.finalByte, - // required this.intermediates, - }); - - int? prefix; - - List params; - - int finalByte; - // final List intermediates; - - @override - String toString() { - return params.join(';') + String.fromCharCode(finalByte); - } -} - -/// Function that handles a sequence of characters that starts with an escape. -/// Returns [true] if the sequence was processed, [false] if it was not. -typedef _EscHandler = bool Function(); - -typedef _SbcHandler = void Function(); - -typedef _CsiHandler = void Function(); diff --git a/lib/src/core/input/handler.dart b/lib/src/core/input/handler.dart deleted file mode 100644 index 6cff00bc..00000000 --- a/lib/src/core/input/handler.dart +++ /dev/null @@ -1,215 +0,0 @@ -import 'package:xterm/src/core/input/keys.dart'; -import 'package:xterm/src/core/input/keytab/keytab.dart'; -import 'package:xterm/src/core/state.dart'; -import 'package:xterm/src/core/platform.dart'; - -/// The key event received from the keyboard, along with the state of the -/// modifier keys and state of the terminal. Typically consumed by the -/// [TerminalInputHandler] to produce a escape sequence that can be recognized -/// by the terminal. -/// -/// See also: -/// - [TerminalInputHandler] -class TerminalKeyboardEvent { - final TerminalKey key; - - final bool shift; - - final bool ctrl; - - final bool alt; - - final TerminalState state; - - final bool altBuffer; - - final TerminalTargetPlatform platform; - - TerminalKeyboardEvent({ - required this.key, - required this.shift, - required this.ctrl, - required this.alt, - required this.state, - required this.altBuffer, - required this.platform, - }); - - TerminalKeyboardEvent copyWith({ - TerminalKey? key, - bool? shift, - bool? ctrl, - bool? alt, - TerminalState? state, - bool? altBuffer, - TerminalTargetPlatform? platform, - }) { - return TerminalKeyboardEvent( - key: key ?? this.key, - shift: shift ?? this.shift, - ctrl: ctrl ?? this.ctrl, - alt: alt ?? this.alt, - state: state ?? this.state, - altBuffer: altBuffer ?? this.altBuffer, - platform: platform ?? this.platform, - ); - } - - @override - String toString() { - return 'TerminalKeyboardEvent(key: $key, shift: $shift, ctrl: $ctrl, alt: $alt, state: $state, altBuffer: $altBuffer, platform: $platform)'; - } -} - -/// TerminalInputHandler contains the logic for translating a [TerminalKeyboardEvent] -/// into escape sequences that can be recognized by the terminal. -abstract class TerminalInputHandler { - /// Translates a [TerminalKeyboardEvent] into an escape sequence. If the event - /// cannot be translated, null is returned. - String? call(TerminalKeyboardEvent event); -} - -/// A [TerminalInputHandler] that chains multiple handlers together. If any -/// handler returns a non-null value, it is returned. Otherwise, null is -/// returned. -class CascadeInputHandler implements TerminalInputHandler { - final List _handlers; - - const CascadeInputHandler(this._handlers); - - @override - String? call(TerminalKeyboardEvent event) { - for (var handler in _handlers) { - final result = handler(event); - if (result != null) { - return result; - } - } - return null; - } -} - -/// The default input handler for the terminal. That is composed of a -/// [KeytabInputHandler], a [CtrlInputHandler], and a [AltInputHandler]. -/// -/// It's possible to override the default input handler behavior by chaining -/// another input handler before or after the default input handler using -/// [CascadeInputHandler]. -/// -/// See also: -/// * [CascadeInputHandler] -const defaultInputHandler = CascadeInputHandler([ - KeytabInputHandler(), - CtrlInputHandler(), - AltInputHandler(), -]); - -/// A [TerminalInputHandler] that translates key events according to a keytab -/// file. If no keytab is provided, [Keytab.defaultKeytab] is used. -class KeytabInputHandler implements TerminalInputHandler { - const KeytabInputHandler([this.keytab]); - - final Keytab? keytab; - - @override - String? call(TerminalKeyboardEvent event) { - final keytab = this.keytab ?? Keytab.defaultKeytab; - - final record = keytab.find( - event.key, - ctrl: event.ctrl, - alt: event.alt, - shift: event.shift, - newLineMode: event.state.lineFeedMode, - appCursorKeys: event.state.appKeypadMode, - appKeyPad: event.state.appKeypadMode, - appScreen: event.altBuffer, - macos: event.platform == TerminalTargetPlatform.macos, - ); - - if (record == null) { - return null; - } - - var result = record.action.unescapedValue(); - result = insertModifiers(event, result); - return result; - } - - String insertModifiers(TerminalKeyboardEvent event, String action) { - String? code; - - if (event.shift && event.alt && event.ctrl) { - code = '8'; - } else if (event.ctrl && event.alt) { - code = '7'; - } else if (event.shift && event.ctrl) { - code = '6'; - } else if (event.ctrl) { - code = '5'; - } else if (event.shift && event.alt) { - code = '4'; - } else if (event.alt) { - code = '3'; - } else if (event.shift) { - code = '2'; - } - - if (code != null) { - return action.replaceAll('*', code); - } - - return action; - } -} - -/// A [TerminalInputHandler] that translates ctrl + key events into escape -/// sequences. For example, ctrl + a becomes ^A. -class CtrlInputHandler implements TerminalInputHandler { - const CtrlInputHandler(); - - @override - String? call(TerminalKeyboardEvent event) { - if (!event.ctrl || event.shift || event.alt) { - return null; - } - - final key = event.key; - - if (key.index >= TerminalKey.keyA.index && - key.index <= TerminalKey.keyZ.index) { - final input = key.index - TerminalKey.keyA.index + 1; - return String.fromCharCode(input); - } - - return null; - } -} - -/// A [TerminalInputHandler] that translates alt + key events into escape -/// sequences. For example, alt + a becomes ^[a. -class AltInputHandler implements TerminalInputHandler { - const AltInputHandler(); - - @override - String? call(TerminalKeyboardEvent event) { - if (!event.alt || event.ctrl || event.shift) { - return null; - } - - if (event.platform == TerminalTargetPlatform.macos) { - return null; - } - - final key = event.key; - - if (key.index >= TerminalKey.keyA.index && - key.index <= TerminalKey.keyZ.index) { - final charCode = key.index - TerminalKey.keyA.index + 65; - final input = [0x1b, charCode]; - return String.fromCharCodes(input); - } - - return null; - } -} diff --git a/lib/src/core/input/keys.dart b/lib/src/core/input/keys.dart deleted file mode 100644 index ed26c2da..00000000 --- a/lib/src/core/input/keys.dart +++ /dev/null @@ -1,835 +0,0 @@ -enum TerminalKey { - /// Represents the logical "None" key on the keyboard. - none, - - /// Represents the logical "Hyper" key on the keyboard. - hyper, - - /// Represents the logical "Super Key" key on the keyboard. - superKey, - - /// Represents the logical "Fn Lock" key on the keyboard. - fnLock, - - /// Represents the logical "Suspend" key on the keyboard. - suspend, - - /// Represents the logical "Resume" key on the keyboard. - resume, - - /// Represents the logical "Turbo" key on the keyboard. - turbo, - - /// Represents the logical "Privacy Screen Toggle" key on the keyboard. - privacyScreenToggle, - - /// Represents the logical "Sleep" key on the keyboard. - sleep, - - /// Represents the logical "Wake Up" key on the keyboard. - wakeUp, - - /// Represents the logical "Display Toggle Int Ext" key on the keyboard. - displayToggleIntExt, - - /// Represents the logical "Usb Reserved" key on the keyboard. - usbReserved, - - /// Represents the logical "Usb Error Roll Over" key on the keyboard. - usbErrorRollOver, - - /// Represents the logical "Usb Post Fail" key on the keyboard. - usbPostFail, - - /// Represents the logical "Usb Error Undefined" key on the keyboard. - usbErrorUndefined, - - /// Represents the logical "Key A" key on the keyboard. - keyA, - - /// Represents the logical "Key B" key on the keyboard. - keyB, - - /// Represents the logical "Key C" key on the keyboard. - keyC, - - /// Represents the logical "Key D" key on the keyboard. - keyD, - - /// Represents the logical "Key E" key on the keyboard. - keyE, - - /// Represents the logical "Key F" key on the keyboard. - keyF, - - /// Represents the logical "Key G" key on the keyboard. - keyG, - - /// Represents the logical "Key H" key on the keyboard. - keyH, - - /// Represents the logical "Key I" key on the keyboard. - keyI, - - /// Represents the logical "Key J" key on the keyboard. - keyJ, - - /// Represents the logical "Key K" key on the keyboard. - keyK, - - /// Represents the logical "Key L" key on the keyboard. - keyL, - - /// Represents the logical "Key M" key on the keyboard. - keyM, - - /// Represents the logical "Key N" key on the keyboard. - keyN, - - /// Represents the logical "Key O" key on the keyboard. - keyO, - - /// Represents the logical "Key P" key on the keyboard. - keyP, - - /// Represents the logical "Key Q" key on the keyboard. - keyQ, - - /// Represents the logical "Key R" key on the keyboard. - keyR, - - /// Represents the logical "Key S" key on the keyboard. - keyS, - - /// Represents the logical "Key T" key on the keyboard. - keyT, - - /// Represents the logical "Key U" key on the keyboard. - keyU, - - /// Represents the logical "Key V" key on the keyboard. - keyV, - - /// Represents the logical "Key W" key on the keyboard. - keyW, - - /// Represents the logical "Key X" key on the keyboard. - keyX, - - /// Represents the logical "Key Y" key on the keyboard. - keyY, - - /// Represents the logical "Key Z" key on the keyboard. - keyZ, - - /// Represents the logical "Digit 1" key on the keyboard. - digit1, - - /// Represents the logical "Digit 2" key on the keyboard. - digit2, - - /// Represents the logical "Digit 3" key on the keyboard. - digit3, - - /// Represents the logical "Digit 4" key on the keyboard. - digit4, - - /// Represents the logical "Digit 5" key on the keyboard. - digit5, - - /// Represents the logical "Digit 6" key on the keyboard. - digit6, - - /// Represents the logical "Digit 7" key on the keyboard. - digit7, - - /// Represents the logical "Digit 8" key on the keyboard. - digit8, - - /// Represents the logical "Digit 9" key on the keyboard. - digit9, - - /// Represents the logical "Digit 0" key on the keyboard. - digit0, - - /// Represents the logical "Enter" key on the keyboard. - enter, - - /// Represents the logical "Escape" key on the keyboard. - escape, - - /// Represents the logical "Backspace" key on the keyboard. - backspace, - - /// Represents the logical "Tab" key on the keyboard. - tab, - - /// Represents the logical "Space" key on the keyboard. - space, - - /// Represents the logical "Minus" key on the keyboard. - minus, - - /// Represents the logical "Equal" key on the keyboard. - equal, - - /// Represents the logical "Bracket Left" key on the keyboard. - bracketLeft, - - /// Represents the logical "Bracket Right" key on the keyboard. - bracketRight, - - /// Represents the logical "Backslash" key on the keyboard. - backslash, - - /// Represents the logical "Semicolon" key on the keyboard. - semicolon, - - /// Represents the logical "Quote" key on the keyboard. - quote, - - /// Represents the logical "Backquote" key on the keyboard. - backquote, - - /// Represents the logical "Comma" key on the keyboard. - comma, - - /// Represents the logical "Period" key on the keyboard. - period, - - /// Represents the logical "Slash" key on the keyboard. - slash, - - /// Represents the logical "Caps Lock" key on the keyboard. - capsLock, - - /// Represents the logical "F1" key on the keyboard. - f1, - - /// Represents the logical "F2" key on the keyboard. - f2, - - /// Represents the logical "F3" key on the keyboard. - f3, - - /// Represents the logical "F4" key on the keyboard. - f4, - - /// Represents the logical "F5" key on the keyboard. - f5, - - /// Represents the logical "F6" key on the keyboard. - f6, - - /// Represents the logical "F7" key on the keyboard. - f7, - - /// Represents the logical "F8" key on the keyboard. - f8, - - /// Represents the logical "F9" key on the keyboard. - f9, - - /// Represents the logical "F10" key on the keyboard. - f10, - - /// Represents the logical "F11" key on the keyboard. - f11, - - /// Represents the logical "F12" key on the keyboard. - f12, - - /// Represents the logical "Print Screen" key on the keyboard. - printScreen, - - /// Represents the logical "Scroll Lock" key on the keyboard. - scrollLock, - - /// Represents the logical "Pause" key on the keyboard. - pause, - - /// Represents the logical "Insert" key on the keyboard. - insert, - - /// Represents the logical "Home" key on the keyboard. - home, - - /// Represents the logical "Page Up" key on the keyboard. - pageUp, - - /// Represents the logical "Delete" key on the keyboard. - delete, - - /// Represents the logical "End" key on the keyboard. - end, - - /// Represents the logical "Page Down" key on the keyboard. - pageDown, - - /// Represents the logical "Arrow Right" key on the keyboard. - arrowRight, - - /// Represents the logical "Arrow Left" key on the keyboard. - arrowLeft, - - /// Represents the logical "Arrow Down" key on the keyboard. - arrowDown, - - /// Represents the logical "Arrow Up" key on the keyboard. - arrowUp, - - /// Represents the logical "Num Lock" key on the keyboard. - numLock, - - /// Represents the logical "Numpad Divide" key on the keyboard. - numpadDivide, - - /// Represents the logical "Numpad Multiply" key on the keyboard. - numpadMultiply, - - /// Represents the logical "Numpad Subtract" key on the keyboard. - numpadSubtract, - - /// Represents the logical "Numpad Add" key on the keyboard. - numpadAdd, - - /// Represents the logical "Numpad Enter" key on the keyboard. - numpadEnter, - - /// Represents the logical "Numpad 1" key on the keyboard. - numpad1, - - /// Represents the logical "Numpad 2" key on the keyboard. - numpad2, - - /// Represents the logical "Numpad 3" key on the keyboard. - numpad3, - - /// Represents the logical "Numpad 4" key on the keyboard. - numpad4, - - /// Represents the logical "Numpad 5" key on the keyboard. - numpad5, - - /// Represents the logical "Numpad 6" key on the keyboard. - numpad6, - - /// Represents the logical "Numpad 7" key on the keyboard. - numpad7, - - /// Represents the logical "Numpad 8" key on the keyboard. - numpad8, - - /// Represents the logical "Numpad 9" key on the keyboard. - numpad9, - - /// Represents the logical "Numpad 0" key on the keyboard. - numpad0, - - /// Represents the logical "Numpad Decimal" key on the keyboard. - numpadDecimal, - - /// Represents the logical "Intl Backslash" key on the keyboard. - intlBackslash, - - /// Represents the logical "Context Menu" key on the keyboard. - contextMenu, - - /// Represents the logical "Power" key on the keyboard. - power, - - /// Represents the logical "Numpad Equal" key on the keyboard. - numpadEqual, - - /// Represents the logical "F13" key on the keyboard. - f13, - - /// Represents the logical "F14" key on the keyboard. - f14, - - /// Represents the logical "F15" key on the keyboard. - f15, - - /// Represents the logical "F16" key on the keyboard. - f16, - - /// Represents the logical "F17" key on the keyboard. - f17, - - /// Represents the logical "F18" key on the keyboard. - f18, - - /// Represents the logical "F19" key on the keyboard. - f19, - - /// Represents the logical "F20" key on the keyboard. - f20, - - /// Represents the logical "F21" key on the keyboard. - f21, - - /// Represents the logical "F22" key on the keyboard. - f22, - - /// Represents the logical "F23" key on the keyboard. - f23, - - /// Represents the logical "F24" key on the keyboard. - f24, - - /// Represents the logical "Open" key on the keyboard. - open, - - /// Represents the logical "Help" key on the keyboard. - help, - - /// Represents the logical "Select" key on the keyboard. - select, - - /// Represents the logical "Again" key on the keyboard. - again, - - /// Represents the logical "Undo" key on the keyboard. - undo, - - /// Represents the logical "Cut" key on the keyboard. - cut, - - /// Represents the logical "Copy" key on the keyboard. - copy, - - /// Represents the logical "Paste" key on the keyboard. - paste, - - /// Represents the logical "Find" key on the keyboard. - find, - - /// Represents the logical "Audio Volume Mute" key on the keyboard. - audioVolumeMute, - - /// Represents the logical "Audio Volume Up" key on the keyboard. - audioVolumeUp, - - /// Represents the logical "Audio Volume Down" key on the keyboard. - audioVolumeDown, - - /// Represents the logical "Numpad Comma" key on the keyboard. - numpadComma, - - /// Represents the logical "Intl Ro" key on the keyboard. - intlRo, - - /// Represents the logical "Kana Mode" key on the keyboard. - kanaMode, - - /// Represents the logical "Intl Yen" key on the keyboard. - intlYen, - - /// Represents the logical "Convert" key on the keyboard. - convert, - - /// Represents the logical "Non Convert" key on the keyboard. - nonConvert, - - /// Represents the logical "Lang 1" key on the keyboard. - lang1, - - /// Represents the logical "Lang 2" key on the keyboard. - lang2, - - /// Represents the logical "Lang 3" key on the keyboard. - lang3, - - /// Represents the logical "Lang 4" key on the keyboard. - lang4, - - /// Represents the logical "Lang 5" key on the keyboard. - lang5, - - /// Represents the logical "Abort" key on the keyboard. - abort, - - /// Represents the logical "Props" key on the keyboard. - props, - - /// Represents the logical "Numpad Paren Left" key on the keyboard. - numpadParenLeft, - - /// Represents the logical "Numpad Paren Right" key on the keyboard. - numpadParenRight, - - /// Represents the logical "Numpad Backspace" key on the keyboard. - numpadBackspace, - - /// Represents the logical "Numpad Memory Store" key on the keyboard. - numpadMemoryStore, - - /// Represents the logical "Numpad Memory Recall" key on the keyboard. - numpadMemoryRecall, - - /// Represents the logical "Numpad Memory Clear" key on the keyboard. - numpadMemoryClear, - - /// Represents the logical "Numpad Memory Add" key on the keyboard. - numpadMemoryAdd, - - /// Represents the logical "Numpad Memory Subtract" key on the keyboard. - numpadMemorySubtract, - - /// Represents the logical "Numpad Sign Change" key on the keyboard. - numpadSignChange, - - /// Represents the logical "Numpad Clear" key on the keyboard. - numpadClear, - - /// Represents the logical "Numpad Clear Entry" key on the keyboard. - numpadClearEntry, - - /// Represents the logical "Control Left" key on the keyboard. - controlLeft, - - /// Represents the logical "Shift Left" key on the keyboard. - shiftLeft, - - /// Represents the logical "Alt Left" key on the keyboard. - altLeft, - - /// Represents the logical "Meta Left" key on the keyboard. - metaLeft, - - /// Represents the logical "Control Right" key on the keyboard. - controlRight, - - /// Represents the logical "Shift Right" key on the keyboard. - shiftRight, - - /// Represents the logical "Alt Right" key on the keyboard. - altRight, - - /// Represents the logical "Meta Right" key on the keyboard. - metaRight, - - /// Represents the logical "Info" key on the keyboard. - info, - - /// Represents the logical "Closed Caption Toggle" key on the keyboard. - closedCaptionToggle, - - /// Represents the logical "Brightness Up" key on the keyboard. - brightnessUp, - - /// Represents the logical "Brightness Down" key on the keyboard. - brightnessDown, - - /// Represents the logical "Brightness Toggle" key on the keyboard. - brightnessToggle, - - /// Represents the logical "Brightness Minimum" key on the keyboard. - brightnessMinimum, - - /// Represents the logical "Brightness Maximum" key on the keyboard. - brightnessMaximum, - - /// Represents the logical "Brightness Auto" key on the keyboard. - brightnessAuto, - - /// Represents the logical "Media Last" key on the keyboard. - mediaLast, - - /// Represents the logical "Launch Phone" key on the keyboard. - launchPhone, - - /// Represents the logical "Program Guide" key on the keyboard. - programGuide, - - /// Represents the logical "Exit" key on the keyboard. - exit, - - /// Represents the logical "Channel Up" key on the keyboard. - channelUp, - - /// Represents the logical "Channel Down" key on the keyboard. - channelDown, - - /// Represents the logical "Media Play" key on the keyboard. - mediaPlay, - - /// Represents the logical "Media Pause" key on the keyboard. - mediaPause, - - /// Represents the logical "Media Record" key on the keyboard. - mediaRecord, - - /// Represents the logical "Media Fast Forward" key on the keyboard. - mediaFastForward, - - /// Represents the logical "Media Rewind" key on the keyboard. - mediaRewind, - - /// Represents the logical "Media Track Next" key on the keyboard. - mediaTrackNext, - - /// Represents the logical "Media Track Previous" key on the keyboard. - mediaTrackPrevious, - - /// Represents the logical "Media Stop" key on the keyboard. - mediaStop, - - /// Represents the logical "Eject" key on the keyboard. - eject, - - /// Represents the logical "Media Play Pause" key on the keyboard. - mediaPlayPause, - - /// Represents the logical "Speech Input Toggle" key on the keyboard. - speechInputToggle, - - /// Represents the logical "Bass Boost" key on the keyboard. - bassBoost, - - /// Represents the logical "Media Select" key on the keyboard. - mediaSelect, - - /// Represents the logical "Launch Word Processor" key on the keyboard. - launchWordProcessor, - - /// Represents the logical "Launch Spreadsheet" key on the keyboard. - launchSpreadsheet, - - /// Represents the logical "Launch Mail" key on the keyboard. - launchMail, - - /// Represents the logical "Launch Contacts" key on the keyboard. - launchContacts, - - /// Represents the logical "Launch Calendar" key on the keyboard. - launchCalendar, - - /// Represents the logical "Launch App2" key on the keyboard. - launchApp2, - - /// Represents the logical "Launch App1" key on the keyboard. - launchApp1, - - /// Represents the logical "Launch Internet Browser" key on the keyboard. - launchInternetBrowser, - - /// Represents the logical "Log Off" key on the keyboard. - logOff, - - /// Represents the logical "Lock Screen" key on the keyboard. - lockScreen, - - /// Represents the logical "Launch Control Panel" key on the keyboard. - launchControlPanel, - - /// Represents the logical "Select Task" key on the keyboard. - selectTask, - - /// Represents the logical "Launch Documents" key on the keyboard. - launchDocuments, - - /// Represents the logical "Spell Check" key on the keyboard. - spellCheck, - - /// Represents the logical "Launch Keyboard Layout" key on the keyboard. - launchKeyboardLayout, - - /// Represents the logical "Launch Screen Saver" key on the keyboard. - launchScreenSaver, - - /// Represents the logical "Launch Assistant" key on the keyboard. - launchAssistant, - - /// Represents the logical "Launch Audio Browser" key on the keyboard. - launchAudioBrowser, - - /// Represents the logical "New Key" key on the keyboard. - newKey, - - /// Represents the logical "Close" key on the keyboard. - close, - - /// Represents the logical "Save" key on the keyboard. - save, - - /// Represents the logical "Print" key on the keyboard. - print, - - /// Represents the logical "Browser Search" key on the keyboard. - browserSearch, - - /// Represents the logical "Browser Home" key on the keyboard. - browserHome, - - /// Represents the logical "Browser Back" key on the keyboard. - browserBack, - - /// Represents the logical "Browser Forward" key on the keyboard. - browserForward, - - /// Represents the logical "Browser Stop" key on the keyboard. - browserStop, - - /// Represents the logical "Browser Refresh" key on the keyboard. - browserRefresh, - - /// Represents the logical "Browser Favorites" key on the keyboard. - browserFavorites, - - /// Represents the logical "Zoom In" key on the keyboard. - zoomIn, - - /// Represents the logical "Zoom Out" key on the keyboard. - zoomOut, - - /// Represents the logical "Zoom Toggle" key on the keyboard. - zoomToggle, - - /// Represents the logical "Redo" key on the keyboard. - redo, - - /// Represents the logical "Mail Reply" key on the keyboard. - mailReply, - - /// Represents the logical "Mail Forward" key on the keyboard. - mailForward, - - /// Represents the logical "Mail Send" key on the keyboard. - mailSend, - - /// Represents the logical "Keyboard Layout Select" key on the keyboard. - keyboardLayoutSelect, - - /// Represents the logical "Show All Windows" key on the keyboard. - showAllWindows, - - /// Represents the logical "Game Button 1" key on the keyboard. - gameButton1, - - /// Represents the logical "Game Button 2" key on the keyboard. - gameButton2, - - /// Represents the logical "Game Button 3" key on the keyboard. - gameButton3, - - /// Represents the logical "Game Button 4" key on the keyboard. - gameButton4, - - /// Represents the logical "Game Button 5" key on the keyboard. - gameButton5, - - /// Represents the logical "Game Button 6" key on the keyboard. - gameButton6, - - /// Represents the logical "Game Button 7" key on the keyboard. - gameButton7, - - /// Represents the logical "Game Button 8" key on the keyboard. - gameButton8, - - /// Represents the logical "Game Button 9" key on the keyboard. - gameButton9, - - /// Represents the logical "Game Button 10" key on the keyboard. - gameButton10, - - /// Represents the logical "Game Button 11" key on the keyboard. - gameButton11, - - /// Represents the logical "Game Button 12" key on the keyboard. - gameButton12, - - /// Represents the logical "Game Button 13" key on the keyboard. - gameButton13, - - /// Represents the logical "Game Button 14" key on the keyboard. - gameButton14, - - /// Represents the logical "Game Button 15" key on the keyboard. - gameButton15, - - /// Represents the logical "Game Button 16" key on the keyboard. - gameButton16, - - /// Represents the logical "Game Button A" key on the keyboard. - gameButtonA, - - /// Represents the logical "Game Button B" key on the keyboard. - gameButtonB, - - /// Represents the logical "Game Button C" key on the keyboard. - gameButtonC, - - /// Represents the logical "Game Button Left 1" key on the keyboard. - gameButtonLeft1, - - /// Represents the logical "Game Button Left 2" key on the keyboard. - gameButtonLeft2, - - /// Represents the logical "Game Button Mode" key on the keyboard. - gameButtonMode, - - /// Represents the logical "Game Button Right 1" key on the keyboard. - gameButtonRight1, - - /// Represents the logical "Game Button Right 2" key on the keyboard. - gameButtonRight2, - - /// Represents the logical "Game Button Select" key on the keyboard. - gameButtonSelect, - - /// Represents the logical "Game Button Start" key on the keyboard. - gameButtonStart, - - /// Represents the logical "Game Button Thumb Left" key on the keyboard. - gameButtonThumbLeft, - - /// Represents the logical "Game Button Thumb Right" key on the keyboard. - gameButtonThumbRight, - - /// Represents the logical "Game Button X" key on the keyboard. - gameButtonX, - - /// Represents the logical "Game Button Y" key on the keyboard. - gameButtonY, - - /// Represents the logical "Game Button Z" key on the keyboard. - gameButtonZ, - - /// Represents the logical "Fn" key on the keyboard. - fn, - - /// Represents the logical "Shift" key on the keyboard. - /// - /// This key represents the union of the keys {shiftLeft, shiftRight} when - /// comparing keys. This key will never be generated directly, its main use is - /// in defining key maps. - shift, - - /// Represents the logical "Meta" key on the keyboard. - /// - /// This key represents the union of the keys {metaLeft, metaRight} when - /// comparing keys. This key will never be generated directly, its main use is - /// in defining key maps. - meta, - - /// Represents the logical "Alt" key on the keyboard. - /// - /// This key represents the union of the keys {altLeft, altRight} when - /// comparing keys. This key will never be generated directly, its main use is - /// in defining key maps. - alt, - - /// Represents the logical "Control" key on the keyboard. - /// - /// This key represents the union of the keys {controlLeft, controlRight} when - /// comparing keys. This key will never be generated directly, its main use is - /// in defining key maps. - control, - - // Missing flutter keys. - - backtab, - returnKey, -} diff --git a/lib/src/core/input/keytab/keytab.dart b/lib/src/core/input/keytab/keytab.dart deleted file mode 100644 index 0999366f..00000000 --- a/lib/src/core/input/keytab/keytab.dart +++ /dev/null @@ -1,113 +0,0 @@ -import 'package:xterm/src/core/input/keys.dart'; -import 'package:xterm/src/core/input/keytab/keytab_default.dart'; -import 'package:xterm/src/core/input/keytab/keytab_parse.dart'; -import 'package:xterm/src/core/input/keytab/keytab_record.dart'; -import 'package:xterm/src/core/input/keytab/keytab_token.dart'; - -class Keytab { - Keytab({ - required this.name, - required this.records, - }); - - factory Keytab.parse(String source) { - final tokens = tokenize(source).toList(); - final parser = KeytabParser()..addTokens(tokens); - return parser.result; - } - - static final defaultKeytab = Keytab.parse(kDefaultKeytab); - - final String? name; - - final List records; - - KeytabRecord? find( - TerminalKey key, { - bool ctrl = false, - bool alt = false, - bool shift = false, - bool newLineMode = false, - bool appCursorKeys = false, - bool appKeyPad = false, - bool keyPad = false, - bool appScreen = false, - bool macos = false, - // bool meta, - }) { - for (var record in records) { - if (record.key != key) { - continue; - } - - if (record.anyModifier == true) { - if (ctrl == false && alt == false && shift == false) { - continue; - } - } else if (record.anyModifier == false) { - if (ctrl != false || alt != false || shift != false) { - continue; - } - } else { - if (record.ctrl != null && record.ctrl != ctrl) { - continue; - } - - if (record.shift != null && record.shift != shift) { - continue; - } - - if (record.alt != null && record.alt != alt) { - continue; - } - } - - if (record.newLine != null && record.newLine != newLineMode) { - continue; - } - - if (record.appCursorKeys != null && - record.appCursorKeys != appCursorKeys) { - continue; - } - - if (record.appKeyPad != null && record.appKeyPad != appKeyPad) { - continue; - } - - if (record.keyPad != null && record.keyPad != keyPad) { - continue; - } - - if (record.appScreen != null && record.appScreen != appScreen) { - continue; - } - - if (record.macos != null && record.macos != macos) { - continue; - } - - // TODO: support VT52 - if (record.ansi == false) { - continue; - } - - return record; - } - - return null; - } - - @override - String toString() { - final buffer = StringBuffer(); - - buffer.writeln('keyboard "$name"'); - - for (var record in records) { - buffer.writeln(record); - } - - return buffer.toString(); - } -} diff --git a/lib/src/core/input/keytab/keytab_default.dart b/lib/src/core/input/keytab/keytab_default.dart deleted file mode 100644 index b451ca44..00000000 --- a/lib/src/core/input/keytab/keytab_default.dart +++ /dev/null @@ -1,213 +0,0 @@ -import 'package:xterm/src/core/input/keytab/keytab_parse.dart'; -import 'package:xterm/src/core/input/keytab/keytab_token.dart'; - -const kDefaultKeytab = r''' -# [README.default.Keytab] Default Keyboard Table -# -# To customize your keyboard, copy this file to something ending with -# .keytab and change it to meet you needs. -# -# Please read the README-KeyTab and the doc/user/README.keyboard files -# in this case. -# -# -------------------------------------------------------------- - -keyboard "Default (XFree 4)" - -# -------------------------------------------------------------- -# -# Note that this particular table is a "risc" version made to -# ease customization without bothering with obsolete details. -# See VT100.keytab for the more hairy stuff. -# -# -------------------------------------------------------------- - -# common keys - -key Escape : "\E" - -key Tab -Shift : "\t" -key Tab +Shift+Ansi : "\E[Z" -key Tab +Shift-Ansi : "\t" -key Backtab +Ansi : "\E[Z" -key Backtab -Ansi : "\t" - -key Return-Shift-NewLine : "\r" -key Return-Shift+NewLine : "\r\n" - -key Return+Shift : "\EOM" - -key Backspace +Alt : "\x17" - -# Backspace and Delete codes are preserving CTRL-H. -# -# Backspace without CTRL sends '^?'; this matches XTerm behaviour, so that -# pressing Alt+Backspace will send \E + Del, which is the expected behaviour -# in some apps (e.g. emacs), and it was the behaviour before the commit -# that add the Backspace +Control rule -key Backspace -Control : "\x7f" - -# Match xterm behaviour: Backspace sends '^H' when Control is pressed -# BS, hex \x08, \b -key Backspace +Control : "\b" - -# Arrow keys in VT52 mode -# shift up/down are reserved for scrolling. -# shift left/right are reserved for switching between tabs (this is hardcoded). - -key Up -Shift-Ansi : "\EA" -key Down -Shift-Ansi : "\EB" -key Right-Shift-Ansi : "\EC" -key Left -Shift-Ansi : "\ED" - -# Arrow keys in ANSI mode with Application - and Normal Cursor Mode) - -key Up -Shift-AnyMod+Ansi+AppCuKeys : "\EOA" -key Down -Shift-AnyMod+Ansi+AppCuKeys : "\EOB" -key Right -Shift-AnyMod+Ansi+AppCuKeys : "\EOC" -key Left -Shift-AnyMod+Ansi+AppCuKeys : "\EOD" - -key Up -Shift-AnyMod+Ansi-AppCuKeys : "\E[A" -key Down -Shift-AnyMod+Ansi-AppCuKeys : "\E[B" -key Right -Shift-AnyMod+Ansi-AppCuKeys : "\E[C" -key Left -Shift-AnyMod+Ansi-AppCuKeys : "\E[D" - -key Up -Shift+AnyMod+Ansi : "\E[1;5A" -key Down -Shift+AnyMod+Ansi : "\E[1;5B" - -# Right / Left with Control -key Right -Shift-Alt+Control+Ansi : "\E[1;5C" -key Left -Shift-Alt+Control+Ansi : "\E[1;5D" - -# Right / Left with Alt not on a Mac -key Right -Shift+Alt-Control+Ansi-Mac : "\E[1;5C" -key Left -Shift+Alt-Control+Ansi-Mac : "\E[1;5D" - -# Right / Left with Alt on a Mac -key Right -Shift+Alt-Control+Ansi+Mac : "\Ef" -key Left -Shift+Alt-Control+Ansi+Mac : "\Eb" - -key Up +Shift+AppScreen : "\E[1;*A" -key Down +Shift+AppScreen : "\E[1;*B" -key Left +Shift+AppScreen : "\E[1;*D" -key Right +Shift+AppScreen : "\E[1;*C" - -# Keypad keys with NumLock ON -# (see https://web.archive.org/web/20070807181942/http://www.nw.com/nw/WWW/products/wizcon/vt100.html -# https://vt100.net/docs/vt100-ug/chapter3.html) -# -# Not enabled for now because it breaks the keypad in Vim. -# -#key 0 +KeyPad+AppKeyPad : "\EOp" -#key 1 +KeyPad+AppKeyPad : "\EOq" -#key 2 +KeyPad+AppKeyPad : "\EOr" -#key 3 +KeyPad+AppKeyPad : "\EOs" -#key 4 +KeyPad+AppKeyPad : "\EOt" -#key 5 +KeyPad+AppKeyPad : "\EOu" -#key 6 +KeyPad+AppKeyPad : "\EOv" -#key 7 +KeyPad+AppKeyPad : "\EOw" -#key 8 +KeyPad+AppKeyPad : "\EOx" -#key 9 +KeyPad+AppKeyPad : "\EOy" -#key + +KeyPad+AppKeyPad : "\EOl" -#key - +KeyPad+AppKeyPad : "\EOm" -#key . +KeyPad+AppKeyPad : "\EOn" -#key * +KeyPad+AppKeyPad : "\EOM" -#key Enter +KeyPad+AppKeyPad : "\r" - -# Keypad keys with NumLock Off -key Up -Shift+Ansi+AppCuKeys+KeyPad : "\EOA" -key Down -Shift+Ansi+AppCuKeys+KeyPad : "\EOB" -key Right -Shift+Ansi+AppCuKeys+KeyPad : "\EOC" -key Left -Shift+Ansi+AppCuKeys+KeyPad : "\EOD" - -key Up -Shift+Ansi-AppCuKeys+KeyPad : "\E[A" -key Down -Shift+Ansi-AppCuKeys+KeyPad : "\E[B" -key Right -Shift+Ansi-AppCuKeys+KeyPad : "\E[C" -key Left -Shift+Ansi-AppCuKeys+KeyPad : "\E[D" - -key Home +AppCuKeys+KeyPad : "\EOH" -key End +AppCuKeys+KeyPad : "\EOF" -key Home -AppCuKeys+KeyPad : "\E[H" -key End -AppCuKeys+KeyPad : "\E[F" - -key Insert +KeyPad : "\E[2~" -key Delete +KeyPad : "\E[3~" -key PgUp -Shift+KeyPad : "\E[5~" -key PgDown -Shift+KeyPad : "\E[6~" - -# the key labelled 5 on the Keypad, is Qt::Key_Clear (a very intuitive -# and discoverable name...) -key Clear +KeyPad : "\E[E" - -# other grey PC keys - -key Enter+NewLine : "\r\n" -key Enter-NewLine : "\r" - -key NumEnter+NewLine : "\r\n" -key NumEnter-NewLine : "\r" - -key Home -AnyMod-AppCuKeys : "\E[H" -key End -AnyMod-AppCuKeys : "\E[F" -key Home -AnyMod+AppCuKeys : "\EOH" -key End -AnyMod+AppCuKeys : "\EOF" -key Home +AnyMod : "\E[1;*H" -key End +AnyMod : "\E[1;*F" - -key Insert -AnyMod : "\E[2~" -key Delete -AnyMod : "\E[3~" -key Insert +AnyMod : "\E[2;*~" -key Delete +AnyMod : "\E[3;*~" - -key PgUp -Shift-AnyMod : "\E[5~" -key PgDown -Shift-AnyMod : "\E[6~" -key PgUp -Shift+AnyMod : "\E[5;*~" -key PgDown -Shift+AnyMod : "\E[6;*~" - -# Function keys -key F1 -AnyMod : "\EOP" -key F2 -AnyMod : "\EOQ" -key F3 -AnyMod : "\EOR" -key F4 -AnyMod : "\EOS" -key F5 -AnyMod : "\E[15~" -key F6 -AnyMod : "\E[17~" -key F7 -AnyMod : "\E[18~" -key F8 -AnyMod : "\E[19~" -key F9 -AnyMod : "\E[20~" -key F10 -AnyMod : "\E[21~" -key F11 -AnyMod : "\E[23~" -key F12 -AnyMod : "\E[24~" - -key F1 +AnyMod : "\EO*P" -key F2 +AnyMod : "\EO*Q" -key F3 +AnyMod : "\EO*R" -key F4 +AnyMod : "\EO*S" -key F5 +AnyMod : "\E[15;*~" -key F6 +AnyMod : "\E[17;*~" -key F7 +AnyMod : "\E[18;*~" -key F8 +AnyMod : "\E[19;*~" -key F9 +AnyMod : "\E[20;*~" -key F10 +AnyMod : "\E[21;*~" -key F11 +AnyMod : "\E[23;*~" -key F12 +AnyMod : "\E[24;*~" - -# Work around dead keys - -key Space +Control : "\x00" - -# Some keys are used by konsole to cause operations. -# The scroll* operations refer to the history buffer. - -key Up +Shift-AppScreen : scrollLineUp -key PgUp +Shift-AppScreen : scrollPageUp -key Home +Shift-AppScreen : scrollUpToTop -key Down +Shift-AppScreen : scrollLineDown -key PgDown +Shift-AppScreen : scrollPageDown -key End +Shift-AppScreen : scrollDownToBottom -'''; - -void main() { - final tokens = tokenize(kDefaultKeytab).toList(); - final parser = KeytabParser()..addTokens(tokens); - print(parser.result); -} diff --git a/lib/src/core/input/keytab/keytab_escape.dart b/lib/src/core/input/keytab/keytab_escape.dart deleted file mode 100644 index 5375bc34..00000000 --- a/lib/src/core/input/keytab/keytab_escape.dart +++ /dev/null @@ -1,21 +0,0 @@ -final _esc = String.fromCharCode(0x1b); - -String keytabUnescape(String str) { - str = str - .replaceAll(r'\E', _esc) - .replaceAll(r'\\', '\\') - .replaceAll(r'\"', '"') - .replaceAll(r'\t', '\t') - .replaceAll(r'\r', '\r') - .replaceAll(r'\n', '\n') - .replaceAll(r'\b', '\b'); - - final hexPattern = RegExp(r'\\x([0-9a-fA-F][0-9a-fA-F])'); - str = str.replaceAllMapped(hexPattern, (match) { - final hexString = match.group(1)!; - final hexValue = int.parse(hexString, radix: 16); - return String.fromCharCode(hexValue); - }); - - return str; -} diff --git a/lib/src/core/input/keytab/keytab_parse.dart b/lib/src/core/input/keytab/keytab_parse.dart deleted file mode 100644 index 96f80358..00000000 --- a/lib/src/core/input/keytab/keytab_parse.dart +++ /dev/null @@ -1,186 +0,0 @@ -import 'package:xterm/src/core/input/keytab/keytab.dart'; -import 'package:xterm/src/core/input/keytab/keytab_record.dart'; -import 'package:xterm/src/core/input/keytab/keytab_token.dart'; -import 'package:xterm/src/core/input/keytab/qt_keyname.dart'; - -class ParseError {} - -class TokensReader { - TokensReader(this.tokens); - - final List tokens; - - var _pos = 0; - - bool get done => _pos > tokens.length - 1; - - KeytabToken? take() { - final result = peek(); - _pos += 1; - return result; - } - - KeytabToken? peek() { - if (done) return null; - return tokens[_pos]; - } -} - -class KeytabParser { - String? _name; - final _records = []; - - void addTokens(List tokens) { - final reader = TokensReader(tokens); - - while (!reader.done) { - if (reader.peek()!.type == KeytabTokenType.keyboard) { - _parseName(reader); - continue; - } - - if (reader.peek()!.type == KeytabTokenType.keyDefine) { - _parseKeyDefine(reader); - continue; - } - - throw ParseError(); - } - } - - Keytab get result { - return Keytab(name: _name, records: _records); - } - - void _parseName(TokensReader reader) { - if (reader.take()!.type != KeytabTokenType.keyboard) { - throw ParseError(); - } - - final name = reader.take()!; - if (name.type != KeytabTokenType.input) { - throw ParseError(); - } - - _name = name.value; - } - - void _parseKeyDefine(TokensReader reader) { - if (reader.take()!.type != KeytabTokenType.keyDefine) { - throw ParseError(); - } - - final keyName = reader.take()!; - - if (keyName.type != KeytabTokenType.keyName) { - throw ParseError(); - } - - final key = qtKeynameMap[keyName.value]; - if (key == null) { - throw ParseError(); - } - - bool? alt; - bool? ctrl; - bool? shift; - bool? anyModifier; - bool? ansi; - bool? appScreen; - bool? keyPad; - bool? appCursorKeys; - bool? appKeyPad; - bool? newLine; - bool? mac; - - while (reader.peek()!.type == KeytabTokenType.modeStatus) { - bool modeStatus; - switch (reader.take()!.value) { - case '+': - modeStatus = true; - break; - case '-': - modeStatus = false; - break; - default: - throw ParseError(); - } - - final mode = reader.take(); - if (mode!.type != KeytabTokenType.mode) { - throw ParseError(); - } - - switch (mode.value) { - case 'Alt': - alt = modeStatus; - break; - case 'Control': - ctrl = modeStatus; - break; - case 'Shift': - shift = modeStatus; - break; - case 'AnyMod': - anyModifier = modeStatus; - break; - case 'Ansi': - ansi = modeStatus; - break; - case 'AppScreen': - appScreen = modeStatus; - break; - case 'KeyPad': - keyPad = modeStatus; - break; - case 'AppCuKeys': - appCursorKeys = modeStatus; - break; - case 'AppKeyPad': - appKeyPad = modeStatus; - break; - case 'NewLine': - newLine = modeStatus; - break; - case 'Mac': - mac = modeStatus; - break; - default: - throw ParseError(); - } - } - - if (reader.take()!.type != KeytabTokenType.colon) { - throw ParseError(); - } - - final actionToken = reader.take()!; - KeytabAction action; - if (actionToken.type == KeytabTokenType.input) { - action = KeytabAction(KeytabActionType.input, actionToken.value); - } else if (actionToken.type == KeytabTokenType.shortcut) { - action = KeytabAction(KeytabActionType.shortcut, actionToken.value); - } else { - throw ParseError(); - } - - final record = KeytabRecord( - qtKeyName: keyName.value, - key: key, - action: action, - alt: alt, - ctrl: ctrl, - shift: shift, - anyModifier: anyModifier, - ansi: ansi, - appScreen: appScreen, - keyPad: keyPad, - appCursorKeys: appCursorKeys, - appKeyPad: appKeyPad, - newLine: newLine, - macos: mac, - ); - - _records.add(record); - } -} diff --git a/lib/src/core/input/keytab/keytab_record.dart b/lib/src/core/input/keytab/keytab_record.dart deleted file mode 100644 index 7ba3caeb..00000000 --- a/lib/src/core/input/keytab/keytab_record.dart +++ /dev/null @@ -1,134 +0,0 @@ -import 'package:xterm/src/core/input/keys.dart'; -import 'package:xterm/src/core/input/keytab/keytab_escape.dart'; - -enum KeytabActionType { - input, - shortcut, -} - -class KeytabAction { - KeytabAction(this.type, this.value); - - final KeytabActionType type; - - final String value; - - String unescapedValue() { - if (type == KeytabActionType.input) { - return keytabUnescape(value); - } else { - return value; - } - } - - @override - String toString() { - switch (type) { - case KeytabActionType.input: - return '"$value"'; - case KeytabActionType.shortcut: - return value; - } - } -} - -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.macos, - }); - - 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? macos; - - @override - String toString() { - final buffer = StringBuffer(); - buffer.write('$qtKeyName '); - - if (alt != null) { - buffer.write(_toMode(alt!, 'Alt')); - } - - if (ctrl != null) { - buffer.write(_toMode(ctrl!, 'Control')); - } - - if (shift != null) { - buffer.write(_toMode(shift!, 'Shift')); - } - - if (anyModifier != null) { - buffer.write(_toMode(anyModifier!, 'AnyMod')); - } - - if (ansi != null) { - buffer.write(_toMode(ansi!, 'Ansi')); - } - - if (appScreen != null) { - buffer.write(_toMode(appScreen!, 'AppScreen')); - } - - if (keyPad != null) { - buffer.write(_toMode(keyPad!, 'KeyPad')); - } - - if (appCursorKeys != null) { - buffer.write(_toMode(appCursorKeys!, 'AppCuKeys')); - } - - if (appKeyPad != null) { - buffer.write(_toMode(appKeyPad!, 'AppKeyPad')); - } - - if (newLine != null) { - buffer.write(_toMode(newLine!, 'NewLine')); - } - - if (macos != null) { - buffer.write(_toMode(macos!, 'Mac')); - } - - buffer.write(' : $action'); - - return buffer.toString(); - } - - static String _toMode(bool status, String mode) { - if (status == true) { - return '+$mode'; - } - - if (status == false) { - return '-$mode'; - } - - return ''; - } -} diff --git a/lib/src/core/input/keytab/keytab_token.dart b/lib/src/core/input/keytab/keytab_token.dart deleted file mode 100644 index a8ab8706..00000000 --- a/lib/src/core/input/keytab/keytab_token.dart +++ /dev/null @@ -1,179 +0,0 @@ -import 'dart:math' show min; - -enum KeytabTokenType { - keyDefine, - keyboard, - keyName, - mode, - modeStatus, - colon, - input, - shortcut, -} - -class KeytabToken { - KeytabToken(this.type, this.value); - - final KeytabTokenType type; - final String value; - - @override - String toString() { - return '$type<$value>'; - } -} - -class LineReader { - LineReader(this.line); - - final String line; - - var _pos = 0; - - bool get done => _pos > line.length - 1; - - String? take([int count = 1]) { - final result = peek(count); - _pos += count; - return result; - } - - String? peek([int count = 1]) { - if (done) return null; - final end = min(_pos + count, line.length); - final result = line.substring(_pos, end); - return result; - } - - void skipWhitespace() { - while (peek() == ' ' || peek() == '\t') { - _pos += 1; - } - } - - String readString() { - final buffer = StringBuffer(); - final pattern = RegExp(r'\w|_'); - - while (!done && line[_pos].contains(pattern)) { - buffer.write(line[_pos]); - _pos++; - } - - return buffer.toString(); - } - - String readUntil(Pattern pattern, {bool inclusive = false}) { - final buffer = StringBuffer(); - - while (!done && !line[_pos].contains(pattern)) { - buffer.write(line[_pos]); - _pos++; - } - - if (!done && inclusive) { - buffer.write(line[_pos]); - _pos++; - } - - return buffer.toString(); - } -} - -class TokenizeError {} - -Iterable tokenize(String source) sync* { - final lines = source.split('\n'); - - for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim(); - line = line.replaceFirst(RegExp('#.*'), ''); - - if (line == '') { - continue; - } - - if (_isKeyboardNameDefine(line)) { - yield* _parseKeyboardNameDefine(line); - } - - if (_isKeyDefine(line)) { - yield* _parseKeyDefine(line); - } - } -} - -bool _isKeyboardNameDefine(String line) { - return line.startsWith('keyboard '); -} - -bool _isKeyDefine(String line) { - return line.startsWith('key '); -} - -Iterable _parseKeyboardNameDefine(String line) sync* { - final reader = LineReader(line.trim()); - - if (reader.readString() == 'keyboard') { - yield KeytabToken(KeytabTokenType.keyboard, 'keyboard'); - } else { - throw TokenizeError(); - } - - reader.skipWhitespace(); - - yield _readInput(reader); -} - -Iterable _parseKeyDefine(String line) sync* { - final reader = LineReader(line.trim()); - - if (reader.readString() == 'key') { - yield KeytabToken(KeytabTokenType.keyDefine, 'key'); - } else { - throw TokenizeError(); - } - - reader.skipWhitespace(); - - final keyName = reader.readString(); - yield KeytabToken(KeytabTokenType.keyName, keyName); - - reader.skipWhitespace(); - - while (reader.peek() == '+' || reader.peek() == '-') { - final modeStatus = reader.take()!; - yield KeytabToken(KeytabTokenType.modeStatus, modeStatus); - final mode = reader.readString(); - yield KeytabToken(KeytabTokenType.mode, mode); - reader.skipWhitespace(); - } - - if (reader.take() == ':') { - yield KeytabToken(KeytabTokenType.colon, ':'); - } else { - throw TokenizeError(); - } - - reader.skipWhitespace(); - - if (reader.peek() == '"') { - yield _readInput(reader); - } else { - final action = reader.readString(); - yield KeytabToken(KeytabTokenType.shortcut, action); - } -} - -KeytabToken _readInput(LineReader reader) { - reader.skipWhitespace(); - - if (reader.take() != '"') { - throw TokenizeError(); - } - - final value = reader.readUntil('"'); - reader.take(); - - return KeytabToken(KeytabTokenType.input, value); -} diff --git a/lib/src/core/input/keytab/qt_keyname.dart b/lib/src/core/input/keytab/qt_keyname.dart deleted file mode 100644 index 4eca3e63..00000000 --- a/lib/src/core/input/keytab/qt_keyname.dart +++ /dev/null @@ -1,477 +0,0 @@ -import 'package:xterm/src/core/input/keys.dart'; - -/// See: https://doc.qt.io/qt-5/qt.html#Key-enum -const qtKeynameMap = { - 'Escape': TerminalKey.escape, - 'Tab': TerminalKey.tab, - 'Backtab': TerminalKey.backtab, - 'Backspace': TerminalKey.backspace, - 'Return': TerminalKey.returnKey, - 'Enter': TerminalKey.enter, - 'NumEnter': TerminalKey.numpadEnter, - 'Insert': TerminalKey.insert, - 'Delete': TerminalKey.delete, - 'Pause': TerminalKey.pause, - 'Print': TerminalKey.print, -// 'SysReq': TerminalKey.sysReq, - 'Clear': TerminalKey.numpadClear, - 'Home': TerminalKey.home, - 'End': TerminalKey.end, - 'Left': TerminalKey.arrowLeft, - 'Up': TerminalKey.arrowUp, - 'Right': TerminalKey.arrowRight, - 'Down': TerminalKey.arrowDown, - 'PageUp': TerminalKey.pageUp, - 'PageDown': TerminalKey.pageDown, - 'PgUp': TerminalKey.pageUp, - 'PgDown': TerminalKey.pageDown, - 'Shift': TerminalKey.shift, - 'Control': TerminalKey.control, - 'Meta': TerminalKey.meta, - 'Alt': TerminalKey.alt, -// 'AltGr': TerminalKey.altGr, - 'CapsLock': TerminalKey.capsLock, - 'NumLock': TerminalKey.numLock, - 'ScrollLock': TerminalKey.scrollLock, - 'F1': TerminalKey.f1, - 'F2': TerminalKey.f2, - 'F3': TerminalKey.f3, - 'F4': TerminalKey.f4, - 'F5': TerminalKey.f5, - 'F6': TerminalKey.f6, - 'F7': TerminalKey.f7, - 'F8': TerminalKey.f8, - 'F9': TerminalKey.f9, - 'F10': TerminalKey.f10, - 'F11': TerminalKey.f11, - 'F12': TerminalKey.f12, - 'F13': TerminalKey.f13, - 'F14': TerminalKey.f14, - 'F15': TerminalKey.f15, - 'F16': TerminalKey.f16, - 'F17': TerminalKey.f17, - 'F18': TerminalKey.f18, - 'F19': TerminalKey.f19, - 'F20': TerminalKey.f20, - 'F21': TerminalKey.f21, - 'F22': TerminalKey.f22, - 'F23': TerminalKey.f23, - 'F24': TerminalKey.f24, -// 'F25': TerminalKey.f25, -// 'F26': TerminalKey.f26, -// 'F27': TerminalKey.f27, -// 'F28': TerminalKey.f28, -// 'F29': TerminalKey.f29, -// 'F30': TerminalKey.f30, -// 'F31': TerminalKey.f31, -// 'F32': TerminalKey.f32, -// 'F33': TerminalKey.f33, -// 'F34': TerminalKey.f34, -// 'F35': TerminalKey.f35, -// 'Super_L': TerminalKey.super_L, -// 'Super_R': TerminalKey.super_R, -// 'Menu': TerminalKey.menu, -// 'Hyper_L': TerminalKey.hyper_L, -// 'Hyper_R': TerminalKey.hyper_R, - 'Help': TerminalKey.help, -// 'Direction_L': TerminalKey.direction_L, -// 'Direction_R': TerminalKey.direction_R, - 'Space': TerminalKey.space, - // 'Any': TerminalKey.any, - // 'Exclam': TerminalKey.exclam, - // 'QuoteDbl': TerminalKey.quoteDbl, - // 'NumberSign': TerminalKey.numberSign, - // 'Dollar': TerminalKey.dollar, - // 'Percent': TerminalKey.percent, - // 'Ampersand': TerminalKey.ampersand, - // 'Apostrophe': TerminalKey.apostrophe, - 'ParenLeft': TerminalKey.numpadParenLeft, - 'ParenRight': TerminalKey.numpadParenRight, - // 'Asterisk': TerminalKey.asterisk, - // 'Plus': TerminalKey.plus, - 'Comma': TerminalKey.comma, - 'Minus': TerminalKey.minus, - 'Period': TerminalKey.period, - 'Slash': TerminalKey.slash, - '0': TerminalKey.digit0, - '1': TerminalKey.digit1, - '2': TerminalKey.digit2, - '3': TerminalKey.digit3, - '4': TerminalKey.digit4, - '5': TerminalKey.digit5, - '6': TerminalKey.digit6, - '7': TerminalKey.digit7, - '8': TerminalKey.digit8, - '9': TerminalKey.digit9, -// 'Colon': TerminalKey.colon, - 'Semicolon': TerminalKey.semicolon, -// 'Less': TerminalKey.less, -// 'Equal': TerminalKey.equal, -// 'Greater': TerminalKey.greater, -// 'Question': TerminalKey.question, -// 'At': TerminalKey.at, - 'A': TerminalKey.keyA, - 'B': TerminalKey.keyB, - 'C': TerminalKey.keyC, - 'D': TerminalKey.keyD, - 'E': TerminalKey.keyE, - 'F': TerminalKey.keyF, - 'G': TerminalKey.keyG, - 'H': TerminalKey.keyH, - 'I': TerminalKey.keyI, - 'J': TerminalKey.keyJ, - 'K': TerminalKey.keyK, - 'L': TerminalKey.keyL, - 'M': TerminalKey.keyM, - 'N': TerminalKey.keyN, - 'O': TerminalKey.keyO, - 'P': TerminalKey.keyP, - 'Q': TerminalKey.keyQ, - 'R': TerminalKey.keyR, - 'S': TerminalKey.keyS, - 'T': TerminalKey.keyT, - 'U': TerminalKey.keyU, - 'V': TerminalKey.keyV, - 'W': TerminalKey.keyW, - 'X': TerminalKey.keyX, - 'Y': TerminalKey.keyY, - 'Z': TerminalKey.keyZ, - 'BracketLeft': TerminalKey.bracketLeft, - 'Backslash': TerminalKey.backslash, - 'BracketRight': TerminalKey.bracketRight, -// 'AsciiCircum': TerminalKey.asciiCircum, - // 'Underscore': TerminalKey.underscore, - // 'QuoteLeft': TerminalKey.quoteLeft, -// 'BraceLeft': TerminalKey.braceLeft, - // 'Bar': TerminalKey.bar, -// 'BraceRight': TerminalKey.braceRight, - // 'AsciiTilde': TerminalKey.asciiTilde, -// 'nobreakspace': TerminalKey.nobreakspace, -// 'exclamdown': TerminalKey.exclamdown, -// 'cent': TerminalKey.cent, -// 'sterling': TerminalKey.sterling, -// 'currency': TerminalKey.currency, -// 'yen': TerminalKey.yen, -// 'brokenbar': TerminalKey.brokenbar, -// 'section': TerminalKey.section, -// 'diaeresis': TerminalKey.diaeresis, -// 'copyright': TerminalKey.copyright, -// 'ordfeminine': TerminalKey.ordfeminine, -// 'guillemotleft': TerminalKey.guillemotleft, -// 'notsign': TerminalKey.notsign, -// 'hyphen': TerminalKey.hyphen, -// 'registered': TerminalKey.registered, -// 'macron': TerminalKey.macron, -// 'degree': TerminalKey.degree, -// 'plusminus': TerminalKey.plusminus, -// 'twosuperior': TerminalKey.twosuperior, -// 'threesuperior': TerminalKey.threesuperior, -// 'acute': TerminalKey.acute, -// // 'mu': TerminalKey.mu, -// 'paragraph': TerminalKey.paragraph, -// 'periodcentered': TerminalKey.periodcentered, -// 'cedilla': TerminalKey.cedilla, -// 'onesuperior': TerminalKey.onesuperior, -// 'masculine': TerminalKey.masculine, -// 'guillemotright': TerminalKey.guillemotright, -// 'onequarter': TerminalKey.onequarter, -// 'onehalf': TerminalKey.onehalf, -// 'threequarters': TerminalKey.threequarters, -// 'questiondown': TerminalKey.questiondown, -// 'Agrave': TerminalKey.agrave, -// 'Aacute': TerminalKey.aacute, -// 'Acircumflex': TerminalKey.acircumflex, -// 'Atilde': TerminalKey.atilde, -// 'Adiaeresis': TerminalKey.adiaeresis, -// 'Aring': TerminalKey.aring, -// 'AE': TerminalKey.aE, -// 'Ccedilla': TerminalKey.ccedilla, -// 'Egrave': TerminalKey.egrave, -// 'Eacute': TerminalKey.eacute, -// 'Ecircumflex': TerminalKey.ecircumflex, -// 'Ediaeresis': TerminalKey.ediaeresis, -// 'Igrave': TerminalKey.igrave, -// 'Iacute': TerminalKey.iacute, -// 'Icircumflex': TerminalKey.icircumflex, -// 'Idiaeresis': TerminalKey.idiaeresis, -// 'ETH': TerminalKey.eTH, -// 'Ntilde': TerminalKey.ntilde, -// 'Ograve': TerminalKey.ograve, -// 'Oacute': TerminalKey.oacute, -// 'Ocircumflex': TerminalKey.ocircumflex, -// 'Otilde': TerminalKey.otilde, -// 'Odiaeresis': TerminalKey.odiaeresis, -// 'multiply': TerminalKey.multiply, -// 'Ooblique': TerminalKey.ooblique, -// 'Ugrave': TerminalKey.ugrave, -// 'Uacute': TerminalKey.uacute, -// 'Ucircumflex': TerminalKey.ucircumflex, -// 'Udiaeresis': TerminalKey.udiaeresis, -// 'Yacute': TerminalKey.yacute, -// 'THORN': TerminalKey.tHORN, -// 'ssharp': TerminalKey.ssharp, -// 'division': TerminalKey.division, -// 'ydiaeresis': TerminalKey.ydiaeresis, -// 'Multi_key': TerminalKey.multi_key, -// 'Codeinput': TerminalKey.codeinput, -// 'SingleCandidate': TerminalKey.singleCandidate, -// 'MultipleCandidate': TerminalKey.multipleCandidate, -// 'PreviousCandidate': TerminalKey.previousCandidate, -// 'Mode_switch': TerminalKey.mode_switch, -// 'Kanji': TerminalKey.kanji, -// 'Muhenkan': TerminalKey.muhenkan, -// 'Henkan': TerminalKey.henkan, -// 'Romaji': TerminalKey.romaji, -// 'Hiragana': TerminalKey.hiragana, -// 'Katakana': TerminalKey.katakana, -// 'Hiragana_Katakana': TerminalKey.hiragana_Katakana, -// 'Zenkaku': TerminalKey.zenkaku, -// 'Hankaku': TerminalKey.hankaku, -// 'Zenkaku_Hankaku': TerminalKey.zenkaku_Hankaku, -// 'Touroku': TerminalKey.touroku, -// 'Massyo': TerminalKey.massyo, -// 'Kana_Lock': TerminalKey.kana_Lock, -// 'Kana_Shift': TerminalKey.kana_Shift, -// 'Eisu_Shift': TerminalKey.eisu_Shift, -// 'Eisu_toggle': TerminalKey.eisu_toggle, -// 'Hangul': TerminalKey.hangul, -// 'Hangul_Start': TerminalKey.hangul_Start, -// 'Hangul_End': TerminalKey.hangul_End, -// 'Hangul_Hanja': TerminalKey.hangul_Hanja, -// 'Hangul_Jamo': TerminalKey.hangul_Jamo, -// 'Hangul_Romaja': TerminalKey.hangul_Romaja, -// 'Hangul_Jeonja': TerminalKey.hangul_Jeonja, -// 'Hangul_Banja': TerminalKey.hangul_Banja, -// 'Hangul_PreHanja': TerminalKey.hangul_PreHanja, -// 'Hangul_PostHanja': TerminalKey.hangul_PostHanja, -// 'Hangul_Special': TerminalKey.hangul_Special, -// 'Dead_Grave': TerminalKey.dead_Grave, -// 'Dead_Acute': TerminalKey.dead_Acute, -// 'Dead_Circumflex': TerminalKey.dead_Circumflex, -// 'Dead_Tilde': TerminalKey.dead_Tilde, -// 'Dead_Macron': TerminalKey.dead_Macron, -// 'Dead_Breve': TerminalKey.dead_Breve, -// 'Dead_Abovedot': TerminalKey.dead_Abovedot, -// 'Dead_Diaeresis': TerminalKey.dead_Diaeresis, -// 'Dead_Abovering': TerminalKey.dead_Abovering, -// 'Dead_Doubleacute': TerminalKey.dead_Doubleacute, -// 'Dead_Caron': TerminalKey.dead_Caron, -// 'Dead_Cedilla': TerminalKey.dead_Cedilla, -// 'Dead_Ogonek': TerminalKey.dead_Ogonek, -// 'Dead_Iota': TerminalKey.dead_Iota, -// 'Dead_Voiced_Sound': TerminalKey.dead_Voiced_Sound, -// 'Dead_Semivoiced_Sound': TerminalKey.dead_Semivoiced_Sound, -// 'Dead_Belowdot': TerminalKey.dead_Belowdot, -// 'Dead_Hook': TerminalKey.dead_Hook, -// 'Dead_Horn': TerminalKey.dead_Horn, -// 'Dead_Stroke': TerminalKey.dead_Stroke, -// 'Dead_Abovecomma': TerminalKey.dead_Abovecomma, -// 'Dead_Abovereversedcomma': TerminalKey.dead_Abovereversedcomma, -// 'Dead_Doublegrave': TerminalKey.dead_Doublegrave, -// 'Dead_Belowring': TerminalKey.dead_Belowring, -// 'Dead_Belowmacron': TerminalKey.dead_Belowmacron, -// 'Dead_Belowcircumflex': TerminalKey.dead_Belowcircumflex, -// 'Dead_Belowtilde': TerminalKey.dead_Belowtilde, -// 'Dead_Belowbreve': TerminalKey.dead_Belowbreve, -// 'Dead_Belowdiaeresis': TerminalKey.dead_Belowdiaeresis, -// 'Dead_Invertedbreve': TerminalKey.dead_Invertedbreve, -// 'Dead_Belowcomma': TerminalKey.dead_Belowcomma, -// 'Dead_Currency': TerminalKey.dead_Currency, -// 'Dead_a': TerminalKey.dead_a, -// 'Dead_A': TerminalKey.dead_A, -// 'Dead_e': TerminalKey.dead_e, -// 'Dead_E': TerminalKey.dead_E, -// 'Dead_i': TerminalKey.dead_i, -// 'Dead_I': TerminalKey.dead_I, -// 'Dead_o': TerminalKey.dead_o, -// 'Dead_O': TerminalKey.dead_O, -// 'Dead_u': TerminalKey.dead_u, -// 'Dead_U': TerminalKey.dead_U, -// 'Dead_Small_Schwa': TerminalKey.dead_Small_Schwa, -// 'Dead_Capital_Schwa': TerminalKey.dead_Capital_Schwa, -// 'Dead_Greek': TerminalKey.dead_Greek, -// 'Dead_Lowline': TerminalKey.dead_Lowline, -// 'Dead_Aboveverticalline': TerminalKey.dead_Aboveverticalline, -// 'Dead_Belowverticalline': TerminalKey.dead_Belowverticalline, -// 'Dead_Longsolidusoverlay': TerminalKey.dead_Longsolidusoverlay, -// 'Back': TerminalKey.back, -// 'Forward': TerminalKey.forward, -// 'Stop': TerminalKey.stop, -// 'Refresh': TerminalKey.refresh, - 'VolumeDown': TerminalKey.audioVolumeDown, - 'VolumeMute': TerminalKey.audioVolumeMute, - 'VolumeUp': TerminalKey.audioVolumeUp, - 'BassBoost': TerminalKey.bassBoost, -// 'BassUp': TerminalKey.bassUp, -// 'BassDown': TerminalKey.bassDown, -// 'TrebleUp': TerminalKey.trebleUp, -// 'TrebleDown': TerminalKey.trebleDown, - 'MediaPlay': TerminalKey.mediaPlay, - 'MediaStop': TerminalKey.mediaStop, -// 'MediaPrevious': TerminalKey.mediaPrevious, -// 'MediaNext': TerminalKey.mediaNext, - 'MediaRecord': TerminalKey.mediaRecord, - 'MediaPause': TerminalKey.mediaPause, - 'MediaTogglePlayPause': TerminalKey.mediaPlayPause, - 'HomePage': TerminalKey.browserHome, -// 'Favorites': TerminalKey.favorites, -// 'Search': TerminalKey.search, -// 'Standby': TerminalKey.standby, -// 'OpenUrl': TerminalKey.openUrl, -// 'LaunchMail': TerminalKey.launchMail, -// 'LaunchMedia': TerminalKey.launchMedia, -// 'Launch0': TerminalKey.launch0, -// 'Launch1': TerminalKey.launch1, -// 'Launch2': TerminalKey.launch2, -// 'Launch3': TerminalKey.launch3, -// 'Launch4': TerminalKey.launch4, -// 'Launch5': TerminalKey.launch5, -// 'Launch6': TerminalKey.launch6, -// 'Launch7': TerminalKey.launch7, -// 'Launch8': TerminalKey.launch8, -// 'Launch9': TerminalKey.launch9, -// 'LaunchA': TerminalKey.launchA, -// 'LaunchB': TerminalKey.launchB, -// 'LaunchC': TerminalKey.launchC, -// 'LaunchD': TerminalKey.launchD, -// 'LaunchE': TerminalKey.launchE, -// 'LaunchF': TerminalKey.launchF, -// 'LaunchG': TerminalKey.launchG, -// 'LaunchH': TerminalKey.launchH, - 'MonBrightnessUp': TerminalKey.brightnessUp, - 'MonBrightnessDown': TerminalKey.brightnessDown, -// 'KeyboardLightOnOff': TerminalKey.keyboardLightOnOff, -// 'KeyboardBrightnessUp': TerminalKey.keyboardBrightnessUp, -// 'KeyboardBrightnessDown': TerminalKey.keyboardBrightnessDown, - 'PowerOff': TerminalKey.power, - 'WakeUp': TerminalKey.wakeUp, - 'Eject': TerminalKey.eject, -// 'ScreenSaver': TerminalKey.screenSaver, -// 'WWW': TerminalKey.wWW, -// 'Memo': TerminalKey.memo, -// 'LightBulb': TerminalKey.lightBulb, -// 'Shop': TerminalKey.shop, -// 'History': TerminalKey.history, -// 'AddFavorite': TerminalKey.addFavorite, -// 'HotLinks': TerminalKey.hotLinks, -// 'BrightnessAdjust': TerminalKey.brightnessAdjust, -// 'Finance': TerminalKey.finance, -// 'Community': TerminalKey.community, -// 'AudioRewind': TerminalKey.audioRewind, -// 'BackForward': TerminalKey.backForward, -// 'ApplicationLeft': TerminalKey.applicationLeft, -// 'ApplicationRight': TerminalKey.applicationRight, -// 'Book': TerminalKey.book, -// 'CD': TerminalKey.cD, -// 'Calculator': TerminalKey.calculator, -// 'ToDoList': TerminalKey.toDoList, -// 'ClearGrab': TerminalKey.clearGrab, - 'Close': TerminalKey.close, - 'Copy': TerminalKey.copy, - 'Cut': TerminalKey.cut, -// 'Display': TerminalKey.display, -// 'DOS': TerminalKey.dOS, -// 'Documents': TerminalKey.documents, -// 'Excel': TerminalKey.excel, -// 'Explorer': TerminalKey.explorer, -// 'Game': TerminalKey.game, -// 'Go': TerminalKey.go, -// 'iTouch': TerminalKey.iTouch, -// 'LogOff': TerminalKey.logOff, -// 'Market': TerminalKey.market, -// 'Meeting': TerminalKey.meeting, -// 'MenuKB': TerminalKey.menuKB, -// 'MenuPB': TerminalKey.menuPB, -// 'MySites': TerminalKey.mySites, -// 'News': TerminalKey.news, -// 'OfficeHome': TerminalKey.officeHome, -// 'Option': TerminalKey.option, -// 'Paste': TerminalKey.paste, -// 'Phone': TerminalKey.phone, -// 'Calendar': TerminalKey.calendar, -// 'Reply': TerminalKey.reply, -// 'Reload': TerminalKey.reload, -// 'RotateWindows': TerminalKey.rotateWindows, -// 'RotationPB': TerminalKey.rotationPB, -// 'RotationKB': TerminalKey.rotationKB, - 'Save': TerminalKey.save, -// 'Send': TerminalKey.send, -// 'Spell': TerminalKey.spell, -// 'SplitScreen': TerminalKey.splitScreen, -// 'Support': TerminalKey.support, -// 'TaskPane': TerminalKey.taskPane, -// 'Terminal': TerminalKey.terminal, -// 'Tools': TerminalKey.tools, -// 'Travel': TerminalKey.travel, -// 'Video': TerminalKey.video, -// 'Word': TerminalKey.word, -// 'Xfer': TerminalKey.xfer, - 'ZoomIn': TerminalKey.zoomIn, - 'ZoomOut': TerminalKey.zoomOut, -// 'Away': TerminalKey.away, -// 'Messenger': TerminalKey.messenger, -// 'WebCam': TerminalKey.webCam, -// 'MailForward': TerminalKey.mailForward, -// 'Pictures': TerminalKey.pictures, -// 'Music': TerminalKey.music, -// 'Battery': TerminalKey.battery, -// 'Bluetooth': TerminalKey.bluetooth, -// 'WLAN': TerminalKey.wLAN, -// 'UWB': TerminalKey.uWB, -// 'AudioForward': TerminalKey.audioForward, -// 'AudioRepeat': TerminalKey.audioRepeat, -// 'AudioRandomPlay': TerminalKey.audioRandomPlay, -// 'Subtitle': TerminalKey.subtitle, -// 'AudioCycleTrack': TerminalKey.audioCycleTrack, -// 'Time': TerminalKey.time, -// 'Hibernate': TerminalKey.hibernate, -// 'View': TerminalKey.view, -// 'TopMenu': TerminalKey.topMenu, -// 'PowerDown': TerminalKey.powerDown, -// 'Suspend': TerminalKey.suspend, -// 'ContrastAdjust': TerminalKey.contrastAdjust, -// 'TouchpadToggle': TerminalKey.touchpadToggle, -// 'TouchpadOn': TerminalKey.touchpadOn, -// 'TouchpadOff': TerminalKey.touchpadOff, -// 'MicMute': TerminalKey.micMute, -// 'Red': TerminalKey.red, -// 'Green': TerminalKey.green, -// 'Yellow': TerminalKey.yellow, -// 'Blue': TerminalKey.blue, - 'ChannelUp': TerminalKey.channelUp, - 'ChannelDown': TerminalKey.channelDown, -// 'Guide': TerminalKey.guide, - 'Info': TerminalKey.info, -// 'Settings': TerminalKey.settings, -// 'MicVolumeUp': TerminalKey.micVolumeUp, -// 'MicVolumeDown': TerminalKey.micVolumeDown, -// 'New': TerminalKey.new, - 'Open': TerminalKey.open, - 'Find': TerminalKey.find, - 'Undo': TerminalKey.undo, - 'Redo': TerminalKey.redo, - 'MediaLast': TerminalKey.mediaLast, -// 'unknown': TerminalKey.unknown, -// 'Call': TerminalKey.call, -// 'Camera': TerminalKey.camera, -// 'CameraFocus': TerminalKey.cameraFocus, -// 'Context1': TerminalKey.context1, -// 'Context2': TerminalKey.context2, -// 'Context3': TerminalKey.context3, -// 'Context4': TerminalKey.context4, -// 'Flip': TerminalKey.flip, -// 'Hangup': TerminalKey.hangup, -// 'No': TerminalKey.no, - 'Select': TerminalKey.select, -// 'Yes': TerminalKey.yes, -// 'ToggleCallHangup': TerminalKey.toggleCallHangup, -// 'VoiceDial': TerminalKey.voiceDial, -// 'LastNumberRedial': TerminalKey.lastNumberRedial, -// 'Execute': TerminalKey.execute, -// 'Printer': TerminalKey.printer, -// 'Play': TerminalKey.play, - 'Sleep': TerminalKey.sleep, -// 'Zoom': TerminalKey.zoom, - 'Exit': TerminalKey.exit, -// 'Cancel': TerminalKey.cancel, -}; diff --git a/lib/src/core/mouse/button.dart b/lib/src/core/mouse/button.dart deleted file mode 100644 index 53dd08b0..00000000 --- a/lib/src/core/mouse/button.dart +++ /dev/null @@ -1,29 +0,0 @@ -enum TerminalMouseButton { - left(id: 0), - - middle(id: 1), - - right(id: 2), - - wheelUp(id: 64 + 4, isWheel: true), - - wheelDown(id: 64 + 5, isWheel: true), - - wheelLeft(id: 64 + 6, isWheel: true), - - wheelRight(id: 64 + 7, isWheel: true), - ; - - /// The id that is used to report a button press or release to the terminal. - /// - /// Mouse wheel up / down use button IDs 4 = 0100 (binary) and 5 = 0101 (binary). - /// The bits three and four of the button are transposed by 64 and 128 - /// respectively, when reporting the id of the button and have have to be - /// adjusted correspondingly. - final int id; - - /// Whether this button is a mouse wheel button. - final bool isWheel; - - const TerminalMouseButton({required this.id, this.isWheel = false}); -} diff --git a/lib/src/core/mouse/button_state.dart b/lib/src/core/mouse/button_state.dart deleted file mode 100644 index 9c8dc4c2..00000000 --- a/lib/src/core/mouse/button_state.dart +++ /dev/null @@ -1,5 +0,0 @@ -enum TerminalMouseButtonState { - up, - - down, -} diff --git a/lib/src/core/mouse/handler.dart b/lib/src/core/mouse/handler.dart deleted file mode 100644 index bb043886..00000000 --- a/lib/src/core/mouse/handler.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/mouse/button_state.dart'; -import 'package:xterm/src/core/mouse/mode.dart'; -import 'package:xterm/src/core/mouse/button.dart'; -import 'package:xterm/src/core/mouse/reporter.dart'; -import 'package:xterm/src/core/platform.dart'; -import 'package:xterm/src/core/state.dart'; - -class TerminalMouseEvent { - /// The button that is pressed or released. - final TerminalMouseButton button; - - /// The current state of the button. - final TerminalMouseButtonState buttonState; - - /// The position of button state change. - final CellOffset position; - - /// The state of the terminal. - final TerminalState state; - - /// The platform of the terminal. - final TerminalTargetPlatform platform; - - TerminalMouseEvent({ - required this.button, - required this.buttonState, - required this.position, - required this.state, - required this.platform, - }); -} - -const defaultMouseHandler = CascadeMouseHandler([ - ClickMouseHandler(), - UpDownMouseHandler(), -]); - -abstract class TerminalMouseHandler { - const TerminalMouseHandler(); - - String? call(TerminalMouseEvent event); -} - -class CascadeMouseHandler implements TerminalMouseHandler { - final List _handlers; - - const CascadeMouseHandler(this._handlers); - - @override - String? call(TerminalMouseEvent event) { - for (var handler in _handlers) { - final result = handler(event); - if (result != null) { - return result; - } - } - return null; - } -} - -class ClickMouseHandler implements TerminalMouseHandler { - const ClickMouseHandler(); - - @override - String? call(TerminalMouseEvent event) { - switch (event.state.mouseMode) { - case MouseMode.clickOnly: - // Only clicks and only the first 3 buttons are reported. - if (event.buttonState == TerminalMouseButtonState.down && - (event.button.id < 3)) { - return MouseReporter.report( - event.button, - event.buttonState, - event.position, - event.state.mouseReportMode, - ); - } - return null; - case MouseMode.none: - case MouseMode.upDownScroll: - case MouseMode.upDownScrollDrag: - case MouseMode.upDownScrollMove: - return null; - } - } -} - -class UpDownMouseHandler implements TerminalMouseHandler { - const UpDownMouseHandler(); - - @override - String? call(TerminalMouseEvent event) { - switch (event.state.mouseMode) { - case MouseMode.none: - case MouseMode.clickOnly: - return null; - case MouseMode.upDownScroll: - case MouseMode.upDownScrollDrag: - case MouseMode.upDownScrollMove: - // Up events are never reported for mouse wheel buttons. - if (event.button.isWheel && - event.buttonState == TerminalMouseButtonState.up) { - return null; - } - return MouseReporter.report( - event.button, - event.buttonState, - event.position, - event.state.mouseReportMode, - ); - } - } -} diff --git a/lib/src/core/mouse/mode.dart b/lib/src/core/mouse/mode.dart deleted file mode 100644 index ecd006b0..00000000 --- a/lib/src/core/mouse/mode.dart +++ /dev/null @@ -1,36 +0,0 @@ -/// https://terminalguide.namepad.de/mouse/ -enum MouseMode { - none, - - clickOnly, - - upDownScroll(reportScroll: true), - - upDownScrollDrag(reportScroll: true), - - upDownScrollMove(reportScroll: true), - ; - - const MouseMode({this.reportScroll = false}); - - final bool reportScroll; -} - -/// https://terminalguide.namepad.de/mouse/ -enum MouseReportMode { - /// The default mouse reporting mode where digits are encoded as bytes with - /// `32 + code`. This mode has a range from 1 to 223. - normal, - - /// When code < 96 this is the same as [normal], otherwise the `code + 32` is - /// encoded as 2 bytes in UTF-8. This mode has a range from 1 to 2015. - utf, - - /// In this mode the code are encoded as 10-based numbers. Tha range is - /// unlimited. - sgr, - - /// Similar to [sgr], the difference is that the button id is encoded as - /// `32 + code`. - urxvt, -} diff --git a/lib/src/core/mouse/reporter.dart b/lib/src/core/mouse/reporter.dart deleted file mode 100644 index 3417b634..00000000 --- a/lib/src/core/mouse/reporter.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/mouse/mode.dart'; -import 'package:xterm/src/core/mouse/button.dart'; -import 'package:xterm/src/core/mouse/button_state.dart'; - -abstract class MouseReporter { - static String report( - TerminalMouseButton button, - TerminalMouseButtonState state, - CellOffset position, - MouseReportMode reportMode, - ) { - // x and y offsets have to be incremented by 1 as the offset if 0-based, - // The position has to be reported using 1-based coordinates. - final x = position.x + 1; - final y = position.y + 1; - switch (reportMode) { - case MouseReportMode.normal: - case MouseReportMode.utf: - // Button ID 3 is used to signal a button release. - final buttonID = state == TerminalMouseButtonState.up ? 3 : button.id; - // The button ID is reported as shifted by 32 to produce a printable - // character. - final btn = String.fromCharCode(32 + buttonID); - // Normal mode only supports a maximum position of 223, while utf - // supports positions up to 2015. Both modes send a null byte if the - // position exceeds that limit. - final col = (reportMode == MouseReportMode.normal && x > 223) || - (reportMode == MouseReportMode.utf && x > 2015) - ? '\x00' - : String.fromCharCode(32 + x); - final row = (reportMode == MouseReportMode.normal && y > 223) || - (reportMode == MouseReportMode.utf && y > 2015) - ? '\x00' - : String.fromCharCode(32 + y + 1); - return "\x1b[M$btn$col$row"; - case MouseReportMode.sgr: - final buttonID = button.id; - final upDown = state == TerminalMouseButtonState.down ? 'M' : 'm'; - return "\x1b[<$buttonID;$x;$y$upDown"; - case MouseReportMode.urxvt: - // The button ID uses the same id as to report it as in normal mode. - final buttonID = - 32 + (state == TerminalMouseButtonState.up ? 3 : button.id); - return "\x1b[$buttonID;$x;${y}M"; - } - } -} diff --git a/lib/src/core/platform.dart b/lib/src/core/platform.dart deleted file mode 100644 index 3c955fd8..00000000 --- a/lib/src/core/platform.dart +++ /dev/null @@ -1,17 +0,0 @@ -enum TerminalTargetPlatform { - unknown, - - android, - - ios, - - fuchsia, - - linux, - - macos, - - windows, - - web, -} diff --git a/lib/src/core/reflow.dart b/lib/src/core/reflow.dart deleted file mode 100644 index 06e326e6..00000000 --- a/lib/src/core/reflow.dart +++ /dev/null @@ -1,197 +0,0 @@ -import 'package:xterm/src/core/buffer/line.dart'; -import 'package:xterm/src/utils/circular_buffer.dart'; - -class _LineBuilder { - _LineBuilder([this._capacity = 80]) { - _result = BufferLine(_capacity); - } - - final int _capacity; - - late BufferLine _result; - - int _length = 0; - - int get length => _length; - - bool get isEmpty => _length == 0; - - bool get isNotEmpty => _length != 0; - - /// Adds a range of cells from [src] to the builder. Anchors within the range - /// will be reparented to the new line returned by [take]. - void add(BufferLine src, int start, int length) { - _result.copyFrom(src, start, _length, length); - _length += length; - } - - /// Reuses the given [line] as the initial buffer for this builder. - void setBuffer(BufferLine line, int length) { - _result = line; - _length = length; - } - - void addAnchor(CellAnchor anchor, int offset) { - anchor.reparent(_result, _length + offset); - } - - BufferLine take({required bool wrapped}) { - final result = _result; - result.isWrapped = wrapped; - // result.resize(_length); - - _result = BufferLine(_capacity); - _length = 0; - - return result; - } -} - -/// Holds a the state of reflow operation of a single logical line. -class _LineReflow { - final int oldWidth; - - final int newWidth; - - _LineReflow(this.oldWidth, this.newWidth); - - final _lines = []; - - late final _builder = _LineBuilder(newWidth); - - /// Adds a line to the reflow operation. This method will try to reuse the - /// given line if possible. - void add(BufferLine line) { - final trimmedLength = line.getTrimmedLength(oldWidth); - - // A fast path for empty lines - if (trimmedLength == 0) { - _lines.add(line); - return; - } - - // We already have some content in the buffer, so we copy the content into - // the builder instead of reusing the line. - if (_lines.isNotEmpty || _builder.isNotEmpty) { - _addPart(line, from: 0, to: trimmedLength); - return; - } - - if (newWidth >= oldWidth) { - // Reuse the line to avoid copying the content and object allocation. - _builder.setBuffer(line, trimmedLength); - } else { - _lines.add(line); - - if (trimmedLength > newWidth) { - if (line.getWidth(newWidth - 1) == 2) { - _addPart(line, from: newWidth - 1, to: trimmedLength); - } else { - _addPart(line, from: newWidth, to: trimmedLength); - } - } - } - - line.resize(newWidth); - - if (line.getWidth(newWidth - 1) == 2) { - line.resetCell(newWidth - 1); - } - } - - /// Adds part of [line] from [from] to [to] to the reflow operation. - /// Anchors within the range will be removed from [line] and reparented to - /// the new line(s) returned by [finish]. - void _addPart(BufferLine line, {required int from, required int to}) { - var cellsLeft = to - from; - - while (cellsLeft > 0) { - final bufferRemainingCells = newWidth - _builder.length; - - // How many cells we should copy in this iteration. - var cellsToCopy = cellsLeft; - - // Whether the buffer is filled up in this iteration. - var lineFilled = false; - - if (cellsToCopy >= bufferRemainingCells) { - cellsToCopy = bufferRemainingCells; - lineFilled = true; - } - - // Leave the last cell to the next iteration if it's a wide char. - if (lineFilled && line.getWidth(from + cellsToCopy - 1) == 2) { - cellsToCopy--; - } - - for (var anchor in line.anchors.toList()) { - if (anchor.x >= from && anchor.x <= from + cellsToCopy) { - _builder.addAnchor(anchor, anchor.x - from); - } - } - - _builder.add(line, from, cellsToCopy); - - from += cellsToCopy; - cellsLeft -= cellsToCopy; - - // Create a new line if the buffer is filled up. - if (lineFilled) { - _lines.add(_builder.take(wrapped: _lines.isNotEmpty)); - } - } - - if (line.anchors.isNotEmpty) { - for (var anchor in line.anchors.toList()) { - if (anchor.x >= to) { - _builder.addAnchor(anchor, anchor.x - to); - } - } - } - } - - /// Finalizes the reflow operation and returns the result. - List finish() { - if (_builder.isNotEmpty) { - _lines.add(_builder.take(wrapped: _lines.isNotEmpty)); - } - - return _lines; - } -} - -List reflow( - IndexAwareCircularBuffer lines, - int oldWidth, - int newWidth, -) { - final result = []; - - for (var i = 0; i < lines.length; i++) { - final line = lines[i]; - - final reflow = _LineReflow(oldWidth, newWidth); - - reflow.add(line); - - for (var offset = i + 1; offset < lines.length; offset++) { - final nextLine = lines[offset]; - - if (!nextLine.isWrapped) { - break; - } - - i++; - - reflow.add(nextLine); - } - - result.addAll(reflow.finish()); - } - - for (var line in result) { - line.resize(newWidth); - } - - return result; -} diff --git a/lib/src/core/snapshot.dart b/lib/src/core/snapshot.dart deleted file mode 100644 index 319fc4a2..00000000 --- a/lib/src/core/snapshot.dart +++ /dev/null @@ -1,3 +0,0 @@ -abstract class TerminalSnapshot { - void trimScrollback(); -} diff --git a/lib/src/core/state.dart b/lib/src/core/state.dart deleted file mode 100644 index 85684f86..00000000 --- a/lib/src/core/state.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:xterm/src/core/cursor.dart'; -import 'package:xterm/src/core/mouse/mode.dart'; - -abstract class TerminalState { - int get viewWidth; - - int get viewHeight; - - CursorStyle get cursor; - - bool get reflowEnabled; - - /* Modes */ - - bool get insertMode; - - bool get lineFeedMode; - - /* DEC Private modes */ - - bool get cursorKeysMode; - - bool get reverseDisplayMode; - - bool get originMode; - - bool get autoWrapMode; - - MouseMode get mouseMode; - - MouseReportMode get mouseReportMode; - - bool get cursorBlinkMode; - - bool get cursorVisibleMode; - - bool get appKeypadMode; - - bool get reportFocusMode; - - bool get altBufferMouseScrollMode; - - bool get bracketedPasteMode; -} diff --git a/lib/src/core/tabs.dart b/lib/src/core/tabs.dart deleted file mode 100644 index 385f9499..00000000 --- a/lib/src/core/tabs.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'dart:math' show min; - -const _kMaxColumns = 1024; - -/// Manages the tab stop state for a terminal. -class TabStops { - final _stops = List.filled(_kMaxColumns, false); - - TabStops() { - _initialize(); - } - - /// Initializes the tab stops to the default 8 column intervals. - void _initialize() { - const interval = 8; - for (var i = 0; i < _kMaxColumns; i += interval) { - _stops[i] = true; - } - } - - /// Finds the next tab stop index, which satisfies [start] <= index < [end]. - int? find(int start, int end) { - if (start >= end) { - return null; - } - end = min(end, _stops.length); - for (var i = start; i < end; i++) { - if (_stops[i]) { - return i; - } - } - return null; - } - - /// Sets the tab stop at [index]. If there is already a tab stop at [index], - /// this method does nothing. - /// - /// See also: - /// * [clearAt] which does the opposite. - void setAt(int index) { - assert(index >= 0 && index < _kMaxColumns); - _stops[index] = true; - } - - /// Clears the tab stop at [index]. If there is no tab stop at [index], this - /// method does nothing. - void clearAt(int index) { - assert(index >= 0 && index < _kMaxColumns); - _stops[index] = false; - } - - /// Clears all tab stops without resetting them to the default 8 column - /// intervals. - void clearAll() { - _stops.fillRange(0, _kMaxColumns, false); - } - - /// Returns true if there is a tab stop at [index]. - bool isSetAt(int index) { - return _stops[index]; - } - - /// Resets the tab stops to the default 8 column intervals. - void reset() { - clearAll(); - _initialize(); - } -} diff --git a/lib/src/terminal.dart b/lib/src/terminal.dart deleted file mode 100644 index 461e2084..00000000 --- a/lib/src/terminal.dart +++ /dev/null @@ -1,906 +0,0 @@ -import 'dart:math' show max; - -import 'package:xterm/src/base/observable.dart'; -import 'package:xterm/src/core/buffer/buffer.dart'; -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/buffer/line.dart'; -import 'package:xterm/src/core/cursor.dart'; -import 'package:xterm/src/core/escape/emitter.dart'; -import 'package:xterm/src/core/escape/handler.dart'; -import 'package:xterm/src/core/escape/parser.dart'; -import 'package:xterm/src/core/input/handler.dart'; -import 'package:xterm/src/core/input/keys.dart'; -import 'package:xterm/src/core/mouse/button.dart'; -import 'package:xterm/src/core/mouse/button_state.dart'; -import 'package:xterm/src/core/mouse/handler.dart'; -import 'package:xterm/src/core/mouse/mode.dart'; -import 'package:xterm/src/core/platform.dart'; -import 'package:xterm/src/core/state.dart'; -import 'package:xterm/src/core/tabs.dart'; -import 'package:xterm/src/utils/ascii.dart'; -import 'package:xterm/src/utils/circular_buffer.dart'; - -/// [Terminal] is an interface to interact with command line applications. It -/// translates escape sequences from the application into updates to the -/// [buffer] and events such as [onTitleChange] or [onBell], as well as -/// translating user input into escape sequences that the application can -/// understand. -class Terminal with Observable implements TerminalState, EscapeHandler { - /// The number of lines that the scrollback buffer can hold. If the buffer - /// exceeds this size, the lines at the top of the buffer will be removed. - final int maxLines; - - /// Function that is called when the program requests the terminal to ring - /// the bell. If not set, the terminal will do nothing. - void Function()? onBell; - - /// Function that is called when the program requests the terminal to change - /// the title of the window to [title]. - void Function(String title)? onTitleChange; - - /// Function that is called when the program requests the terminal to change - /// the icon of the window. [icon] is the name of the icon. - void Function(String icon)? onIconChange; - - /// Function that is called when the terminal emits data to the underlying - /// program. This is typically caused by user inputs from [textInput], - /// [keyInput], [mouseInput], or [paste]. - void Function(String data)? onOutput; - - /// Function that is called when the dimensions of the terminal change. - void Function(int width, int height, int pixelWidth, int pixelHeight)? - onResize; - - /// The [TerminalInputHandler] used by this terminal. [defaultInputHandler] is - /// used when not specified. User of this class can provide their own - /// implementation of [TerminalInputHandler] or extend [defaultInputHandler] - /// with [CascadeInputHandler]. - TerminalInputHandler? inputHandler; - - TerminalMouseHandler? mouseHandler; - - /// The callback that is called when the terminal receives a unrecognized - /// escape sequence. - void Function(String code, List args)? onPrivateOSC; - - /// Flag to toggle os specific behaviors. - final TerminalTargetPlatform platform; - - /// Characters that break selection when double clicking. If not set, the - /// [Buffer.defaultWordSeparators] will be used. - final Set? wordSeparators; - - Terminal({ - this.maxLines = 1000, - this.onBell, - this.onTitleChange, - this.onIconChange, - this.onOutput, - this.onResize, - this.platform = TerminalTargetPlatform.unknown, - this.inputHandler = defaultInputHandler, - this.mouseHandler = defaultMouseHandler, - this.onPrivateOSC, - this.reflowEnabled = true, - this.wordSeparators, - }); - - late final _parser = EscapeParser(this); - - final _emitter = const EscapeEmitter(); - - late var _buffer = _mainBuffer; - - late final _mainBuffer = Buffer( - this, - maxLines: maxLines, - isAltBuffer: false, - wordSeparators: wordSeparators, - ); - - late final _altBuffer = Buffer( - this, - maxLines: maxLines, - isAltBuffer: true, - wordSeparators: wordSeparators, - ); - - final _tabStops = TabStops(); - - /// The last character written to the buffer. Used to implement some escape - /// sequences that repeat the last character. - var _precedingCodepoint = 0; - - /* TerminalState */ - - int _viewWidth = 80; - - int _viewHeight = 24; - - final _cursorStyle = CursorStyle(); - - bool _insertMode = false; - - bool _lineFeedMode = false; - - bool _cursorKeysMode = false; - - bool _reverseDisplayMode = false; - - bool _originMode = false; - - bool _autoWrapMode = true; - - MouseMode _mouseMode = MouseMode.none; - - MouseReportMode _mouseReportMode = MouseReportMode.normal; - - bool _cursorBlinkMode = false; - - bool _cursorVisibleMode = true; - - bool _appKeypadMode = false; - - bool _reportFocusMode = false; - - bool _altBufferMouseScrollMode = false; - - bool _bracketedPasteMode = false; - - /* State getters */ - - /// Number of cells in a terminal row. - @override - int get viewWidth => _viewWidth; - - /// Number of rows in this terminal. - @override - int get viewHeight => _viewHeight; - - @override - CursorStyle get cursor => _cursorStyle; - - @override - bool get insertMode => _insertMode; - - @override - bool get lineFeedMode => _lineFeedMode; - - @override - bool get cursorKeysMode => _cursorKeysMode; - - @override - bool get reverseDisplayMode => _reverseDisplayMode; - - @override - bool get originMode => _originMode; - - @override - bool get autoWrapMode => _autoWrapMode; - - @override - MouseMode get mouseMode => _mouseMode; - - @override - MouseReportMode get mouseReportMode => _mouseReportMode; - - @override - bool get cursorBlinkMode => _cursorBlinkMode; - - @override - bool get cursorVisibleMode => _cursorVisibleMode; - - @override - bool get appKeypadMode => _appKeypadMode; - - @override - bool get reportFocusMode => _reportFocusMode; - - @override - bool get altBufferMouseScrollMode => _altBufferMouseScrollMode; - - @override - bool get bracketedPasteMode => _bracketedPasteMode; - - /// Current active buffer of the terminal. This is initially [mainBuffer] and - /// can be switched back and forth from [altBuffer] to [mainBuffer] when - /// the underlying program requests it. - Buffer get buffer => _buffer; - - Buffer get mainBuffer => _mainBuffer; - - Buffer get altBuffer => _altBuffer; - - bool get isUsingAltBuffer => _buffer == _altBuffer; - - /// Lines of the active buffer. - IndexAwareCircularBuffer get lines => _buffer.lines; - - /// Whether the terminal performs reflow when the viewport size changes or - /// simply truncates lines. true by default. - @override - bool reflowEnabled; - - /// Writes the data from the underlying program to the terminal. Calling this - /// updates the states of the terminal and emits events such as [onBell] or - /// [onTitleChange] when the escape sequences in [data] request it. - void write(String data) { - _parser.write(data); - notifyListeners(); - } - - /// Sends a key event to the underlying program. - /// - /// See also: - /// - [charInput] - /// - [textInput] - /// - [paste] - bool keyInput( - TerminalKey key, { - bool shift = false, - bool alt = false, - bool ctrl = false, - }) { - final output = inputHandler?.call( - TerminalKeyboardEvent( - key: key, - shift: shift, - alt: alt, - ctrl: ctrl, - state: this, - altBuffer: isUsingAltBuffer, - platform: platform, - ), - ); - - if (output != null) { - onOutput?.call(output); - return true; - } - - return false; - } - - /// Similary to [keyInput], but takes a character as input instead of a - /// [TerminalKey]. - /// - /// See also: - /// - [keyInput] - /// - [textInput] - /// - [paste] - bool charInput( - int charCode, { - bool alt = false, - bool ctrl = false, - }) { - if (ctrl) { - // a(97) ~ z(122) - if (charCode >= Ascii.a && charCode <= Ascii.z) { - final output = charCode - Ascii.a + 1; - onOutput?.call(String.fromCharCode(output)); - return true; - } - - // [(91) ~ _(95) - if (charCode >= Ascii.openBracket && charCode <= Ascii.underscore) { - final output = charCode - Ascii.openBracket + 27; - onOutput?.call(String.fromCharCode(output)); - return true; - } - } - - if (alt && platform != TerminalTargetPlatform.macos) { - if (charCode >= Ascii.a && charCode <= Ascii.z) { - final code = charCode - Ascii.a + 65; - final input = [0x1b, code]; - onOutput?.call(String.fromCharCodes(input)); - return true; - } - } - - return false; - } - - /// Sends regular text input to the underlying program. - /// - /// See also: - /// - [keyInput] - /// - [charInput] - /// - [paste] - void textInput(String text) { - onOutput?.call(text); - } - - /// Similar to [textInput], except that when the program tells the terminal - /// that it supports [bracketedPasteMode], the text is wrapped in escape - /// sequences to indicate that it is a paste operation. Prefer this method - /// over [textInput] when pasting text. - /// - /// See also: - /// - [textInput] - void paste(String text) { - if (_bracketedPasteMode) { - onOutput?.call(_emitter.bracketedPaste(text)); - } else { - textInput(text); - } - } - - // Handle a mouse event and return true if it was handled. - bool mouseInput( - TerminalMouseButton button, - TerminalMouseButtonState buttonState, - CellOffset position, - ) { - final output = mouseHandler?.call(TerminalMouseEvent( - button: button, - buttonState: buttonState, - position: position, - state: this, - platform: platform, - )); - if (output != null) { - onOutput?.call(output); - return true; - } - return false; - } - - /// Resize the terminal screen. [newWidth] and [newHeight] should be greater - /// than 0. Text reflow is currently not implemented and will be avaliable in - /// the future. - @override - void resize( - int newWidth, - int newHeight, [ - int? pixelWidth, - int? pixelHeight, - ]) { - newWidth = max(newWidth, 1); - newHeight = max(newHeight, 1); - - onResize?.call(newWidth, newHeight, pixelWidth ?? 0, pixelHeight ?? 0); - - //we need to resize both buffers so that they are ready when we switch between them - _altBuffer.resize(_viewWidth, _viewHeight, newWidth, newHeight); - _mainBuffer.resize(_viewWidth, _viewHeight, newWidth, newHeight); - - _viewWidth = newWidth; - _viewHeight = newHeight; - - if (buffer == _altBuffer) { - buffer.clearScrollback(); - } - - _altBuffer.resetVerticalMargins(); - _mainBuffer.resetVerticalMargins(); - } - - @override - String toString() { - return 'Terminal(#$hashCode, $_viewWidth x $_viewHeight, ${_buffer.height} lines)'; - } - - /* Handlers */ - - @override - void writeChar(int char) { - _precedingCodepoint = char; - _buffer.writeChar(char); - } - - /* SBC */ - - @override - void bell() { - onBell?.call(); - } - - @override - void backspaceReturn() { - _buffer.moveCursorX(-1); - } - - @override - void tab() { - final nextStop = _tabStops.find(_buffer.cursorX + 1, _viewWidth); - - if (nextStop != null) { - _buffer.setCursorX(nextStop); - } else { - _buffer.setCursorX(_viewWidth); - _buffer.cursorGoForward(); // Enter pending-wrap state - } - } - - @override - void lineFeed() { - _buffer.lineFeed(); - } - - @override - void carriageReturn() { - _buffer.setCursorX(0); - } - - @override - void shiftOut() { - _buffer.charset.use(1); - } - - @override - void shiftIn() { - _buffer.charset.use(0); - } - - @override - void unknownSBC(int char) { - // no-op - } - - /* ANSI sequence */ - - @override - void saveCursor() { - _buffer.saveCursor(); - } - - @override - void restoreCursor() { - _buffer.restoreCursor(); - } - - @override - void index() { - _buffer.index(); - } - - @override - void nextLine() { - _buffer.index(); - _buffer.setCursorX(0); - } - - @override - void setTapStop() { - _tabStops.isSetAt(_buffer.cursorX); - } - - @override - void reverseIndex() { - _buffer.reverseIndex(); - } - - @override - void designateCharset(int charset, int name) { - _buffer.charset.designate(charset, name); - } - - @override - void unkownEscape(int char) { - // no-op - } - - /* CSI */ - - @override - void repeatPreviousCharacter(int count) { - if (_precedingCodepoint == 0) { - return; - } - - for (var i = 0; i < count; i++) { - _buffer.writeChar(_precedingCodepoint); - } - } - - @override - void setCursor(int x, int y) { - _buffer.setCursor(x, y); - } - - @override - void setCursorX(int x) { - _buffer.setCursorX(x); - } - - @override - void setCursorY(int y) { - _buffer.setCursorY(y); - } - - @override - void moveCursorX(int offset) { - _buffer.moveCursorX(offset); - } - - @override - void moveCursorY(int n) { - _buffer.moveCursorY(n); - } - - @override - void clearTabStopUnderCursor() { - _tabStops.clearAt(_buffer.cursorX); - } - - @override - void clearAllTabStops() { - _tabStops.clearAll(); - } - - @override - void sendPrimaryDeviceAttributes() { - onOutput?.call(_emitter.primaryDeviceAttributes()); - } - - @override - void sendSecondaryDeviceAttributes() { - onOutput?.call(_emitter.secondaryDeviceAttributes()); - } - - @override - void sendTertiaryDeviceAttributes() { - onOutput?.call(_emitter.tertiaryDeviceAttributes()); - } - - @override - void sendOperatingStatus() { - onOutput?.call(_emitter.operatingStatus()); - } - - @override - void sendCursorPosition() { - onOutput?.call(_emitter.cursorPosition(_buffer.cursorX, _buffer.cursorY)); - } - - @override - void setMargins(int top, [int? bottom]) { - _buffer.setVerticalMargins(top, bottom ?? viewHeight - 1); - } - - @override - void cursorNextLine(int amount) { - _buffer.moveCursorY(amount); - _buffer.setCursorX(0); - } - - @override - void cursorPrecedingLine(int amount) { - _buffer.moveCursorY(-amount); - _buffer.setCursorX(0); - } - - @override - void eraseDisplayBelow() { - _buffer.eraseDisplayFromCursor(); - } - - @override - void eraseDisplayAbove() { - _buffer.eraseDisplayToCursor(); - } - - @override - void eraseDisplay() { - _buffer.eraseDisplay(); - } - - @override - void eraseScrollbackOnly() { - _buffer.clearScrollback(); - } - - @override - void eraseLineRight() { - _buffer.eraseLineFromCursor(); - } - - @override - void eraseLineLeft() { - _buffer.eraseLineToCursor(); - } - - @override - void eraseLine() { - _buffer.eraseLine(); - } - - @override - void insertLines(int amount) { - _buffer.insertLines(amount); - } - - @override - void deleteLines(int amount) { - _buffer.deleteLines(amount); - } - - @override - void deleteChars(int amount) { - _buffer.deleteChars(amount); - } - - @override - void scrollUp(int amount) { - _buffer.scrollUp(amount); - } - - @override - void scrollDown(int amount) { - _buffer.scrollDown(amount); - } - - @override - void eraseChars(int amount) { - _buffer.eraseChars(amount); - } - - @override - void insertBlankChars(int amount) { - _buffer.insertBlankChars(amount); - } - - @override - void sendSize() { - onOutput?.call(_emitter.size(viewHeight, viewWidth)); - } - - @override - void unknownCSI(int finalByte) { - // no-op - } - - /* Modes */ - - @override - void setInsertMode(bool enabled) { - _insertMode = enabled; - } - - @override - void setLineFeedMode(bool enabled) { - _lineFeedMode = enabled; - } - - @override - void setUnknownMode(int mode, bool enabled) { - // no-op - } - - /* DEC Private modes */ - - @override - void setCursorKeysMode(bool enabled) { - _cursorKeysMode = enabled; - } - - @override - void setReverseDisplayMode(bool enabled) { - _reverseDisplayMode = enabled; - } - - @override - void setOriginMode(bool enabled) { - _originMode = enabled; - } - - @override - void setColumnMode(bool enabled) { - // no-op - } - - @override - void setAutoWrapMode(bool enabled) { - _autoWrapMode = enabled; - } - - @override - void setMouseMode(MouseMode mode) { - _mouseMode = mode; - } - - @override - void setCursorBlinkMode(bool enabled) { - _cursorBlinkMode = enabled; - } - - @override - void setCursorVisibleMode(bool enabled) { - _cursorVisibleMode = enabled; - } - - @override - void useAltBuffer() { - _buffer = _altBuffer; - } - - @override - void useMainBuffer() { - _buffer = _mainBuffer; - } - - @override - void clearAltBuffer() { - _altBuffer.clear(); - } - - @override - void setAppKeypadMode(bool enabled) { - _appKeypadMode = enabled; - } - - @override - void setReportFocusMode(bool enabled) { - _reportFocusMode = enabled; - } - - @override - void setMouseReportMode(MouseReportMode mode) { - _mouseReportMode = mode; - } - - @override - void setAltBufferMouseScrollMode(bool enabled) { - _altBufferMouseScrollMode = enabled; - } - - @override - void setBracketedPasteMode(bool enabled) { - _bracketedPasteMode = enabled; - } - - @override - void setUnknownDecMode(int mode, bool enabled) { - // no-op - } - - /* Select Graphic Rendition (SGR) */ - - @override - void resetCursorStyle() { - _cursorStyle.reset(); - } - - @override - void setCursorBold() { - _cursorStyle.setBold(); - } - - @override - void setCursorFaint() { - _cursorStyle.setFaint(); - } - - @override - void setCursorItalic() { - _cursorStyle.setItalic(); - } - - @override - void setCursorUnderline() { - _cursorStyle.setUnderline(); - } - - @override - void setCursorBlink() { - _cursorStyle.setBlink(); - } - - @override - void setCursorInverse() { - _cursorStyle.setInverse(); - } - - @override - void setCursorInvisible() { - _cursorStyle.setInvisible(); - } - - @override - void setCursorStrikethrough() { - _cursorStyle.setStrikethrough(); - } - - @override - void unsetCursorBold() { - _cursorStyle.unsetBold(); - } - - @override - void unsetCursorFaint() { - _cursorStyle.unsetFaint(); - } - - @override - void unsetCursorItalic() { - _cursorStyle.unsetItalic(); - } - - @override - void unsetCursorUnderline() { - _cursorStyle.unsetUnderline(); - } - - @override - void unsetCursorBlink() { - _cursorStyle.unsetBlink(); - } - - @override - void unsetCursorInverse() { - _cursorStyle.unsetInverse(); - } - - @override - void unsetCursorInvisible() { - _cursorStyle.unsetInvisible(); - } - - @override - void unsetCursorStrikethrough() { - _cursorStyle.unsetStrikethrough(); - } - - @override - void setForegroundColor16(int color) { - _cursorStyle.setForegroundColor16(color); - } - - @override - void setForegroundColor256(int index) { - _cursorStyle.setForegroundColor256(index); - } - - @override - void setForegroundColorRgb(int r, int g, int b) { - _cursorStyle.setForegroundColorRgb(r, g, b); - } - - @override - void resetForeground() { - _cursorStyle.resetForegroundColor(); - } - - @override - void setBackgroundColor16(int color) { - _cursorStyle.setBackgroundColor16(color); - } - - @override - void setBackgroundColor256(int index) { - _cursorStyle.setBackgroundColor256(index); - } - - @override - void setBackgroundColorRgb(int r, int g, int b) { - _cursorStyle.setBackgroundColorRgb(r, g, b); - } - - @override - void resetBackground() { - _cursorStyle.resetBackgroundColor(); - } - - @override - void unsupportedStyle(int param) { - // no-op - } - - /* OSC */ - - @override - void setTitle(String name) { - onTitleChange?.call(name); - } - - @override - void setIconName(String name) { - onIconChange?.call(name); - } - - @override - void unknownOSC(String ps, List pt) { - onPrivateOSC?.call(ps, pt); - } -} diff --git a/lib/src/terminal_view.dart b/lib/src/terminal_view.dart index d5f519f5..86cbf2cf 100644 --- a/lib/src/terminal_view.dart +++ b/lib/src/terminal_view.dart @@ -2,9 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/input/keys.dart'; -import 'package:xterm/src/terminal.dart'; +import 'package:xterm_core/xterm_core.dart'; import 'package:xterm/src/ui/controller.dart'; import 'package:xterm/src/ui/cursor_type.dart'; import 'package:xterm/src/ui/custom_text_edit.dart'; @@ -162,7 +160,8 @@ class TerminalViewState extends State { late ScrollController _scrollController; - RenderTerminal get renderTerminal => _viewportKey.currentContext!.findRenderObject() as RenderTerminal; + RenderTerminal get renderTerminal => + _viewportKey.currentContext!.findRenderObject() as RenderTerminal; @override void initState() { @@ -264,7 +263,8 @@ class TerminalViewState extends State { onAction: (action) { _scrollToBottom(); // Android sends TextInputAction.newline when the user presses the virtual keyboard's enter key. - if (action == TextInputAction.done || action == TextInputAction.newline) { + if (action == TextInputAction.done || + action == TextInputAction.newline) { widget.terminal.keyInput(TerminalKey.enter); } }, @@ -300,8 +300,10 @@ class TerminalViewState extends State { terminalController: _controller, onTapUp: _onTapUp, onTapDown: _onTapDown, - onSecondaryTapDown: widget.onSecondaryTapDown != null ? _onSecondaryTapDown : null, - onSecondaryTapUp: widget.onSecondaryTapUp != null ? _onSecondaryTapUp : null, + onSecondaryTapDown: + widget.onSecondaryTapDown != null ? _onSecondaryTapDown : null, + onSecondaryTapUp: + widget.onSecondaryTapUp != null ? _onSecondaryTapUp : null, readOnly: widget.readOnly, child: child, ); @@ -333,7 +335,8 @@ class TerminalViewState extends State { } Rect get globalCursorRect { - return renderTerminal.localToGlobal(renderTerminal.cursorOffset) & renderTerminal.cellSize; + return renderTerminal.localToGlobal(renderTerminal.cursorOffset) & + renderTerminal.cellSize; } void _onTapUp(TapUpDetails details) { diff --git a/lib/src/ui/controller.dart b/lib/src/ui/controller.dart index 1e107c2d..4479b37e 100644 --- a/lib/src/ui/controller.dart +++ b/lib/src/ui/controller.dart @@ -1,11 +1,6 @@ import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; -import 'package:xterm/src/base/disposable.dart'; -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/buffer/line.dart'; -import 'package:xterm/src/core/buffer/range.dart'; -import 'package:xterm/src/core/buffer/range_block.dart'; -import 'package:xterm/src/core/buffer/range_line.dart'; +import 'package:xterm_core/xterm_core.dart'; import 'package:xterm/src/ui/pointer_input.dart'; import 'package:xterm/src/ui/selection_mode.dart'; diff --git a/lib/src/ui/gesture/gesture_handler.dart b/lib/src/ui/gesture/gesture_handler.dart index 2f6d7b69..1239c7ce 100644 --- a/lib/src/ui/gesture/gesture_handler.dart +++ b/lib/src/ui/gesture/gesture_handler.dart @@ -1,7 +1,6 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/widgets.dart'; -import 'package:xterm/src/core/mouse/button.dart'; -import 'package:xterm/src/core/mouse/button_state.dart'; +import 'package:xterm_core/xterm_core.dart'; import 'package:xterm/src/terminal_view.dart'; import 'package:xterm/src/ui/controller.dart'; import 'package:xterm/src/ui/gesture/gesture_detector.dart'; diff --git a/lib/src/ui/input_map.dart b/lib/src/ui/input_map.dart index 3f65d1d1..e48916ca 100644 --- a/lib/src/ui/input_map.dart +++ b/lib/src/ui/input_map.dart @@ -1,5 +1,5 @@ import 'package:flutter/services.dart'; -import 'package:xterm/src/core/input/keys.dart'; +import 'package:xterm_core/xterm_core.dart'; final _keyToTerminalKey = { LogicalKeyboardKey.hyper: TerminalKey.hyper, diff --git a/lib/src/ui/palette_builder.dart b/lib/src/ui/palette_builder.dart index 4e098659..334aa4c8 100644 --- a/lib/src/ui/palette_builder.dart +++ b/lib/src/ui/palette_builder.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; import 'package:xterm/src/ui/terminal_theme.dart'; -import 'package:xterm/src/utils/lookup_table.dart'; +import 'package:xterm_core/xterm_core.dart'; class PaletteBuilder { final TerminalTheme theme; diff --git a/lib/src/ui/render.dart b/lib/src/ui/render.dart index de2a2f7f..1c592d08 100644 --- a/lib/src/ui/render.dart +++ b/lib/src/ui/render.dart @@ -3,12 +3,7 @@ import 'dart:ui'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; -import 'package:xterm/src/core/buffer/cell_offset.dart'; -import 'package:xterm/src/core/buffer/range.dart'; -import 'package:xterm/src/core/buffer/segment.dart'; -import 'package:xterm/src/core/mouse/button.dart'; -import 'package:xterm/src/core/mouse/button_state.dart'; -import 'package:xterm/src/terminal.dart'; +import 'package:xterm_core/xterm_core.dart'; import 'package:xterm/src/ui/controller.dart'; import 'package:xterm/src/ui/cursor_type.dart'; import 'package:xterm/src/ui/painter.dart'; diff --git a/lib/src/ui/scroll_handler.dart b/lib/src/ui/scroll_handler.dart index d0ad9a8d..2ebb7381 100644 --- a/lib/src/ui/scroll_handler.dart +++ b/lib/src/ui/scroll_handler.dart @@ -1,5 +1,5 @@ import 'package:flutter/widgets.dart'; -import 'package:xterm/core.dart'; +import 'package:xterm_core/xterm_core.dart'; import 'package:xterm/src/ui/infinite_scroll_view.dart'; /// Handles scrolling gestures in the alternate screen buffer. In alternate diff --git a/lib/src/ui/shortcut/actions.dart b/lib/src/ui/shortcut/actions.dart index a06670b7..bdc8316b 100644 --- a/lib/src/ui/shortcut/actions.dart +++ b/lib/src/ui/shortcut/actions.dart @@ -1,6 +1,6 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:xterm/src/terminal.dart'; +import 'package:xterm_core/xterm_core.dart'; import 'package:xterm/src/ui/controller.dart'; import 'package:xterm/src/ui/selection_mode.dart'; diff --git a/lib/src/utils/ascii.dart b/lib/src/utils/ascii.dart deleted file mode 100644 index b5a67ab6..00000000 --- a/lib/src/utils/ascii.dart +++ /dev/null @@ -1,403 +0,0 @@ -// ignore_for_file: constant_identifier_names - -abstract class Ascii { - /* - * Helper functions - */ - - static bool isNonPrintable(int c) { - return c < 32 || c == 127; - } - - /* - * Non-printable ASCII characters - */ - - /// Null character - static const NULL = 00; - - /// Start of Header - static const SOH = 01; - - /// Start of Text - static const STX = 02; - - /// End of Text, hearts card suit - static const ETX = 03; - - /// End of Transmission, diamonds card suit - static const EOT = 04; - - /// Enquiry, clubs card suit - static const ENQ = 05; - - /// Acknowledgement, spade card suit - static const ACK = 06; - - /// Bell - static const BEL = 07; - - /// Backspace - static const BS = 08; - - /// Horizontal Tab - static const HT = 09; - - /// Line feed - static const LF = 10; - - /// Vertical Tab, male symbol, symbol for Mars - static const VT = 11; - - /// Form feed, female symbol, symbol for Venus - static const FF = 12; - - /// Carriage return - static const CR = 13; - - /// Shift Out - static const SO = 14; - - /// Shift In - static const SI = 15; - - /// Data link escape - static const DLE = 16; - - /// Device control 1 - static const DC1 = 17; - - /// Device control 2 - static const DC2 = 18; - - /// Device control 3 - static const DC3 = 19; - - /// Device control 4 - static const DC4 = 20; - - /// NAK Negative-acknowledge - static const NAK = 21; - - /// Synchronous idle - static const SYN = 22; - - /// End of trans. block - static const ETB = 23; - - /// Cancel - static const CAN = 24; - - /// End of medium - static const EM = 25; - - /// Substitute - static const SUB = 26; - - /// Escape - static const ESC = 27; - - /// File separator - static const FS = 28; - - /// Group separator - static const GS = 29; - - /// Record separator - static const RS = 30; - - /// Unit separator - static const US = 31; - - /// Delete - static const DEL = 127; - - /* - * Printable ASCII characters - */ - - /// Space " " - static const space = 32; - - /// Exclamation mark "!" - static const exclamationMark = 33; - - /// Double quotes '"' - static const doubleQuotes = 34; - - /// Number sign '#' - static const numberSign = 35; - - /// Dollar sign '$' - static const dollarSign = 36; - - /// Percent sign '%' - static const percentSign = 37; - - /// Ampersand '&' - static const ampersand = 38; - - /// Single quote "'" - static const singleQuote = 39; - - /// round brackets or parentheses, opening round bracket '(' - static const openParentheses = 40; - - /// parentheses or round brackets, closing parentheses ')' - static const closeParentheses = 41; - - /// Asterisk '*' - static const asterisk = 42; - - /// Plus sign '+' - static const plus = 43; - - /// Comma "," - static const comma = 44; - - /// Hyphen , minus sign '-' - static const minus = 45; - - /// Dot, full stop '.' - static const dot = 46; - - /// Slash , forward slash , fraction bar , division slash '/' - static const slash = 47; - - /// number zero - static const num0 = 48; - - /// number one - static const num1 = 49; - - /// number two - static const num2 = 50; - - /// number three - static const num3 = 51; - - /// number four - static const num4 = 52; - - /// number five - static const num5 = 53; - - /// number six - static const num6 = 54; - - /// number seven - static const num7 = 55; - - /// number eight - static const num8 = 56; - - /// number nine - static const num9 = 57; - - /// Colon ':' - static const colon = 58; - - /// Semicolon ';' - static const semicolon = 59; - - /// Less-than sign '<' - static const lessThan = 60; - - /// Equals sign '=' - static const equal = 61; - - /// Greater-than sign ; Inequality sign '>' - static const greaterThan = 62; - - /// Question mark '?' - static const questionMark = 63; - - /// At sign '@' - static const atSign = 64; - - /// Capital letter A - static const A = 65; - - /// Capital letter B - static const B = 66; - - /// Capital letter C - static const C = 67; - - /// Capital letter D - static const D = 68; - - /// Capital letter E - static const E = 69; - - /// Capital letter F - static const F = 70; - - /// Capital letter G - static const G = 71; - - /// Capital letter H - static const H = 72; - - /// Capital letter I - static const I = 73; - - /// Capital letter J - static const J = 74; - - /// Capital letter K - static const K = 75; - - /// Capital letter L - static const L = 76; - - /// Capital letter M - static const M = 77; - - /// Capital letter N - static const N = 78; - - /// Capital letter O - static const O = 79; - - /// Capital letter P - static const P = 80; - - /// Capital letter Q - static const Q = 81; - - /// Capital letter R - static const R = 82; - - /// Capital letter S - static const S = 83; - - /// Capital letter T - static const T = 84; - - /// Capital letter U - static const U = 85; - - /// Capital letter V - static const V = 86; - - /// Capital letter W - static const W = 87; - - /// Capital letter X - static const X = 88; - - /// Capital letter Y - static const Y = 89; - - /// Capital letter Z - static const Z = 90; - - /// square brackets or box brackets, opening bracket '[' - static const openBracket = 91; - - /// Backslash , reverse slash '\\' - static const backslash = 92; - - /// box brackets or square brackets, closing bracket ']' - static const closeBracket = 93; - - /// Circumflex accent or Caret '^' - static const caret = 94; - - /// underscore , understrike , underbar or low line '_' - static const underscore = 95; - - /// Grave accent '`' - static const graveAccent = 96; - - /// Lowercase letter a , minuscule a - static const a = 97; - - /// Lowercase letter b , minuscule b - static const b = 98; - - /// Lowercase letter c , minuscule c - static const c = 99; - - /// Lowercase letter d , minuscule d - static const d = 100; - - /// Lowercase letter e , minuscule e - static const e = 101; - - /// Lowercase letter f , minuscule f - static const f = 102; - - /// Lowercase letter g , minuscule g - static const g = 103; - - /// Lowercase letter h , minuscule h - static const h = 104; - - /// Lowercase letter i , minuscule i - static const i = 105; - - /// Lowercase letter j , minuscule j - static const j = 106; - - /// Lowercase letter k , minuscule k - static const k = 107; - - /// Lowercase letter l , minuscule l - static const l = 108; - - /// Lowercase letter m , minuscule m - static const m = 109; - - /// Lowercase letter n , minuscule n - static const n = 110; - - /// Lowercase letter o , minuscule o - static const o = 111; - - /// Lowercase letter p , minuscule p - static const p = 112; - - /// Lowercase letter q , minuscule q - static const q = 113; - - /// Lowercase letter r , minuscule r - static const r = 114; - - /// Lowercase letter s , minuscule s - static const s = 115; - - /// Lowercase letter t , minuscule t - static const t = 116; - - /// Lowercase letter u , minuscule u - static const u = 117; - - /// Lowercase letter v , minuscule v - static const v = 118; - - /// Lowercase letter w , minuscule w - static const w = 119; - - /// Lowercase letter x , minuscule x - static const x = 120; - - /// Lowercase letter y , minuscule y - static const y = 121; - - /// Lowercase letter z , minuscule z - static const z = 122; - - /// braces or curly brackets, opening braces '{' - static const openBrace = 123; - - /// vertical-bar, vbar, vertical line or vertical slash '|' - static const verticalBar = 124; - - /// curly brackets or braces, closing curly brackets '}' - static const closeBrace = 125; - - /// Tilde ; swung dash '~' - static const tilde = 126; -} diff --git a/lib/src/utils/byte_consumer.dart b/lib/src/utils/byte_consumer.dart deleted file mode 100644 index 4a2ad382..00000000 --- a/lib/src/utils/byte_consumer.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'dart:collection'; - -class ByteConsumer { - final _queue = ListQueue>(); - - final _consumed = ListQueue>(); - - var _currentOffset = 0; - - var _length = 0; - - var _totalConsumed = 0; - - void add(String data) { - if (data.isEmpty) return; - final runes = data.runes.toList(growable: false); - _queue.addLast(runes); - _length += runes.length; - } - - int peek() { - final data = _queue.first; - if (_currentOffset < data.length) { - return data[_currentOffset]; - } else { - final result = consume(); - rollback(); - return result; - } - } - - int consume() { - final data = _queue.first; - - if (_currentOffset >= data.length) { - _consumed.add(_queue.removeFirst()); - _currentOffset -= data.length; - return consume(); - } - - _length--; - _totalConsumed++; - return data[_currentOffset++]; - } - - /// Rolls back the last [n] call. - void rollback([int n = 1]) { - _currentOffset -= n; - _totalConsumed -= n; - _length += n; - while (_currentOffset < 0) { - final rollback = _consumed.removeLast(); - _queue.addFirst(rollback); - _currentOffset += rollback.length; - } - } - - /// Rolls back to the state when this consumer had [length] bytes. - void rollbackTo(int length) { - rollback(length - _length); - } - - int get length => _length; - - int get totalConsumed => _totalConsumed; - - bool get isEmpty => _length == 0; - - bool get isNotEmpty => _length != 0; - - /// Unreferences data blocks that have been consumed. After calling this - /// method, the consumer will not be able to roll back to consumed blocks. - void unrefConsumedBlocks() { - _consumed.clear(); - } - - /// Resets the consumer to its initial state. - void reset() { - _queue.clear(); - _consumed.clear(); - _currentOffset = 0; - _totalConsumed = 0; - _length = 0; - } -} - -// void main() { -// final consumer = ByteConsumer(); -// consumer.add(Uint8List.fromList([1, 2, 3])); -// consumer.add(Uint8List.fromList([4, 5, 6])); - -// while (consumer.isNotEmpty) { -// print(consumer.consume()); -// } - -// consumer.rollback(5); - -// while (consumer.isNotEmpty) { -// print(consumer.consume()); -// } - -// consumer.rollbackTo(3); - -// while (consumer.isNotEmpty) { -// print(consumer.consume()); -// } -// } diff --git a/lib/src/utils/char_code.dart b/lib/src/utils/char_code.dart deleted file mode 100644 index 9eb79e0a..00000000 --- a/lib/src/utils/char_code.dart +++ /dev/null @@ -1,5 +0,0 @@ -extension StringCharCode on String { - int get charCode { - return codeUnitAt(0); - } -} diff --git a/lib/src/utils/circular_buffer.dart b/lib/src/utils/circular_buffer.dart deleted file mode 100644 index f74fb436..00000000 --- a/lib/src/utils/circular_buffer.dart +++ /dev/null @@ -1,315 +0,0 @@ -/// A circular buffer in which elements know their index in the buffer. -class IndexAwareCircularBuffer { - /// Creates a new circular list with the specified [maxLength]. - IndexAwareCircularBuffer(int maxLength) - : _array = List.filled(maxLength, null); - - /// The backing array for this list. Length is always equal to [maxLength]. - late List _array; - - /// The number of elements in the list. This is always less than or equal to - /// [maxLength]. - var _length = 0; - - /// The index of the first element in [_array]. - var _startIndex = 0; - - /// The start index of this list, including items that has been dropped in - /// overflow - var _absoluteStartIndex = 0; - - /// Gets the cyclic index for the specified regular index. The cyclic index - /// can then be used on the backing array to get the element associated with - /// the regular index. - @pragma('vm:prefer-inline') - int _getCyclicIndex(int index) { - return (_startIndex + index) % _array.length; - } - - /// Removes the element at [index] from the list. - @pragma('vm:prefer-inline') - void _dropChild(int index) { - final cyclicIndex = _getCyclicIndex(index); - _array[cyclicIndex]?._detach(); - _array[cyclicIndex] = null; - } - - /// Adds the specified [child] to the list at the specified [index]. - @pragma('vm:prefer-inline') - void _adoptChild(int index, T child) { - final cyclicIndex = _getCyclicIndex(index); - _array[cyclicIndex]?._detach(); - _array[cyclicIndex] = child.._attach(this, index); - } - - /// Moves the element at [fromIndex] to [toIndex]. Both indexes should be - /// less than [maxLength]. - @pragma('vm:prefer-inline') - void _moveChild(int fromIndex, int toIndex) { - final fromCyclicIndex = _getCyclicIndex(fromIndex); - final toCyclicIndex = _getCyclicIndex(toIndex); - _array[toCyclicIndex]?._detach(); - _array[toCyclicIndex] = _array[fromCyclicIndex]?.._move(toIndex); - _array[fromCyclicIndex] = null; - } - - /// Gets the element at the specified [index] in the list. - @pragma('vm:prefer-inline') - T? _getChild(int index) { - return _array[_getCyclicIndex(index)]; - } - - /// The number of elements that can be stored in the list. - int get maxLength { - return _array.length; - } - - /// Sets the number of elements that can be stored in the list. This operation - /// is relatively expensive, as it requires the backing array to be - /// reallocated. - set maxLength(int value) { - if (value <= 0) { - throw ArgumentError.value(value, 'value', "maxLength can't be negative!"); - } - - if (value == _array.length) return; - - // Reconstruct array, starting at index 0. Only transfer values from the - // indexes 0 to length. - final newArray = List.generate( - value, - (index) => index < _length ? _getChild(index) : null, - ); - - _startIndex = 0; - _array = newArray; - } - - /// Number of elements in the list. - int get length { - return _length; - } - - /// Iterates over the list and calls [callback] for each element. - void forEach(void Function(T item) callback) { - final length = _length; - for (int i = 0; i < length; i++) { - callback(_getChild(i)!); - } - } - - /// Gets the element at the specified [index] in the list. Throws if the - /// index is out of bounds. - T operator [](int index) { - RangeError.checkValueInInterval(index, 0, length - 1, 'index'); - return _getChild(index)!; - } - - /// Sets the element at the specified [index] in the list. Throws if the - /// index is out of bounds. - operator []=(int index, T value) { - RangeError.checkValueInInterval(index, 0, length - 1, 'index'); - _adoptChild(index, value); - } - - /// Removes all elements from the list. - void clear() { - for (var i = 0; i < _length; i++) { - _dropChild(i); - } - _startIndex = 0; - _length = 0; - } - - /// Adds all elements in [items] to the list. - void pushAll(Iterable items) { - for (var element in items) { - push(element); - } - } - - /// Adds [value] to the end of the list. May cause the first element to be - /// trimmed if the list is full. - void push(T value) { - _adoptChild(_length, value); - - if (_length == _array.length) { - // When the list is full, we trim the first element - _startIndex++; - _absoluteStartIndex++; - if (_startIndex == _array.length) { - _startIndex = 0; - } - } else { - // When the list is not full, we just increase the length - _length++; - } - } - - /// Removes and returns the last value on the list, throws if the list is - /// empty. - T pop() { - assert(_length > 0, 'Cannot pop from an empty list'); - final result = _getChild(_length - 1); - _dropChild(_length - 1); - _length--; - return result!; - } - - /// Deletes [count] elements starting at [index], shifting all elements after - /// [index] to the left. - void remove(int index, [int count = 1]) { - if (count > 0) { - if (index + count >= _length) { - count = _length - index; - } - for (var i = index; i < _length - count; i++) { - _moveChild(i + count, i); - } - for (var i = _length - count; i < _length; i++) { - _dropChild(i); - } - _length -= count; - } - } - - /// Inserts [item] at [index], shifting all elements after [index] to the - /// right. May cause the first element to be trimmed if the list is full. - void insert(int index, T item) { - RangeError.checkValueInInterval(index, 0, _length, 'index'); - - if (index == _length) { - return push(item); - } - - if (index == 0 && _length >= _array.length) { - // when something is inserted at index 0 and the list is full then - // the new value immediately gets removed => nothing changes - return; - } - - for (var i = _length - 1; i >= index; i--) { - _moveChild(i, i + 1); - } - - _adoptChild(index, item); - - if (_length >= _array.length) { - _startIndex += 1; - _absoluteStartIndex += 1; - } else { - _length++; - } - } - - /// Inserts [items] at [index] in order. - void insertAll(int index, List items) { - for (var i = items.length - 1; i >= 0; i--) { - insert(index, items[i]); - // when the list is full then we have to move the index down - // as newly inserted values remove values with a lower index - if (_length >= _array.length) { - index--; - if (index < 0) { - return; - } - } - } - } - - /// Removes [count] elements starting at [index], shifting all elements after - /// [index] to the left. - /// - /// This method is cheap since it does not actually modify the list, but - /// instead just adjusts the start index and length. - void trimStart(int count) { - if (count > _length) count = _length; - _startIndex += count; - _startIndex %= _array.length; - _length -= count; - } - - /// Replaces all elements in the list with [replacement]. - void replaceWith(List replacement) { - for (var i = 0; i < _length; i++) { - _dropChild(i); - } - - var copyStart = 0; - if (replacement.length > maxLength) { - copyStart = replacement.length - maxLength; - } - - for (var i = 0; i < copyStart; i++) { - _dropChild(i); - } - - final copyLength = replacement.length - copyStart; - for (var i = 0; i < copyLength; i++) { - _adoptChild(i, replacement[copyStart + i]); - } - - _startIndex = 0; - _length = copyLength; - } - - /// Replaces the element at [index] with [value] and returns the replaced - /// item. - T swap(int index, T value) { - final result = _getChild(index); - _adoptChild(index, value); - return result!; - } - - /// Whether adding another element would cause the first element to be - /// trimmed. - bool get isFull => length == maxLength; - - /// Returns a list containing all elements in the list. - List toList() { - return List.generate(length, (index) => this[index]); - } - - String debugDump() { - final buffer = StringBuffer(); - buffer.writeln('CircularList:'); - for (var i = 0; i < _length; i++) { - final child = _getChild(i); - buffer.writeln(' $i: $child'); - } - return buffer.toString(); - } -} - -mixin IndexedItem { - IndexAwareCircularBuffer? _owner; - - int? _absoluteIndex; - - /// The index of this item in the buffer. Must only be accessed when - /// [attached] is true. - int get index => _absoluteIndex! - _owner!._absoluteStartIndex; - - /// Whether this item is currently stored in a buffer. - bool get attached => _owner != null; - - /// Sets the owner and index of this item. This is called by the buffer when - /// the item is adopted. - void _attach(IndexAwareCircularBuffer owner, int index) { - _owner = owner; - _absoluteIndex = owner._absoluteStartIndex + index; - } - - /// Marks this item as detached from a buffer. This is called after the item - /// has been removed from the buffer. - void _detach() { - _owner = null; - _absoluteIndex = null; - } - - /// Moves this item to [newIndex] in the buffer. - void _move(int newIndex) { - assert(attached); - _absoluteIndex = _owner!._absoluteStartIndex + newIndex; - } -} diff --git a/lib/src/utils/debugger.dart b/lib/src/utils/debugger.dart deleted file mode 100644 index 303bbbbe..00000000 --- a/lib/src/utils/debugger.dart +++ /dev/null @@ -1,595 +0,0 @@ -import 'package:xterm/src/core/escape/handler.dart'; -import 'package:xterm/src/core/escape/parser.dart'; -import 'package:xterm/src/core/mouse/mode.dart'; -import 'package:xterm/src/base/observable.dart'; - -class TerminalCommand { - TerminalCommand( - this.start, - this.end, - this.chars, - this.escapedChars, - this.explanation, - this.error, - ); - - final int start; - - final int end; - - final String chars; - - final String escapedChars; - - final List explanation; - - final bool error; -} - -class TerminalDebugger with Observable { - late final _parser = EscapeParser(_handler); - - late final _handler = _TerminalDebuggerHandler(recordCommand); - - final recorded = []; - - final commands = []; - - void write(String chunk) { - recorded.addAll(chunk.runes); - _parser.write(chunk); - notifyListeners(); - } - - void recordCommand(String explanation, {bool error = false}) { - final start = _parser.tokenBegin; - final end = _parser.tokenEnd; - - if (commands.isNotEmpty && commands.last.end == end) { - commands.last.explanation.add(explanation); - } else { - final charCodes = recorded.sublist(start, end); - final chars = String.fromCharCodes(charCodes); - final escapedChars = _escape(chars); - commands.add( - TerminalCommand(start, end, chars, escapedChars, [explanation], error), - ); - } - } - - String getRecord(TerminalCommand command) { - final charCodes = recorded.sublist(0, command.end); - return String.fromCharCodes(charCodes); - } - - static String _escape(String chars) { - final escaped = StringBuffer(); - for (final char in chars.runes) { - if (char == 0x1b) { - escaped.write('ESC'); - } else if (char < 32) { - escaped.write('^0x${char.toRadixString(16)}'); - } else if (char == 127) { - escaped.write('^?'); - } else { - escaped.writeCharCode(char); - } - } - return escaped.toString(); - } -} - -class _TerminalDebuggerHandler implements EscapeHandler { - _TerminalDebuggerHandler(this.onCommand); - - final void Function(String explanation, {bool error}) onCommand; - - @override - void writeChar(int char) { - onCommand('writeChar(${String.fromCharCode(char)})'); - } - - /* SBC */ - - @override - void bell() { - onCommand('bell'); - } - - @override - void backspaceReturn() { - onCommand('backspaceReturn'); - } - - @override - void tab() { - onCommand('tab'); - } - - @override - void lineFeed() { - onCommand('lineFeed'); - } - - @override - void carriageReturn() { - onCommand('carriageReturn'); - } - - @override - void shiftOut() { - onCommand('shiftOut'); - } - - @override - void shiftIn() { - onCommand('shiftIn'); - } - - @override - void unknownSBC(int char) { - onCommand('unkownSBC(${String.fromCharCode(char)})', error: true); - } - - /* ANSI sequence */ - - @override - void saveCursor() { - onCommand('saveCursor'); - } - - @override - void restoreCursor() { - onCommand('restoreCursor'); - } - - @override - void index() { - onCommand('index'); - } - - @override - void nextLine() { - onCommand('nextLine'); - } - - @override - void setTapStop() { - onCommand('setTapStop'); - } - - @override - void reverseIndex() { - onCommand('reverseIndex'); - } - - @override - void designateCharset(int charset, int name) { - onCommand('designateCharset($charset, $name)'); - } - - @override - void unkownEscape(int char) { - onCommand('unkownEscape(${String.fromCharCode(char)})', error: true); - } - - /* CSI */ - - @override - void repeatPreviousCharacter(int count) { - onCommand('repeatPreviousCharacter($count)'); - } - - @override - void unknownCSI(int finalByte) { - onCommand('unkownCSI(${String.fromCharCode(finalByte)})', error: true); - } - - @override - void setCursor(int x, int y) { - onCommand('setCursor($x, $y)'); - } - - @override - void setCursorX(int x) { - onCommand('setCursorX($x)'); - } - - @override - void setCursorY(int y) { - onCommand('setCursorY($y)'); - } - - @override - void sendPrimaryDeviceAttributes() { - onCommand('sendPrimaryDeviceAttributes'); - } - - @override - void clearTabStopUnderCursor() { - onCommand('clearTabStopUnderCursor'); - } - - @override - void clearAllTabStops() { - onCommand('clearAllTabStops'); - } - - @override - void moveCursorX(int offset) { - onCommand('moveCursorX($offset)'); - } - - @override - void moveCursorY(int n) { - onCommand('moveCursorY($n)'); - } - - @override - void sendSecondaryDeviceAttributes() { - onCommand('sendSecondaryDeviceAttributes'); - } - - @override - void sendTertiaryDeviceAttributes() { - onCommand('sendTertiaryDeviceAttributes'); - } - - @override - void sendOperatingStatus() { - onCommand('sendOperatingStatus'); - } - - @override - void sendCursorPosition() { - onCommand('sendCursorPosition'); - } - - @override - void setMargins(int i, [int? bottom]) { - onCommand('setMargins($i, $bottom)'); - } - - @override - void cursorNextLine(int amount) { - onCommand('cursorNextLine($amount)'); - } - - @override - void cursorPrecedingLine(int amount) { - onCommand('cursorPrecedingLine($amount)'); - } - - @override - void eraseDisplayBelow() { - onCommand('eraseDisplayBelow'); - } - - @override - void eraseDisplayAbove() { - onCommand('eraseDisplayAbove'); - } - - @override - void eraseDisplay() { - onCommand('eraseDisplay'); - } - - @override - void eraseScrollbackOnly() { - onCommand('eraseScrollbackOnly'); - } - - @override - void eraseLineRight() { - onCommand('eraseLineRight'); - } - - @override - void eraseLineLeft() { - onCommand('eraseLineLeft'); - } - - @override - void eraseLine() { - onCommand('eraseLine'); - } - - @override - void insertLines(int amount) { - onCommand('insertLines($amount)'); - } - - @override - void deleteLines(int amount) { - onCommand('deleteLines($amount)'); - } - - @override - void deleteChars(int amount) { - onCommand('deleteChars($amount)'); - } - - @override - void scrollUp(int amount) { - onCommand('scrollUp($amount)'); - } - - @override - void scrollDown(int amount) { - onCommand('scrollDown($amount)'); - } - - @override - void eraseChars(int amount) { - onCommand('eraseChars($amount)'); - } - - @override - void insertBlankChars(int amount) { - onCommand('insertBlankChars($amount)'); - } - - @override - void resize(int cols, int rows) { - onCommand('resize($cols, $rows)'); - } - - @override - void sendSize() { - onCommand('sendSize'); - } - - /* Modes */ - - @override - void setInsertMode(bool enabled) { - onCommand('setInsertMode($enabled)'); - } - - @override - void setLineFeedMode(bool enabled) { - onCommand('setLineFeedMode($enabled)'); - } - - @override - void setUnknownMode(int mode, bool enabled) { - onCommand('setUnknownMode($mode, $enabled)', error: true); - } - - /* DEC Private modes */ - - @override - void setCursorKeysMode(bool enabled) { - onCommand('setCursorKeysMode($enabled)'); - } - - @override - void setReverseDisplayMode(bool enabled) { - onCommand('setReverseDisplayMode($enabled)'); - } - - @override - void setOriginMode(bool enabled) { - onCommand('setOriginMode($enabled)'); - } - - @override - void setColumnMode(bool enabled) { - onCommand('setColumnMode($enabled)'); - } - - @override - void setAutoWrapMode(bool enabled) { - onCommand('setAutoWrapMode($enabled)'); - } - - @override - void setMouseMode(MouseMode mode) { - onCommand('setMouseMode($mode)'); - } - - @override - void setCursorBlinkMode(bool enabled) { - onCommand('setCursorBlinkMode($enabled)'); - } - - @override - void setCursorVisibleMode(bool enabled) { - onCommand('setCursorVisibleMode($enabled)'); - } - - @override - void useAltBuffer() { - onCommand('useAltBuffer'); - } - - @override - void useMainBuffer() { - onCommand('useMainBuffer'); - } - - @override - void clearAltBuffer() { - onCommand('clearAltBuffer'); - } - - @override - void setAppKeypadMode(bool enabled) { - onCommand('setAppKeypadMode($enabled)'); - } - - @override - void setReportFocusMode(bool enabled) { - onCommand('setReportFocusMode($enabled)'); - } - - @override - void setMouseReportMode(MouseReportMode mode) { - onCommand('setMouseReportMode($mode)'); - } - - @override - void setAltBufferMouseScrollMode(bool enabled) { - onCommand('setAltBufferMouseScrollMode($enabled)'); - } - - @override - void setBracketedPasteMode(bool enabled) { - onCommand('setBracketedPasteMode($enabled)'); - } - - @override - void setUnknownDecMode(int mode, bool enabled) { - onCommand('setUnknownDecMode($mode, $enabled)', error: true); - } - - /* Select Graphic Rendition (SGR) */ - - @override - void resetCursorStyle() { - onCommand('resetCursorStyle'); - } - - @override - void setCursorBold() { - onCommand('setCursorBold'); - } - - @override - void setCursorFaint() { - onCommand('setCursorFaint'); - } - - @override - void setCursorItalic() { - onCommand('setCursorItalic'); - } - - @override - void setCursorUnderline() { - onCommand('setCursorUnderline'); - } - - @override - void setCursorBlink() { - onCommand('setCursorBlink'); - } - - @override - void setCursorInverse() { - onCommand('setCursorInverse'); - } - - @override - void setCursorInvisible() { - onCommand('setCursorInvisible'); - } - - @override - void setCursorStrikethrough() { - onCommand('setCursorStrikethrough'); - } - - @override - void unsetCursorBold() { - onCommand('unsetCursorBold'); - } - - @override - void unsetCursorFaint() { - onCommand('unsetCursorFaint'); - } - - @override - void unsetCursorItalic() { - onCommand('unsetCursorItalic'); - } - - @override - void unsetCursorUnderline() { - onCommand('unsetCursorUnderline'); - } - - @override - void unsetCursorBlink() { - onCommand('unsetCursorBlink'); - } - - @override - void unsetCursorInverse() { - onCommand('unsetCursorInverse'); - } - - @override - void unsetCursorInvisible() { - onCommand('unsetCursorInvisible'); - } - - @override - void unsetCursorStrikethrough() { - onCommand('unsetCursorStrikethrough'); - } - - @override - void setForegroundColor16(int color) { - onCommand('setForegroundColor16($color)'); - } - - @override - void setForegroundColor256(int index) { - onCommand('setForegroundColor256($index)'); - } - - @override - void setForegroundColorRgb(int r, int g, int b) { - onCommand('setForegroundColorRgb($r, $g, $b)'); - } - - @override - void resetForeground() { - onCommand('resetForeground'); - } - - @override - void setBackgroundColor16(int color) { - onCommand('setBackgroundColor16($color)'); - } - - @override - void setBackgroundColor256(int index) { - onCommand('setBackgroundColor256($index)'); - } - - @override - void setBackgroundColorRgb(int r, int g, int b) { - onCommand('setBackgroundColorRgb($r, $g, $b)'); - } - - @override - void resetBackground() { - onCommand('resetBackground'); - } - - @override - void unsupportedStyle(int param) { - onCommand('unsupportedStyle($param)', error: true); - } - - /* OSC */ - - @override - void setTitle(String name) { - onCommand('setTitle($name)'); - } - - @override - void setIconName(String name) { - onCommand('setIconName($name)'); - } - - @override - void unknownOSC(String code, List args) { - onCommand('unknownOSC($code, $args)', error: true); - } -} diff --git a/lib/src/utils/debugger_view.dart b/lib/src/utils/debugger_view.dart index f5ff556a..76b824b6 100644 --- a/lib/src/utils/debugger_view.dart +++ b/lib/src/utils/debugger_view.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:xterm/src/utils/debugger.dart'; +import 'package:xterm_core/xterm_core.dart'; class TerminalDebuggerView extends StatefulWidget { const TerminalDebuggerView( diff --git a/lib/src/utils/hash_values.dart b/lib/src/utils/hash_values.dart deleted file mode 100644 index cdc43ed0..00000000 --- a/lib/src/utils/hash_values.dart +++ /dev/null @@ -1,111 +0,0 @@ -class _HashEnd { - const _HashEnd(); -} - -const _HashEnd _hashEnd = _HashEnd(); - -class _Jenkins { - static int combine(int hash, Object? o) { - assert(o is! Iterable); - hash = 0x1fffffff & (hash + o.hashCode); - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } -} - -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); - if (!identical(arg03, _hashEnd)) { - result = _Jenkins.combine(result, arg03); - if (!identical(arg04, _hashEnd)) { - result = _Jenkins.combine(result, arg04); - if (!identical(arg05, _hashEnd)) { - result = _Jenkins.combine(result, arg05); - if (!identical(arg06, _hashEnd)) { - result = _Jenkins.combine(result, arg06); - if (!identical(arg07, _hashEnd)) { - result = _Jenkins.combine(result, arg07); - if (!identical(arg08, _hashEnd)) { - result = _Jenkins.combine(result, arg08); - if (!identical(arg09, _hashEnd)) { - result = _Jenkins.combine(result, arg09); - if (!identical(arg10, _hashEnd)) { - result = _Jenkins.combine(result, arg10); - if (!identical(arg11, _hashEnd)) { - result = _Jenkins.combine(result, arg11); - if (!identical(arg12, _hashEnd)) { - result = _Jenkins.combine(result, arg12); - if (!identical(arg13, _hashEnd)) { - result = _Jenkins.combine(result, arg13); - if (!identical(arg14, _hashEnd)) { - result = _Jenkins.combine(result, arg14); - if (!identical(arg15, _hashEnd)) { - result = _Jenkins.combine(result, arg15); - if (!identical(arg16, _hashEnd)) { - result = _Jenkins.combine(result, arg16); - if (!identical(arg17, _hashEnd)) { - result = _Jenkins.combine(result, arg17); - if (!identical(arg18, _hashEnd)) { - result = _Jenkins.combine(result, arg18); - if (!identical(arg19, _hashEnd)) { - result = _Jenkins.combine(result, arg19); - if (!identical(arg20, _hashEnd)) { - result = _Jenkins.combine(result, arg20); - // I can see my house from here! - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - return _Jenkins.finish(result); -} - -int hashList(Iterable arguments) { - int result = 0; - for (Object argument in arguments) { - result = _Jenkins.combine(result, argument); - } - return _Jenkins.finish(result); -} diff --git a/lib/src/utils/lookup_table.dart b/lib/src/utils/lookup_table.dart deleted file mode 100644 index 377294bb..00000000 --- a/lib/src/utils/lookup_table.dart +++ /dev/null @@ -1,34 +0,0 @@ -/// Fixed-size list based lookup table, optimized for small positive integer -/// keys. -class FastLookupTable { - FastLookupTable(Map data) { - var maxIndex = data.keys.first; - - for (var key in data.keys) { - if (key > maxIndex) { - maxIndex = key; - } - } - - _maxIndex = maxIndex; - - _table = List.filled(maxIndex + 1, null); - - for (var entry in data.entries) { - _table[entry.key] = entry.value; - } - } - - late final List _table; - late final int _maxIndex; - - T? operator [](int index) { - if (index > _maxIndex) { - return null; - } - - return _table[index]; - } - - int get maxIndex => _maxIndex; -} diff --git a/lib/src/utils/unicode_v11.dart b/lib/src/utils/unicode_v11.dart deleted file mode 100644 index fd95ba0b..00000000 --- a/lib/src/utils/unicode_v11.dart +++ /dev/null @@ -1,512 +0,0 @@ -// ignore_for_file: constant_identifier_names - -import 'dart:typed_data'; - -const BMP_COMBINING = [ - [0x0300, 0x036F], - [0x0483, 0x0489], - [0x0591, 0x05BD], - [0x05BF, 0x05BF], - [0x05C1, 0x05C2], - [0x05C4, 0x05C5], - [0x05C7, 0x05C7], - [0x0600, 0x0605], - [0x0610, 0x061A], - [0x061C, 0x061C], - [0x064B, 0x065F], - [0x0670, 0x0670], - [0x06D6, 0x06DD], - [0x06DF, 0x06E4], - [0x06E7, 0x06E8], - [0x06EA, 0x06ED], - [0x070F, 0x070F], - [0x0711, 0x0711], - [0x0730, 0x074A], - [0x07A6, 0x07B0], - [0x07EB, 0x07F3], - [0x07FD, 0x07FD], - [0x0816, 0x0819], - [0x081B, 0x0823], - [0x0825, 0x0827], - [0x0829, 0x082D], - [0x0859, 0x085B], - [0x08D3, 0x0902], - [0x093A, 0x093A], - [0x093C, 0x093C], - [0x0941, 0x0948], - [0x094D, 0x094D], - [0x0951, 0x0957], - [0x0962, 0x0963], - [0x0981, 0x0981], - [0x09BC, 0x09BC], - [0x09C1, 0x09C4], - [0x09CD, 0x09CD], - [0x09E2, 0x09E3], - [0x09FE, 0x09FE], - [0x0A01, 0x0A02], - [0x0A3C, 0x0A3C], - [0x0A41, 0x0A42], - [0x0A47, 0x0A48], - [0x0A4B, 0x0A4D], - [0x0A51, 0x0A51], - [0x0A70, 0x0A71], - [0x0A75, 0x0A75], - [0x0A81, 0x0A82], - [0x0ABC, 0x0ABC], - [0x0AC1, 0x0AC5], - [0x0AC7, 0x0AC8], - [0x0ACD, 0x0ACD], - [0x0AE2, 0x0AE3], - [0x0AFA, 0x0AFF], - [0x0B01, 0x0B01], - [0x0B3C, 0x0B3C], - [0x0B3F, 0x0B3F], - [0x0B41, 0x0B44], - [0x0B4D, 0x0B4D], - [0x0B56, 0x0B56], - [0x0B62, 0x0B63], - [0x0B82, 0x0B82], - [0x0BC0, 0x0BC0], - [0x0BCD, 0x0BCD], - [0x0C00, 0x0C00], - [0x0C04, 0x0C04], - [0x0C3E, 0x0C40], - [0x0C46, 0x0C48], - [0x0C4A, 0x0C4D], - [0x0C55, 0x0C56], - [0x0C62, 0x0C63], - [0x0C81, 0x0C81], - [0x0CBC, 0x0CBC], - [0x0CBF, 0x0CBF], - [0x0CC6, 0x0CC6], - [0x0CCC, 0x0CCD], - [0x0CE2, 0x0CE3], - [0x0D00, 0x0D01], - [0x0D3B, 0x0D3C], - [0x0D41, 0x0D44], - [0x0D4D, 0x0D4D], - [0x0D62, 0x0D63], - [0x0DCA, 0x0DCA], - [0x0DD2, 0x0DD4], - [0x0DD6, 0x0DD6], - [0x0E31, 0x0E31], - [0x0E34, 0x0E3A], - [0x0E47, 0x0E4E], - [0x0EB1, 0x0EB1], - [0x0EB4, 0x0EBC], - [0x0EC8, 0x0ECD], - [0x0F18, 0x0F19], - [0x0F35, 0x0F35], - [0x0F37, 0x0F37], - [0x0F39, 0x0F39], - [0x0F71, 0x0F7E], - [0x0F80, 0x0F84], - [0x0F86, 0x0F87], - [0x0F8D, 0x0F97], - [0x0F99, 0x0FBC], - [0x0FC6, 0x0FC6], - [0x102D, 0x1030], - [0x1032, 0x1037], - [0x1039, 0x103A], - [0x103D, 0x103E], - [0x1058, 0x1059], - [0x105E, 0x1060], - [0x1071, 0x1074], - [0x1082, 0x1082], - [0x1085, 0x1086], - [0x108D, 0x108D], - [0x109D, 0x109D], - [0x1160, 0x11FF], - [0x135D, 0x135F], - [0x1712, 0x1714], - [0x1732, 0x1734], - [0x1752, 0x1753], - [0x1772, 0x1773], - [0x17B4, 0x17B5], - [0x17B7, 0x17BD], - [0x17C6, 0x17C6], - [0x17C9, 0x17D3], - [0x17DD, 0x17DD], - [0x180B, 0x180E], - [0x1885, 0x1886], - [0x18A9, 0x18A9], - [0x1920, 0x1922], - [0x1927, 0x1928], - [0x1932, 0x1932], - [0x1939, 0x193B], - [0x1A17, 0x1A18], - [0x1A1B, 0x1A1B], - [0x1A56, 0x1A56], - [0x1A58, 0x1A5E], - [0x1A60, 0x1A60], - [0x1A62, 0x1A62], - [0x1A65, 0x1A6C], - [0x1A73, 0x1A7C], - [0x1A7F, 0x1A7F], - [0x1AB0, 0x1ABE], - [0x1B00, 0x1B03], - [0x1B34, 0x1B34], - [0x1B36, 0x1B3A], - [0x1B3C, 0x1B3C], - [0x1B42, 0x1B42], - [0x1B6B, 0x1B73], - [0x1B80, 0x1B81], - [0x1BA2, 0x1BA5], - [0x1BA8, 0x1BA9], - [0x1BAB, 0x1BAD], - [0x1BE6, 0x1BE6], - [0x1BE8, 0x1BE9], - [0x1BED, 0x1BED], - [0x1BEF, 0x1BF1], - [0x1C2C, 0x1C33], - [0x1C36, 0x1C37], - [0x1CD0, 0x1CD2], - [0x1CD4, 0x1CE0], - [0x1CE2, 0x1CE8], - [0x1CED, 0x1CED], - [0x1CF4, 0x1CF4], - [0x1CF8, 0x1CF9], - [0x1DC0, 0x1DF9], - [0x1DFB, 0x1DFF], - [0x200B, 0x200F], - [0x202A, 0x202E], - [0x2060, 0x2064], - [0x2066, 0x206F], - [0x20D0, 0x20F0], - [0x2CEF, 0x2CF1], - [0x2D7F, 0x2D7F], - [0x2DE0, 0x2DFF], - [0x302A, 0x302D], - [0x3099, 0x309A], - [0xA66F, 0xA672], - [0xA674, 0xA67D], - [0xA69E, 0xA69F], - [0xA6F0, 0xA6F1], - [0xA802, 0xA802], - [0xA806, 0xA806], - [0xA80B, 0xA80B], - [0xA825, 0xA826], - [0xA8C4, 0xA8C5], - [0xA8E0, 0xA8F1], - [0xA8FF, 0xA8FF], - [0xA926, 0xA92D], - [0xA947, 0xA951], - [0xA980, 0xA982], - [0xA9B3, 0xA9B3], - [0xA9B6, 0xA9B9], - [0xA9BC, 0xA9BD], - [0xA9E5, 0xA9E5], - [0xAA29, 0xAA2E], - [0xAA31, 0xAA32], - [0xAA35, 0xAA36], - [0xAA43, 0xAA43], - [0xAA4C, 0xAA4C], - [0xAA7C, 0xAA7C], - [0xAAB0, 0xAAB0], - [0xAAB2, 0xAAB4], - [0xAAB7, 0xAAB8], - [0xAABE, 0xAABF], - [0xAAC1, 0xAAC1], - [0xAAEC, 0xAAED], - [0xAAF6, 0xAAF6], - [0xABE5, 0xABE5], - [0xABE8, 0xABE8], - [0xABED, 0xABED], - [0xFB1E, 0xFB1E], - [0xFE00, 0xFE0F], - [0xFE20, 0xFE2F], - [0xFEFF, 0xFEFF], - [0xFFF9, 0xFFFB], -]; - -const HIGH_COMBINING = [ - [0x101FD, 0x101FD], - [0x102E0, 0x102E0], - [0x10376, 0x1037A], - [0x10A01, 0x10A03], - [0x10A05, 0x10A06], - [0x10A0C, 0x10A0F], - [0x10A38, 0x10A3A], - [0x10A3F, 0x10A3F], - [0x10AE5, 0x10AE6], - [0x10D24, 0x10D27], - [0x10F46, 0x10F50], - [0x11001, 0x11001], - [0x11038, 0x11046], - [0x1107F, 0x11081], - [0x110B3, 0x110B6], - [0x110B9, 0x110BA], - [0x110BD, 0x110BD], - [0x110CD, 0x110CD], - [0x11100, 0x11102], - [0x11127, 0x1112B], - [0x1112D, 0x11134], - [0x11173, 0x11173], - [0x11180, 0x11181], - [0x111B6, 0x111BE], - [0x111C9, 0x111CC], - [0x1122F, 0x11231], - [0x11234, 0x11234], - [0x11236, 0x11237], - [0x1123E, 0x1123E], - [0x112DF, 0x112DF], - [0x112E3, 0x112EA], - [0x11300, 0x11301], - [0x1133B, 0x1133C], - [0x11340, 0x11340], - [0x11366, 0x1136C], - [0x11370, 0x11374], - [0x11438, 0x1143F], - [0x11442, 0x11444], - [0x11446, 0x11446], - [0x1145E, 0x1145E], - [0x114B3, 0x114B8], - [0x114BA, 0x114BA], - [0x114BF, 0x114C0], - [0x114C2, 0x114C3], - [0x115B2, 0x115B5], - [0x115BC, 0x115BD], - [0x115BF, 0x115C0], - [0x115DC, 0x115DD], - [0x11633, 0x1163A], - [0x1163D, 0x1163D], - [0x1163F, 0x11640], - [0x116AB, 0x116AB], - [0x116AD, 0x116AD], - [0x116B0, 0x116B5], - [0x116B7, 0x116B7], - [0x1171D, 0x1171F], - [0x11722, 0x11725], - [0x11727, 0x1172B], - [0x1182F, 0x11837], - [0x11839, 0x1183A], - [0x119D4, 0x119D7], - [0x119DA, 0x119DB], - [0x119E0, 0x119E0], - [0x11A01, 0x11A0A], - [0x11A33, 0x11A38], - [0x11A3B, 0x11A3E], - [0x11A47, 0x11A47], - [0x11A51, 0x11A56], - [0x11A59, 0x11A5B], - [0x11A8A, 0x11A96], - [0x11A98, 0x11A99], - [0x11C30, 0x11C36], - [0x11C38, 0x11C3D], - [0x11C3F, 0x11C3F], - [0x11C92, 0x11CA7], - [0x11CAA, 0x11CB0], - [0x11CB2, 0x11CB3], - [0x11CB5, 0x11CB6], - [0x11D31, 0x11D36], - [0x11D3A, 0x11D3A], - [0x11D3C, 0x11D3D], - [0x11D3F, 0x11D45], - [0x11D47, 0x11D47], - [0x11D90, 0x11D91], - [0x11D95, 0x11D95], - [0x11D97, 0x11D97], - [0x11EF3, 0x11EF4], - [0x13430, 0x13438], - [0x16AF0, 0x16AF4], - [0x16B30, 0x16B36], - [0x16F4F, 0x16F4F], - [0x16F8F, 0x16F92], - [0x1BC9D, 0x1BC9E], - [0x1BCA0, 0x1BCA3], - [0x1D167, 0x1D169], - [0x1D173, 0x1D182], - [0x1D185, 0x1D18B], - [0x1D1AA, 0x1D1AD], - [0x1D242, 0x1D244], - [0x1DA00, 0x1DA36], - [0x1DA3B, 0x1DA6C], - [0x1DA75, 0x1DA75], - [0x1DA84, 0x1DA84], - [0x1DA9B, 0x1DA9F], - [0x1DAA1, 0x1DAAF], - [0x1E000, 0x1E006], - [0x1E008, 0x1E018], - [0x1E01B, 0x1E021], - [0x1E023, 0x1E024], - [0x1E026, 0x1E02A], - [0x1E130, 0x1E136], - [0x1E2EC, 0x1E2EF], - [0x1E8D0, 0x1E8D6], - [0x1E944, 0x1E94A], - [0xE0001, 0xE0001], - [0xE0020, 0xE007F], - [0xE0100, 0xE01EF], -]; - -const BMP_WIDE = [ - [0x1100, 0x115F], - [0x231A, 0x231B], - [0x2329, 0x232A], - [0x23E9, 0x23EC], - [0x23F0, 0x23F0], - [0x23F3, 0x23F3], - [0x25FD, 0x25FE], - [0x2614, 0x2615], - [0x2648, 0x2653], - [0x267F, 0x267F], - [0x2693, 0x2693], - [0x26A1, 0x26A1], - [0x26AA, 0x26AB], - [0x26BD, 0x26BE], - [0x26C4, 0x26C5], - [0x26CE, 0x26CE], - [0x26D4, 0x26D4], - [0x26EA, 0x26EA], - [0x26F2, 0x26F3], - [0x26F5, 0x26F5], - [0x26FA, 0x26FA], - [0x26FD, 0x26FD], - [0x2705, 0x2705], - [0x270A, 0x270B], - [0x2728, 0x2728], - [0x274C, 0x274C], - [0x274E, 0x274E], - [0x2753, 0x2755], - [0x2757, 0x2757], - [0x2795, 0x2797], - [0x27B0, 0x27B0], - [0x27BF, 0x27BF], - [0x2B1B, 0x2B1C], - [0x2B50, 0x2B50], - [0x2B55, 0x2B55], - [0x2E80, 0x2E99], - [0x2E9B, 0x2EF3], - [0x2F00, 0x2FD5], - [0x2FF0, 0x2FFB], - [0x3000, 0x3029], - [0x302E, 0x303E], - [0x3041, 0x3096], - [0x309B, 0x30FF], - [0x3105, 0x312F], - [0x3131, 0x318E], - [0x3190, 0x31BA], - [0x31C0, 0x31E3], - [0x31F0, 0x321E], - [0x3220, 0x3247], - [0x3250, 0x4DBF], - [0x4E00, 0xA48C], - [0xA490, 0xA4C6], - [0xA960, 0xA97C], - [0xAC00, 0xD7A3], - [0xF900, 0xFAFF], - [0xFE10, 0xFE19], - [0xFE30, 0xFE52], - [0xFE54, 0xFE66], - [0xFE68, 0xFE6B], - [0xFF01, 0xFF60], - [0xFFE0, 0xFFE6], -]; - -const HIGH_WIDE = [ - [0x16FE0, 0x16FE3], - [0x17000, 0x187F7], - [0x18800, 0x18AF2], - [0x1B000, 0x1B11E], - [0x1B150, 0x1B152], - [0x1B164, 0x1B167], - [0x1B170, 0x1B2FB], - [0x1F004, 0x1F004], - [0x1F0CF, 0x1F0CF], - [0x1F18E, 0x1F18E], - [0x1F191, 0x1F19A], - [0x1F200, 0x1F202], - [0x1F210, 0x1F23B], - [0x1F240, 0x1F248], - [0x1F250, 0x1F251], - [0x1F260, 0x1F265], - [0x1F300, 0x1F320], - [0x1F32D, 0x1F335], - [0x1F337, 0x1F37C], - [0x1F37E, 0x1F393], - [0x1F3A0, 0x1F3CA], - [0x1F3CF, 0x1F3D3], - [0x1F3E0, 0x1F3F0], - [0x1F3F4, 0x1F3F4], - [0x1F3F8, 0x1F43E], - [0x1F440, 0x1F440], - [0x1F442, 0x1F4FC], - [0x1F4FF, 0x1F53D], - [0x1F54B, 0x1F54E], - [0x1F550, 0x1F567], - [0x1F57A, 0x1F57A], - [0x1F595, 0x1F596], - [0x1F5A4, 0x1F5A4], - [0x1F5FB, 0x1F64F], - [0x1F680, 0x1F6C5], - [0x1F6CC, 0x1F6CC], - [0x1F6D0, 0x1F6D2], - [0x1F6D5, 0x1F6D5], - [0x1F6EB, 0x1F6EC], - [0x1F6F4, 0x1F6FA], - [0x1F7E0, 0x1F7EB], - [0x1F90D, 0x1F971], - [0x1F973, 0x1F976], - [0x1F97A, 0x1F9A2], - [0x1F9A5, 0x1F9AA], - [0x1F9AE, 0x1F9CA], - [0x1F9CD, 0x1F9FF], - [0x1FA70, 0x1FA73], - [0x1FA78, 0x1FA7A], - [0x1FA80, 0x1FA82], - [0x1FA90, 0x1FA95], - [0x20000, 0x2FFFD], - [0x30000, 0x3FFFD], -]; - -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> data) { - var min = 0; - var max = data.length - 1; - int mid; - if (ucs < data[0][0] || ucs > data[max][1]) { - return false; - } - while (max >= min) { - mid = (min + max) >> 1; - if (ucs > data[mid][1]) { - min = mid + 1; - } else if (ucs < data[mid][0]) { - max = mid - 1; - } else { - return true; - } - } - return false; -} - -class UnicodeV11 { - final version = '11'; - - int wcwidth(int codePoint) { - if (codePoint < 32) return 0; - if (codePoint < 127) return 1; - if (codePoint < 65536) return table[codePoint]; - if (bisearch(codePoint, HIGH_COMBINING)) return 0; - if (bisearch(codePoint, HIGH_WIDE)) return 2; - return 1; - } -} - -final unicodeV11 = UnicodeV11(); diff --git a/lib/utils.dart b/lib/utils.dart index 74c0abac..5bbab3cc 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -1,2 +1,3 @@ -export 'src/utils/debugger.dart'; +export 'package:xterm_core/xterm_core.dart' + show TerminalCommand, TerminalDebugger; export 'src/utils/debugger_view.dart'; diff --git a/lib/xterm.dart b/lib/xterm.dart index 60e7299d..e3a3c5de 100644 --- a/lib/xterm.dart +++ b/lib/xterm.dart @@ -1,3 +1,3 @@ -export 'core.dart'; +export 'package:xterm_core/xterm_core.dart'; export 'ui.dart'; export 'zmodem.dart'; diff --git a/pubspec.lock b/pubspec.lock index 1bd3e87c..61f9de8c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,34 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" url: "https://pub.dev" source: hosted - version: "61.0.0" + version: "67.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" url: "https://pub.dev" source: hosted - version: "5.13.0" - analyzer_plugin: - dependency: transitive - description: - name: analyzer_plugin - sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d - url: "https://pub.dev" - source: hosted - version: "0.11.2" - ansicolor: - dependency: transitive - description: - name: ansicolor - sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" - url: "https://pub.dev" - source: hosted - version: "2.0.2" + version: "6.4.1" args: dependency: transitive description: @@ -125,10 +109,10 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" checked_yaml: dependency: transitive description: @@ -141,10 +125,10 @@ packages: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" code_builder: dependency: transitive description: @@ -157,10 +141,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.1" convert: dependency: "direct main" description: @@ -185,30 +169,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" - csslib: - dependency: transitive - description: - name: csslib - sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - dart_code_metrics: - dependency: "direct dev" - description: - name: dart_code_metrics - sha256: "3dede3f7abc077a4181ec7445448a289a9ce08e2981e6a4d49a3fb5099d47e1f" - url: "https://pub.dev" - source: hosted - version: "5.7.6" - dart_code_metrics_presets: - dependency: transitive - description: - name: dart_code_metrics_presets - sha256: b71eadf02a3787ebd5c887623f83f6fdc204d45c75a081bd636c4104b3fd8b73 - url: "https://pub.dev" - source: hosted - version: "1.8.0" dart_style: dependency: transitive description: @@ -229,10 +189,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" file: dependency: transitive description: @@ -283,22 +243,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" - html: - dependency: transitive - description: - name: html - sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" - url: "https://pub.dev" - source: hosted - version: "0.15.4" - http: - dependency: transitive - description: - name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" - url: "https://pub.dev" - source: hosted - version: "0.13.6" http_multi_server: dependency: transitive description: @@ -343,26 +287,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.2" lints: dependency: "direct dev" description: @@ -383,26 +327,26 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: "direct main" description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.17.0" mime: dependency: transitive description: @@ -439,26 +383,10 @@ packages: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://pub.dev" - source: hosted - version: "1.9.0" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "6.0.2" - platform: - dependency: transitive - description: - name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" - url: "https://pub.dev" - source: hosted - version: "3.1.4" + version: "1.9.1" pool: dependency: transitive description: @@ -467,14 +395,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: - dependency: transitive - description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" - url: "https://pub.dev" - source: hosted - version: "4.2.4" pub_semver: dependency: transitive description: @@ -483,14 +403,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - pub_updater: - dependency: transitive - description: - name: pub_updater - sha256: "05ae70703e06f7fdeb05f7f02dd680b8aad810e87c756a618f33e1794635115c" - url: "https://pub.dev" - source: hosted - version: "0.3.0" pubspec_parse: dependency: transitive description: @@ -543,7 +455,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_gen: dependency: transitive description: @@ -580,18 +492,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" stream_transform: dependency: transitive description: @@ -620,26 +532,26 @@ packages: dependency: "direct dev" description: name: test - sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f + sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" url: "https://pub.dev" source: hosted - version: "1.24.9" + version: "1.26.3" test_api: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.7" test_core: dependency: transitive description: name: test_core - sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a + sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" url: "https://pub.dev" source: hosted - version: "0.5.9" + version: "0.6.12" timing: dependency: transitive description: @@ -656,22 +568,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - uuid: - dependency: transitive - description: - name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" - url: "https://pub.dev" - source: hosted - version: "3.0.7" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -712,14 +616,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" - xml: - dependency: transitive + xterm_core: + dependency: "direct main" description: - name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.dev" - source: hosted - version: "6.5.0" + path: "." + ref: HEAD + resolved-ref: a9f4d54c36890d349e673a46b8e638239914d0d0 + url: "https://github.com/isegal/xterm_core.dart" + source: git + version: "4.0.0" yaml: dependency: transitive description: @@ -737,5 +642,5 @@ packages: source: hosted version: "0.0.6" sdks: - dart: ">=3.3.0 <4.0.0" - flutter: ">=3.10.0" + dart: ">=3.8.0-0 <4.0.0" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml index 945265ef..67e21973 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,6 +3,8 @@ description: xterm.dart is a fast and fully-featured terminal emulator for Flutt version: 4.0.0 homepage: https://github.com/TerminalStudio/xterm.dart +publish_to: none + environment: sdk: ">=3.0.0 <4.0.0" flutter: ">=3.19.0" @@ -12,6 +14,10 @@ dependencies: meta: ^1.3.0 quiver: ^3.0.0 equatable: ^2.0.3 + xterm_core: + # NOTE: Temporary location until hand over to original maintainer and + # set up a pub.dev package. + git: https://github.com/isegal/xterm_core.dart flutter: sdk: flutter zmodem: ^0.0.6 @@ -21,7 +27,6 @@ dev_dependencies: sdk: flutter test: ^1.6.5 lints: ^3.0.0 - dart_code_metrics: ^5.0.0 mockito: ^5.3.1 build_runner: ^2.1.1 diff --git a/test/buffer/buffer_line_test.dart b/test/buffer/buffer_line_test.dart deleted file mode 100644 index 43d2cae0..00000000 --- a/test/buffer/buffer_line_test.dart +++ /dev/null @@ -1,251 +0,0 @@ -// import 'package:flutter_test/flutter_test.dart'; -// import 'package:xterm/buffer/line/line.dart'; -// import 'package:xterm/terminal/cursor.dart'; - -void main() { - // group("BufferLine Tests", () { - // test("creation test", () { - // final line = BufferLine(); - // expect(line, isNotNull); - // }); - - // test("set isWrapped", () { - // final line = BufferLine(isWrapped: false); - // expect(line.isWrapped, isFalse); - - // line.isWrapped = true; - // expect(line.isWrapped, isTrue); - - // line.isWrapped = false; - // expect(line.isWrapped, isFalse); - // }); - - // test("ensure() works", () { - // final line = BufferLine(length: 10); - // expect(() => line.cellSetContent(1000, 65), throwsRangeError); - - // line.ensure(1000); - // line.cellSetContent(1000, 65); - // }); - - // test("insert() works", () { - // final line = BufferLine(length: 10); - // line.cellSetContent(0, 65); - // line.cellSetContent(1, 66); - // line.cellSetContent(2, 67); - - // line.insert(1); - - // final result = [ - // line.cellGetContent(0), - // line.cellGetContent(1), - // line.cellGetContent(2), - // line.cellGetContent(3), - // ]; - - // expect(result, equals([65, 0, 66, 67])); - // }); - - // test("insertN() works", () { - // final line = BufferLine(length: 10); - // line.cellSetContent(0, 65); - // line.cellSetContent(1, 66); - // line.cellSetContent(2, 67); - - // line.insertN(1, 2); - - // final result = [ - // line.cellGetContent(0), - // line.cellGetContent(1), - // line.cellGetContent(2), - // line.cellGetContent(3), - // line.cellGetContent(4), - // ]; - - // expect(result, equals([65, 0, 0, 66, 67])); - // }); - - // test("removeN() works", () { - // final line = BufferLine(length: 10); - // line.cellSetContent(0, 65); - // line.cellSetContent(1, 66); - // line.cellSetContent(2, 67); - // line.cellSetContent(3, 68); - // line.cellSetContent(4, 69); - - // line.removeN(1, 2); - - // final result = [ - // line.cellGetContent(0), - // line.cellGetContent(1), - // line.cellGetContent(2), - // line.cellGetContent(3), - // line.cellGetContent(4), - // ]; - - // expect(result, equals([65, 68, 69, 0, 0])); - // }); - - // test("clear() works", () { - // final line = BufferLine(length: 10); - // line.cellSetContent(1, 65); - // line.cellSetContent(2, 66); - // line.cellSetContent(3, 67); - // line.cellSetContent(4, 68); - // line.cellSetContent(5, 69); - - // line.clear(); - - // final result = [ - // line.cellGetContent(1), - // line.cellGetContent(2), - // line.cellGetContent(3), - // line.cellGetContent(4), - // line.cellGetContent(5), - // ]; - - // expect(result, equals([0, 0, 0, 0, 0])); - // }); - - // test("cellInitialize() works", () { - // final line = BufferLine(length: 10); - // line.cellInitialize( - // 0, - // content: 0x01, - // width: 0x02, - // cursor: Cursor(fg: 0x03, bg: 0x04, flags: 0x05), - // ); - - // final result = [ - // line.cellGetContent(0), - // line.cellGetWidth(0), - // line.cellGetFgColor(0), - // line.cellGetBgColor(0), - // line.cellGetFlags(0), - // ]; - - // expect(result, equals([0x01, 0x02, 0x03, 0x04, 0x05])); - // }); - - // test("cellHasContent() works", () { - // final line = BufferLine(length: 10); - - // line.cellSetContent(0, 0x01); - // expect(line.cellHasContent(0), isTrue); - - // line.cellSetContent(0, 0x00); - // expect(line.cellHasContent(0), isFalse); - // }); - - // test("cellGetContent() and cellSetContent() works", () { - // final line = BufferLine(length: 10); - // final content = 0x01; - // line.cellSetContent(0, content); - // expect(line.cellGetContent(0), equals(content)); - // }); - - // test("cellGetFgColor() and cellSetFgColor() works", () { - // final line = BufferLine(length: 10); - // final content = 0x01; - // line.cellSetFgColor(0, content); - // expect(line.cellGetFgColor(0), equals(content)); - // }); - - // test("cellGetBgColor() and cellSetBgColor() works", () { - // final line = BufferLine(length: 10); - // final content = 0x01; - // line.cellSetBgColor(0, content); - // expect(line.cellGetBgColor(0), equals(content)); - // }); - - // test("cellHasFlag() and cellSetFlag() works", () { - // final line = BufferLine(length: 10); - // final flag = 0x03; - // line.cellSetFlag(0, flag); - // expect(line.cellHasFlag(0, flag), isTrue); - // }); - - // test("cellGetFlags() and cellSetFlags() works", () { - // final line = BufferLine(length: 10); - // final content = 0x01; - // line.cellSetFlags(0, content); - // expect(line.cellGetFlags(0), equals(content)); - // }); - - // test("cellGetWidth() and cellSetWidth() works", () { - // final line = BufferLine(length: 10); - // final content = 0x01; - // line.cellSetWidth(0, content); - // expect(line.cellGetWidth(0), equals(content)); - // }); - - // test("getTrimmedLength() works", () { - // final line = BufferLine(length: 10); - // expect(line.getTrimmedLength(), equals(0)); - - // line.cellSetContent(5, 0x01); - // expect(line.getTrimmedLength(), equals(5)); - - // line.clear(); - // expect(line.getTrimmedLength(), equals(0)); - // }); - - // test("copyCellsFrom() works", () { - // final line1 = BufferLine(length: 10); - // final line2 = BufferLine(length: 10); - - // line1.cellSetContent(0, 123); - // line1.cellSetContent(1, 124); - // line1.cellSetContent(2, 125); - - // line2.copyCellsFrom(line1, 1, 3, 2); - - // expect(line2.cellGetContent(2), equals(0)); - // expect(line2.cellGetContent(3), equals(124)); - // expect(line2.cellGetContent(4), equals(125)); - // expect(line2.cellGetContent(5), equals(0)); - // }); - - // test("removeRange() works", () { - // final line = BufferLine(length: 10); - // line.cellSetContent(0, 65); - // line.cellSetContent(1, 66); - // line.cellSetContent(2, 67); - // line.cellSetContent(3, 68); - // line.cellSetContent(4, 69); - - // line.removeRange(1, 3); - - // final result = [ - // line.cellGetContent(0), - // line.cellGetContent(1), - // line.cellGetContent(2), - // line.cellGetContent(3), - // line.cellGetContent(4), - // ]; - - // expect(result, equals([65, 68, 69, 0, 0])); - // }); - - // test("clearRange() works", () { - // final line = BufferLine(length: 10); - // line.cellSetContent(0, 65); - // line.cellSetContent(1, 66); - // line.cellSetContent(2, 67); - // line.cellSetContent(3, 68); - // line.cellSetContent(4, 69); - - // line.clearRange(1, 3); - - // final result = [ - // line.cellGetContent(0), - // line.cellGetContent(1), - // line.cellGetContent(2), - // line.cellGetContent(3), - // line.cellGetContent(4), - // ]; - - // expect(result, equals([65, 0, 0, 68, 69])); - // }); - // }); -} diff --git a/test/frontend/input_test.dart b/test/frontend/input_test.dart deleted file mode 100644 index bf439bb7..00000000 --- a/test/frontend/input_test.dart +++ /dev/null @@ -1,137 +0,0 @@ -// import 'package:flutter/material.dart'; -// import 'package:flutter/services.dart'; -// import 'package:flutter_test/flutter_test.dart'; -// import 'package:mockito/annotations.dart'; -// import 'package:mockito/mockito.dart'; -// import 'package:xterm/xterm.dart'; - -// @GenerateMocks([ -// TerminalUiInteraction, -// ]) -void main() { -// group('InputBehaviorDesktop', () { -// test('can handle fast typing', () { -// final mockTerminal = MockTerminalUiInteraction(); -// final inputBehavior = InputBehaviorDesktop(); - -// inputBehavior.onTextEdit(composing('l', -1, -1), mockTerminal); -// verify(mockTerminal.raiseOnInput('l')); -// verifyNever(mockTerminal.updateComposingString(any)); - -// inputBehavior.onTextEdit(composing('ls', -1, -1), mockTerminal); -// verify(mockTerminal.raiseOnInput('s')); -// verifyNever(mockTerminal.updateComposingString(any)); - -// inputBehavior.onTextEdit(TextEditingValue.empty, mockTerminal); -// verifyNever(mockTerminal.raiseOnInput(any)); -// verifyNever(mockTerminal.updateComposingString(any)); -// }); - -// test('can handle English', () { -// final mockTerminal = MockTerminalUiInteraction(); -// final inputBehavior = InputBehaviorDesktop(); - -// // typing 'hello' - -// inputBehavior.onTextEdit(composing('h', 1, 1), mockTerminal); -// verify(mockTerminal.raiseOnInput('h')); -// verifyNever(mockTerminal.updateComposingString(any)); - -// inputBehavior.onTextEdit(TextEditingValue.empty, mockTerminal); -// inputBehavior.onTextEdit(composing('e', 1, 1), mockTerminal); -// verify(mockTerminal.raiseOnInput('e')); -// verifyNever(mockTerminal.updateComposingString(any)); - -// inputBehavior.onTextEdit(TextEditingValue.empty, mockTerminal); -// inputBehavior.onTextEdit(composing('l', 1, 1), mockTerminal); -// verify(mockTerminal.raiseOnInput('l')); -// verifyNever(mockTerminal.updateComposingString(any)); - -// inputBehavior.onTextEdit(TextEditingValue.empty, mockTerminal); -// inputBehavior.onTextEdit(composing('l', 1, 1), mockTerminal); -// verify(mockTerminal.raiseOnInput('l')); -// verifyNever(mockTerminal.updateComposingString(any)); - -// inputBehavior.onTextEdit(TextEditingValue.empty, mockTerminal); -// inputBehavior.onTextEdit(composing('o', 1, 1), mockTerminal); -// verify(mockTerminal.raiseOnInput('o')); -// verifyNever(mockTerminal.updateComposingString(any)); -// }); - -// test('can handle Chinese', () { -// final mockTerminal = MockTerminalUiInteraction(); -// final inputBehavior = InputBehaviorDesktop(); - -// // typing '你好' - -// inputBehavior.onTextEdit(composing('n', 0, 1), mockTerminal); -// inputBehavior.onTextEdit(composing('ni', 0, 2), mockTerminal); -// inputBehavior.onTextEdit(composing('ni h', 0, 4), mockTerminal); -// inputBehavior.onTextEdit(composing('ni ha', 0, 5), mockTerminal); -// inputBehavior.onTextEdit(composing('ni hao', 0, 6), mockTerminal); -// inputBehavior.onTextEdit(composing('你好', 0, 2), mockTerminal); -// verify(mockTerminal.updateComposingString(any)).called(6); -// verifyNever(mockTerminal.raiseOnInput(any)); - -// inputBehavior.onTextEdit(composing('你好', -1, -1), mockTerminal); -// verify(mockTerminal.raiseOnInput('你好')); -// verify(mockTerminal.updateComposingString('')); -// }); - -// test('can handle Japanese', () { -// final mockTerminal = MockTerminalUiInteraction(); -// final inputBehavior = InputBehaviorDesktop(); - -// // typing 'どうも' - -// inputBehavior.onTextEdit(composing('d', 0, 1), mockTerminal); -// inputBehavior.onTextEdit(composing('ど', 0, 1), mockTerminal); -// inputBehavior.onTextEdit(composing('どう', 0, 2), mockTerminal); -// inputBehavior.onTextEdit(composing('どうm', 0, 3), mockTerminal); -// inputBehavior.onTextEdit(composing('どうも', 0, 3), mockTerminal); -// verify(mockTerminal.updateComposingString(any)).called(5); -// verifyNever(mockTerminal.raiseOnInput(any)); - -// inputBehavior.onTextEdit(composing('どうも', -1, -1), mockTerminal); -// verify(mockTerminal.raiseOnInput('どうも')); -// verify(mockTerminal.updateComposingString('')); -// }); - -// test('can handle Korean', () { -// final mockTerminal = MockTerminalUiInteraction(); -// final inputBehavior = InputBehaviorDesktop(); - -// // typing '안녕' - -// inputBehavior.onTextEdit(composing('ㅇ', 0, 1), mockTerminal); -// inputBehavior.onTextEdit(composing('아', 0, 1), mockTerminal); -// inputBehavior.onTextEdit(composing('안', 0, 1), mockTerminal); -// inputBehavior.onTextEdit(composing('안', 0, 1), mockTerminal); -// verify(mockTerminal.updateComposingString(any)).called(4); -// verifyNever(mockTerminal.raiseOnInput(any)); - -// inputBehavior.onTextEdit(composing('안', 1, 1), mockTerminal); -// verify(mockTerminal.raiseOnInput('안')); -// verify(mockTerminal.updateComposingString('')); - -// inputBehavior.onTextEdit(TextEditingValue.empty, mockTerminal); -// inputBehavior.onTextEdit(composing('ㄴ', 0, 1), mockTerminal); -// inputBehavior.onTextEdit(composing('녀', 0, 1), mockTerminal); -// inputBehavior.onTextEdit(composing('녕', 0, 1), mockTerminal); -// verify(mockTerminal.updateComposingString(any)).called(3); -// verifyNever(mockTerminal.raiseOnInput(any)); - -// inputBehavior.onTextEdit(composing('녕', 1, 1), mockTerminal); -// verify(mockTerminal.raiseOnInput('녕')); -// verify(mockTerminal.updateComposingString('')); -// }); -// }); -// } - -// TextEditingValue composing(String text, int start, int end) { -// return TextEditingValue( -// text: text, -// selection: TextSelection.collapsed(offset: text.length), -// composing: TextRange(start: start, end: end), -// ); -} diff --git a/test/src/core/buffer/buffer_test.dart b/test/src/core/buffer/buffer_test.dart deleted file mode 100644 index 384dc43c..00000000 --- a/test/src/core/buffer/buffer_test.dart +++ /dev/null @@ -1,247 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/xterm.dart'; - -void main() { - group('Buffer.getText()', () { - test('should return the text', () { - final terminal = Terminal(); - terminal.write('Hello World'); - expect(terminal.buffer.getText(), startsWith('Hello World')); - }); - - test('can handle line wrap', () { - final terminal = Terminal(); - terminal.resize(10, 10); - - final line1 = 'This is a long line that should wrap'; - final line2 = 'This is a short line'; - final line3 = 'This is a long long long long line that should wrap'; - final line4 = 'Short'; - - terminal.write('$line1\r\n'); - terminal.write('$line2\r\n'); - terminal.write('$line3\r\n'); - terminal.write('$line4\r\n'); - - final lines = terminal.buffer.getText().split('\n'); - expect(lines[0], line1); - expect(lines[1], line2); - expect(lines[2], line3); - expect(lines[3], line4); - }); - - test('can handle negative start', () { - final terminal = Terminal(); - - terminal.write('Hello World'); - - expect( - terminal.buffer.getText( - BufferRangeLine(CellOffset(-100, -100), CellOffset(100, 100)), - ), - startsWith('Hello World'), - ); - }); - - test('can handle invalid end', () { - final terminal = Terminal(); - - terminal.write('Hello World'); - - expect( - terminal.buffer.getText( - BufferRangeLine(CellOffset(0, 0), CellOffset(100, 100)), - ), - startsWith('Hello World'), - ); - }); - - test('can handle reversed range', () { - final terminal = Terminal(); - - terminal.write('Hello World'); - - expect( - terminal.buffer.getText( - BufferRangeLine(CellOffset(5, 5), CellOffset(0, 0)), - ), - startsWith('Hello World'), - ); - }); - - test('can handle block range', () { - final terminal = Terminal(); - - terminal.write('Hello World\r\n'); - terminal.write('Nice to meet you\r\n'); - - expect( - terminal.buffer.getText( - BufferRangeBlock(CellOffset(2, 0), CellOffset(5, 1)), - ), - startsWith('llo\nce '), - ); - }); - }); - - group('Buffer.resize()', () { - test('should resize the buffer', () { - final terminal = Terminal(); - terminal.resize(10, 10); - - expect(terminal.viewWidth, 10); - expect(terminal.viewHeight, 10); - - for (var i = 0; i < terminal.lines.length; i++) { - final line = terminal.lines[i]; - expect(line.length, 10); - } - - terminal.resize(20, 20); - - expect(terminal.viewWidth, 20); - expect(terminal.viewHeight, 20); - - for (var i = 0; i < terminal.lines.length; i++) { - final line = terminal.lines[i]; - expect(line.length, 20); - } - }); - }); - - group('Buffer.deleteLines()', () { - test('works', () { - final terminal = Terminal(); - terminal.resize(10, 10); - - for (var i = 1; i <= 10; i++) { - terminal.write('line$i'); - - if (i < 10) { - terminal.write('\r\n'); - } - } - - terminal.setMargins(3, 7); - terminal.setCursor(0, 5); - - terminal.buffer.deleteLines(1); - - expect(terminal.buffer.lines[2].toString(), 'line3'); - expect(terminal.buffer.lines[3].toString(), 'line4'); - expect(terminal.buffer.lines[4].toString(), 'line5'); - expect(terminal.buffer.lines[5].toString(), 'line7'); - expect(terminal.buffer.lines[6].toString(), 'line8'); - expect(terminal.buffer.lines[7].toString(), ''); - expect(terminal.buffer.lines[8].toString(), 'line9'); - expect(terminal.buffer.lines[9].toString(), 'line10'); - }); - }); - - group('Buffer.insertLines()', () { - test('works', () { - final terminal = Terminal(); - - for (var i = 0; i < 10; i++) { - terminal.write('line$i\r\n'); - } - - print(terminal.buffer); - - terminal.setMargins(2, 6); - terminal.setCursor(0, 4); - - print(terminal.buffer.absoluteCursorY); - - terminal.buffer.insertLines(1); - - print(terminal.buffer); - - expect(terminal.buffer.lines[3].toString(), 'line3'); - expect(terminal.buffer.lines[4].toString(), ''); // inserted - expect(terminal.buffer.lines[5].toString(), 'line4'); // moved - expect(terminal.buffer.lines[6].toString(), 'line5'); // moved - expect(terminal.buffer.lines[7].toString(), 'line7'); - }); - - test('has no effect if cursor is out of scroll region', () { - final terminal = Terminal(); - - for (var i = 0; i < 10; i++) { - terminal.write('line$i\r\n'); - } - - terminal.setMargins(2, 6); - terminal.setCursor(0, 1); - - terminal.buffer.insertLines(1); - - expect(terminal.buffer.lines[2].toString(), 'line2'); - expect(terminal.buffer.lines[3].toString(), 'line3'); - expect(terminal.buffer.lines[4].toString(), 'line4'); - expect(terminal.buffer.lines[5].toString(), 'line5'); - expect(terminal.buffer.lines[6].toString(), 'line6'); - expect(terminal.buffer.lines[7].toString(), 'line7'); - }); - }); - - group('Buffer.getWordBoundary supports custom word separators', () { - test('can set word separators', () { - final terminal = Terminal(wordSeparators: {'o'.codeUnitAt(0)}); - - terminal.write('Hello World'); - - expect( - terminal.mainBuffer.getWordBoundary(CellOffset(0, 0)), - BufferRangeLine(CellOffset(0, 0), CellOffset(4, 0)), - ); - - expect( - terminal.mainBuffer.getWordBoundary(CellOffset(5, 0)), - BufferRangeLine(CellOffset(5, 0), CellOffset(7, 0)), - ); - }); - }); - - test('does not delete lines beyond the scroll region', () { - final terminal = Terminal(); - terminal.resize(10, 10); - - for (var i = 1; i <= 10; i++) { - terminal.write('line$i'); - - if (i < 10) { - terminal.write('\r\n'); - } - } - - terminal.setMargins(3, 7); - terminal.setCursor(0, 5); - - terminal.buffer.deleteLines(20); - - expect(terminal.buffer.lines[2].toString(), 'line3'); - expect(terminal.buffer.lines[3].toString(), 'line4'); - expect(terminal.buffer.lines[4].toString(), 'line5'); - expect(terminal.buffer.lines[5].toString(), ''); - expect(terminal.buffer.lines[6].toString(), ''); - expect(terminal.buffer.lines[7].toString(), ''); - expect(terminal.buffer.lines[8].toString(), 'line9'); - expect(terminal.buffer.lines[9].toString(), 'line10'); - }); - - group('Buffer.eraseDisplayFromCursor()', () { - test('works', () { - final terminal = Terminal(); - terminal.resize(3, 3); - terminal.write('123\r\n456\r\n789'); - - terminal.setCursor(1, 1); - terminal.buffer.eraseDisplayFromCursor(); - - expect(terminal.buffer.lines[0].toString(), '123'); - expect(terminal.buffer.lines[1].toString(), '4'); - expect(terminal.buffer.lines[2].toString(), ''); - }); - }); -} diff --git a/test/src/core/buffer/line_test.dart b/test/src/core/buffer/line_test.dart deleted file mode 100644 index ff210174..00000000 --- a/test/src/core/buffer/line_test.dart +++ /dev/null @@ -1,122 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/xterm.dart'; - -void main() { - group('BufferLine.getText()', () { - test('should return the text', () { - final terminal = Terminal(); - terminal.write('Hello World'); - expect(terminal.buffer.lines[0].getText(), 'Hello World'); - }); - - test('getText() should support wide characters', () { - final text = '😀😁😂🤣😃'; - final terminal = Terminal(); - terminal.write(text); - expect(terminal.buffer.lines[0].getText(), equals(text)); - }); - - test('can specify a range', () { - final terminal = Terminal(); - terminal.write('Hello World'); - expect(terminal.buffer.lines[0].getText(0, 5), 'Hello'); - }); - - test('can handle invalid ranges', () { - final terminal = Terminal(); - terminal.write('Hello World'); - expect(terminal.buffer.lines[0].getText(0, 100), 'Hello World'); - }); - - test('can handle negative ranges', () { - final terminal = Terminal(); - terminal.write('Hello World'); - expect(terminal.buffer.lines[0].getText(-100, 100), 'Hello World'); - }); - - test('can handle reversed ranges', () { - final terminal = Terminal(); - terminal.write('Hello World'); - expect(terminal.buffer.lines[0].getText(5, 0), ''); - }); - }); - - group('BufferLine.getTrimmedLength()', () { - test('can get trimmed length', () { - final line = BufferLine(10); - - final text = 'ABCDEF'; - - for (var i = 0; i < text.length; i++) { - line.setCodePoint(i, text.codeUnitAt(i)); - } - - expect(line.getTrimmedLength(), equals(text.length)); - }); - - test('can get trimmed length with wide characters', () { - final terminal = Terminal(); - final text = '😀😁😂🤣😃'; - - terminal.write(text); - - expect(terminal.buffer.lines[0].getTrimmedLength(), equals(text.length)); - }); - - test('can handle length larger than the line', () { - final line = BufferLine(10); - - final text = 'ABCDEF'; - - for (var i = 0; i < text.length; i++) { - line.setCodePoint(i, text.codeUnitAt(i)); - } - - expect(line.getTrimmedLength(1000), equals(text.length)); - }); - - test('can handle negative start', () { - final line = BufferLine(10); - - final text = 'ABCDEF'; - - for (var i = 0; i < text.length; i++) { - line.setCodePoint(i, text.codeUnitAt(i)); - } - - expect(line.getTrimmedLength(-1000), equals(0)); - }); - }); - - group('BufferLine.resize', () { - test('can resize', () { - final line = BufferLine(10); - - final text = 'ABCDEF'; - - for (var i = 0; i < text.length; i++) { - line.setCodePoint(i, text.codeUnitAt(i)); - } - - line.resize(20); - - expect(line.length, equals(20)); - }); - }); - - group('Buffer.createAnchor', () { - test('works', () { - final terminal = Terminal(); - final line = terminal.buffer.lines[3]; - final anchor = line.createAnchor(5); - - terminal.insertLines(5); - expect(anchor.x, 5); - expect(anchor.y, 8); - - terminal.buffer.clear(); - expect(line.attached, false); - expect(anchor.attached, false); - }); - }); -} diff --git a/test/src/core/buffer/range_block_test.dart b/test/src/core/buffer/range_block_test.dart deleted file mode 100644 index f9272ffd..00000000 --- a/test/src/core/buffer/range_block_test.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/xterm.dart'; - -void main() { - group('BufferLineRange', () { - test('toSegments() works', () { - final range = BufferRangeBlock(CellOffset(10, 10), CellOffset(12, 12)); - final segments = range.toSegments().toList(); - - expect(segments, hasLength(3)); - - expect(segments[0].start, equals(10)); - expect(segments[0].end, equals(12)); - - expect(segments[1].start, equals(10)); - expect(segments[1].end, equals(12)); - - expect(segments[2].start, equals(10)); - expect(segments[2].end, 12); - }); - - test('toSegments() works with reversed range', () { - final range = BufferRangeBlock(CellOffset(12, 12), CellOffset(10, 10)); - final segments = range.toSegments().toList(); - - expect(segments, hasLength(3)); - - expect(segments[0].start, equals(10)); - expect(segments[0].end, equals(12)); - - expect(segments[1].start, equals(10)); - expect(segments[1].end, equals(12)); - - expect(segments[2].start, equals(10)); - expect(segments[2].end, 12); - }); - - test('contains() works', () { - final range = BufferRangeBlock(CellOffset(10, 10), CellOffset(10, 12)); - - expect(range.contains(CellOffset(10, 10)), isTrue); - expect(range.contains(CellOffset(10, 11)), isTrue); - expect(range.contains(CellOffset(10, 12)), isTrue); - - expect(range.contains(CellOffset(10, 9)), isFalse); - expect(range.contains(CellOffset(10, 13)), isFalse); - }); - - test('contains() works with reversed range', () { - final range = BufferRangeBlock(CellOffset(10, 12), CellOffset(10, 10)); - - expect(range.contains(CellOffset(10, 10)), isTrue); - expect(range.contains(CellOffset(10, 11)), isTrue); - expect(range.contains(CellOffset(10, 12)), isTrue); - - expect(range.contains(CellOffset(10, 9)), isFalse); - expect(range.contains(CellOffset(10, 13)), isFalse); - }); - - test('merge() works', () { - final range1 = BufferRangeBlock(CellOffset(10, 10), CellOffset(10, 12)); - final range2 = BufferRangeBlock(CellOffset(10, 13), CellOffset(10, 15)); - - final merged = range1.merge(range2); - - expect(merged.begin, equals(CellOffset(10, 10))); - expect(merged.end, equals(CellOffset(10, 15))); - }); - - test('merge() works with reversed range', () { - final range1 = BufferRangeBlock(CellOffset(10, 12), CellOffset(10, 10)); - final range2 = BufferRangeBlock(CellOffset(10, 13), CellOffset(10, 15)); - - final merged = range1.merge(range2); - - expect(merged.begin, equals(CellOffset(10, 10))); - expect(merged.end, equals(CellOffset(10, 15))); - }); - - test('extend() works', () { - final range = BufferRangeBlock(CellOffset(10, 10), CellOffset(10, 12)); - - final extended = range.extend(CellOffset(10, 13)); - - expect(extended.begin, equals(CellOffset(10, 10))); - expect(extended.end, equals(CellOffset(10, 13))); - }); - - test('extend() works with reversed range', () { - final range = BufferRangeBlock(CellOffset(10, 12), CellOffset(10, 10)); - - final extended = range.extend(CellOffset(10, 13)); - - expect(extended.begin, equals(CellOffset(10, 10))); - expect(extended.end, equals(CellOffset(10, 13))); - }); - - test('extend() works with reversed range and reversed extend', () { - final range = BufferRangeBlock(CellOffset(10, 12), CellOffset(10, 10)); - - final extended = range.extend(CellOffset(10, 9)); - - expect(extended.begin, equals(CellOffset(10, 9))); - expect(extended.end, equals(CellOffset(10, 12))); - }); - }); -} diff --git a/test/src/core/buffer/range_line_test.dart b/test/src/core/buffer/range_line_test.dart deleted file mode 100644 index 7a3e73b1..00000000 --- a/test/src/core/buffer/range_line_test.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/xterm.dart'; - -void main() { - group('BufferRangeLine', () { - test('toSegments() works', () { - final range = BufferRangeLine(CellOffset(10, 10), CellOffset(10, 12)); - final segments = range.toSegments().toList(); - - expect(segments, hasLength(3)); - - expect(segments[0].start, equals(10)); - expect(segments[0].end, null); - - expect(segments[1].start, null); - expect(segments[1].end, null); - - expect(segments[2].start, null); - expect(segments[2].end, 10); - }); - - test('toSegments() works with reversed range', () { - final range = BufferRangeLine(CellOffset(10, 12), CellOffset(10, 10)); - final segments = range.toSegments().toList(); - - expect(segments, hasLength(3)); - - expect(segments[0].start, 10); - expect(segments[0].end, null); - - expect(segments[1].start, null); - expect(segments[1].end, null); - - expect(segments[2].start, null); - expect(segments[2].end, 10); - }); - - test('contains() works', () { - final range = BufferRangeLine(CellOffset(10, 10), CellOffset(10, 12)); - - expect(range.contains(CellOffset(10, 10)), isTrue); - expect(range.contains(CellOffset(10, 11)), isTrue); - expect(range.contains(CellOffset(10, 12)), isTrue); - - expect(range.contains(CellOffset(10, 9)), isFalse); - expect(range.contains(CellOffset(10, 13)), isFalse); - }); - - test('contains() works with reversed range', () { - final range = BufferRangeLine(CellOffset(10, 12), CellOffset(10, 10)); - - expect(range.contains(CellOffset(10, 10)), isTrue); - expect(range.contains(CellOffset(10, 11)), isTrue); - expect(range.contains(CellOffset(10, 12)), isTrue); - - expect(range.contains(CellOffset(10, 9)), isFalse); - expect(range.contains(CellOffset(10, 13)), isFalse); - }); - - test('merge() works', () { - final range1 = BufferRangeLine(CellOffset(10, 10), CellOffset(10, 12)); - final range2 = BufferRangeLine(CellOffset(10, 13), CellOffset(10, 15)); - - final merged = range1.merge(range2); - - expect(merged.begin, equals(CellOffset(10, 10))); - expect(merged.end, equals(CellOffset(10, 15))); - }); - - test('merge() works with reversed range', () { - final range1 = BufferRangeLine(CellOffset(10, 12), CellOffset(10, 10)); - final range2 = BufferRangeLine(CellOffset(10, 13), CellOffset(10, 15)); - - final merged = range1.merge(range2); - - expect(merged.begin, equals(CellOffset(10, 10))); - expect(merged.end, equals(CellOffset(10, 15))); - }); - - test('extend() works', () { - final range = BufferRangeLine(CellOffset(10, 10), CellOffset(10, 12)); - - final extended = range.extend(CellOffset(10, 13)); - - expect(extended.begin, equals(CellOffset(10, 10))); - expect(extended.end, equals(CellOffset(10, 13))); - }); - - test('extend() works with reversed range', () { - final range = BufferRangeLine(CellOffset(10, 12), CellOffset(10, 10)); - - final extended = range.extend(CellOffset(10, 13)); - - expect(extended.begin, equals(CellOffset(10, 10))); - expect(extended.end, equals(CellOffset(10, 13))); - }); - - test('extend() works with reversed range and reversed extend', () { - final range = BufferRangeLine(CellOffset(10, 12), CellOffset(10, 10)); - - final extended = range.extend(CellOffset(10, 9)); - - expect(extended.begin, equals(CellOffset(10, 9))); - expect(extended.end, equals(CellOffset(10, 12))); - }); - }); -} diff --git a/test/src/core/buffer/segment_test.dart b/test/src/core/buffer/segment_test.dart deleted file mode 100644 index 914f4d18..00000000 --- a/test/src/core/buffer/segment_test.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/xterm.dart'; - -void main() { - group('BufferSegment', () { - test('isWithin() works', () { - final segments = BufferRangeLine(CellOffset(10, 10), CellOffset(10, 12)) - .toSegments() - .toList(); - - expect(segments[0].start, equals(10)); - expect(segments[0].end, null); - expect(segments[0].isWithin(CellOffset(10, 10)), isTrue); - expect(segments[0].isWithin(CellOffset(11, 10)), isTrue); - expect(segments[0].isWithin(CellOffset(100, 10)), isTrue); - expect(segments[0].isWithin(CellOffset(9, 10)), isFalse); - - expect(segments[1].start, null); - expect(segments[1].end, null); - expect(segments[1].isWithin(CellOffset(10, 11)), isTrue); - expect(segments[1].isWithin(CellOffset(11, 11)), isTrue); - expect(segments[1].isWithin(CellOffset(100, 11)), isTrue); - expect(segments[1].isWithin(CellOffset(0, 11)), isTrue); - - expect(segments[2].start, null); - expect(segments[2].end, 10); - expect(segments[2].isWithin(CellOffset(0, 12)), isTrue); - expect(segments[2].isWithin(CellOffset(10, 12)), isTrue); - expect(segments[2].isWithin(CellOffset(11, 12)), isFalse); - }); - }); -} diff --git a/test/src/core/escape/parser_test.dart b/test/src/core/escape/parser_test.dart deleted file mode 100644 index 96fa5bb1..00000000 --- a/test/src/core/escape/parser_test.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:mockito/annotations.dart'; -import 'package:mockito/mockito.dart'; -import 'package:test/test.dart'; -import 'package:xterm/xterm.dart'; - -@GenerateNiceMocks([MockSpec()]) -import 'parser_test.mocks.dart'; - -void main() { - group('EscapeParser', () { - test('can parse window manipulation', () { - final parser = EscapeParser(MockEscapeHandler()); - parser.write('\x1b[8;24;80t'); - verify(parser.handler.resize(80, 24)); - }); - }); -} diff --git a/test/src/core/escape/parser_test.mocks.dart b/test/src/core/escape/parser_test.mocks.dart deleted file mode 100644 index dad85800..00000000 --- a/test/src/core/escape/parser_test.mocks.dart +++ /dev/null @@ -1,870 +0,0 @@ -// Mocks generated by Mockito 5.3.1 from annotations -// in xterm/test/src/core/escape/parser_test.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:mockito/mockito.dart' as _i1; -import 'package:xterm/src/core/escape/handler.dart' as _i2; -import 'package:xterm/src/core/mouse/mode.dart' as _i3; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class - -/// A class which mocks [EscapeHandler]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockEscapeHandler extends _i1.Mock implements _i2.EscapeHandler { - @override - void writeChar(int? char) => super.noSuchMethod( - Invocation.method( - #writeChar, - [char], - ), - returnValueForMissingStub: null, - ); - @override - void bell() => super.noSuchMethod( - Invocation.method( - #bell, - [], - ), - returnValueForMissingStub: null, - ); - @override - void backspaceReturn() => super.noSuchMethod( - Invocation.method( - #backspaceReturn, - [], - ), - returnValueForMissingStub: null, - ); - @override - void tab() => super.noSuchMethod( - Invocation.method( - #tab, - [], - ), - returnValueForMissingStub: null, - ); - @override - void lineFeed() => super.noSuchMethod( - Invocation.method( - #lineFeed, - [], - ), - returnValueForMissingStub: null, - ); - @override - void carriageReturn() => super.noSuchMethod( - Invocation.method( - #carriageReturn, - [], - ), - returnValueForMissingStub: null, - ); - @override - void shiftOut() => super.noSuchMethod( - Invocation.method( - #shiftOut, - [], - ), - returnValueForMissingStub: null, - ); - @override - void shiftIn() => super.noSuchMethod( - Invocation.method( - #shiftIn, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unknownSBC(int? char) => super.noSuchMethod( - Invocation.method( - #unknownSBC, - [char], - ), - returnValueForMissingStub: null, - ); - @override - void saveCursor() => super.noSuchMethod( - Invocation.method( - #saveCursor, - [], - ), - returnValueForMissingStub: null, - ); - @override - void restoreCursor() => super.noSuchMethod( - Invocation.method( - #restoreCursor, - [], - ), - returnValueForMissingStub: null, - ); - @override - void index() => super.noSuchMethod( - Invocation.method( - #index, - [], - ), - returnValueForMissingStub: null, - ); - @override - void nextLine() => super.noSuchMethod( - Invocation.method( - #nextLine, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setTapStop() => super.noSuchMethod( - Invocation.method( - #setTapStop, - [], - ), - returnValueForMissingStub: null, - ); - @override - void reverseIndex() => super.noSuchMethod( - Invocation.method( - #reverseIndex, - [], - ), - returnValueForMissingStub: null, - ); - @override - void designateCharset(int? charset, int? name) => super.noSuchMethod( - Invocation.method( - #designateCharset, - [charset, name], - ), - returnValueForMissingStub: null, - ); - @override - void unkownEscape(int? char) => super.noSuchMethod( - Invocation.method( - #unkownEscape, - [char], - ), - returnValueForMissingStub: null, - ); - @override - void repeatPreviousCharacter(int? n) => super.noSuchMethod( - Invocation.method( - #repeatPreviousCharacter, - [n], - ), - returnValueForMissingStub: null, - ); - @override - void setCursor( - int? x, - int? y, - ) => - super.noSuchMethod( - Invocation.method( - #setCursor, - [ - x, - y, - ], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorX(int? x) => super.noSuchMethod( - Invocation.method( - #setCursorX, - [x], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorY(int? y) => super.noSuchMethod( - Invocation.method( - #setCursorY, - [y], - ), - returnValueForMissingStub: null, - ); - @override - void sendPrimaryDeviceAttributes() => super.noSuchMethod( - Invocation.method( - #sendPrimaryDeviceAttributes, - [], - ), - returnValueForMissingStub: null, - ); - @override - void clearTabStopUnderCursor() => super.noSuchMethod( - Invocation.method( - #clearTabStopUnderCursor, - [], - ), - returnValueForMissingStub: null, - ); - @override - void clearAllTabStops() => super.noSuchMethod( - Invocation.method( - #clearAllTabStops, - [], - ), - returnValueForMissingStub: null, - ); - @override - void moveCursorX(int? offset) => super.noSuchMethod( - Invocation.method( - #moveCursorX, - [offset], - ), - returnValueForMissingStub: null, - ); - @override - void moveCursorY(int? n) => super.noSuchMethod( - Invocation.method( - #moveCursorY, - [n], - ), - returnValueForMissingStub: null, - ); - @override - void sendSecondaryDeviceAttributes() => super.noSuchMethod( - Invocation.method( - #sendSecondaryDeviceAttributes, - [], - ), - returnValueForMissingStub: null, - ); - @override - void sendTertiaryDeviceAttributes() => super.noSuchMethod( - Invocation.method( - #sendTertiaryDeviceAttributes, - [], - ), - returnValueForMissingStub: null, - ); - @override - void sendOperatingStatus() => super.noSuchMethod( - Invocation.method( - #sendOperatingStatus, - [], - ), - returnValueForMissingStub: null, - ); - @override - void sendCursorPosition() => super.noSuchMethod( - Invocation.method( - #sendCursorPosition, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setMargins( - int? i, [ - int? bottom, - ]) => - super.noSuchMethod( - Invocation.method( - #setMargins, - [ - i, - bottom, - ], - ), - returnValueForMissingStub: null, - ); - @override - void cursorNextLine(int? amount) => super.noSuchMethod( - Invocation.method( - #cursorNextLine, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void cursorPrecedingLine(int? amount) => super.noSuchMethod( - Invocation.method( - #cursorPrecedingLine, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void eraseDisplayBelow() => super.noSuchMethod( - Invocation.method( - #eraseDisplayBelow, - [], - ), - returnValueForMissingStub: null, - ); - @override - void eraseDisplayAbove() => super.noSuchMethod( - Invocation.method( - #eraseDisplayAbove, - [], - ), - returnValueForMissingStub: null, - ); - @override - void eraseDisplay() => super.noSuchMethod( - Invocation.method( - #eraseDisplay, - [], - ), - returnValueForMissingStub: null, - ); - @override - void eraseScrollbackOnly() => super.noSuchMethod( - Invocation.method( - #eraseScrollbackOnly, - [], - ), - returnValueForMissingStub: null, - ); - @override - void eraseLineRight() => super.noSuchMethod( - Invocation.method( - #eraseLineRight, - [], - ), - returnValueForMissingStub: null, - ); - @override - void eraseLineLeft() => super.noSuchMethod( - Invocation.method( - #eraseLineLeft, - [], - ), - returnValueForMissingStub: null, - ); - @override - void eraseLine() => super.noSuchMethod( - Invocation.method( - #eraseLine, - [], - ), - returnValueForMissingStub: null, - ); - @override - void insertLines(int? amount) => super.noSuchMethod( - Invocation.method( - #insertLines, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void deleteLines(int? amount) => super.noSuchMethod( - Invocation.method( - #deleteLines, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void deleteChars(int? amount) => super.noSuchMethod( - Invocation.method( - #deleteChars, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void scrollUp(int? amount) => super.noSuchMethod( - Invocation.method( - #scrollUp, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void scrollDown(int? amount) => super.noSuchMethod( - Invocation.method( - #scrollDown, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void eraseChars(int? amount) => super.noSuchMethod( - Invocation.method( - #eraseChars, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void insertBlankChars(int? amount) => super.noSuchMethod( - Invocation.method( - #insertBlankChars, - [amount], - ), - returnValueForMissingStub: null, - ); - @override - void unknownCSI(int? finalByte) => super.noSuchMethod( - Invocation.method( - #unknownCSI, - [finalByte], - ), - returnValueForMissingStub: null, - ); - @override - void setInsertMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setInsertMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setLineFeedMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setLineFeedMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setUnknownMode( - int? mode, - bool? enabled, - ) => - super.noSuchMethod( - Invocation.method( - #setUnknownMode, - [ - mode, - enabled, - ], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorKeysMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setCursorKeysMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setReverseDisplayMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setReverseDisplayMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setOriginMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setOriginMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setColumnMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setColumnMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setAutoWrapMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setAutoWrapMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setMouseMode(_i3.MouseMode? mode) => super.noSuchMethod( - Invocation.method( - #setMouseMode, - [mode], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorBlinkMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setCursorBlinkMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorVisibleMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setCursorVisibleMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void useAltBuffer() => super.noSuchMethod( - Invocation.method( - #useAltBuffer, - [], - ), - returnValueForMissingStub: null, - ); - @override - void useMainBuffer() => super.noSuchMethod( - Invocation.method( - #useMainBuffer, - [], - ), - returnValueForMissingStub: null, - ); - @override - void clearAltBuffer() => super.noSuchMethod( - Invocation.method( - #clearAltBuffer, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setAppKeypadMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setAppKeypadMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setReportFocusMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setReportFocusMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setMouseReportMode(_i3.MouseReportMode? mode) => super.noSuchMethod( - Invocation.method( - #setMouseReportMode, - [mode], - ), - returnValueForMissingStub: null, - ); - @override - void setAltBufferMouseScrollMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setAltBufferMouseScrollMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setBracketedPasteMode(bool? enabled) => super.noSuchMethod( - Invocation.method( - #setBracketedPasteMode, - [enabled], - ), - returnValueForMissingStub: null, - ); - @override - void setUnknownDecMode( - int? mode, - bool? enabled, - ) => - super.noSuchMethod( - Invocation.method( - #setUnknownDecMode, - [ - mode, - enabled, - ], - ), - returnValueForMissingStub: null, - ); - @override - void resize( - int? cols, - int? rows, - ) => - super.noSuchMethod( - Invocation.method( - #resize, - [ - cols, - rows, - ], - ), - returnValueForMissingStub: null, - ); - @override - void sendSize() => super.noSuchMethod( - Invocation.method( - #sendSize, - [], - ), - returnValueForMissingStub: null, - ); - @override - void resetCursorStyle() => super.noSuchMethod( - Invocation.method( - #resetCursorStyle, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorBold() => super.noSuchMethod( - Invocation.method( - #setCursorBold, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorFaint() => super.noSuchMethod( - Invocation.method( - #setCursorFaint, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorItalic() => super.noSuchMethod( - Invocation.method( - #setCursorItalic, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorUnderline() => super.noSuchMethod( - Invocation.method( - #setCursorUnderline, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorBlink() => super.noSuchMethod( - Invocation.method( - #setCursorBlink, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorInverse() => super.noSuchMethod( - Invocation.method( - #setCursorInverse, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorInvisible() => super.noSuchMethod( - Invocation.method( - #setCursorInvisible, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setCursorStrikethrough() => super.noSuchMethod( - Invocation.method( - #setCursorStrikethrough, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsetCursorBold() => super.noSuchMethod( - Invocation.method( - #unsetCursorBold, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsetCursorFaint() => super.noSuchMethod( - Invocation.method( - #unsetCursorFaint, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsetCursorItalic() => super.noSuchMethod( - Invocation.method( - #unsetCursorItalic, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsetCursorUnderline() => super.noSuchMethod( - Invocation.method( - #unsetCursorUnderline, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsetCursorBlink() => super.noSuchMethod( - Invocation.method( - #unsetCursorBlink, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsetCursorInverse() => super.noSuchMethod( - Invocation.method( - #unsetCursorInverse, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsetCursorInvisible() => super.noSuchMethod( - Invocation.method( - #unsetCursorInvisible, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsetCursorStrikethrough() => super.noSuchMethod( - Invocation.method( - #unsetCursorStrikethrough, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setForegroundColor16(int? color) => super.noSuchMethod( - Invocation.method( - #setForegroundColor16, - [color], - ), - returnValueForMissingStub: null, - ); - @override - void setForegroundColor256(int? index) => super.noSuchMethod( - Invocation.method( - #setForegroundColor256, - [index], - ), - returnValueForMissingStub: null, - ); - @override - void setForegroundColorRgb( - int? r, - int? g, - int? b, - ) => - super.noSuchMethod( - Invocation.method( - #setForegroundColorRgb, - [ - r, - g, - b, - ], - ), - returnValueForMissingStub: null, - ); - @override - void resetForeground() => super.noSuchMethod( - Invocation.method( - #resetForeground, - [], - ), - returnValueForMissingStub: null, - ); - @override - void setBackgroundColor16(int? color) => super.noSuchMethod( - Invocation.method( - #setBackgroundColor16, - [color], - ), - returnValueForMissingStub: null, - ); - @override - void setBackgroundColor256(int? index) => super.noSuchMethod( - Invocation.method( - #setBackgroundColor256, - [index], - ), - returnValueForMissingStub: null, - ); - @override - void setBackgroundColorRgb( - int? r, - int? g, - int? b, - ) => - super.noSuchMethod( - Invocation.method( - #setBackgroundColorRgb, - [ - r, - g, - b, - ], - ), - returnValueForMissingStub: null, - ); - @override - void resetBackground() => super.noSuchMethod( - Invocation.method( - #resetBackground, - [], - ), - returnValueForMissingStub: null, - ); - @override - void unsupportedStyle(int? param) => super.noSuchMethod( - Invocation.method( - #unsupportedStyle, - [param], - ), - returnValueForMissingStub: null, - ); - @override - void setTitle(String? name) => super.noSuchMethod( - Invocation.method( - #setTitle, - [name], - ), - returnValueForMissingStub: null, - ); - @override - void setIconName(String? name) => super.noSuchMethod( - Invocation.method( - #setIconName, - [name], - ), - returnValueForMissingStub: null, - ); - @override - void unknownOSC(String? code, List? args) => super.noSuchMethod( - Invocation.method( - #unknownOSC, - [code], - ), - returnValueForMissingStub: null, - ); -} diff --git a/test/src/core/input/handler_test.dart b/test/src/core/input/handler_test.dart deleted file mode 100644 index 724f0e04..00000000 --- a/test/src/core/input/handler_test.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/src/core/input/keytab/keytab.dart'; -import 'package:xterm/xterm.dart'; - -void main() { - group('defaultInputHandler', () { - test('supports numpad enter', () { - final output = []; - final terminal = Terminal(onOutput: output.add); - terminal.keyInput(TerminalKey.numpadEnter); - expect(output, ['\r']); - }); - }); - - group('KeytabInputHandler', () { - test('can insert modifier code', () { - final handler = KeytabInputHandler( - Keytab.parse(r'key Home +AnyMod : "\E[1;*H"'), - ); - - final terminal = Terminal(inputHandler: handler); - - late String output; - - terminal.onOutput = (data) { - output = data; - }; - - terminal.keyInput(TerminalKey.home, ctrl: true); - - expect(output, '\x1b[1;5H'); - - terminal.keyInput(TerminalKey.home, shift: true); - - expect(output, '\x1b[1;2H'); - }); - }); -} diff --git a/test/src/core/input/keytab/keytab_test.dart b/test/src/core/input/keytab/keytab_test.dart deleted file mode 100644 index 1f577633..00000000 --- a/test/src/core/input/keytab/keytab_test.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/src/core/input/keys.dart'; -import 'package:xterm/src/core/input/keytab/keytab.dart'; - -void main() { - group('Keytab.find()', () { - test('can match keyPad', () { - final keytab = Keytab.parse(r'key Home +KeyPad : "TEST"'); - final record = keytab.find(TerminalKey.home, keyPad: true); - expect(record!.action.unescapedValue(), 'TEST'); - - final record1 = keytab.find(TerminalKey.home); - expect(record1, isNull); - }); - }); -} diff --git a/test/src/core/mouse/reporter_test.dart b/test/src/core/mouse/reporter_test.dart deleted file mode 100644 index 79eb7cdb..00000000 --- a/test/src/core/mouse/reporter_test.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/src/core/mouse/reporter.dart'; -import 'package:xterm/xterm.dart'; - -void main() { - group('MouseReporter', () { - test('report() supports normal mode', () { - final output = MouseReporter.report( - TerminalMouseButton.left, - TerminalMouseButtonState.down, - CellOffset(0, 0), - MouseReportMode.normal, - ); - - expect(output, equals('\x1B[M !"')); - }); - - test('report() supports utf mode', () { - final output = MouseReporter.report( - TerminalMouseButton.left, - TerminalMouseButtonState.down, - CellOffset(0, 0), - MouseReportMode.utf, - ); - - expect(output, equals('\x1B[M !"')); - }); - - test('report() supports sgr mode', () { - final output = MouseReporter.report( - TerminalMouseButton.left, - TerminalMouseButtonState.down, - CellOffset(0, 0), - MouseReportMode.sgr, - ); - - expect(output, equals('\x1B[<0;1;1M')); - }); - - test('report() supports urxvt mode', () { - final output = MouseReporter.report( - TerminalMouseButton.left, - TerminalMouseButtonState.down, - CellOffset(0, 0), - MouseReportMode.urxvt, - ); - - expect(output, equals('\x1B[32;1;1M')); - }); - }); -} diff --git a/test/src/core/reflow_test.dart b/test/src/core/reflow_test.dart deleted file mode 100644 index 8a345f31..00000000 --- a/test/src/core/reflow_test.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/src/terminal.dart'; - -void main() { - test('reflow() can reflow a single line', () { - final terminal = Terminal(); - - terminal.write('1234567890abcdefg'); - terminal.resize(10, 10); - - expect(terminal.buffer.lines[0].toString(), '1234567890'); - expect(terminal.buffer.lines[1].toString(), 'abcdefg'); - expect(terminal.buffer.lines[0].isWrapped, isFalse); - expect(terminal.buffer.lines[1].isWrapped, isTrue); - - terminal.resize(13, 10); - - expect(terminal.buffer.lines[0].toString(), '1234567890abc'); - expect(terminal.buffer.lines[1].toString(), 'defg'); - expect(terminal.buffer.lines[0].isWrapped, isFalse); - expect(terminal.buffer.lines[1].isWrapped, isTrue); - - terminal.resize(20, 10); - - expect(terminal.buffer.lines[0].toString(), '1234567890abcdefg'); - expect(terminal.buffer.lines[0].isWrapped, isFalse); - }); - - test('reflow() can reflow a single line to multiple lines', () { - final terminal = Terminal(); - - terminal.write('1234567890abcdefg'); - terminal.resize(5, 10); - - expect(terminal.buffer.lines[0].toString(), '12345'); - expect(terminal.buffer.lines[1].toString(), '67890'); - expect(terminal.buffer.lines[2].toString(), 'abcde'); - expect(terminal.buffer.lines[3].toString(), 'fg'); - - expect(terminal.buffer.lines[0].isWrapped, isFalse); - expect(terminal.buffer.lines[1].isWrapped, isTrue); - expect(terminal.buffer.lines[2].isWrapped, isTrue); - expect(terminal.buffer.lines[3].isWrapped, isTrue); - - terminal.resize(6, 10); - - expect(terminal.buffer.lines[0].toString(), '123456'); - expect(terminal.buffer.lines[1].toString(), '7890ab'); - expect(terminal.buffer.lines[2].toString(), 'cdefg'); - - expect(terminal.buffer.lines[0].isWrapped, isFalse); - expect(terminal.buffer.lines[1].isWrapped, isTrue); - expect(terminal.buffer.lines[2].isWrapped, isTrue); - }); - - test('reflow() can reflow wide characters', () { - final terminal = Terminal(); - - terminal.write('床前明月光疑是地上霜'); - terminal.resize(10, 10); - - expect(terminal.buffer.lines[0].toString(), '床前明月光'); - expect(terminal.buffer.lines[1].toString(), '疑是地上霜'); - - terminal.resize(9, 10); - - expect(terminal.buffer.lines[0].toString(), '床前明月'); - expect(terminal.buffer.lines[1].toString(), '光疑是地'); - expect(terminal.buffer.lines[2].toString(), '上霜'); - - terminal.resize(11, 10); - - expect(terminal.buffer.lines[0].toString(), '床前明月光'); - expect(terminal.buffer.lines[1].toString(), '疑是地上霜'); - - terminal.resize(13, 10); - expect(terminal.buffer.lines[0].toString(), '床前明月光疑'); - expect(terminal.buffer.lines[1].toString(), '是地上霜'); - }); - - test('lines has correct length after reflow', () { - final terminal = Terminal(); - - terminal.write('1234567890abcdefg'); - terminal.resize(10, 10); - - for (var i = 0; i < 10; i++) { - expect(terminal.buffer.lines[i].length, 10); - } - - terminal.resize(13, 10); - for (var i = 0; i < 10; i++) { - expect(terminal.buffer.lines[i].length, 13); - } - }); -} diff --git a/test/src/core/tabs_test.dart b/test/src/core/tabs_test.dart deleted file mode 100644 index 8c17e420..00000000 --- a/test/src/core/tabs_test.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:xterm/src/core/tabs.dart'; - -void main() { - group('TabStops', () { - test('has default tab stops after created', () { - final tabStops = TabStops(); - - expect(tabStops.isSetAt(0), true); - expect(tabStops.isSetAt(1), false); - expect(tabStops.isSetAt(7), false); - expect(tabStops.isSetAt(8), true); - expect(tabStops.isSetAt(9), false); - expect(tabStops.isSetAt(15), false); - expect(tabStops.isSetAt(16), true); - }); - }); - - group('TabStops.find()', () { - test('includes start', () { - final tabStops = TabStops(); - expect(tabStops.find(0, 10), 0); - }); - - test('excludes end', () { - final tabStops = TabStops(); - expect(tabStops.find(0, 8), 0); - expect(tabStops.find(1, 9), 8); - }); - }); -} diff --git a/test/src/terminal_test.dart b/test/src/terminal_test.dart deleted file mode 100644 index d54d649f..00000000 --- a/test/src/terminal_test.dart +++ /dev/null @@ -1,209 +0,0 @@ -import 'package:test/test.dart'; -import 'package:xterm/core.dart'; - -void main() { - group('Terminal.inputHandler', () { - test('can be set to null', () { - final terminal = Terminal(inputHandler: null); - expect(() => terminal.keyInput(TerminalKey.keyA), returnsNormally); - }); - - test('can be changed', () { - final handler1 = _TestInputHandler(); - final handler2 = _TestInputHandler(); - final terminal = Terminal(inputHandler: handler1); - - terminal.keyInput(TerminalKey.keyA); - expect(handler1.events, isNotEmpty); - - terminal.inputHandler = handler2; - - terminal.keyInput(TerminalKey.keyA); - expect(handler2.events, isNotEmpty); - }); - }); - - group('Terminal.mouseInput', () { - test('can handle mouse events', () { - final output = []; - - final terminal = Terminal(onOutput: output.add); - - terminal.mouseInput( - TerminalMouseButton.left, - TerminalMouseButtonState.down, - CellOffset(10, 10), - ); - - expect(output, isEmpty); - - // enable mouse reporting - terminal.write('\x1b[?1000h'); - - terminal.mouseInput( - TerminalMouseButton.left, - TerminalMouseButtonState.down, - CellOffset(10, 10), - ); - - expect(output, ['\x1B[M +,']); - }); - }); - - group('Terminal.reflowEnabled', () { - test('prevents reflow when set to false', () { - final terminal = Terminal(reflowEnabled: false); - - terminal.write('Hello World'); - terminal.resize(5, 5); - - expect(terminal.buffer.lines[0].toString(), 'Hello'); - expect(terminal.buffer.lines[1].toString(), isEmpty); - }); - - test('preserves hidden cells when reflow is disabled', () { - final terminal = Terminal(reflowEnabled: false); - - terminal.write('Hello World'); - terminal.resize(5, 5); - terminal.resize(20, 5); - - expect(terminal.buffer.lines[0].toString(), 'Hello World'); - expect(terminal.buffer.lines[1].toString(), isEmpty); - }); - - test('can be set at runtime', () { - final terminal = Terminal(reflowEnabled: true); - - terminal.resize(5, 5); - terminal.write('Hello World'); - terminal.reflowEnabled = false; - terminal.resize(20, 5); - - expect(terminal.buffer.lines[0].toString(), 'Hello'); - expect(terminal.buffer.lines[1].toString(), ' Worl'); - expect(terminal.buffer.lines[2].toString(), 'd'); - }); - }); - - group('Terminal.mouseInput', () { - test('applys to the main buffer', () { - final terminal = Terminal( - wordSeparators: { - 'z'.codeUnitAt(0), - }, - ); - - expect( - terminal.mainBuffer.wordSeparators, - contains('z'.codeUnitAt(0)), - ); - }); - - test('applys to the alternate buffer', () { - final terminal = Terminal( - wordSeparators: { - 'z'.codeUnitAt(0), - }, - ); - - expect( - terminal.altBuffer.wordSeparators, - contains('z'.codeUnitAt(0)), - ); - }); - }); - - group('Terminal.onPrivateOSC', () { - test(r'works with \a end', () { - String? lastCode; - List? lastData; - - final terminal = Terminal( - onPrivateOSC: (String code, List data) { - lastCode = code; - lastData = data; - }, - ); - - terminal.write('\x1b]6\x07'); - - expect(lastCode, '6'); - expect(lastData, []); - - terminal.write('\x1b]66;hello world\x07'); - - expect(lastCode, '66'); - expect(lastData, ['hello world']); - - terminal.write('\x1b]666;hello;world\x07'); - - expect(lastCode, '666'); - expect(lastData, ['hello', 'world']); - - terminal.write('\x1b]hello;world\x07'); - - expect(lastCode, 'hello'); - expect(lastData, ['world']); - }); - - test(r'works with \x1b\ end', () { - String? lastCode; - List? lastData; - - final terminal = Terminal( - onPrivateOSC: (String code, List data) { - lastCode = code; - lastData = data; - }, - ); - - terminal.write('\x1b]6\x1b\\'); - - expect(lastCode, '6'); - expect(lastData, []); - - terminal.write('\x1b]66;hello world\x1b\\'); - - expect(lastCode, '66'); - expect(lastData, ['hello world']); - - terminal.write('\x1b]666;hello;world\x1b\\'); - - expect(lastCode, '666'); - expect(lastData, ['hello', 'world']); - - terminal.write('\x1b]hello;world\x1b\\'); - - expect(lastCode, 'hello'); - expect(lastData, ['world']); - }); - - test('do not receive common osc', () { - String? lastCode; - List? lastData; - - final terminal = Terminal( - onPrivateOSC: (String code, List data) { - lastCode = code; - lastData = data; - }, - ); - - terminal.write('\x1b]0;hello world\x07'); - - expect(lastCode, isNull); - expect(lastData, isNull); - }); - }); -} - -class _TestInputHandler implements TerminalInputHandler { - final events = []; - - @override - String? call(TerminalKeyboardEvent event) { - events.add(event); - return null; - } -} diff --git a/test/src/terminal_view_test.mocks.dart b/test/src/terminal_view_test.mocks.dart index 41c2127e..e0a0e43a 100644 --- a/test/src/terminal_view_test.mocks.dart +++ b/test/src/terminal_view_test.mocks.dart @@ -4,7 +4,7 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:mockito/mockito.dart' as _i1; -import 'package:xterm/src/core/input/handler.dart' as _i2; +import 'package:xterm_core/src/core/input/handler.dart' as _i2; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values diff --git a/test/src/utils/circular_buffer_test.dart b/test/src/utils/circular_buffer_test.dart deleted file mode 100644 index 11d15faf..00000000 --- a/test/src/utils/circular_buffer_test.dart +++ /dev/null @@ -1,371 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:xterm/src/utils/circular_buffer.dart'; - -class IndexedValue with IndexedItem { - T value; - - IndexedValue(this.value); - - @override - int get hashCode => value.hashCode; - - @override - bool operator ==(Object other) { - if (other is IndexedValue) { - return other.value == value; - } - if (other is T) { - return other == value; - } - return false; - } - - @override - String toString() { - return 'IndexedValue($value), index: ${attached ? index : null}}'; - } -} - -extension ToIndexedValue on T { - IndexedValue get indexed => IndexedValue(this); -} - -void main() { - group("IndexAwareCircularBuffer", () { - test("normal creation test", () { - final cl = IndexAwareCircularBuffer>(1000); - - expect(cl, isNotNull); - expect(cl.maxLength, 1000); - }); - - test("change max value", () { - final cl = IndexAwareCircularBuffer>(2000); - expect(cl.maxLength, 2000); - cl.maxLength = 3000; - expect(cl.maxLength, 3000); - }); - - test("circle works", () { - final cl = IndexAwareCircularBuffer>(10); - expect(cl.maxLength, 10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - - expect(cl.length, 10); - expect(cl[0], 0.indexed); - expect(cl[9], 9.indexed); - - cl.push(IndexedValue(10)); - - expect(cl.length, 10); - expect(cl[0], 1.indexed); - expect(cl[9], 10.indexed); - }); - - test("change max value after circle", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(15, (index) => index).map(IndexedValue.new), - ); - - expect(cl.length, 10); - expect(cl[0], 5.indexed); - expect(cl[9], 14.indexed); - - cl.maxLength = 20; - - expect(cl.length, 10); - expect(cl[0], 5.indexed); - expect(cl[9], 14.indexed); - - cl.pushAll( - List.generate(5, (index) => 15 + index).map(IndexedValue.new), - ); - - expect(cl[0], 5.indexed); - expect(cl[9], 14.indexed); - expect(cl[14], 19.indexed); - }); - - // test("setting the length erases trail", () { - // final cl = CircularList>(10); - // cl.pushAll(List.generate(10, (index) => index).map(Box.new)); - - // expect(cl.length, 10); - // expect(cl[0], 0.box); - // expect(cl[9], 9.box); - - // cl.length = 5; - - // expect(cl.length, 5); - // expect(cl[0], 0.box); - // expect(() => cl[5], throwsRangeError); - // }); - - test("foreach works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - - final collectedItems = List.empty(growable: true); - - cl.forEach((item) { - collectedItems.add(item.value); - }); - - expect(collectedItems.length, 10); - expect(collectedItems[0], 0); - expect(collectedItems[9], 9); - }); - - test("index operator set works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - - expect(cl.length, 10); - expect(cl[5], 5.indexed); - - cl[5] = IndexedValue(50); - - expect(cl[5], 50.indexed); - }); - - test("clear works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl[5], 5.indexed); - - cl.clear(); - - expect(cl.length, 0); - expect(() => cl[5], throwsRangeError); - }); - - test("pop works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[9], 9.indexed); - - final val = cl.pop(); - - expect(val, 9.indexed); - expect(cl.length, 9); - expect(() => cl[9], throwsRangeError); - expect(cl[8], 8.indexed); - }); - - test("pop on empty throws", () { - final cl = IndexAwareCircularBuffer>(10); - expect(() => cl.pop(), throwsA(anything)); - }); - - test("remove one works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[5], 5.indexed); - - cl.remove(5); - - expect(cl.length, 9); - expect(cl[5], 6.indexed); - }); - - test("remove multiple works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[5], 5.indexed); - - cl.remove(5, 3); - - expect(cl.length, 7); - expect(cl[5], 8.indexed); - }); - - test("remove circle works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(15, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[0], 5.indexed); - - cl.remove(0, 9); - - expect(cl.length, 1); - expect(cl[0], 14.indexed); - }); - - test("remove too much works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[5], 5.indexed); - - cl.remove(5, 10); - - expect(cl.length, 5); - expect(cl[0], 0.indexed); - }); - - test("insert works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(5, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 5); - expect(cl[0], 0.indexed); - cl.insert(0, IndexedValue(100)); - - expect(cl.length, 6); - expect(cl[0], 100.indexed); - expect(cl[1], 0.indexed); - }); - - test("insert circular works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[0], 0.indexed); - expect(cl[1], 1.indexed); - expect(cl[9], 9.indexed); - - cl.insert(1, IndexedValue(100)); - - expect(cl.length, 10); - expect(cl[0], 100.indexed); //circle leads to 100 moving one index down - expect(cl[1], 1.indexed); - }); - - test("insert circular immediately remove works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[0], 0.indexed); - expect(cl[1], 1.indexed); - expect(cl[9], 9.indexed); - - cl.insert(0, IndexedValue(100)); - - expect(cl.length, 10); - expect(cl[0], 0.indexed); //the inserted 100 fell over immediately - expect(cl[1], 1.indexed); - }); - - test("insert all works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[0], 0.indexed); - expect(cl[1], 1.indexed); - expect(cl[9], 9.indexed); - - cl.insertAll( - 2, - List.generate(2, (index) => 20 + index) - .map(IndexedValue.new) - .toList(), - ); - - expect(cl.length, 10); - expect(cl[0], 20.indexed); - expect(cl[1], 21.indexed); - expect(cl[3], 3.indexed); - expect(cl[9], 9.indexed); - }); - - test("trim start works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[0], 0.indexed); - expect(cl[1], 1.indexed); - expect(cl[9], 9.indexed); - - cl.trimStart(5); - - expect(cl.length, 5); - expect(cl[0], 5.indexed); - expect(cl[1], 6.indexed); - expect(cl[4], 9.indexed); - }); - - test("trim start with more than length works", () { - final cl = IndexAwareCircularBuffer>(10); - cl.pushAll( - List.generate(10, (index) => index).map(IndexedValue.new), - ); - expect(cl.length, 10); - expect(cl[0], 0.indexed); - expect(cl[1], 1.indexed); - expect(cl[9], 9.indexed); - - cl.trimStart(15); - - expect(cl.length, 0); - }); - - test('can track index of items', () { - final cl = IndexAwareCircularBuffer>(3); - final item0 = IndexedValue(0); - final item1 = IndexedValue(1); - final item2 = IndexedValue(2); - - cl.pushAll([item0, item1, item2]); - - expect(item0.index, 0); - expect(item1.index, 1); - expect(item2.index, 2); - - final item3 = IndexedValue(3); - cl.push(item3); - - expect(item0.attached, false); - expect(item1.index, 0); - expect(item2.index, 1); - expect(item3.index, 2); - - final item11 = IndexedValue(4); - cl.insert(1, item11); - - expect(item0.attached, false); - expect(item1.attached, false); - expect(item11.index, 0); - expect(item2.index, 1); - expect(item3.index, 2); - - cl.remove(0, 2); - - print(cl.debugDump()); - - expect(item11.attached, false); - expect(item2.attached, false); - expect(item3.index, 0); - }); - }); -} diff --git a/test/terminal/terminal_isolate_test.dart b/test/terminal/terminal_isolate_test.dart deleted file mode 100644 index 352d999e..00000000 --- a/test/terminal/terminal_isolate_test.dart +++ /dev/null @@ -1,86 +0,0 @@ -// import 'dart:async'; - -// import 'package:flutter_test/flutter_test.dart'; -// import 'package:xterm/terminal/terminal_backend.dart'; -// import 'package:xterm/terminal/terminal_isolate.dart'; - -void main() { - // group('Start behavior tests', () { - // test('Using TerminalIsolate when not started throws exception', () { - // final fixture = _TestFixture(); - // expect(() => fixture.uut.terminalWidth, throwsA(isA())); - // }); - // test('Using TerminalIsolate after started doesn\'t throw exceptions', - // () async { - // final fixture = _TestFixture(); - - // await fixture.uut.start(testingDontWaitForBootup: true); - - // //no throw - // fixture.uut.showCursor; - // }); - // }); -} - -// class _TestFixture { -// _TestFixture() { -// fakeBackend = FakeBackend(); -// uut = TerminalIsolate(maxLines: 10000, backend: fakeBackend); -// } - -// late final TerminalIsolate uut; -// late final FakeBackend fakeBackend; -// } - -// class FakeBackend implements TerminalBackend { -// @override -// void ackProcessed() {} - -// @override -// // TODO: implement exitCode -// Future get exitCode => _exitCodeCompleter.future; - -// @override -// void init() { -// _exitCodeCompleter = Completer(); -// _outStream = StreamController(); -// _hasInitBeenCalled = true; -// } - -// @override -// Stream get out => _outStream.stream; - -// @override -// void resize(int width, int height, int pixelWidth, int pixelHeight) { -// _width = width; -// _height = height; -// _pixelWidth = pixelWidth; -// _pixelHeight = pixelHeight; -// } - -// @override -// void terminate() { -// _isTerminated = true; -// } - -// @override -// void write(String _) {} - -// bool get hasInitBeenCalled => _hasInitBeenCalled; -// bool get isTerminated => _isTerminated; - -// int? get width => _width; -// int? get height => _height; -// int? get pixelWidth => _pixelWidth; -// int? get pixelHeight => _pixelHeight; - -// bool _hasInitBeenCalled = false; -// bool _isTerminated = false; -// int? _width; -// int? _height; -// int? _pixelWidth; -// int? _pixelHeight; - -// late final _exitCodeCompleter; -// late final _outStream; -// } diff --git a/test/terminal/terminal_search_test.dart b/test/terminal/terminal_search_test.dart deleted file mode 100644 index 3c2b2dc0..00000000 --- a/test/terminal/terminal_search_test.dart +++ /dev/null @@ -1,407 +0,0 @@ -// import 'package:flutter_test/flutter_test.dart'; -// import 'package:mockito/annotations.dart'; -// import 'package:mockito/mockito.dart'; -// import 'package:xterm/buffer/buffer.dart'; -// import 'package:xterm/buffer/line/line.dart'; -// import 'package:xterm/terminal/cursor.dart'; -// import 'package:xterm/terminal/terminal_search.dart'; -// import 'package:xterm/terminal/terminal_search_interaction.dart'; -// import 'package:xterm/util/circular_list.dart'; -// import 'package:xterm/util/unicode_v11.dart'; - -// import 'terminal_search_test.mocks.dart'; - -// class TerminalSearchTestCircularList extends CircularList { -// TerminalSearchTestCircularList(int maxLines) : super(maxLines); -// } - -// @GenerateMocks([ -// TerminalSearchInteraction, -// Buffer, -// TerminalSearchTestCircularList, -// BufferLine -// ]) -void main() { - // group('Terminal Search Tests', () { - // test('Creation works', () { - // _TestFixture(); - // }); - - // test('Doesn\'t trigger anything when not activated', () { - // final fixture = _TestFixture(); - // verifyNoMoreInteractions(fixture.terminalSearchInteractionMock); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.pattern = "some test"; - // task.isActive = false; - // task.searchResult; - // }); - - // test('Basic search works', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent(['Simple Content']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = 'content'; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: false); - // final result = task.searchResult; - // expect(result.allHits.length, 1); - // expect(result.allHits[0].startLineIndex, 0); - // expect(result.allHits[0].startIndex, 7); - // expect(result.allHits[0].endLineIndex, 0); - // expect(result.allHits[0].endIndex, 14); - // }); - - // test('Multiline search works', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent(['Simple Content', 'Second Line']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = 'line'; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: false); - // final result = task.searchResult; - // expect(result.allHits.length, 1); - // expect(result.allHits[0].startLineIndex, 1); - // expect(result.allHits[0].startIndex, 7); - // expect(result.allHits[0].endLineIndex, 1); - // expect(result.allHits[0].endIndex, 11); - // }); - - // test('Emoji search works', () { - // final fixture = _TestFixture(); - // fixture.expectBufferContentLine([ - // '🍏', - // '🍎', - // '🍐', - // '🍊', - // '🍋', - // '🍌', - // '🍉', - // '🍇', - // '🍓', - // '🫐', - // '🍈', - // '🍒', - // '🍑' - // ]); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = '🍋'; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: false); - // final result = task.searchResult; - // expect(result.allHits.length, 1); - // expect(result.allHits[0].startLineIndex, 0); - // expect(result.allHits[0].startIndex, 8); - // expect(result.allHits[0].endLineIndex, 0); - // expect(result.allHits[0].endIndex, 10); - // }); - - // test('CJK search works', () { - // final fixture = _TestFixture(); - // fixture.expectBufferContentLine(['こ', 'ん', 'に', 'ち', 'は', '世', '界']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = 'は'; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: false); - // final result = task.searchResult; - // expect(result.allHits.length, 1); - // expect(result.allHits[0].startLineIndex, 0); - // expect(result.allHits[0].startIndex, 8); - // expect(result.allHits[0].endLineIndex, 0); - // expect(result.allHits[0].endIndex, 10); - // }); - - // test('Finding strings directly on line break works', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent([ - // 'The search hit is '.padRight(fixture.terminalWidth - 3) + 'spl', - // 'it over two lines', - // ]); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = 'split'; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: false); - // final result = task.searchResult; - // expect(result.allHits.length, 1); - // expect(result.allHits[0].startLineIndex, 0); - // expect(result.allHits[0].startIndex, 77); - // expect(result.allHits[0].endLineIndex, 1); - // expect(result.allHits[0].endIndex, 2); - // }); - // }); - - // test('Option: case sensitivity works', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent(['Simple Content', 'Second Line']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = 'line'; - // task.options = TerminalSearchOptions( - // caseSensitive: true, matchWholeWord: false, useRegex: false); - - // final result = task.searchResult; - // expect(result.allHits.length, 0); - - // task.pattern = 'Line'; - // final secondResult = task.searchResult; - // expect(secondResult.allHits.length, 1); - // expect(secondResult.allHits[0].startLineIndex, 1); - // expect(secondResult.allHits[0].startIndex, 7); - // expect(secondResult.allHits[0].endLineIndex, 1); - // expect(secondResult.allHits[0].endIndex, 11); - // }); - - // test('Option: whole word works', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent(['Simple Content', 'Second Line']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = 'lin'; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: true, useRegex: false); - - // final result = task.searchResult; - // expect(result.allHits.length, 0); - - // task.pattern = 'line'; - // final secondResult = task.searchResult; - // expect(secondResult.allHits.length, 1); - // expect(secondResult.allHits[0].startLineIndex, 1); - // expect(secondResult.allHits[0].startIndex, 7); - // expect(secondResult.allHits[0].endLineIndex, 1); - // expect(secondResult.allHits[0].endIndex, 11); - // }); - - // test('Option: regex works', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent(['Simple Content', 'Second Line']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: true); - - // task.pattern = - // r'(^|\s)\w{4}($|\s)'; // match exactly 4 characters (and the whitespace before and/or after) - // final secondResult = task.searchResult; - // expect(secondResult.allHits.length, 1); - // expect(secondResult.allHits[0].startLineIndex, 1); - // expect(secondResult.allHits[0].startIndex, 6); - // expect(secondResult.allHits[0].endLineIndex, 1); - // expect(secondResult.allHits[0].endIndex, 12); - // }); - - // test('Retrigger search when a BufferLine got dirty works', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent( - // ['Simple Content', 'Second Line', 'Third row']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: false); - - // task.pattern = 'line'; - // final result = task.searchResult; - // expect(result.allHits.length, 1); - - // // overwrite expectations, nothing dirty => no new search - // fixture.expectTerminalSearchContent( - // ['Simple Content', 'Second Line', 'Third line'], - // isSearchStringCached: true); - // task.isActive = false; - // task.isActive = true; - - // final secondResult = task.searchResult; - // expect(secondResult.allHits.length, - // 1); // nothing was dirty => we get the cached search result - - // // overwrite expectations, one line is dirty => new search - // fixture.expectTerminalSearchContent( - // ['Simple Content', 'Second Line', 'Third line'], - // isSearchStringCached: false, - // dirtyIndices: [1]); - - // final thirdResult = task.searchResult; - // expect(thirdResult.allHits.length, - // 2); //search has happened again so the new content is found - - // // overwrite expectations, content has changed => new search - // fixture.expectTerminalSearchContent( - // ['First line', 'Second Line', 'Third line'], - // isSearchStringCached: false, - // dirtyIndices: [0]); - - // final fourthResult = task.searchResult; - // expect(fourthResult.allHits.length, - // 3); //search has happened again so the new content is found - // }); - // test('Handles regex special characters in non regex mode correctly', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent(['Simple Content', 'Second Line.\\{']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = 'line.\\{'; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: false); - - // final result = task.searchResult; - // expect(result.allHits.length, 1); - // expect(result.allHits[0].startLineIndex, 1); - // expect(result.allHits[0].startIndex, 7); - // expect(result.allHits[0].endLineIndex, 1); - // expect(result.allHits[0].endIndex, 14); - // }); - // test('TerminalWidth change leads to retriggering search', () { - // final fixture = _TestFixture(); - // fixture.expectTerminalSearchContent(['Simple Content', 'Second Line']); - // final task = fixture.uut.createSearchTask('testsearch'); - // task.isActive = true; - // task.pattern = 'line'; - // task.options = TerminalSearchOptions( - // caseSensitive: false, matchWholeWord: false, useRegex: false); - - // final result = task.searchResult; - // expect(result.allHits.length, 1); - - // // change data to detect a search re-run - // fixture.expectTerminalSearchContent( - // ['First line', 'Second Line']); //has 2 hits - // task.isActive = false; - // task.isActive = true; - // final secondResult = task.searchResult; - // expect( - // secondResult.allHits.length, 1); //nothing changed so the cache is used - - // fixture.terminalWidth = 79; - // task.isActive = false; - // task.isActive = true; - // final thirdResult = task.searchResult; - // //we changed the terminal width which triggered a re-run of the search - // expect(thirdResult.allHits.length, 2); - // }); -} - -// class _TestFixture { -// _TestFixture({ -// terminalWidth = 80, -// }) : _terminalWidth = terminalWidth { -// uut = TerminalSearch(terminalSearchInteractionMock); -// when(terminalSearchInteractionMock.terminalWidth).thenReturn(terminalWidth); -// } - -// int _terminalWidth; -// int get terminalWidth => _terminalWidth; -// set terminalWidth(int terminalWidth) { -// _terminalWidth = terminalWidth; -// when(terminalSearchInteractionMock.terminalWidth).thenReturn(terminalWidth); -// } - -// void expectBufferContentLine( -// List cellData, { -// isUsingAltBuffer = false, -// }) { -// final buffer = _getBufferFromCellData(cellData); -// when(terminalSearchInteractionMock.buffer).thenReturn(buffer); -// when(terminalSearchInteractionMock.isUsingAltBuffer()) -// .thenReturn(isUsingAltBuffer); -// } - -// void expectTerminalSearchContent( -// List lines, { -// isUsingAltBuffer = false, -// isSearchStringCached = true, -// List? dirtyIndices, -// }) { -// final buffer = _getBuffer(lines, -// isCached: isSearchStringCached, dirtyIndices: dirtyIndices); - -// when(terminalSearchInteractionMock.buffer).thenReturn(buffer); -// when(terminalSearchInteractionMock.isUsingAltBuffer()) -// .thenReturn(isUsingAltBuffer); -// } - -// final terminalSearchInteractionMock = MockTerminalSearchInteraction(); -// late final TerminalSearch uut; - -// MockBuffer _getBufferFromCellData(List cellData) { -// final result = MockBuffer(); -// final circularList = MockTerminalSearchTestCircularList(); -// when(result.lines).thenReturn(circularList); -// when(circularList[0]).thenReturn(_getBufferLineFromData(cellData)); -// when(circularList.length).thenReturn(1); - -// return result; -// } - -// MockBuffer _getBuffer( -// List lines, { -// isCached = true, -// List? dirtyIndices, -// }) { -// final result = MockBuffer(); -// final circularList = MockTerminalSearchTestCircularList(); -// when(result.lines).thenReturn(circularList); - -// final bufferLines = _getBufferLinesWithSearchContent( -// lines, -// isCached: isCached, -// dirtyIndices: dirtyIndices, -// ); - -// when(circularList[any]).thenAnswer( -// (realInvocation) => bufferLines[realInvocation.positionalArguments[0]]); -// when(circularList.length).thenReturn(bufferLines.length); - -// return result; -// } - -// BufferLine _getBufferLineFromData(List cellData) { -// final result = BufferLine(length: _terminalWidth); -// int currentIndex = 0; -// for (var data in cellData) { -// final codePoint = data.runes.first; -// final width = unicodeV11.wcwidth(codePoint); -// result.cellInitialize( -// currentIndex, -// content: codePoint, -// width: width, -// cursor: Cursor(bg: 0, fg: 0, flags: 0), -// ); -// currentIndex++; -// for (int i = 1; i < width; i++) { -// result.cellInitialize( -// currentIndex, -// content: 0, -// width: 0, -// cursor: Cursor(bg: 0, fg: 0, flags: 0), -// ); -// currentIndex++; -// } -// } -// return result; -// } - -// List _getBufferLinesWithSearchContent( -// List content, { -// isCached = true, -// List? dirtyIndices, -// }) { -// final result = List.empty(growable: true); -// for (int i = 0; i < content.length; i++) { -// final bl = MockBufferLine(); -// when(bl.hasCachedSearchString).thenReturn(isCached); -// when(bl.toSearchString(any)).thenReturn(content[i]); -// if (dirtyIndices?.contains(i) ?? false) { -// when(bl.isTagDirty(any)).thenReturn(true); -// } else { -// when(bl.isTagDirty(any)).thenReturn(false); -// } -// result.add(bl); -// } - -// return result; -// } -// }