Skip to content

Commands "Add File to Cody", "Add Selection to Cody" and shallow folder #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,24 @@
"main": "./dist/extension.js",
"contributes": {
"commands": [
{
"command": "cody-plus-plus.addFile",
"title": "Add File to Cody",
"category": "Cody++"
},
{
"command": "cody-plus-plus.addSelection",
"title": "Add Selected Files to Cody",
"category": "Cody++"
},
{
"command": "cody-plus-plus.addFolder",
"title": "Add Folder to Cody Chat",
"title": "Add Folder (Recursive) to Cody",
"category": "Cody++"
},
{
"command": "cody-plus-plus.addShallowFolder",
"title": "Add Folder to Cody",
"category": "Cody++"
},
{
Expand All @@ -48,9 +63,24 @@
"menus": {
"explorer/context": [
{
"command": "cody-plus-plus.addFolder",
"when": "explorerResourceIsFolder && cody.activated",
"command": "cody-plus-plus.addFile",
"when": "!explorerResourceIsFolder && !listMultiSelection && explorerViewletFocus && resourceLangId && cody.activated",
"group": "0_cody"
},
{
"command": "cody-plus-plus.addSelection",
"when": "listMultiSelection && explorerViewletFocus && listHasSelectionOrFocus && cody.activated",
"group": "0_cody"
},
{
"command": "cody-plus-plus.addFolder",
"when": "explorerResourceIsFolder && explorerViewletFocus && cody.activated",
"group": "1_cody"
},
{
"command": "cody-plus-plus.addShallowFolder",
"when": "explorerResourceIsFolder && explorerViewletFocus && cody.activated",
"group": "1_cody"
}
],
"view/title": [
Expand Down Expand Up @@ -174,4 +204,4 @@
"zod": "^3.23.8"
},
"packageManager": "[email protected]"
}
}
33 changes: 26 additions & 7 deletions src/commands/addFolder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ import * as vscode from 'vscode'
import { CODY_COMMAND } from '../constants/cody'
import { countFilesInDirectory, walkDirectory } from '../utils/file'

// Command function to add all files in a folder to Cody
// Command function to add all files in a folder to Cody (recursive)
export async function addFolderCommand(uri: vscode.Uri) {
await addFolderInternal(uri, true)
}

// Command function to add only files in the current folder to Cody (non-recursive)
export async function addShallowFolderCommand(uri: vscode.Uri) {
await addFolderInternal(uri, false)
}

// Internal helper function to handle both recursive and non-recursive folder scanning
async function addFolderInternal(uri: vscode.Uri, recursive: boolean) {
// Retrieve extension configurations
const config = vscode.workspace.getConfiguration('codyPlusPlus')
// Maximum number of files before prompting the user
Expand All @@ -17,8 +27,13 @@ export async function addFolderCommand(uri: vscode.Uri) {
console.log('CODY++', 'EXCLUDED FOLDERS', { excludedFolders })

try {
// Pass excludedFolders to countFilesInDirectory
const fileCount = await countFilesInDirectory(uri, excludedFileTypes, excludedFolders)
// Count files
const fileCount = await countFilesInDirectory(
uri,
excludedFileTypes,
excludedFolders,
recursive
)

// Prompt the user if file count exceeds threshold
if (fileCount > fileThreshold) {
Expand All @@ -33,10 +48,14 @@ export async function addFolderCommand(uri: vscode.Uri) {
}
}

// Traverse the directory
await walkDirectory(uri, excludedFileTypes, excludedFolders, async fileUri => {
await executeMentionFileCommand(fileUri)
})
// Process files using walkDirectory with shallow flag based on recursive parameter
await walkDirectory(
uri,
excludedFileTypes,
excludedFolders,
executeMentionFileCommand,
!recursive
)
} catch (error: any) {
vscode.window.showErrorMessage(`Failed to add folder to Cody: ${error.message}`)
}
Expand Down
68 changes: 68 additions & 0 deletions src/commands/addToCody.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import * as vscode from 'vscode'
import { CODY_COMMAND } from '../constants/cody'
import { countFilesInDirectory, walkDirectory } from '../utils/file'

export async function addFile(uri: vscode.Uri) {
try {
await executeMentionFileCommand(uri)
} catch (error: any) {
vscode.window.showErrorMessage(`Failed to add file to Cody: ${error.message}`)
}
}

export async function addSelection(uris: vscode.Uri[]) {
if (!uris || uris.length === 0) {
vscode.window.showWarningMessage('No files selected to add to Cody.')
return
}

const config = vscode.workspace.getConfiguration('codyPlusPlus')
const fileThreshold: number = config.get<number>('fileThreshold', 15)
const excludedFileTypes: string[] = config.get<string[]>('excludedFileTypes', [])
const excludedFolders: string[] = config.get<string[]>('excludedFolders', [])

try {
let totalFileCount = 0
for (const uri of uris) {
const stat = await vscode.workspace.fs.stat(uri)
if (stat.type === vscode.FileType.Directory) {
totalFileCount += await countFilesInDirectory(uri, excludedFileTypes, excludedFolders)
} else {
totalFileCount++
}
}

if (totalFileCount > fileThreshold) {
const userResponse = await vscode.window.showWarningMessage(
`The selection contains ${totalFileCount} files. Do you want to proceed?`,
{ modal: true },
'Yes',
'No'
)
if (userResponse !== 'Yes') {
return
}
}

for (const uri of uris) {
const stat = await vscode.workspace.fs.stat(uri)
if (stat.type === vscode.FileType.File) {
await executeMentionFileCommand(uri)
} else if (stat.type === vscode.FileType.Directory) {
await walkDirectory(uri, excludedFileTypes, excludedFolders, async fileUri => {
await executeMentionFileCommand(fileUri)
})
}
}
} catch (error: any) {
vscode.window.showErrorMessage(`Failed to add selection to Cody: ${error.message}`)
}
}

async function executeMentionFileCommand(uri: vscode.Uri) {
try {
await vscode.commands.executeCommand(CODY_COMMAND.MENTION.FILE, uri)
} catch (error: any) {
vscode.window.showErrorMessage(`Failed to trigger Cody to mention file: ${error.message}`)
}
}
24 changes: 22 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import * as vscode from 'vscode'
// Import custom command handlers
import { addCustomCommand, editCustomCommand } from './commands/addCustomCommand'
import { addFolderCommand } from './commands/addFolder'
import { addFolderCommand, addShallowFolderCommand } from './commands/addFolder'
import { addFile, addSelection } from './commands/addToCody'
// Import services and views
import { CustomCommandService } from './services/customCommand.service'
import { CustomCommandsTreeView } from './views/CustomCommandsTreeView'
Expand All @@ -20,6 +21,12 @@ export function activate(context: vscode.ExtensionContext) {
addFolderCommand
)

// Register the "Add Shallow Folder" command, which adds only files in the current folder to Cody
const addShallowFolderDisposable = vscode.commands.registerCommand(
'cody-plus-plus.addShallowFolder',
addShallowFolderCommand
)

// Register the "Add Custom Command" command, which opens a UI to create a custom command
const addCustomCommandDisposable = vscode.commands.registerCommand(
'cody-plus-plus.addCustomCommand',
Expand Down Expand Up @@ -53,16 +60,29 @@ export function activate(context: vscode.ExtensionContext) {
}
)

const addFileToCodyDisposable = vscode.commands.registerCommand('cody-plus-plus.addFile', addFile)

const addSelectionToCodyDisposable = vscode.commands.registerCommand(
'cody-plus-plus.addSelection',
async (contextSelection: vscode.Uri, allSelections: vscode.Uri[]) => {
const urisToAdd = allSelections || [contextSelection]
await addSelection(urisToAdd)
}
)

// Create and register the tree view for displaying custom commands in the sidebar
const customCommandsTreeView = new CustomCommandsTreeView()
vscode.window.registerTreeDataProvider('customCommands', customCommandsTreeView)

// Add all disposables to the extension context for proper cleanup on deactivation
context.subscriptions.push(
addFolderDisposable,
addShallowFolderDisposable,
addCustomCommandDisposable,
editCommandDisposable,
deleteCommandDisposable
deleteCommandDisposable,
addFileToCodyDisposable,
addSelectionToCodyDisposable
)
}

Expand Down
17 changes: 9 additions & 8 deletions src/utils/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import * as vscode from 'vscode'
export async function countFilesInDirectory(
uri: vscode.Uri,
excludedFileTypes: string[] = [],
excludedFolders: string[] = []
excludedFolders: string[] = [],
shallow: boolean = false
): Promise<number> {
let fileCount = 0
// Read the contents of the directory
Expand All @@ -28,20 +29,20 @@ export async function countFilesInDirectory(
if (fileType === vscode.FileType.File && !isFileExcluded) {
// Increment count for non-excluded files
fileCount++
} else if (fileType === vscode.FileType.Directory) {
} else if (fileType === vscode.FileType.Directory && !shallow) {
// Recursively count files in subdirectories
fileCount += await countFilesInDirectory(fileUri, excludedFileTypes, excludedFolders)
fileCount += await countFilesInDirectory(fileUri, excludedFileTypes, excludedFolders, shallow)
}
}
return fileCount
}

// Walk through a directory and execute a callback for each file, excluding specified folders
export async function walkDirectory(
uri: vscode.Uri,
excludedFileTypes: string[] = [],
excludedFolders: string[] = [],
callback: (fileUri: vscode.Uri) => Promise<void>
callback: (fileUri: vscode.Uri) => Promise<void>,
shallow: boolean = false
) {
// Read the contents of the directory
const files = await vscode.workspace.fs.readDirectory(uri)
Expand All @@ -54,14 +55,14 @@ export async function walkDirectory(
console.log('CODY++', `File ${fileName} is being processed`)
// Execute callback for non-excluded files
await callback(fileUri)
} else if (fileType === vscode.FileType.Directory) {
} else if (fileType === vscode.FileType.Directory && !shallow) {
const isFolderExcluded = isFolderNameExcluded(fileName, excludedFolders)
if (isFolderExcluded) {
console.log('CODY++', `Folder ${fileName} is excluded`)
continue
}
// Recursively walk through subdirectories
await walkDirectory(fileUri, excludedFileTypes, excludedFolders, callback)
// Recursively walk through subdirectories unless shallow mode is enabled
await walkDirectory(fileUri, excludedFileTypes, excludedFolders, callback, shallow)
}
}
}
Expand Down
Loading