mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 12:21:13 -05:00
Make mentions clickable
This commit is contained in:
@@ -28,6 +28,7 @@ class WorkspaceTracker {
|
|||||||
|
|
||||||
private registerListeners() {
|
private registerListeners() {
|
||||||
// Listen for file creation
|
// Listen for file creation
|
||||||
|
// .bind(this) ensures the callback refers to class instance when using this, not necessary when using arrow function
|
||||||
this.disposables.push(vscode.workspace.onDidCreateFiles(this.onFilesCreated.bind(this)))
|
this.disposables.push(vscode.workspace.onDidCreateFiles(this.onFilesCreated.bind(this)))
|
||||||
|
|
||||||
// Listen for file deletion
|
// Listen for file deletion
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import axios from "axios"
|
|||||||
import { getTheme } from "../utils/getTheme"
|
import { getTheme } from "../utils/getTheme"
|
||||||
import { openFile, openImage } from "../utils/open-file"
|
import { openFile, openImage } from "../utils/open-file"
|
||||||
import WorkspaceTracker from "../integrations/WorkspaceTracker"
|
import WorkspaceTracker from "../integrations/WorkspaceTracker"
|
||||||
|
import { openMention } from "../utils/context-mentions"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
||||||
@@ -423,6 +424,9 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
|
|||||||
case "openFile":
|
case "openFile":
|
||||||
openFile(message.text!)
|
openFile(message.text!)
|
||||||
break
|
break
|
||||||
|
case "openMention":
|
||||||
|
openMention(message.text)
|
||||||
|
break
|
||||||
// Add more switch case statements here as more webview message commands
|
// Add more switch case statements here as more webview message commands
|
||||||
// are created within the webview context (i.e. inside media/main.js)
|
// are created within the webview context (i.e. inside media/main.js)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export interface WebviewMessage {
|
|||||||
| "requestOllamaModels"
|
| "requestOllamaModels"
|
||||||
| "openImage"
|
| "openImage"
|
||||||
| "openFile"
|
| "openFile"
|
||||||
|
| "openMention"
|
||||||
text?: string
|
text?: string
|
||||||
askResponse?: ClaudeAskResponse
|
askResponse?: ClaudeAskResponse
|
||||||
apiConfiguration?: ApiConfiguration
|
apiConfiguration?: ApiConfiguration
|
||||||
|
|||||||
9
src/shared/context-mentions.ts
Normal file
9
src/shared/context-mentions.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
Mention regex
|
||||||
|
- File and folder paths (starting with '/')
|
||||||
|
- URLs (containing '://')
|
||||||
|
- The 'problems' keyword
|
||||||
|
- Word boundary after 'problems' to avoid partial matches
|
||||||
|
*/
|
||||||
|
export const mentionRegex = /@((?:\/|\w+:\/\/)[^\s]+|problems\b)/
|
||||||
|
export const mentionRegexGlobal = new RegExp(mentionRegex.source, "g")
|
||||||
28
src/utils/context-mentions.ts
Normal file
28
src/utils/context-mentions.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import * as vscode from "vscode"
|
||||||
|
import * as path from "path"
|
||||||
|
import { openFile } from "./open-file"
|
||||||
|
|
||||||
|
export function openMention(mention?: string): void {
|
||||||
|
if (!mention) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mention.startsWith("/")) {
|
||||||
|
const relPath = mention.slice(1)
|
||||||
|
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
|
||||||
|
if (!cwd) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const absPath = path.resolve(cwd, relPath)
|
||||||
|
if (mention.endsWith("/")) {
|
||||||
|
vscode.commands.executeCommand("revealInExplorer", vscode.Uri.file(absPath))
|
||||||
|
// vscode.commands.executeCommand("vscode.openFolder", , { forceNewWindow: false }) opens in new window
|
||||||
|
} else {
|
||||||
|
openFile(absPath)
|
||||||
|
}
|
||||||
|
} else if (mention === "problems") {
|
||||||
|
vscode.commands.executeCommand("workbench.actions.view.problems")
|
||||||
|
} else if (mention.startsWith("http")) {
|
||||||
|
vscode.env.openExternal(vscode.Uri.parse(mention))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,15 +4,14 @@ import { useExtensionState } from "../context/ExtensionStateContext"
|
|||||||
import {
|
import {
|
||||||
getContextMenuOptions,
|
getContextMenuOptions,
|
||||||
insertMention,
|
insertMention,
|
||||||
mentionRegex,
|
|
||||||
mentionRegexGlobal,
|
|
||||||
removeMention,
|
removeMention,
|
||||||
shouldShowContextMenu,
|
shouldShowContextMenu,
|
||||||
ContextMenuOptionType,
|
ContextMenuOptionType,
|
||||||
} from "../utils/mention-context"
|
} from "../utils/context-mentions"
|
||||||
import { MAX_IMAGES_PER_MESSAGE } from "./ChatView"
|
import { MAX_IMAGES_PER_MESSAGE } from "./ChatView"
|
||||||
import ContextMenu from "./ContextMenu"
|
import ContextMenu from "./ContextMenu"
|
||||||
import Thumbnails from "./Thumbnails"
|
import Thumbnails from "./Thumbnails"
|
||||||
|
import { mentionRegex, mentionRegexGlobal } from "../../../src/shared/context-mentions"
|
||||||
|
|
||||||
interface ChatTextAreaProps {
|
interface ChatTextAreaProps {
|
||||||
inputValue: string
|
inputValue: string
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useMemo, useRef } from "react"
|
import React, { useEffect, useMemo, useRef } from "react"
|
||||||
import { ContextMenuOptionType, ContextMenuQueryItem, getContextMenuOptions } from "../utils/mention-context"
|
import { ContextMenuOptionType, ContextMenuQueryItem, getContextMenuOptions } from "../utils/context-mentions"
|
||||||
import { formatFilePathForTruncation } from "./CodeAccordian"
|
import { formatFilePathForTruncation } from "./CodeAccordian"
|
||||||
|
|
||||||
interface ContextMenuProps {
|
interface ContextMenuProps {
|
||||||
@@ -109,14 +109,15 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
|
|||||||
ref={menuRef}
|
ref={menuRef}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: "var(--vscode-dropdown-background)",
|
backgroundColor: "var(--vscode-dropdown-background)",
|
||||||
border: "1px solid var(--vscode-dropdown-border)",
|
border: "1px solid var(--vscode-editorGroup-border)",
|
||||||
borderRadius: "3px",
|
borderRadius: "3px",
|
||||||
|
boxShadow: "0 4px 10px rgba(0, 0, 0, 0.25)",
|
||||||
zIndex: 1000,
|
zIndex: 1000,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
boxShadow: "0 8px 16px rgba(0,0,0,0.24)",
|
|
||||||
maxHeight: "200px",
|
maxHeight: "200px",
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
|
overflow: "hidden",
|
||||||
}}>
|
}}>
|
||||||
{/* Can't use virtuoso since it requires fixed height and menu height is dynamic based on # of items */}
|
{/* Can't use virtuoso since it requires fixed height and menu height is dynamic based on # of items */}
|
||||||
{filteredOptions.map((option, index) => (
|
{filteredOptions.map((option, index) => (
|
||||||
@@ -127,7 +128,7 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
|
|||||||
padding: "8px 12px",
|
padding: "8px 12px",
|
||||||
cursor: isOptionSelectable(option) ? "pointer" : "default",
|
cursor: isOptionSelectable(option) ? "pointer" : "default",
|
||||||
color: "var(--vscode-dropdown-foreground)",
|
color: "var(--vscode-dropdown-foreground)",
|
||||||
borderBottom: "1px solid var(--vscode-dropdown-border)",
|
borderBottom: "1px solid var(--vscode-editorGroup-border)",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import React, { memo, useEffect, useMemo, useRef, useState } from "react"
|
|||||||
import { useWindowSize } from "react-use"
|
import { useWindowSize } from "react-use"
|
||||||
import { ClaudeMessage } from "../../../src/shared/ExtensionMessage"
|
import { ClaudeMessage } from "../../../src/shared/ExtensionMessage"
|
||||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||||
import { mentionRegexGlobal } from "../utils/mention-context"
|
|
||||||
import { vscode } from "../utils/vscode"
|
import { vscode } from "../utils/vscode"
|
||||||
import Thumbnails from "./Thumbnails"
|
import Thumbnails from "./Thumbnails"
|
||||||
|
import { mentionRegexGlobal } from "../../../src/shared/context-mentions"
|
||||||
|
|
||||||
interface TaskHeaderProps {
|
interface TaskHeaderProps {
|
||||||
task: ClaudeMessage
|
task: ClaudeMessage
|
||||||
@@ -351,7 +351,9 @@ export const highlightMentions = (text?: string, withShadow = true) => {
|
|||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
key={index}
|
key={index}
|
||||||
className={withShadow ? "mention-context-highlight-with-shadow" : "mention-context-highlight"}>
|
className={withShadow ? "mention-context-highlight-with-shadow" : "mention-context-highlight"}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
onClick={() => vscode.postMessage({ type: "openMention", text: part })}>
|
||||||
@{part}
|
@{part}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
/*
|
import { mentionRegex } from "../../../src/shared/context-mentions"
|
||||||
Mention regex
|
|
||||||
- File and folder paths (starting with '/')
|
|
||||||
- URLs (containing '://')
|
|
||||||
- The 'problems' keyword
|
|
||||||
- Word boundary after 'problems' to avoid partial matches
|
|
||||||
*/
|
|
||||||
export const mentionRegex = /@((?:\/|\w+:\/\/)[^\s]+|problems\b)/
|
|
||||||
export const mentionRegexGlobal = new RegExp(mentionRegex.source, "g")
|
|
||||||
|
|
||||||
export function insertMention(text: string, position: number, value: string): string {
|
export function insertMention(text: string, position: number, value: string): string {
|
||||||
const beforeCursor = text.slice(0, position)
|
const beforeCursor = text.slice(0, position)
|
||||||
Reference in New Issue
Block a user