Skip to content

Commit

Permalink
More docs
Browse files Browse the repository at this point in the history
  • Loading branch information
pokey committed Jul 14, 2023
1 parent bc4c816 commit e8564ad
Show file tree
Hide file tree
Showing 33 changed files with 521 additions and 304 deletions.
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export { default as DefaultMap } from "./util/DefaultMap";
export * from "./types/GeneralizedRange";
export * from "./types/RangeOffsets";
export * from "./util/omitByDeep";
export * from "./util/range";
export * from "./testUtil/isTesting";
export * from "./testUtil/testConstants";
export * from "./testUtil/getFixturePaths";
Expand Down
22 changes: 22 additions & 0 deletions packages/common/src/util/range.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { range as lodashRange } from "lodash";
import { Range } from "../types/Range";
import { TextEditor } from "../types/TextEditor";

/**
* @param editor The editor containing the range
* @param range The range to get the line ranges for
* @returns A list of ranges, one for each line in the given range, with the
* first and last ranges trimmed to the start and end of the given range.
*/
export function getLineRanges(editor: TextEditor, range: Range): Range[] {
const { document } = editor;
const lineRanges = lodashRange(range.start.line, range.end.line + 1).map(
(lineNumber) => document.lineAt(lineNumber).range,
);
lineRanges[0] = lineRanges[0].with(range.start);
lineRanges[lineRanges.length - 1] = lineRanges[lineRanges.length - 1].with(
undefined,
range.end,
);
return lineRanges;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import * as sinon from "sinon";
import {
createDecorationTypeCallToPlainObject,
setDecorationsCallToPlainObject,
} from "./toPlainObject";
} from "./spyCallsToPlainObject";
import { Fakes, ExpectedArgs } from "./scopeVisualizerTest.types";

export function checkAndResetFakes(fakes: Fakes, expected: ExpectedArgs) {
const actual = getAndResetFakes(fakes);
const actual = getSpyCallsAndResetFakes(fakes);
assert.deepStrictEqual(actual, expected, JSON.stringify(actual));
}

