|
| 1 | +import * as vscode from 'vscode' |
| 2 | +import * as path from 'path' |
| 3 | +import { |
| 4 | + WorkspaceProvider, |
| 5 | + FileItem |
| 6 | +} from '../context/providers/workspace-provider' |
| 7 | +import { natural_sort } from '../utils/natural-sort' |
| 8 | + |
| 9 | +interface FileQuickPickItem extends vscode.QuickPickItem { |
| 10 | + full_path: string |
| 11 | +} |
| 12 | + |
| 13 | +export const add_file_to_context_command = ( |
| 14 | + workspace_provider: WorkspaceProvider |
| 15 | +) => { |
| 16 | + return vscode.commands.registerCommand( |
| 17 | + 'codeWebChat.addFileToContext', |
| 18 | + async () => { |
| 19 | + const workspace_roots = workspace_provider.getWorkspaceRoots() |
| 20 | + if (workspace_roots.length === 0) { |
| 21 | + return |
| 22 | + } |
| 23 | + |
| 24 | + const quick_pick = vscode.window.createQuickPick<FileQuickPickItem>() |
| 25 | + quick_pick.placeholder = 'Select a file to add to context' |
| 26 | + quick_pick.matchOnDescription = true |
| 27 | + quick_pick.busy = true |
| 28 | + quick_pick.show() |
| 29 | + |
| 30 | + quick_pick.onDidTriggerItemButton(async (e) => { |
| 31 | + const item = e.item |
| 32 | + if (e.button.tooltip == 'Add Parent Folder to Context') { |
| 33 | + const workspace_root = workspace_provider.get_workspace_root_for_file( |
| 34 | + item.full_path |
| 35 | + ) |
| 36 | + |
| 37 | + if (!workspace_root) return |
| 38 | + |
| 39 | + const folders: { label: string; full_path: string }[] = [] |
| 40 | + let current_dir = path.dirname(item.full_path) |
| 41 | + |
| 42 | + while ( |
| 43 | + current_dir.startsWith(workspace_root) && |
| 44 | + current_dir != workspace_root |
| 45 | + ) { |
| 46 | + const relative = path.relative(workspace_root, current_dir) |
| 47 | + folders.push({ |
| 48 | + label: relative.replace(/\\/g, '/'), |
| 49 | + full_path: current_dir |
| 50 | + }) |
| 51 | + current_dir = path.dirname(current_dir) |
| 52 | + } |
| 53 | + |
| 54 | + if (folders.length == 0) { |
| 55 | + vscode.window.showInformationMessage('No parent folders to add.') |
| 56 | + return |
| 57 | + } |
| 58 | + |
| 59 | + const folder_quick_pick = vscode.window.createQuickPick<{ |
| 60 | + label: string |
| 61 | + full_path: string |
| 62 | + }>() |
| 63 | + folder_quick_pick.placeholder = 'Select a folder to add to context' |
| 64 | + folder_quick_pick.items = folders.map((f) => ({ |
| 65 | + label: f.label, |
| 66 | + full_path: f.full_path |
| 67 | + })) |
| 68 | + |
| 69 | + folder_quick_pick.onDidAccept(async () => { |
| 70 | + const selected = folder_quick_pick.selectedItems[0] |
| 71 | + if (selected) { |
| 72 | + const file_item = new FileItem( |
| 73 | + path.basename(selected.full_path), |
| 74 | + vscode.Uri.file(selected.full_path), |
| 75 | + vscode.TreeItemCollapsibleState.Collapsed, |
| 76 | + true, |
| 77 | + vscode.TreeItemCheckboxState.Unchecked, |
| 78 | + false, |
| 79 | + false, |
| 80 | + undefined, |
| 81 | + undefined, |
| 82 | + undefined, |
| 83 | + false, |
| 84 | + undefined |
| 85 | + ) |
| 86 | + |
| 87 | + await workspace_provider.update_check_state( |
| 88 | + file_item, |
| 89 | + vscode.TreeItemCheckboxState.Checked |
| 90 | + ) |
| 91 | + folder_quick_pick.hide() |
| 92 | + quick_pick.hide() |
| 93 | + } |
| 94 | + }) |
| 95 | + |
| 96 | + folder_quick_pick.onDidHide(() => { |
| 97 | + folder_quick_pick.dispose() |
| 98 | + }) |
| 99 | + |
| 100 | + folder_quick_pick.show() |
| 101 | + } |
| 102 | + }) |
| 103 | + |
| 104 | + try { |
| 105 | + const all_files: string[] = [] |
| 106 | + for (const root of workspace_roots) { |
| 107 | + const files = await workspace_provider.find_all_files(root) |
| 108 | + all_files.push(...files) |
| 109 | + } |
| 110 | + |
| 111 | + const items: FileQuickPickItem[] = all_files.map((file_path) => { |
| 112 | + const workspace_root = |
| 113 | + workspace_provider.get_workspace_root_for_file(file_path) |
| 114 | + |
| 115 | + const relative_path = workspace_root |
| 116 | + ? path.relative(workspace_root, file_path) |
| 117 | + : file_path |
| 118 | + |
| 119 | + const filename = path.basename(relative_path) |
| 120 | + let directory = path.dirname(relative_path) |
| 121 | + if (directory === '.') { |
| 122 | + directory = '' |
| 123 | + } |
| 124 | + |
| 125 | + if (workspace_roots.length > 1 && workspace_root) { |
| 126 | + const workspace_name = |
| 127 | + workspace_provider.get_workspace_name(workspace_root) |
| 128 | + directory = directory |
| 129 | + ? `${workspace_name} • ${directory}` |
| 130 | + : workspace_name |
| 131 | + } |
| 132 | + |
| 133 | + return { |
| 134 | + label: filename, |
| 135 | + description: directory, |
| 136 | + full_path: file_path, |
| 137 | + buttons: [ |
| 138 | + { |
| 139 | + iconPath: new vscode.ThemeIcon('folder'), |
| 140 | + tooltip: 'Add Parent Folder to Context' |
| 141 | + } |
| 142 | + ] |
| 143 | + } |
| 144 | + }) |
| 145 | + |
| 146 | + items.sort((a, b) => { |
| 147 | + const label_diff = natural_sort(a.label, b.label) |
| 148 | + if (label_diff !== 0) return label_diff |
| 149 | + return natural_sort(a.description || '', b.description || '') |
| 150 | + }) |
| 151 | + |
| 152 | + quick_pick.items = items |
| 153 | + quick_pick.busy = false |
| 154 | + |
| 155 | + quick_pick.onDidAccept(async () => { |
| 156 | + const selected = quick_pick.selectedItems[0] |
| 157 | + if (selected) { |
| 158 | + const current_checked = workspace_provider.get_checked_files() |
| 159 | + if (!current_checked.includes(selected.full_path)) { |
| 160 | + await workspace_provider.set_checked_files([ |
| 161 | + ...current_checked, |
| 162 | + selected.full_path |
| 163 | + ]) |
| 164 | + } |
| 165 | + quick_pick.hide() |
| 166 | + } |
| 167 | + }) |
| 168 | + |
| 169 | + quick_pick.onDidHide(() => { |
| 170 | + quick_pick.dispose() |
| 171 | + }) |
| 172 | + } catch (error) { |
| 173 | + console.error(error) |
| 174 | + quick_pick.hide() |
| 175 | + } |
| 176 | + } |
| 177 | + ) |
| 178 | +} |
0 commit comments