Skip to content

Commit 81fe7e8

Browse files
committed
Fix detecting Cursor IDE name
1 parent 25e5f47 commit 81fe7e8

2 files changed

Lines changed: 67 additions & 13 deletions

File tree

src/utils.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as vscode from 'vscode';
22
import { COMMON_AI_EXTENSIONS, TIME_BETWEEN_HEARTBEATS_MS } from './constants';
33

44
export class Utils {
5-
private static appNames = {
5+
private static appNames: { [key: string]: string } = {
66
'Arduino IDE': 'arduino',
77
'Azure Data Studio': 'azdata',
88
Cursor: 'cursor',
@@ -15,6 +15,16 @@ export class Utils {
1515
Windsurf: 'windsurf',
1616
};
1717

18+
private static editorNameFromHint(hint?: string): string | undefined {
19+
const normalized = hint?.replace(/\s/g, '').toLowerCase();
20+
if (!normalized) return undefined;
21+
22+
for (const editor of Object.keys(this.appNames)) {
23+
const editorKey = editor.replace(/\s/g, '').toLowerCase();
24+
if (normalized.includes(editorKey)) return this.appNames[editor];
25+
}
26+
}
27+
1828
public static quote(str: string): string {
1929
if (str.includes(' ')) return `"${str.replace(/"/g, '\\"')}"`;
2030
return str;
@@ -199,22 +209,16 @@ export class Utils {
199209
return false;
200210
}
201211

202-
public static getEditorName(): string {
203-
if (this.appNames[vscode.env.appName]) {
204-
return this.appNames[vscode.env.appName];
205-
}
212+
public static getEditorName(env: typeof vscode.env = vscode.env): string {
213+
const editor = this.editorNameFromHint(env.uriScheme) || this.editorNameFromHint(env.appRoot);
214+
if (editor) return editor;
206215

207-
const appRoot = vscode.env.appRoot.toLowerCase();
208-
for (const editor of Object.keys(this.appNames)) {
209-
if (appRoot.includes(editor.toLowerCase())) {
210-
return this.appNames[editor];
211-
}
212-
}
216+
if (this.appNames[env.appName]) return this.appNames[env.appName];
213217

214-
if (vscode.env.appName.toLowerCase().includes('visual')) {
218+
if (env.appName.toLowerCase().includes('visual')) {
215219
return 'vscode';
216220
} else {
217-
return vscode.env.appName.replace(/\s/g, '').toLowerCase();
221+
return env.appName.replace(/\s/g, '').toLowerCase();
218222
}
219223
}
220224

test/extension.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,59 @@
11
import * as assert from 'assert';
22
import * as path from 'path';
33
import * as vscode from 'vscode';
4+
import { Utils } from '../src/utils';
45
import { WakaTime } from '../src/wakatime';
56

7+
const mockEnv = (overrides: Partial<typeof vscode.env>): typeof vscode.env => {
8+
return {
9+
appName: 'Visual Studio Code',
10+
appRoot: '/Applications/Visual Studio Code.app/Contents/Resources/app',
11+
uriScheme: 'vscode',
12+
...overrides,
13+
} as typeof vscode.env;
14+
};
15+
616
// Defines a Mocha test suite to group tests of similar kind together
717
suite("WakaTime Tests", () => {
818
// Should be implemented after integration with CI/CD
919
});
20+
21+
suite('Utils.getEditorName Tests', () => {
22+
test('detects editor from appName', () => {
23+
assert.strictEqual(Utils.getEditorName(mockEnv({ appName: 'Cursor' })), 'cursor');
24+
assert.strictEqual(Utils.getEditorName(mockEnv({ appName: 'Windsurf' })), 'windsurf');
25+
});
26+
27+
test('detects Cursor from uriScheme when appName reports vscode', () => {
28+
const env = mockEnv({ uriScheme: 'cursor' });
29+
assert.strictEqual(Utils.getEditorName(env), 'cursor');
30+
});
31+
32+
test('prefers uriScheme over appName', () => {
33+
const env = mockEnv({ appName: 'Visual Studio Code', uriScheme: 'windsurf' });
34+
assert.strictEqual(Utils.getEditorName(env), 'windsurf');
35+
});
36+
37+
test('detects Cursor from appRoot when appName and uriScheme report vscode', () => {
38+
const env = mockEnv({ appRoot: '/Applications/Cursor.app/Contents/Resources/app' });
39+
assert.strictEqual(Utils.getEditorName(env), 'cursor');
40+
});
41+
42+
test('appRoot matching ignores whitespace in editor names', () => {
43+
const env = mockEnv({ appRoot: 'C:\\Program Files\\Azure Data Studio\\resources\\app' });
44+
assert.strictEqual(Utils.getEditorName(env), 'azdata');
45+
});
46+
47+
test('falls back to vscode for Visual Studio Code', () => {
48+
assert.strictEqual(Utils.getEditorName(mockEnv({})), 'vscode');
49+
});
50+
51+
test('falls back to normalized appName for unknown editors', () => {
52+
const env = mockEnv({
53+
appName: 'Some Editor',
54+
appRoot: '/opt/some-editor/resources/app',
55+
uriScheme: 'some-editor',
56+
});
57+
assert.strictEqual(Utils.getEditorName(env), 'someeditor');
58+
});
59+
});

0 commit comments

Comments
 (0)