export function getAndResetFakes({
function getSpyCallsAndResetFakes({
createTextEditorDecorationType,
setDecorations,
dispose,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ScopeVisualizerColorConfig } from "@cursorless/vscode-common";

/**
* Fake color config to use for testing. We use an alpha of 50% and try to use
* different rgb channels where possible to make it easier to see what happens
* when we blend colors.
*/
export const COLOR_CONFIG: ScopeVisualizerColorConfig = {
dark: {
content: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "./scopeVisualizerTest.types";

export async function injectFakes(): Promise<Fakes> {
const { vscodeApi: vscodeApi } = (await getCursorlessApi()).testHelpers!;
const { vscodeApi } = (await getCursorlessApi()).testHelpers!;

const dispose = sinon.fake<[number], void>();

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import { checkAndResetFakes } from "./checkAndResetFakes";
import { injectFakes } from "./injectFakes";
import { ExpectedArgs } from "./scopeVisualizerTest.types";

/**
* Tests that the scope visualizer works with multiline content, by
* ensuring that the correct decorations are applied so that it looks
* as follows:
*
* ![basic multiline content](./runBasicMultilineContentTest.png)
*/
export async function runBasicMultilineContentTest() {
await openNewEditor(contents, {
languageId: "typescript",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import { checkAndResetFakes } from "./checkAndResetFakes";
import { injectFakes } from "./injectFakes";
import { ExpectedArgs } from "./scopeVisualizerTest.types";

/**
* Tests that the scope visualizer works with removal ranges, by ensuring that
* the correct decorations are applied so that it looks as follows:
*
* ![basic removal](./runBasicRemovalTest.png)
*/
export async function runBasicRemovalTest() {
await openNewEditor("aaa bbb");

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import { injectFakes } from "./injectFakes";
import { checkAndResetFakes } from "./checkAndResetFakes";
import { ExpectedArgs } from "./scopeVisualizerTest.types";

/**
* Tests that the scope visualizer works with nested multiline content, by
* ensuring that the correct decorations are applied so that it looks as
* follows:
*
* ![nested multiline content](./runNestedMultilineContentTest.png)
*/
export async function runNestedMultilineContentTest() {
await openNewEditor(contents, {
languageId: "typescript",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { injectFakes } from "./injectFakes";
import { checkAndResetFakes } from "./checkAndResetFakes";
import { ExpectedArgs } from "./scopeVisualizerTest.types";

/**
* Tests that the scope visualizer updates correctly when the document is
* edited.
*/
export async function runUpdateTest() {
const editor = await openNewEditor("aaa");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* The colors used to render a range type, such as "domain", "content", etc.
*/
export interface RangeTypeColors {
background: ThemeColors;
borderSolid: ThemeColors;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { VscodeFancyRangeHighlighterRenderer } from "./VscodeFancyRangeHighlight
import { generateDecorationsForCharacterRange } from "./generateDecorationsForCharacterRange";
import { generateDecorationsForLineRange } from "./generateDecorationsForLineRange";
import { generateDifferentiatedRanges } from "./generateDifferentiatedRanges";
import { DifferentiatedStyledRange } from "./getDecorationRanges.types";
import { DifferentiatedStyledRange } from "./decorationStyle.types";
import { groupDifferentiatedStyledRanges } from "./groupDifferentiatedStyledRanges";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
DecorationStyle,
DifferentiatedStyle,
DifferentiatedStyledRangeList,
} from "./getDecorationRanges.types";
} from "./decorationStyle.types";
import { getDifferentiatedStyleMapKey } from "./getDifferentiatedStyleMapKey";

const BORDER_WIDTH = "1px";
const BORDER_RADIUS = "2px";
Expand All @@ -31,34 +32,39 @@ export class VscodeFancyRangeHighlighterRenderer {
constructor(colors: RangeTypeColors) {
this.decorationTypes = new CompositeKeyDefaultMap(
({ style }) => getDecorationStyle(colors, style),
({
style: { top, right, bottom, left, isWholeLine },
differentiationIndex,
}) => [
top,
right,
bottom,
left,
isWholeLine ?? false,
differentiationIndex,
],
getDifferentiatedStyleMapKey,
);
}

/**
* Renders the given ranges in the given editor.
*
* @param editor The editor to render the decorations in.
* @param decoratedRanges A list with one element per differentiated style,
* each of which contains a list of ranges to render for that style. We render
* the ranges in order of increasing differentiation index.
* {@link VscodeFancyRangeHighlighter} uses this to ensure that nested ranges
* are rendered after their parents. Otherwise they partially interleave,
* which looks bad.
*/
setRanges(
editor: VscodeTextEditorImpl,
decoratedRanges: DifferentiatedStyledRangeList[],
) {
): void {
/**
* Keep track of which styles have no ranges, so that we can set their
* range list to `[]`
*/
const untouchedDecorationTypes = new Set(this.decorationTypes.values());

decoratedRanges.sort(
(a, b) =>
a.differentiatedStyles.differentiationIndex -
b.differentiatedStyles.differentiationIndex,
a.differentiatedStyle.differentiationIndex -
b.differentiatedStyle.differentiationIndex,
);

decoratedRanges.forEach(
({ differentiatedStyles: styleParameters, ranges }) => {
({ differentiatedStyle: styleParameters, ranges }) => {
const decorationType = this.decorationTypes.get(styleParameters);

vscodeApi.editor.setDecorations(
Expand Down Expand Up @@ -141,6 +147,9 @@ function getBorderRadius(borders: DecorationStyle): string {
}

function getSingleCornerBorderRadius(side1: BorderStyle, side2: BorderStyle) {
// We only round the corners if both sides are solid, as that makes them look
// more finished, whereas we want the dotted borders to look unfinished / cut
// off.
return side1 === BorderStyle.solid && side2 === BorderStyle.solid
? BORDER_RADIUS
: "0px";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
CharacterRange,
GeneralizedRange,
LineRange,
Range,
} from "@cursorless/common";
import { GeneralizedRange, Range } from "@cursorless/common";

export enum BorderStyle {
porous = "dashed",
Expand All @@ -19,8 +14,19 @@ export interface DecorationStyle {
isWholeLine?: boolean;
}

/**
* A decoration style that is differentiated from other styles by a number. We
* use this number to ensure that adjacent ranges are rendered with different
* TextEditorDecorationTypes, so that they don't get merged together due to a
* VSCode bug.
*/
export interface DifferentiatedStyle {
style: DecorationStyle;

/**
* A number that is different from the differentiation indices of any other
* ranges that are touching this range.
*/
differentiationIndex: number;
}

Expand All @@ -35,21 +41,16 @@ export interface DifferentiatedStyledRange {
}

export interface DifferentiatedStyledRangeList {
differentiatedStyles: DifferentiatedStyle;
differentiatedStyle: DifferentiatedStyle;
ranges: Range[];
}

export interface DifferentiatedGeneralizedRange {
range: GeneralizedRange;
differentiationIndex: number;
}

export interface DifferentiatedCharacterRange
extends DifferentiatedGeneralizedRange {
range: CharacterRange;
}

export interface DifferentiatedLineRange
extends DifferentiatedGeneralizedRange {
range: LineRange;
/**
* A number that is different from the differentiation indices of any other
* ranges that are touching this range.
*/
differentiationIndex: number;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Range, TextEditor, getLineRanges } from "@cursorless/common";
import { BorderStyle, StyledRange } from "../decorationStyle.types";
import { handleMultipleLines } from "./handleMultipleLines";

/**
* Returns an iterable of styled ranges for the given range. If the range spans
* multiple lines, we have complex logic to draw dotted / solid / no borders to ensure
* that the range is visually distinct from adjacent ranges but looks continuous.
*/
export function* generateDecorationsForCharacterRange(
editor: TextEditor,
range: Range,
): Iterable<StyledRange> {
if (range.isSingleLine) {
yield {
range,
style: {
top: BorderStyle.solid,
right: BorderStyle.solid,
bottom: BorderStyle.solid,
left: BorderStyle.solid,
},
};
return;
}

yield* handleMultipleLines(getLineRanges(editor, range));
}
Loading

0 comments on commit e8564ad

Please sign in to comment.