Roo-Code/src/shared/context-mentions.ts
John Richmond 34d7dcf8c3
Support mentioning filenames with spaces (#3044)
* Support mentioning filenames with spaces

Allows spaces to be escaped in mentions with \. Does not attempt more
comprehensive escape handling. (IMO a more structured representation or
moving to something like @[something complex] is probably a better long
term approach, but the scope of that seems problematic.

Adapted from 8955d45708.

Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com>

* Older array creation to make check-types happier

---------

Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com>
2025-04-29 22:27:16 -04:00

101 lines
4.4 KiB
TypeScript

/*
Mention regex:
- **Purpose**:
- To identify and highlight specific mentions in text that start with '@'.
- These mentions can be file paths, URLs, or the exact word 'problems'.
- 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.
- **Regex Breakdown**:
- `/@`:
- **@**: The mention must start with the '@' symbol.
- `((?:\/|\w+:\/\/)[^\s]+?|problems\b|git-changes\b)`:
- **Capturing Group (`(...)`)**: Captures the part of the string that matches one of the specified patterns.
- `(?:\/|\w+:\/\/)`:
- **Non-Capturing Group (`(?:...)`)**: Groups the alternatives without capturing them for back-referencing.
- `\/`:
- **Slash (`/`)**: Indicates that the mention is a file or folder path starting with a '/'.
- `|`: Logical OR.
- `\w+:\/\/`:
- **Protocol (`\w+://`)**: Matches URLs that start with a word character sequence followed by '://', such as 'http://', 'https://', 'ftp://', etc.
- `(?:[^\s\\]|\\ )+?`:
- **Non-Capturing Group (`(?:...)`)**: Groups the alternatives without capturing them.
- **Non-Whitespace and Non-Backslash (`[^\s\\]`)**: Matches any character that is not whitespace or a backslash.
- **OR (`|`)**: Logical OR.
- **Escaped Space (`\\ `)**: Matches a backslash followed by a space (an escaped space).
- **Non-Greedy (`+?`)**: Ensures the smallest possible match, preventing the inclusion of trailing punctuation.
- `|`: Logical OR.
- `problems\b`:
- **Exact Word ('problems')**: Matches the exact word 'problems'.
- **Word Boundary (`\b`)**: Ensures that 'problems' is matched as a whole word and not as part of another word (e.g., 'problematic').
- `|`: Logical OR.
- `terminal\b`:
- **Exact Word ('terminal')**: Matches the exact word 'terminal'.
- **Word Boundary (`\b`)**: Ensures that 'terminal' is matched as a whole word and not as part of another word (e.g., 'terminals').
- `(?=[.,;:!?]?(?=[\s\r\n]|$))`:
- **Positive Lookahead (`(?=...)`)**: Ensures that the match is followed by specific patterns without including them in the match.
- `[.,;:!?]?`:
- **Optional Punctuation (`[.,;:!?]?`)**: Matches zero or one of the specified punctuation marks.
- `(?=[\s\r\n]|$)`:
- **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.
- **Summary**:
- The regex effectively matches:
- Mentions that are file or folder paths starting with '/' and containing any non-whitespace characters (including periods within the path).
- File paths can include spaces if they are escaped with a backslash (e.g., `@/path/to/file\ with\ spaces.txt`).
- URLs that start with a protocol (like 'http://') followed by any non-whitespace characters (including query parameters).
- The exact word 'problems'.
- The exact word 'git-changes'.
- The exact word 'terminal'.
- It ensures that any trailing punctuation marks (such as ',', '.', '!', etc.) are not included in the matched mention, allowing the punctuation to follow the mention naturally in the text.
- **Global Regex**:
- `mentionRegexGlobal`: Creates a global version of the `mentionRegex` to find all matches within a given string.
*/
export const mentionRegex =
/@((?:\/|\w+:\/\/)(?:[^\s\\]|\\ )+?|[a-f0-9]{7,40}\b|problems\b|git-changes\b|terminal\b)(?=[.,;:!?]?(?=[\s\r\n]|$))/
export const mentionRegexGlobal = new RegExp(mentionRegex.source, "g")
export interface MentionSuggestion {
type: "file" | "folder" | "git" | "problems"
label: string
description?: string
value: string
icon?: string
}
export interface GitMentionSuggestion extends MentionSuggestion {
type: "git"
hash: string
shortHash: string
subject: string
author: string
date: string
}
export function formatGitSuggestion(commit: {
hash: string
shortHash: string
subject: string
author: string
date: string
}): GitMentionSuggestion {
return {
type: "git",
label: commit.subject,
description: `${commit.shortHash} by ${commit.author} on ${commit.date}`,
value: commit.hash,
icon: "$(git-commit)", // VSCode git commit icon
hash: commit.hash,
shortHash: commit.shortHash,
subject: commit.subject,
author: commit.author,
date: commit.date,
}
}
// Helper function to unescape paths with backslash-escaped spaces
export function unescapeSpaces(path: string): string {
return path.replace(/\\ /g, " ")
}