Skip to content

Commit aa95401

Browse files
bjaspanBarry Jaspanpre-commit-ci-lite[bot]auscompgeek
authored
Convert VscodeHatRendered to use vscode.workspace.fs (#2194)
This is part of porting Cursorless to work in the web environment. This is a re-roll of #2153 which I messed up with bad git-fu. ## Checklist - [ ] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [ ] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [ ] I have not broken the cheatsheet --------- Co-authored-by: Barry Jaspan <[email protected]> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: David Vo <[email protected]>
1 parent 08abb7f commit aa95401

File tree

1 file changed

+51
-35
lines changed

1 file changed

+51
-35
lines changed

packages/cursorless-vscode/src/ide/vscode/hats/VscodeHatRenderer.ts

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "@cursorless/common";
88
import { VscodeApi } from "@cursorless/vscode-common";
99
import { cloneDeep, isEqual } from "lodash";
10-
import * as fs from "node:fs";
10+
import * as fs from "fs/promises";
1111
import * as path from "node:path";
1212
import * as vscode from "vscode";
1313
import { vscodeGetConfigurationString } from "../VscodeConfiguration";
@@ -24,6 +24,7 @@ import {
2424
defaultShapeAdjustments,
2525
} from "./shapeAdjustments";
2626
import { performPr1868ShapeUpdateInit } from "./performPr1868ShapeUpdateInit";
27+
import { TextDecoder } from "util";
2728

2829
const CURSORLESS_HAT_SHAPES_SUFFIX = ".svg";
2930

@@ -65,7 +66,8 @@ export default class VscodeHatRenderer {
6566
private notifier: Notifier<[]> = new Notifier();
6667
private lastSeenEnabledHatStyles: ExtendedHatStyleMap = {};
6768
private hatsDirWatcherDisposable?: vscode.Disposable;
68-
private hatShapeOverrides: Record<string, string> = {};
69+
private hatShapeOverrides: Record<string, vscode.Uri> = {};
70+
private decoder: TextDecoder = new TextDecoder("utf-8");
6971

7072
constructor(
7173
private vscodeApi: VscodeApi,
@@ -133,10 +135,13 @@ export default class VscodeHatRenderer {
133135
if (hatsDir) {
134136
await this.updateShapeOverrides(hatsDir);
135137

136-
if (fs.existsSync(hatsDir)) {
138+
try {
139+
await fs.access(hatsDir);
137140
this.hatsDirWatcherDisposable = watchDir(hatsDir, () =>
138141
this.updateShapeOverrides(hatsDir),
139142
);
143+
} catch (e) {
144+
console.error("cannot watch hatsDir", hatsDir, e);
140145
}
141146
} else {
142147
this.hatShapeOverrides = {};
@@ -150,7 +155,10 @@ export default class VscodeHatRenderer {
150155

151156
for (const file of files) {
152157
const name = path.basename(file, CURSORLESS_HAT_SHAPES_SUFFIX);
153-
this.hatShapeOverrides[name] = file;
158+
this.hatShapeOverrides[name] = vscode.Uri.from({
159+
scheme: "file",
160+
path: file,
161+
});
154162
}
155163

156164
await this.recomputeDecorations();
@@ -207,35 +215,41 @@ export default class VscodeHatRenderer {
207215
);
208216

209217
const hatSvgMap = Object.fromEntries(
210-
HAT_SHAPES.map((shape) => {
211-
const { sizeAdjustment = 0, verticalOffset = 0 } =
212-
defaultShapeAdjustments[shape];
213-
214-
const {
215-
sizeAdjustment: userIndividualSizeAdjustment = 0,
216-
verticalOffset: userIndividualVerticalOffset = 0,
217-
} = userIndividualAdjustments[shape] ?? {};
218-
219-
const scaleFactor =
220-
1 +
221-
(sizeAdjustment + userSizeAdjustment + userIndividualSizeAdjustment) /
218+
await Promise.all(
219+
HAT_SHAPES.map(async (shape) => {
220+
const { sizeAdjustment = 0, verticalOffset = 0 } =
221+
defaultShapeAdjustments[shape];
222+
223+
const {
224+
sizeAdjustment: userIndividualSizeAdjustment = 0,
225+
verticalOffset: userIndividualVerticalOffset = 0,
226+
} = userIndividualAdjustments[shape] ?? {};
227+
228+
const scaleFactor =
229+
1 +
230+
(sizeAdjustment +
231+
userSizeAdjustment +
232+
userIndividualSizeAdjustment) /
233+
100;
234+
235+
const finalVerticalOffsetEm =
236+
(verticalOffset +
237+
userVerticalOffset +
238+
userIndividualVerticalOffset) /
222239
100;
223240

224-
const finalVerticalOffsetEm =
225-
(verticalOffset + userVerticalOffset + userIndividualVerticalOffset) /
226-
100;
227-
228-
return [
229-
shape,
230-
this.processSvg(
231-
this.fontMeasurements,
241+
return [
232242
shape,
233-
scaleFactor,
234-
defaultShapeAdjustments[shape].strokeFactor ?? 1,
235-
finalVerticalOffsetEm,
236-
),
237-
];
238-
}),
243+
await this.processSvg(
244+
this.fontMeasurements,
245+
shape,
246+
scaleFactor,
247+
defaultShapeAdjustments[shape].strokeFactor ?? 1,
248+
finalVerticalOffsetEm,
249+
),
250+
];
251+
}),
252+
),
239253
);
240254

241255
this.decorationMap = Object.fromEntries(
@@ -373,22 +387,24 @@ export default class VscodeHatRenderer {
373387
* @param hatVerticalOffsetEm How far off top of characters should hats be
374388
* @returns An object with the new SVG and its measurements
375389
*/
376-
private processSvg(
390+
private async processSvg(
377391
fontMeasurements: FontMeasurements,
378392
shape: HatShape,
379393
scaleFactor: number,
380394
strokeFactor: number,
381395
hatVerticalOffsetEm: number,
382-
): SvgInfo | null {
396+
): Promise<SvgInfo | null> {
383397
const iconPath =
384398
this.hatShapeOverrides[shape] ??
385-
path.join(
386-
this.extensionContext.extensionPath,
399+
vscode.Uri.joinPath(
400+
this.extensionContext.extensionUri,
387401
"images",
388402
"hats",
389403
`${shape}.svg`,
390404
);
391-
const rawSvg = fs.readFileSync(iconPath, "utf8");
405+
const rawSvg = this.decoder.decode(
406+
await vscode.workspace.fs.readFile(iconPath),
407+
);
392408
const { characterWidth, characterHeight, fontSize } = fontMeasurements;
393409

394410
if (!this.checkSvg(shape, rawSvg)) {

0 commit comments

Comments
 (0)