Skip to content

Commit d70ba1d

Browse files
authored
Merge pull request #3318 from meganrogge/bufferRange
Fix selection range
2 parents e5c9b0e + 9403478 commit d70ba1d

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

src/browser/services/SelectionService.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import * as Browser from 'common/Platform';
1010
import { SelectionModel } from 'browser/selection/SelectionModel';
1111
import { CellData } from 'common/buffer/CellData';
1212
import { EventEmitter, IEvent } from 'common/EventEmitter';
13-
import { ICharSizeService, IMouseService, ISelectionService, IRenderService } from 'browser/services/Services';
13+
import { IMouseService, ISelectionService, IRenderService } from 'browser/services/Services';
1414
import { ILinkifier2 } from 'browser/Types';
1515
import { IBufferService, IOptionsService, ICoreService } from 'common/services/Services';
1616
import { getCoordsRelativeToElement } from 'browser/input/Mouse';
1717
import { moveToCellSequence } from 'browser/input/MoveToCell';
1818
import { Disposable } from 'common/Lifecycle';
19+
import { getRangeLength } from 'common/buffer/BufferRange';
1920

2021
/**
2122
* The number of pixels the mouse needs to be above or below the viewport in
@@ -323,7 +324,8 @@ export class SelectionService extends Disposable implements ISelectionService {
323324
const range = this._linkifier.currentLink?.link?.range;
324325
if (range) {
325326
this._model.selectionStart = [range.start.x - 1, range.start.y - 1];
326-
this._model.selectionEnd = [range.end.x, range.end.y - 1];
327+
this._model.selectionStartLength = getRangeLength(range, this._bufferService.cols);
328+
this._model.selectionEnd = undefined;
327329
return true;
328330
}
329331

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright (c) 2021 The xterm.js authors. All rights reserved.
3+
* @license MIT
4+
*/
5+
6+
import { assert } from 'chai';
7+
import { getRangeLength } from 'common/buffer/BufferRange';
8+
import { IBufferRange } from 'xterm';
9+
10+
describe('BufferRange', () => {
11+
describe('getRangeLength', () => {
12+
it('should get range for single line', () => {
13+
assert.equal(getRangeLength(createRange(1, 1, 4, 1), 0), 4);
14+
});
15+
it('should throw for invalid range', () => {
16+
assert.throws(() => getRangeLength(createRange(1, 3, 1, 1), 0));
17+
});
18+
it('should get range multiple lines', () => {
19+
assert.equal(getRangeLength(createRange(1, 1, 4, 5), 5), 23);
20+
});
21+
it('should get range for end line right after start line', () => {
22+
assert.equal(getRangeLength(createRange(1, 1, 7, 2), 5), 11);
23+
});
24+
});
25+
});
26+
27+
function createRange(x1: number, y1: number, x2: number, y2: number): IBufferRange {
28+
return {
29+
start: { x: x1, y: y1 },
30+
end: { x: x2, y: y2 }
31+
};
32+
}

src/common/buffer/BufferRange.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright (c) 2021 The xterm.js authors. All rights reserved.
3+
* @license MIT
4+
*/
5+
6+
import { IBufferRange } from 'xterm';
7+
8+
export function getRangeLength(range: IBufferRange, cols: number): number {
9+
if (range.start.y === range.end.y) {
10+
return range.end.x - range.start.x + 1;
11+
}
12+
if (range.start.y > range.end.y) {
13+
throw new Error(`Buffer range end (${range.end.x}, ${range.end.y}) cannot be before start (${range.start.x}, ${range.start.y})`);
14+
}
15+
return cols * (range.end.y - range.start.y - 1) + cols - range.start.x + range.end.x;
16+
}

0 commit comments

Comments
 (0)