@@ -23,6 +23,7 @@ import { IKeyMods, IQuickInputButton, IQuickInputService, IQuickPick, IQuickPick
23
23
import { askForPromptFileName } from '../../../../promptSyntax/contributions/createPromptCommand/dialogs/askForPromptName.js' ;
24
24
import { IInstantiationService } from '../../../../../../../../platform/instantiation/common/instantiation.js' ;
25
25
import { CancellationToken } from '../../../../../../../../base/common/cancellation.js' ;
26
+ import { askForPromptSourceFolder } from '../../../../promptSyntax/contributions/createPromptCommand/dialogs/askForPromptSourceFolder.js' ;
26
27
27
28
/**
28
29
* Options for the {@link askToSelectInstructions} function.
@@ -47,6 +48,7 @@ export interface ISelectOptions {
47
48
readonly optionEdit ?: boolean ;
48
49
readonly optionDelete ?: boolean ;
49
50
readonly optionRename ?: boolean ;
51
+ readonly optionMove ?: boolean ;
50
52
}
51
53
52
54
export interface ISelectPromptResult {
@@ -154,6 +156,14 @@ const RENAME_BUTTON: IQuickInputButton = Object.freeze({
154
156
iconClass : ThemeIcon . asClassName ( Codicon . pencil ) ,
155
157
} ) ;
156
158
159
+ /**
160
+ * Button that copies a prompt file.
161
+ */
162
+ const COPY_BUTTON : IQuickInputButton = Object . freeze ( {
163
+ tooltip : localize ( 'copy' , "Copy" ) ,
164
+ iconClass : ThemeIcon . asClassName ( Codicon . copy ) ,
165
+ } ) ;
166
+
157
167
export class PromptFilePickers {
158
168
constructor (
159
169
@ILabelService private readonly _labelService : ILabelService ,
@@ -253,6 +263,9 @@ export class PromptFilePickers {
253
263
if ( options . optionRename !== false ) {
254
264
buttons . push ( RENAME_BUTTON ) ;
255
265
}
266
+ if ( options . optionMove !== false ) {
267
+ buttons . push ( COPY_BUTTON ) ;
268
+ }
256
269
if ( options . optionDelete !== false ) {
257
270
buttons . push ( DELETE_BUTTON ) ;
258
271
}
@@ -343,6 +356,17 @@ export class PromptFilePickers {
343
356
} ;
344
357
}
345
358
359
+ private async keepQuickPickOpen ( quickPick : IQuickPick < IPromptPickerQuickPickItem > , work : ( ) => Promise < void > ) : Promise < void > {
360
+ const previousIgnoreFocusOut = quickPick . ignoreFocusOut ;
361
+ quickPick . ignoreFocusOut = true ;
362
+ try {
363
+ await work ( ) ;
364
+ } finally {
365
+ quickPick . ignoreFocusOut = previousIgnoreFocusOut ;
366
+ }
367
+
368
+ }
369
+
346
370
private async _handleButtonClick ( quickPick : IQuickPick < IPromptPickerQuickPickItem > , context : IQuickPickItemButtonEvent < IPromptPickerQuickPickItem > , options : ISelectOptions ) : Promise < void > {
347
371
const { item, button } = context ;
348
372
const { value, } = item ;
@@ -353,20 +377,32 @@ export class PromptFilePickers {
353
377
return ;
354
378
}
355
379
380
+ // `copy` button was pressed, open the prompt file in editor
381
+ if ( button === COPY_BUTTON ) {
382
+ const currentFolder = dirname ( value ) ;
383
+ const newFolder = await this . _instaService . invokeFunction ( askForPromptSourceFolder , options . type , currentFolder ) ;
384
+ if ( ! newFolder ) {
385
+ return ;
386
+ }
387
+ const newName = await this . _instaService . invokeFunction ( askForPromptFileName , options . type , newFolder . uri , item . label ) ;
388
+ if ( ! newName ) {
389
+ return ;
390
+ }
391
+ const newFile = joinPath ( newFolder . uri , newName ) ;
392
+ await this . _fileService . copy ( value , newFile ) ;
393
+ await this . _openerService . open ( newFile ) ;
394
+
395
+ return ;
396
+ }
397
+
356
398
// `rename` button was pressed, open a rename dialog
357
399
if ( button === RENAME_BUTTON ) {
358
- // don't close the main prompt selection dialog by the confirmation dialog
359
- const previousIgnoreFocusOut = quickPick . ignoreFocusOut ;
360
- quickPick . ignoreFocusOut = true ;
361
- try {
362
- const currentFolder = dirname ( value ) ;
363
- const newName = await this . _instaService . invokeFunction ( askForPromptFileName , options . type , currentFolder ) ;
364
- if ( newName ) {
365
- await this . _fileService . move ( value , joinPath ( currentFolder , newName ) ) ;
366
- }
367
- } finally {
368
- quickPick . ignoreFocusOut = previousIgnoreFocusOut ;
369
- quickPick . items = await this . _createPromptPickItems ( options ) ;
400
+ const currentFolder = dirname ( value ) ;
401
+ const newName = await this . _instaService . invokeFunction ( askForPromptFileName , options . type , currentFolder , item . label ) ;
402
+ if ( newName ) {
403
+ const newFile = joinPath ( currentFolder , newName ) ;
404
+ await this . _fileService . move ( value , newFile ) ;
405
+ await this . _openerService . open ( newFile ) ;
370
406
}
371
407
return ;
372
408
}
@@ -389,56 +425,52 @@ export class PromptFilePickers {
389
425
) ;
390
426
391
427
// don't close the main prompt selection dialog by the confirmation dialog
392
- const previousIgnoreFocusOut = quickPick . ignoreFocusOut ;
393
- quickPick . ignoreFocusOut = true ;
394
-
395
- const filename = getCleanPromptName ( value ) ;
396
- const { confirmed } = await this . _dialogService . confirm ( {
397
- message : localize (
398
- 'commands.prompts.use.select-dialog.delete-prompt.confirm.message' ,
399
- "Are you sure you want to delete '{0}'?" ,
400
- filename ,
401
- ) ,
402
- } ) ;
403
-
404
- // restore the previous value of the `ignoreFocusOut` property
405
- quickPick . ignoreFocusOut = previousIgnoreFocusOut ;
406
-
407
- // if prompt deletion was not confirmed, nothing to do
408
- if ( ! confirmed ) {
409
- return ;
410
- }
428
+ await this . keepQuickPickOpen ( quickPick , async ( ) => {
429
+
430
+ const filename = getCleanPromptName ( value ) ;
431
+ const { confirmed } = await this . _dialogService . confirm ( {
432
+ message : localize (
433
+ 'commands.prompts.use.select-dialog.delete-prompt.confirm.message' ,
434
+ "Are you sure you want to delete '{0}'?" ,
435
+ filename ,
436
+ ) ,
437
+ } ) ;
438
+
439
+ // if prompt deletion was not confirmed, nothing to do
440
+ if ( ! confirmed ) {
441
+ return ;
442
+ }
411
443
412
- // prompt deletion was confirmed so delete the prompt file
413
- await this . _fileService . del ( value ) ;
444
+ // prompt deletion was confirmed so delete the prompt file
445
+ await this . _fileService . del ( value ) ;
414
446
415
- // remove the deleted prompt from the selection dialog list
416
- let removedIndex = - 1 ;
417
- quickPick . items = quickPick . items . filter ( ( option , index ) => {
418
- if ( option === item ) {
419
- removedIndex = index ;
447
+ // remove the deleted prompt from the selection dialog list
448
+ let removedIndex = - 1 ;
449
+ quickPick . items = quickPick . items . filter ( ( option , index ) => {
450
+ if ( option === item ) {
451
+ removedIndex = index ;
420
452
421
- return false ;
422
- }
423
-
424
- return true ;
425
- } ) ;
453
+ return false ;
454
+ }
426
455
427
- // if the deleted item was active item, find a new item to set as active
428
- if ( activeItem && ( activeItem === item ) ) {
429
- assert (
430
- removedIndex >= 0 ,
431
- 'Removed item index must be a valid index.' ,
432
- ) ;
456
+ return true ;
457
+ } ) ;
433
458
434
- // we set the previous item as new active, or the next item
435
- // if removed prompt item was in the beginning of the list
436
- const newActiveItemIndex = Math . max ( removedIndex - 1 , 0 ) ;
437
- const newActiveItem : IPromptPickerQuickPickItem | undefined = quickPick . items [ newActiveItemIndex ] ;
459
+ // if the deleted item was active item, find a new item to set as active
460
+ if ( activeItem && ( activeItem === item ) ) {
461
+ assert (
462
+ removedIndex >= 0 ,
463
+ 'Removed item index must be a valid index.' ,
464
+ ) ;
438
465
439
- quickPick . activeItems = newActiveItem ? [ newActiveItem ] : [ ] ;
440
- }
466
+ // we set the previous item as new active, or the next item
467
+ // if removed prompt item was in the beginning of the list
468
+ const newActiveItemIndex = Math . max ( removedIndex - 1 , 0 ) ;
469
+ const newActiveItem : IPromptPickerQuickPickItem | undefined = quickPick . items [ newActiveItemIndex ] ;
441
470
471
+ quickPick . activeItems = newActiveItem ? [ newActiveItem ] : [ ] ;
472
+ }
473
+ } ) ;
442
474
return ;
443
475
}
444
476
0 commit comments