Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/tabs #161

Merged
merged 6 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions lib/src/core/buffer/buffer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ class Buffer {

final bool isAltBuffer;

Set<int>? wordSeparators;

Buffer(
this.terminal, {
required this.maxLines,
required this.isAltBuffer,
this.wordSeparators,
}) {
for (int i = 0; i < terminal.viewHeight; i++) {
lines.push(_newEmptyLine());
Expand Down Expand Up @@ -464,7 +467,7 @@ class Buffer {
return line;
}

static final _kWordSeparators = <int>{
static final _defaultWordSeparators = <int>{
0,
r' '.codeUnitAt(0),
r'.'.codeUnitAt(0),
Expand All @@ -479,6 +482,7 @@ class Buffer {
};

BufferRangeLine? getWordBoundary(CellOffset position) {
var separators = wordSeparators ?? _defaultWordSeparators;
if (position.y >= lines.length) {
return null;
}
Expand All @@ -492,7 +496,7 @@ class Buffer {
break;
}
final char = line.getCodePoint(start - 1);
if (_kWordSeparators.contains(char)) {
if (separators.contains(char)) {
break;
}
start--;
Expand All @@ -503,7 +507,7 @@ class Buffer {
break;
}
final char = line.getCodePoint(end);
if (_kWordSeparators.contains(char)) {
if (separators.contains(char)) {
break;
}
end++;
Expand Down
30 changes: 26 additions & 4 deletions lib/src/core/tabs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,23 @@ import 'dart:math' show min;

const _kMaxColumns = 1024;

/// Manages the tab stop state for a terminal.
class TabStops {
final _stops = List<bool>.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;
Expand All @@ -18,29 +32,37 @@ class TabStops {
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();
const interval = 8;
for (var i = 0; i < _kMaxColumns; i += interval) {
_stops[i] = true;
}
_initialize();
}
}
19 changes: 16 additions & 3 deletions lib/src/terminal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
/// Flag to toggle os specific behaviors.
final TerminalTargetPlatform platform;

Set<int>? wordSeparators;

Terminal({
this.maxLines = 1000,
this.onBell,
Expand All @@ -73,6 +75,7 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
this.inputHandler = defaultInputHandler,
this.mouseHandler = defaultMouseHandler,
this.reflowEnabled = true,
this.wordSeparators,
});

late final _parser = EscapeParser(this);
Expand All @@ -81,9 +84,19 @@ class Terminal with Observable implements TerminalState, EscapeHandler {

late var _buffer = _mainBuffer;

late final _mainBuffer = Buffer(this, maxLines: maxLines, isAltBuffer: false);
late final _mainBuffer = Buffer(
this,
maxLines: maxLines,
isAltBuffer: false,
wordSeparators: wordSeparators,
);

late final _altBuffer = Buffer(this, maxLines: maxLines, isAltBuffer: true);
late final _altBuffer = Buffer(
this,
maxLines: maxLines,
isAltBuffer: true,
wordSeparators: wordSeparators,
);

final _tabStops = TabStops();

Expand Down Expand Up @@ -383,7 +396,7 @@ class Terminal with Observable implements TerminalState, EscapeHandler {

@override
void tab() {
final nextStop = _tabStops.find(_buffer.cursorX, _viewWidth);
final nextStop = _tabStops.find(_buffer.cursorX + 1, _viewWidth);

if (nextStop != null) {
_buffer.setCursorX(nextStop);
Expand Down
31 changes: 31 additions & 0 deletions test/src/core/tabs_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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);
});
});
}