Skip to content

Commit 9c1869a

Browse files
committed
bug: space in folder and file name
1 parent 6772306 commit 9c1869a

File tree

3 files changed

+67
-16
lines changed

3 files changed

+67
-16
lines changed

src/core/mentions/__tests__/index.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,46 @@ Detailed commit message with multiple lines
144144
expect(result).toContain(`<git_commit hash="${commitHash}">`)
145145
expect(result).toContain(`Error fetching commit info: ${errorMessage}`)
146146
})
147+
148+
it("should parse file paths with spaces", async () => {
149+
// Mock the file content fetching
150+
const fileContent = "This is the content of the file with spaces in its name"
151+
152+
// Mock the getFileOrFolderContent function (which is called internally by parseMentions)
153+
// This is done by mocking the fs.readFile that would be called inside getFileOrFolderContent
154+
const fs = require("fs/promises")
155+
jest.spyOn(fs, "readFile").mockResolvedValue(fileContent)
156+
jest.spyOn(fs, "stat").mockResolvedValue({ isFile: () => true, isDirectory: () => false } as any)
157+
158+
const filePath = "/path/with spaces/my file.txt"
159+
const result = await parseMentions(`Check out this file @${filePath}`, mockCwd, mockUrlContentFetcher)
160+
161+
// Verify the file path with spaces was correctly parsed
162+
expect(result).toContain(`'path/with spaces/my file.txt' (see below for file content)`)
163+
expect(result).toContain(`<file_content path="path/with spaces/my file.txt">`)
164+
})
165+
166+
it("should parse folder paths with spaces", async () => {
167+
// Mock the folder content fetching
168+
const folderContent = "├── file1.txt\n├── file2.txt\n└── subfolder/"
169+
170+
// Mock the getFileOrFolderContent function (which is called internally by parseMentions)
171+
// This is done by mocking the fs.readdir and fs.stat that would be called inside getFileOrFolderContent
172+
const fs = require("fs/promises")
173+
jest.spyOn(fs, "readdir").mockResolvedValue([
174+
{ name: "file1.txt", isFile: () => true, isDirectory: () => false },
175+
{ name: "file2.txt", isFile: () => true, isDirectory: () => false },
176+
{ name: "subfolder", isFile: () => false, isDirectory: () => true }
177+
])
178+
jest.spyOn(fs, "stat").mockResolvedValue({ isFile: () => false, isDirectory: () => true } as any)
179+
180+
const folderPath = "/folder with spaces/"
181+
const result = await parseMentions(`Check out this folder @${folderPath}`, mockCwd, mockUrlContentFetcher)
182+
183+
// Verify the folder path with spaces was correctly parsed
184+
expect(result).toContain(`'folder with spaces/' (see below for folder content)`)
185+
expect(result).toContain(`<folder_content path="folder with spaces/">`)
186+
})
147187
})
148188

