Skip to content

Commit 41764fe

Browse files
committed
Implement tree and list format options for copying file paths
- in General > Context, add option "Copy Paths Format": [bullet list] [tree] - add translations to [Fragment]
1 parent 6185986 commit 41764fe

13 files changed

Lines changed: 221 additions & 4 deletions

File tree

‎apps/editor/package.json‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,15 @@
919919
"default": true,
920920
"scope": "resource"
921921
},
922+
"codeWebChat.copyPathsFormat": {
923+
"type": "string",
924+
"scope": "resource",
925+
"enum": [
926+
"list",
927+
"tree"
928+
],
929+
"default": "list"
930+
},
922931
"codeWebChat.sendWithShiftEnter": {
923932
"type": "boolean",
924933
"scope": "resource",

‎apps/editor/src/commands/copy-paths-command.ts‎

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,46 @@ import { t } from '../i18n'
55
import { WorkspaceProvider } from '../context/providers/workspace/workspace-provider'
66
import { OpenEditorsProvider } from '../context/providers/open-editors/open-editors-provider'
77

8+
interface TreeNode {
9+
[key: string]: TreeNode
10+
}
11+
12+
const build_tree = (paths: string[]): TreeNode => {
13+
const root: TreeNode = {}
14+
for (const path of paths) {
15+
const parts = path.split('/')
16+
let current = root
17+
for (const part of parts) {
18+
if (!current[part]) {
19+
current[part] = {}
20+
}
21+
current = current[part]
22+
}
23+
}
24+
return root
25+
}
26+
27+
const print_tree = (node: TreeNode, prefix = ''): string[] => {
28+
const keys = Object.keys(node).sort()
29+
const lines: string[] = []
30+
for (let i = 0; i < keys.length; i++) {
31+
const key = keys[i]
32+
const is_last = i == keys.length - 1
33+
lines.push(`${prefix}${is_last ? '└── ' : '├── '}${key}`)
34+
const child_prefix = prefix + (is_last ? ' ' : '│ ')
35+
lines.push(...print_tree(node[key], child_prefix))
36+
}
37+
return lines
38+
}
39+
840
const format_paths = (files: string[]) => {
41+
const config = vscode.workspace.getConfiguration('codeWebChat')
42+
const format = config.get<'list' | 'tree'>('copyPathsFormat', 'list')
43+
944
const workspace_folders = vscode.workspace.workspaceFolders
1045
const is_multi_root = !!workspace_folders && workspace_folders.length > 1
1146

12-
const paths = files.map((file_path) => {
47+
const display_paths = files.map((file_path) => {
1348
const file_uri = vscode.Uri.file(file_path)
1449
let display_path: string
1550
const workspace_folder = vscode.workspace.getWorkspaceFolder(file_uri)
@@ -24,10 +59,15 @@ const format_paths = (files: string[]) => {
2459
display_path = vscode.workspace.asRelativePath(file_path)
2560
}
2661

27-
return `- \`${display_path.replace(/\\/g, '/')}\``
62+
return display_path.replace(/\\/g, '/')
2863
})
2964

30-
return paths.join('\n')
65+
if (format == 'tree') {
66+
const root = build_tree(display_paths)
67+
return print_tree(root).join('\n')
68+
}
69+
70+
return display_paths.map((display_path) => `- \`${display_path}\``).join('\n')
3171
}
3272

3373
export const copy_paths_commands = (
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as vscode from 'vscode'
2+
import { SettingsProvider } from '@/views/settings/backend/settings-provider'
3+
4+
export const handle_get_copy_paths_format = async (
5+
provider: SettingsProvider
6+
): Promise<void> => {
7+
const config = vscode.workspace.getConfiguration('codeWebChat')
8+
const value = config.get<'list' | 'tree'>('copyPathsFormat', 'list')
9+
provider.postMessage({
10+
command: 'COPY_PATHS_FORMAT',
11+
value
12+
})
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as vscode from 'vscode'
2+
import { UpdateCopyPathsFormatMessage } from '@/views/settings/types/messages'
3+
4+
export const handle_update_copy_paths_format = async (
5+
message: UpdateCopyPathsFormatMessage
6+
): Promise<void> => {
7+
await vscode.workspace
8+
.getConfiguration('codeWebChat')
9+
.update('copyPathsFormat', message.value, vscode.ConfigurationTarget.Global)
10+
}

‎apps/editor/src/views/settings/backend/message-handlers/index.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export * from './handle-get-reuse-last-tab'
3737
export * from './handle-update-reuse-last-tab'
3838
export * from './handle-get-api-configurations'
3939
export * from './handle-get-auto-run-intelligent-update'
40+
export * from './handle-get-copy-paths-format'
41+
export * from './handle-update-copy-paths-format'
4042
export * from './handle-update-auto-run-intelligent-update'
4143
export * from './handle-open-keybindings'
4244
export * from './handle-open-external-url'

‎apps/editor/src/views/settings/backend/settings-provider.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ import {
4747
handle_delete_web_configuration,
4848
handle_reorder_web_configurations,
4949
handle_create_web_configuration,
50+
handle_get_copy_paths_format,
51+
handle_update_copy_paths_format,
5052
handle_pick_chatbot,
5153
handle_pick_model,
5254
handle_pick_reasoning_effort,
@@ -197,6 +199,10 @@ export class SettingsProvider {
197199
message.command == 'UPDATE_CLEAR_CHECKS_IN_WORKSPACE_BEHAVIOR'
198200
) {
199201
await handle_update_clear_checks_in_workspace_behavior(message)
202+
} else if (message.command == 'GET_COPY_PATHS_FORMAT') {
203+
await handle_get_copy_paths_format(this)
204+
} else if (message.command == 'UPDATE_COPY_PATHS_FORMAT') {
205+
await handle_update_copy_paths_format(message)
200206
} else if (message.command == 'GET_GEMINI_USER_ID') {
201207
await handle_get_gemini_user_id(this)
202208
} else if (message.command == 'UPDATE_GEMINI_USER_ID') {
@@ -296,6 +302,7 @@ export class SettingsProvider {
296302
void handle_get_gemini_user_id(this)
297303
void handle_get_ai_studio_user_id(this)
298304
void handle_get_send_with_shift_enter(this)
305+
void handle_get_copy_paths_format(this)
299306
void handle_get_check_new_files(this)
300307
void handle_get_reuse_last_tab(this)
301308
void handle_get_auto_run_intelligent_update(this)

‎apps/editor/src/views/settings/frontend/Home/Home.tsx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ type Props = {
124124
checkpoint_lifespan: number
125125
edit_format_instructions: EditFormatInstructions
126126
clear_checks_in_workspace_behavior: 'ignore-open-editors' | 'uncheck-all'
127+
copy_paths_format: 'list' | 'tree'
127128
auto_run_intelligent_update: boolean
128129
set_providers: (providers: Provider[]) => void
129130
set_api_configurations: (configurations: ApiConfiguration[]) => void
@@ -150,6 +151,7 @@ type Props = {
150151
on_clear_checks_in_workspace_behavior_change: (
151152
value: 'ignore-open-editors' | 'uncheck-all'
152153
) => void
154+
on_copy_paths_format_change: (value: 'list' | 'tree') => void
153155
on_auto_run_intelligent_update_change: (enabled: boolean) => void
154156
on_open_keybindings: (search?: string) => void
155157
on_open_editor_settings: () => void
@@ -399,6 +401,8 @@ export const Home: React.FC<Props> = (props) => {
399401
clear_checks_in_workspace_behavior={
400402
props.clear_checks_in_workspace_behavior
401403
}
404+
copy_paths_format={props.copy_paths_format}
405+
on_copy_paths_format_change={props.on_copy_paths_format_change}
402406
on_clear_checks_in_workspace_behavior_change={
403407
props.on_clear_checks_in_workspace_behavior_change
404408
}

‎apps/editor/src/views/settings/frontend/Home/sections/GeneralSection.tsx‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ type Props = {
4141
on_clear_checks_in_workspace_behavior_change: (
4242
value: ClearChecksBehavior
4343
) => void
44+
copy_paths_format: 'list' | 'tree'
45+
on_copy_paths_format_change: (value: 'list' | 'tree') => void
4446
on_edit_format_instructions_change: (
4547
instructions: EditFormatInstructions
4648
) => void
@@ -250,6 +252,26 @@ export const GeneralSection = forwardRef<HTMLDivElement, Props>(
250252
/>
251253
}
252254
/>
255+
<UiItem
256+
title={t('general.copy-paths-format.title')}
257+
description={t('general.copy-paths-format.description')}
258+
slot_right={
259+
<UiDropdown
260+
options={[
261+
{
262+
value: 'list',
263+
label: t('general.copy-paths-format.list')
264+
},
265+
{
266+
value: 'tree',
267+
label: t('general.copy-paths-format.tree')
268+
}
269+
]}
270+
value={props.copy_paths_format}
271+
onChange={props.on_copy_paths_format_change}
272+
/>
273+
}
274+
/>
253275
<UiItem
254276
title={t('general.find-relevant-files-instructions.title')}
255277
description={t(

‎apps/editor/src/views/settings/frontend/Settings.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export const Settings = () => {
6565
settings_hook.send_with_shift_enter !== undefined &&
6666
settings_hook.check_new_files !== undefined &&
6767
settings_hook.reuse_last_tab !== undefined &&
68+
settings_hook.copy_paths_format !== undefined &&
6869
settings_hook.clear_checks_in_workspace_behavior !== undefined &&
6970
settings_hook.auto_run_intelligent_update !== undefined
7071
)
@@ -116,6 +117,10 @@ export const Settings = () => {
116117
clear_checks_in_workspace_behavior={
117118
settings_hook.clear_checks_in_workspace_behavior!
118119
}
120+
copy_paths_format={settings_hook.copy_paths_format!}
121+
on_copy_paths_format_change={
122+
settings_hook.handle_copy_paths_format_change
123+
}
119124
auto_run_intelligent_update={settings_hook.auto_run_intelligent_update!}
120125
set_providers={settings_hook.set_providers}
121126
set_api_configurations={settings_hook.set_api_configurations}

‎apps/editor/src/views/settings/frontend/hooks/use-settings.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ export const use_settings = (vscode: any) => {
6363
clear_checks_in_workspace_behavior,
6464
set_clear_checks_in_workspace_behavior
6565
] = useState<'ignore-open-editors' | 'uncheck-all' | undefined>(undefined)
66+
const [copy_paths_format, set_copy_paths_format] = useState<
67+
'list' | 'tree' | undefined
68+
>(undefined)
6669
const [auto_run_intelligent_update, set_auto_run_intelligent_update] =
6770
useState<boolean | undefined>(undefined)
6871

@@ -85,6 +88,7 @@ export const use_settings = (vscode: any) => {
8588
post_message(vscode, { command: 'GET_SEND_WITH_SHIFT_ENTER' })
8689
post_message(vscode, { command: 'GET_CHECK_NEW_FILES' })
8790
post_message(vscode, { command: 'GET_REUSE_LAST_TAB' })
91+
post_message(vscode, { command: 'GET_COPY_PATHS_FORMAT' })
8892
post_message(vscode, { command: 'GET_CLEAR_CHECKS_IN_WORKSPACE_BEHAVIOR' })
8993
post_message(vscode, { command: 'GET_AUTO_RUN_INTELLIGENT_UPDATE' })
9094
}, [vscode])
@@ -129,6 +133,8 @@ export const use_settings = (vscode: any) => {
129133
set_reuse_last_tab(message.enabled)
130134
} else if (message.command == 'CLEAR_CHECKS_IN_WORKSPACE_BEHAVIOR') {
131135
set_clear_checks_in_workspace_behavior(message.value)
136+
} else if (message.command == 'COPY_PATHS_FORMAT') {
137+
set_copy_paths_format(message.value)
132138
} else if (message.command == 'AUTO_RUN_INTELLIGENT_UPDATE') {
133139
set_auto_run_intelligent_update(message.enabled)
134140
}
@@ -354,6 +360,14 @@ export const use_settings = (vscode: any) => {
354360
})
355361
}
356362

363+
const handle_copy_paths_format_change = (value: 'list' | 'tree') => {
364+
set_copy_paths_format(value)
365+
post_message(vscode, {
366+
command: 'UPDATE_COPY_PATHS_FORMAT',
367+
value
368+
})
369+
}
370+
357371
const handle_auto_run_intelligent_update_change = (enabled: boolean) => {
358372
set_auto_run_intelligent_update(enabled)
359373
post_message(vscode, {
@@ -398,6 +412,7 @@ export const use_settings = (vscode: any) => {
398412
check_new_files,
399413
reuse_last_tab,
400414
clear_checks_in_workspace_behavior,
415+
copy_paths_format,
401416
auto_run_intelligent_update,
402417
handle_reorder_providers,
403418
handle_add_provider,
@@ -427,6 +442,7 @@ export const use_settings = (vscode: any) => {
427442
handle_check_new_files_change,
428443
handle_reuse_last_tab_change,
429444
handle_clear_checks_in_workspace_behavior_change,
445+
handle_copy_paths_format_change,
430446
handle_auto_run_intelligent_update_change,
431447
handle_open_keybindings,
432448
handle_open_external_url

0 commit comments

Comments
 (0)