Skip to content

Commit 37db603

Browse files
committed
Rename context merge/replace state keys and standardize merge/replace behavior across all file selection flows
1 parent 9149980 commit 37db603

6 files changed

Lines changed: 219 additions & 95 deletions

File tree

apps/editor/src/commands/apply-context-command/sources/commit-files-source.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from 'path'
33
import * as fs from 'fs'
44
import { execSync } from 'child_process'
55
import { WorkspaceProvider } from '../../../context/providers/workspace/workspace-provider'
6-
import { LAST_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY } from '../../../constants/state-keys'
6+
import { LAST_APPLY_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY } from '../../../constants/state-keys'
77
import { GIT_LOG_SINCE_DURATION } from '../../../constants/values'
88
import { get_git_repository } from '@/utils/git-repository-utils'
99
import { Logger } from '@shared/utils/logger'
@@ -274,7 +274,7 @@ export const handle_commit_files_source = async (
274274

275275
const last_choice_label =
276276
extension_context.workspaceState.get<string>(
277-
LAST_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY
277+
LAST_APPLY_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY
278278
)
279279

280280
const quick_pick = vscode.window.createQuickPick()
@@ -321,7 +321,7 @@ export const handle_commit_files_source = async (
321321
return
322322
} else {
323323
await extension_context.workspaceState.update(
324-
LAST_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY,
324+
LAST_APPLY_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY,
325325
choice.label
326326
)
327327

apps/editor/src/commands/apply-context-command/sources/unstaged-files-source.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { WorkspaceProvider } from '../../../context/providers/workspace/workspac
55
import { dictionary } from '@shared/constants/dictionary'
66
import { Logger } from '@shared/utils/logger'
77
import { display_token_count } from '../../../utils/display-token-count'
8-
import { LAST_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY } from '../../../constants/state-keys'
8+
import { LAST_APPLY_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY } from '../../../constants/state-keys'
99
import { t } from '@/i18n'
1010

1111
export const handle_unstaged_files_source = async (
@@ -200,7 +200,7 @@ export const handle_unstaged_files_source = async (
200200

201201
const last_choice_label =
202202
extension_context.workspaceState.get<string>(
203-
LAST_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY
203+
LAST_APPLY_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY
204204
)
205205

206206
const quick_pick_merge = vscode.window.createQuickPick()
@@ -250,7 +250,7 @@ export const handle_unstaged_files_source = async (
250250
return
251251
} else {
252252
await extension_context.workspaceState.update(
253-
LAST_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY,
253+
LAST_APPLY_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY,
254254
choice.label
255255
)
256256

apps/editor/src/commands/find-relevant-files-command/find-relevant-files-command.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ export const find_relevant_files_command = (
131131
const apply_result = await show_results_and_apply({
132132
extracted_files: api_result,
133133
analysis,
134-
workspace_provider
134+
workspace_provider,
135+
extension_context
135136
})
136137

137138
if (apply_result === 'back') {

apps/editor/src/commands/find-relevant-files-command/utils/show-results-and-apply.ts

Lines changed: 191 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,26 @@ import { WorkspaceProvider } from '../../../context/providers/workspace/workspac
55
import { display_token_count } from '../../../utils/display-token-count'
66
import { FileAnalysisResult } from './analyze-workspace-files'
77
import { t } from '@/i18n'
8+
import { dictionary } from '@shared/constants/dictionary'
9+
import { LAST_FIND_RELEVANT_FILES_MERGE_REPLACE_OPTION_STATE_KEY } from '../../../constants/state-keys'
810

911
export const show_results_and_apply = async (params: {
1012
extracted_files: string[]
1113
analysis: FileAnalysisResult
1214
workspace_provider: WorkspaceProvider
15+
extension_context: vscode.ExtensionContext
1316
}): Promise<'success' | 'back' | 'cancel'> => {
14-
const currently_checked = params.workspace_provider.get_checked_files()
1517
const absolute_paths: string[] = []
1618

1719
for (const rel_path of params.extracted_files) {
1820
const potential_abs = path.join(params.analysis.workspace_root, rel_path)
1921
if (fs.existsSync(potential_abs)) absolute_paths.push(potential_abs)
2022
}
2123

24+
const files_in_searched_folder = params.analysis.files_data.map(
25+
(f) => f.file_path
26+
)
27+
2228
const close_button = {
2329
iconPath: new vscode.ThemeIcon('close'),
2430
tooltip: t('common.close')
@@ -51,88 +57,203 @@ export const show_results_and_apply = async (params: {
5157
})
5258
)
5359

54-
const quick_pick = vscode.window.createQuickPick<
55-
vscode.QuickPickItem & { file_path: string }
56-
>()
57-
quick_pick.items = quick_pick_items
58-
quick_pick.selectedItems = quick_pick_items.filter((item) =>
59-
currently_checked.includes(item.file_path)
60-
)
61-
quick_pick.canSelectMany = true
62-
quick_pick.title = t('command.find-relevant-files.quick-pick.title')
63-
quick_pick.placeholder = t(
64-
'command.find-relevant-files.quick-pick.placeholder'
65-
)
66-
quick_pick.ignoreFocusOut = true
67-
quick_pick.buttons = [vscode.QuickInputButtons.Back, close_button]
60+
while (true) {
61+
const currently_checked = params.workspace_provider.get_checked_files()
6862

69-
return new Promise<'success' | 'back' | 'cancel'>((resolve) => {
70-
let is_resolved = false
63+
const quick_pick = vscode.window.createQuickPick<
64+
vscode.QuickPickItem & { file_path: string }
65+
>()
66+
quick_pick.items = quick_pick_items
67+
quick_pick.selectedItems = quick_pick_items.filter((item) =>
68+
currently_checked.includes(item.file_path)
69+
)
70+
quick_pick.canSelectMany = true
71+
quick_pick.title = t('command.find-relevant-files.quick-pick.title')
72+
quick_pick.placeholder = t(
73+
'command.find-relevant-files.quick-pick.placeholder'
74+
)
75+
quick_pick.ignoreFocusOut = true
76+
quick_pick.buttons = [vscode.QuickInputButtons.Back, close_button]
7177

72-
quick_pick.onDidTriggerButton((button) => {
73-
if (button === vscode.QuickInputButtons.Back) {
74-
is_resolved = true
75-
resolve('back')
76-
quick_pick.hide()
77-
} else if (button === close_button) {
78+
const list_selection = await new Promise<
79+
| readonly (vscode.QuickPickItem & { file_path: string })[]
80+
| 'back'
81+
| 'cancel'
82+
>((resolve) => {
83+
let is_resolved = false
84+
85+
quick_pick.onDidTriggerButton((button) => {
86+
if (button === vscode.QuickInputButtons.Back) {
87+
is_resolved = true
88+
resolve('back')
89+
quick_pick.hide()
90+
} else if (button === close_button) {
91+
is_resolved = true
92+
resolve('cancel')
93+
quick_pick.hide()
94+
}
95+
})
96+
97+
quick_pick.onDidAccept(() => {
7898
is_resolved = true
79-
resolve('cancel')
99+
resolve(quick_pick.selectedItems)
80100
quick_pick.hide()
81-
}
101+
})
102+
103+
quick_pick.onDidTriggerItemButton(async (e) => {
104+
if (e.button === open_file_button) {
105+
try {
106+
const doc = await vscode.workspace.openTextDocument(
107+
e.item.file_path
108+
)
109+
await vscode.window.showTextDocument(doc, { preview: true })
110+
} catch (error) {
111+
vscode.window.showErrorMessage(
112+
t('command.find-relevant-files.error.opening-file', {
113+
error: String(error)
114+
})
115+
)
116+
}
117+
}
118+
})
119+
120+
quick_pick.onDidHide(() => {
121+
if (!is_resolved) {
122+
resolve('back')
123+
}
124+
quick_pick.dispose()
125+
})
126+
127+
quick_pick.show()
82128
})
83129

84-
quick_pick.onDidAccept(async () => {
85-
is_resolved = true
86-
const selected_paths = quick_pick.selectedItems.map(
87-
(item) => item.file_path
88-
)
89-
const unchecked_paths = absolute_paths.filter(
90-
(file_path) => !selected_paths.includes(file_path)
91-
)
130+
if (list_selection === 'back' || list_selection === 'cancel') {
131+
return list_selection
132+
}
133+
134+
const selected_paths = list_selection.map((item) => item.file_path)
135+
const unchecked_paths = absolute_paths.filter(
136+
(file_path) => !selected_paths.includes(file_path)
137+
)
138+
139+
let paths_to_apply: string[] = []
140+
let should_continue_loop = false
141+
142+
const currently_checked_in_folder = currently_checked.filter((f) =>
143+
files_in_searched_folder.includes(f)
144+
)
92145

93-
const paths_to_apply = [
94-
...new Set([
95-
...currently_checked.filter((p) => !unchecked_paths.includes(p)),
96-
...selected_paths
97-
])
146+
if (currently_checked_in_folder.length > 0) {
147+
const selected_paths_set = new Set(selected_paths)
148+
const is_identical =
149+
currently_checked_in_folder.length == selected_paths_set.size &&
150+
currently_checked_in_folder.every((file) =>
151+
selected_paths_set.has(file)
152+
)
153+
154+
if (is_identical) {
155+
vscode.window.showInformationMessage(
156+
dictionary.information_message.CONTEXT_ALREADY_SET
157+
)
158+
return 'success'
159+
}
160+
161+
const quick_pick_options = [
162+
{
163+
label: t('command.apply-context.action.replace.label'),
164+
description: t('command.apply-context.action.replace.description')
165+
},
166+
{
167+
label: t('command.apply-context.action.merge.label'),
168+
description: t('command.apply-context.action.merge.description')
169+
}
98170
]
99-
await params.workspace_provider.set_checked_files(paths_to_apply)
100-
101-
const newly_selected_count = selected_paths.filter(
102-
(p) => !currently_checked.includes(p)
103-
).length
104-
vscode.window.showInformationMessage(
105-
t('command.find-relevant-files.success.added', {
106-
count: newly_selected_count
107-
})
108-
)
109171

110-
resolve('success')
111-
quick_pick.hide()
112-
})
172+
const last_choice_label =
173+
params.extension_context.workspaceState.get<string>(
174+
LAST_FIND_RELEVANT_FILES_MERGE_REPLACE_OPTION_STATE_KEY
175+
)
176+
177+
const quick_pick_merge = vscode.window.createQuickPick()
178+
quick_pick_merge.items = quick_pick_options
179+
quick_pick_merge.placeholder = t('command.apply-context.unstaged.apply', {
180+
count: selected_paths.length
181+
})
182+
quick_pick_merge.buttons = [vscode.QuickInputButtons.Back]
113183

114-
quick_pick.onDidTriggerItemButton(async (e) => {
115-
if (e.button === open_file_button) {
116-
try {
117-
const doc = await vscode.workspace.openTextDocument(e.item.file_path)
118-
await vscode.window.showTextDocument(doc, { preview: true })
119-
} catch (error) {
120-
vscode.window.showErrorMessage(
121-
t('command.find-relevant-files.error.opening-file', {
122-
error: String(error)
123-
})
124-
)
184+
if (last_choice_label) {
185+
const active_item = quick_pick_options.find(
186+
(opt) => opt.label === last_choice_label
187+
)
188+
if (active_item) {
189+
quick_pick_merge.activeItems = [active_item]
125190
}
126191
}
127-
})
128192

129-
quick_pick.onDidHide(() => {
130-
if (!is_resolved) {
131-
resolve('back')
193+
const choice = await new Promise<
194+
vscode.QuickPickItem | 'back' | undefined
195+
>((resolve_choice) => {
196+
let is_accepted = false
197+
quick_pick_merge.onDidTriggerButton((button) => {
198+
if (button === vscode.QuickInputButtons.Back) {
199+
resolve_choice('back')
200+
quick_pick_merge.hide()
201+
}
202+
})
203+
quick_pick_merge.onDidAccept(() => {
204+
is_accepted = true
205+
resolve_choice(quick_pick_merge.selectedItems[0])
206+
quick_pick_merge.hide()
207+
})
208+
quick_pick_merge.onDidHide(() => {
209+
if (!is_accepted) resolve_choice('back')
210+
quick_pick_merge.dispose()
211+
})
212+
quick_pick_merge.show()
213+
})
214+
215+
if (choice === 'back') {
216+
should_continue_loop = true
217+
} else if (!choice) {
218+
return 'cancel'
219+
} else {
220+
await params.extension_context.workspaceState.update(
221+
LAST_FIND_RELEVANT_FILES_MERGE_REPLACE_OPTION_STATE_KEY,
222+
choice.label
223+
)
224+
225+
if (choice.label == t('command.apply-context.action.merge.label')) {
226+
paths_to_apply = [
227+
...new Set([
228+
...currently_checked.filter((p) => !unchecked_paths.includes(p)),
229+
...selected_paths
230+
])
231+
]
232+
} else {
233+
paths_to_apply = [
234+
...new Set([
235+
...currently_checked.filter(
236+
(p) => !files_in_searched_folder.includes(p)
237+
),
238+
...selected_paths
239+
])
240+
]
241+
}
132242
}
133-
quick_pick.dispose()
134-
})
243+
} else {
244+
paths_to_apply = [...new Set([...currently_checked, ...selected_paths])]
245+
}
246+
247+
if (should_continue_loop) {
248+
continue
249+
}
250+
251+
await params.workspace_provider.set_checked_files(paths_to_apply)
135252

136-
quick_pick.show()
137-
})
253+
vscode.window.showInformationMessage(
254+
t('command.find-relevant-files.success.added')
255+
)
256+
257+
return 'success'
258+
}
138259
}

apps/editor/src/constants/state-keys.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ export const LAST_RANGES_SAVE_LOCATION_STATE_KEY = 'last-ranges-save-location'
1010
export const LAST_APPLY_CONTEXT_OPTION_STATE_KEY = 'last-apply-context-option'
1111
export const CONTEXT_CHECKED_PATHS_STATE_KEY = 'context-checked-paths'
1212
export const CONTEXT_CHECKED_TIMESTAMPS_STATE_KEY = 'context-checked-timestamps'
13-
export const LAST_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY =
14-
'last-context-merge-replace-option'
13+
export const LAST_APPLY_CONTEXT_MERGE_REPLACE_OPTION_STATE_KEY =
14+
'last-apply-context-merge-replace-option'
15+
export const LAST_FIND_RELEVANT_FILES_MERGE_REPLACE_OPTION_STATE_KEY =
16+
'last-find-relevant-files-merge-replace-option'
1517
export const LAST_REFACTOR_INSTRUCTION_SOURCE_STATE_KEY =
1618
'last-refactor-instruction-source'
1719
export const LAST_REFACTOR_INSTRUCTION_STATE_KEY = 'last-refactor-instruction'

0 commit comments

Comments
 (0)