149189
describe("openMention", () => {

src/shared/context-mentions.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11
/*
22
Mention regex:
3-
- **Purpose**:
4-
- To identify and highlight specific mentions in text that start with '@'.
3+
- **Purpose**:
4+
- To identify and highlight specific mentions in text that start with '@'.
55
- These mentions can be file paths, URLs, or the exact word 'problems'.
66
- Ensures that trailing punctuation marks (like commas, periods, etc.) are not included in the match, allowing punctuation to follow the mention without being part of it.
77
88
- **Regex Breakdown**:
9-
- `/@`:
9+
- `/@`:
1010
- **@**: The mention must start with the '@' symbol.
11-
12-
- `((?:\/|\w+:\/\/)[^\s]+?|problems\b|git-changes\b)`:
11+
12+
- `((?:\/|\w+:\/\/)(?:[^\s]|\s(?=[^\s]))+?|problems\b|git-changes\b)`:
1313
- **Capturing Group (`(...)`)**: Captures the part of the string that matches one of the specified patterns.
14-
- `(?:\/|\w+:\/\/)`:
14+
- `(?:\/|\w+:\/\/)`:
1515
- **Non-Capturing Group (`(?:...)`)**: Groups the alternatives without capturing them for back-referencing.
16-
- `\/`:
16+
- `\/`:
1717
- **Slash (`/`)**: Indicates that the mention is a file or folder path starting with a '/'.
1818
- `|`: Logical OR.
19-
- `\w+:\/\/`:
19+
- `\w+:\/\/`:
2020
- **Protocol (`\w+://`)**: Matches URLs that start with a word character sequence followed by '://', such as 'http://', 'https://', 'ftp://', etc.
21-
- `[^\s]+?`:
22-
- **Non-Whitespace Characters (`[^\s]+`)**: Matches one or more characters that are not whitespace.
21+
- `(?:[^\s]|\s(?=[^\s]))+?`:
22+
- **Character Pattern**: Matches either a non-whitespace character OR a whitespace character that is followed by a non-whitespace character.
23+
- **This allows spaces within file paths while preventing trailing spaces**.
2324
- **Non-Greedy (`+?`)**: Ensures the smallest possible match, preventing the inclusion of trailing punctuation.
2425
- `|`: Logical OR.
25-
- `problems\b`:
26+
- `problems\b`:
2627
- **Exact Word ('problems')**: Matches the exact word 'problems'.
2728
- **Word Boundary (`\b`)**: Ensures that 'problems' is matched as a whole word and not as part of another word (e.g., 'problematic').
2829
- `|`: Logical OR.
@@ -31,14 +32,14 @@ Mention regex:
3132
- **Word Boundary (`\b`)**: Ensures that 'terminal' is matched as a whole word and not as part of another word (e.g., 'terminals').
3233
- `(?=[.,;:!?]?(?=[\s\r\n]|$))`:
3334
- **Positive Lookahead (`(?=...)`)**: Ensures that the match is followed by specific patterns without including them in the match.
34-
- `[.,;:!?]?`:
35+
- `[.,;:!?]?`:
3536
- **Optional Punctuation (`[.,;:!?]?`)**: Matches zero or one of the specified punctuation marks.
36-
- `(?=[\s\r\n]|$)`:
37+
- `(?=[\s\r\n]|$)`:
3738
- **Nested Positive Lookahead (`(?=[\s\r\n]|$)`)**: Ensures that the punctuation (if present) is followed by a whitespace character, a line break, or the end of the string.
38-
39+
3940
- **Summary**:
4041
- The regex effectively matches:
41-
- Mentions that are file or folder paths starting with '/' and containing any non-whitespace characters (including periods within the path).
42+
- Mentions that are file or folder paths starting with '/' and can contain spaces within the path (e.g., 'my folder/my file.txt').
4243
- URLs that start with a protocol (like 'http://') followed by any non-whitespace characters (including query parameters).
4344
- The exact word 'problems'.
4445
- The exact word 'git-changes'.
@@ -50,7 +51,7 @@ Mention regex:
5051
5152
*/
5253
export const mentionRegex =
53-
/@((?:\/|\w+:\/\/)[^\s]+?|[a-f0-9]{7,40}\b|problems\b|git-changes\b|terminal\b)(?=[.,;:!?]?(?=[\s\r\n]|$))/
54+
/@((?:\/|\w+:\/\/)(?:[^\s]|\s(?=[^\s]))+?|[a-f0-9]{7,40}\b|problems\b|git-changes\b|terminal\b)(?=[.,;:!?]?(?=[\s\r\n]|$))/
5455
export const mentionRegexGlobal = new RegExp(mentionRegex.source, "g")
5556

5657
export interface MentionSuggestion {

webview-ui/src/utils/__tests__/context-mentions.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,4 +372,14 @@ describe("shouldShowContextMenu", () => {
372372
// Position cursor at the end to test the full word
373373
expect(shouldShowContextMenu("@problems", 9)).toBe(true)
374374
})
375+
376+
it("should return true for file paths with spaces", () => {
377+
// Test with a file path containing spaces
378+
expect(shouldShowContextMenu("@/path/to/my file.txt", 20)).toBe(true)
379+
})
380+
381+
it("should return true for folder paths with spaces", () => {
382+
// Test with a folder path containing spaces
383+
expect(shouldShowContextMenu("@/path/to/my folder/", 20)).toBe(true)
384+
})
375385
})

0 commit comments

Comments
 (0)