= ({
return Paste URL to fetch contents
case ContextMenuOptionType.NoResults:
return No results found
+ case ContextMenuOptionType.Git:
+ if (option.value) {
+ return (
+
+ {option.label}
+
+ {option.description}
+
+
+ )
+ } else {
+ return Git Commits
+ }
case ContextMenuOptionType.File:
case ContextMenuOptionType.Folder:
if (option.value) {
@@ -91,6 +112,8 @@ const ContextMenu: React.FC = ({
return "terminal"
case ContextMenuOptionType.URL:
return "link"
+ case ContextMenuOptionType.Git:
+ return "git-commit"
case ContextMenuOptionType.NoResults:
return "info"
default:
@@ -165,7 +188,9 @@ const ContextMenu: React.FC = ({
/>
{renderOptionContent(option)}
- {(option.type === ContextMenuOptionType.File || option.type === ContextMenuOptionType.Folder) &&
+ {(option.type === ContextMenuOptionType.File ||
+ option.type === ContextMenuOptionType.Folder ||
+ option.type === ContextMenuOptionType.Git) &&
!option.value && (
= ({
)}
{(option.type === ContextMenuOptionType.Problems ||
option.type === ContextMenuOptionType.Terminal ||
- ((option.type === ContextMenuOptionType.File || option.type === ContextMenuOptionType.Folder) &&
+ ((option.type === ContextMenuOptionType.File ||
+ option.type === ContextMenuOptionType.Folder ||
+ option.type === ContextMenuOptionType.Git) &&
option.value)) && (
0 ? folders : [{ type: ContextMenuOptionType.NoResults }]
}
+ if (selectedType === ContextMenuOptionType.Git) {
+ const commits = queryItems.filter((item) => item.type === ContextMenuOptionType.Git)
+ return commits.length > 0 ? [workingChanges, ...commits] : [workingChanges]
+ }
+
return [
{ type: ContextMenuOptionType.URL },
{ type: ContextMenuOptionType.Problems },
{ type: ContextMenuOptionType.Terminal },
+ { type: ContextMenuOptionType.Git },
{ type: ContextMenuOptionType.Folder },
{ type: ContextMenuOptionType.File },
]
}
const lowerQuery = query.toLowerCase()
+ const suggestions: ContextMenuQueryItem[] = []
+ // Check for top-level option matches
+ if ("git".startsWith(lowerQuery)) {
+ suggestions.push({
+ type: ContextMenuOptionType.Git,
+ label: "Git Commits",
+ description: "Search repository history",
+ })
+ } else if ("git-changes".startsWith(lowerQuery)) {
+ suggestions.push(workingChanges)
+ }
+ if ("problems".startsWith(lowerQuery)) {
+ suggestions.push({ type: ContextMenuOptionType.Problems })
+ }
if (query.startsWith("http")) {
- return [{ type: ContextMenuOptionType.URL, value: query }]
- } else {
- const matchingItems = queryItems.filter((item) => item.value?.toLowerCase().includes(lowerQuery))
+ suggestions.push({ type: ContextMenuOptionType.URL, value: query })
+ }
- if (matchingItems.length > 0) {
- return matchingItems.map((item) => ({
- type: item.type,
- value: item.value,
- }))
+ // Add exact SHA matches to suggestions
+ if (/^[a-f0-9]{7,40}$/i.test(lowerQuery)) {
+ const exactMatches = queryItems.filter(
+ (item) => item.type === ContextMenuOptionType.Git && item.value?.toLowerCase() === lowerQuery,
+ )
+ if (exactMatches.length > 0) {
+ suggestions.push(...exactMatches)
} else {
- return [{ type: ContextMenuOptionType.NoResults }]
+ // If no exact match but valid SHA format, add as option
+ suggestions.push({
+ type: ContextMenuOptionType.Git,
+ value: lowerQuery,
+ label: `Commit ${lowerQuery}`,
+ description: "Git commit hash",
+ })
}
}
+
+ // Create searchable strings array for fzf
+ const searchableItems = queryItems.map((item) => ({
+ original: item,
+ searchStr: [item.value, item.label, item.description].filter(Boolean).join(" "),
+ }))
+
+ // Initialize fzf instance for fuzzy search
+ const fzf = new Fzf(searchableItems, {
+ selector: (item) => item.searchStr,
+ })
+
+ // Get fuzzy matching items
+ const matchingItems = query ? fzf.find(query).map((result) => result.item.original) : []
+
+ // Separate matches by type
+ const fileMatches = matchingItems.filter(
+ (item) => item.type === ContextMenuOptionType.File || item.type === ContextMenuOptionType.Folder,
+ )
+ const gitMatches = matchingItems.filter((item) => item.type === ContextMenuOptionType.Git)
+ const otherMatches = matchingItems.filter(
+ (item) =>
+ item.type !== ContextMenuOptionType.File &&
+ item.type !== ContextMenuOptionType.Folder &&
+ item.type !== ContextMenuOptionType.Git,
+ )
+
+ // Combine suggestions with matching items in the desired order
+ if (suggestions.length > 0 || matchingItems.length > 0) {
+ const allItems = [...suggestions, ...fileMatches, ...gitMatches, ...otherMatches]
+
+ // Remove duplicates based on type and value
+ const seen = new Set()
+ const deduped = allItems.filter((item) => {
+ const key = `${item.type}-${item.value}`
+ if (seen.has(key)) return false
+ seen.add(key)
+ return true
+ })
+
+ return deduped
+ }
+
+ return [{ type: ContextMenuOptionType.NoResults }]
}
export function shouldShowContextMenu(text: string, position: number): boolean {