From 3592539fe54a09af7de79baec2f94acb35338890 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Tue, 25 Feb 2025 15:53:30 -0500 Subject: [PATCH] PR feedback --- .../src/components/chat/ChatTextArea.tsx | 16 ++----- .../src/utils/__tests__/path-mentions.test.ts | 45 +++++++++++++++++++ webview-ui/src/utils/path-mentions.ts | 38 ++++++++++++++++ 3 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 webview-ui/src/utils/__tests__/path-mentions.test.ts create mode 100644 webview-ui/src/utils/path-mentions.ts diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index 229a91d031..dc78a3fdb3 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -16,6 +16,7 @@ import { vscode } from "../../utils/vscode" import { WebviewMessage } from "../../../../src/shared/WebviewMessage" import { Mode, getAllModes } from "../../../../src/shared/modes" import { CaretIcon } from "../common/CaretIcon" +import { convertToMentionPath } from "../../utils/path-mentions" interface ChatTextAreaProps { inputValue: string @@ -589,19 +590,8 @@ const ChatTextArea = forwardRef( const files = Array.from(e.dataTransfer.files) const text = e.dataTransfer.getData("text") if (text) { - let mentionText = text - const normalizedText = text.replace(/\\/g, "/") - const normalizedCwd = cwd ? cwd.replace(/\\/g, "/") : "" - - // Always use case-insensitive comparison for path matching - if (normalizedCwd) { - const lowerText = normalizedText.toLowerCase() - const lowerCwd = normalizedCwd.toLowerCase() - - if (lowerText.startsWith(lowerCwd)) { - mentionText = "@" + normalizedText.substring(normalizedCwd.length) - } - } + // Convert the path to a mention-friendly format + const mentionText = convertToMentionPath(text, cwd) const newValue = inputValue.slice(0, cursorPosition) + mentionText + " " + inputValue.slice(cursorPosition) diff --git a/webview-ui/src/utils/__tests__/path-mentions.test.ts b/webview-ui/src/utils/__tests__/path-mentions.test.ts new file mode 100644 index 0000000000..bb5591fbe5 --- /dev/null +++ b/webview-ui/src/utils/__tests__/path-mentions.test.ts @@ -0,0 +1,45 @@ +import { convertToMentionPath } from "../path-mentions" + +describe("path-mentions", () => { + describe("convertToMentionPath", () => { + it("should convert an absolute path to a mention path when it starts with cwd", () => { + // Windows-style paths + expect(convertToMentionPath("C:\\Users\\user\\project\\file.txt", "C:\\Users\\user\\project")).toBe( + "@/file.txt", + ) + + // Unix-style paths + expect(convertToMentionPath("/Users/user/project/file.txt", "/Users/user/project")).toBe("@/file.txt") + }) + + it("should handle paths with trailing slashes in cwd", () => { + expect(convertToMentionPath("/Users/user/project/file.txt", "/Users/user/project/")).toBe("@/file.txt") + }) + + it("should be case-insensitive when matching paths", () => { + expect(convertToMentionPath("/Users/User/Project/file.txt", "/users/user/project")).toBe("@/file.txt") + }) + + it("should return the original path when cwd is not provided", () => { + expect(convertToMentionPath("/Users/user/project/file.txt")).toBe("/Users/user/project/file.txt") + }) + + it("should return the original path when it does not start with cwd", () => { + expect(convertToMentionPath("/Users/other/project/file.txt", "/Users/user/project")).toBe( + "/Users/other/project/file.txt", + ) + }) + + it("should normalize backslashes to forward slashes", () => { + expect(convertToMentionPath("C:\\Users\\user\\project\\subdir\\file.txt", "C:\\Users\\user\\project")).toBe( + "@/subdir/file.txt", + ) + }) + + it("should handle nested paths correctly", () => { + expect(convertToMentionPath("/Users/user/project/nested/deeply/file.txt", "/Users/user/project")).toBe( + "@/nested/deeply/file.txt", + ) + }) + }) +}) diff --git a/webview-ui/src/utils/path-mentions.ts b/webview-ui/src/utils/path-mentions.ts new file mode 100644 index 0000000000..960483f593 --- /dev/null +++ b/webview-ui/src/utils/path-mentions.ts @@ -0,0 +1,38 @@ +/** + * Utilities for handling path-related operations in mentions + */ + +/** + * Converts an absolute path to a mention-friendly path + * If the provided path starts with the current working directory, + * it's converted to a relative path prefixed with @ + * + * @param path The path to convert + * @param cwd The current working directory + * @returns A mention-friendly path + */ +export function convertToMentionPath(path: string, cwd?: string): string { + const normalizedPath = path.replace(/\\/g, "/") + let normalizedCwd = cwd ? cwd.replace(/\\/g, "/") : "" + + if (!normalizedCwd) { + return path + } + + // Remove trailing slash from cwd if it exists + if (normalizedCwd.endsWith("/")) { + normalizedCwd = normalizedCwd.slice(0, -1) + } + + // Always use case-insensitive comparison for path matching + const lowerPath = normalizedPath.toLowerCase() + const lowerCwd = normalizedCwd.toLowerCase() + + if (lowerPath.startsWith(lowerCwd)) { + const relativePath = normalizedPath.substring(normalizedCwd.length) + // Ensure there's a slash after the @ symbol when we create the mention path + return "@" + (relativePath.startsWith("/") ? relativePath : "/" + relativePath) + } + + return path +}