add ability to register/deregister character joiner

This commit is contained in:
Jeff Principe
2018-06-02 10:24:52 -07:00
parent c192a27d93
commit eabb25c796
9 changed files with 355 additions and 15 deletions
+45
View File
@@ -0,0 +1,45 @@
import { assert } from 'chai';
import { merge } from './MergeRanges';
describe('merge', () => {
it('inserts a new range before the existing ones', () => {
const result = merge([[1, 2], [2, 3]], [0, 1]);
assert.deepEqual(result, [[0, 1], [1, 2], [2, 3]]);
});
it('inserts in between two ranges', () => {
const result = merge([[0, 2], [4, 6]], [2, 4]);
assert.deepEqual(result, [[0, 2], [2, 4], [4, 6]]);
});
it('inserts after the last range', () => {
const result = merge([[0, 2], [4, 6]], [6, 8]);
assert.deepEqual(result, [[0, 2], [4, 6], [6, 8]]);
});
it('extends the beginning of a range', () => {
const result = merge([[0, 2], [4, 6]], [3, 5]);
assert.deepEqual(result, [[0, 2], [3, 6]]);
});
it('extends the end of a range', () => {
const result = merge([[0, 2], [4, 6]], [1, 4]);
assert.deepEqual(result, [[0, 4], [4, 6]]);
});
it('extends the last range', () => {
const result = merge([[0, 2], [4, 6]], [5, 7]);
assert.deepEqual(result, [[0, 2], [4, 7]]);
});
it('connects two ranges', () => {
const result = merge([[0, 2], [4, 6]], [1, 5]);
assert.deepEqual(result, [[0, 6]]);
});
it('connects more than two ranges', () => {
const result = merge([[0, 2], [4, 6], [8, 10], [12, 14]], [1, 10]);
assert.deepEqual(result, [[0, 10], [12, 14]]);
});
});
+70
View File
@@ -0,0 +1,70 @@
/**
* Merges the range defined by the provided start and end into the list of
* existing ranges. The merge is done in place on the existing range for
* performance and is also returned.
* @param ranges Existing range list
* @param newRange Tuple of two numbers representing the new range to merge in.
* @returns The ranges input with the new range merged in place
*/
export function merge(ranges: [number, number][], newRange: [number, number]): [number, number][] {
let inRange = false;
for (let i = 0; i < ranges.length; i++) {
const range = ranges[i];
if (!inRange) {
if (newRange[1] <= range[0]) {
// Case 1: New range is before the search range
ranges.splice(i, 0, newRange);
return ranges;
}
if (newRange[1] <= range[1]) {
// Case 2: New range is either wholly contained within the
// search range or overlaps with the front of it
range[0] = Math.min(newRange[0], range[0]);
return ranges;
}
if (newRange[0] < range[1]) {
// Case 3: New range either wholly contains the search range
// or overlaps with the end of it
range[0] = Math.min(newRange[0], range[0]);
inRange = true;
}
// Case 4: New range starts after the search range
continue;
} else {
if (newRange[1] <= range[0]) {
// Case 5: New range extends from previous range but doesn't
// reach the current one
ranges[i - 1][1] = newRange[1];
return ranges;
}
if (newRange[1] <= range[1]) {
// Case 6: New range extends from prvious range into the
// current range
ranges[i - 1][1] = Math.max(newRange[1], range[1]);
ranges.splice(i, 1);
inRange = false;
return ranges;
}
// Case 7: New range extends from previous range past the
// end of the current range
ranges.splice(i, 1);
i--;
}
}
if (inRange) {
// Case 8: New range extends past the last existing range
ranges[ranges.length - 1][1] = newRange[1];
} else {
// Case 9: New range starts after the last existing range
ranges.push(newRange);
}
return ranges;
}
+5 -1
View File
@@ -4,7 +4,7 @@
*/
import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Types';
import { LineData, IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ILinkifier, IMouseHelper, ILinkMatcherOptions, XtermListener } from '../Types';
import { LineData, IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ICircularList, ILinkifier, IMouseHelper, ILinkMatcherOptions, XtermListener, CharacterJoinerHandler } from '../Types';
import { Buffer } from '../Buffer';
import * as Browser from '../shared/utils/Browser';
import { ITheme, IDisposable, IMarker } from 'xterm';
@@ -157,6 +157,8 @@ export class MockTerminal implements ITerminal {
}
return line;
}
registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; }
deregisterCharacterJoiner(joinerId: number): void { }
}
export class MockCharMeasure implements ICharMeasure {
@@ -339,6 +341,8 @@ export class MockRenderer implements IRenderer {
onWindowResize(devicePixelRatio: number): void {}
clear(): void {}
refreshRows(start: number, end: number): void {}
registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; }
deregisterCharacterJoiner(): boolean { return true; }
}
export class MockViewport implements IViewport {