@@ -12,7 +12,7 @@ type PromptTemplate = {
1212
1313const ADD_NEW_TEMPLATE_LABEL = '$(add) New prompt template...'
1414
15- export const handle_show_prompt_template_quick_pick = async (
15+ export const handle_prompt_template_quick_pick = async (
1616 prompt_view_provider : PromptViewProvider
1717) : Promise < void > => {
1818 const prompt_type : WebPromptType | ApiPromptType | undefined =
@@ -220,10 +220,16 @@ export const handle_show_prompt_template_quick_pick = async (
220220
221221 templates_quick_pick . items = create_template_items ( prompt_templates )
222222
223+ const first_template_item = templates_quick_pick . items . find ( ( i ) => i . template )
224+ if ( first_template_item ) {
225+ templates_quick_pick . activeItems = [ first_template_item ]
226+ }
227+
223228 const disposables : vscode . Disposable [ ] = [ ]
224229 let is_disposed = false
225230 let notification_count = 0
226231 let is_template_accepted = false
232+ let is_entering_variables = false
227233
228234 disposables . push (
229235 templates_quick_pick . onDidTriggerButton ( ( _button ) => {
@@ -262,14 +268,15 @@ export const handle_show_prompt_template_quick_pick = async (
262268 templates_quick_pick . show ( )
263269 }
264270 }
271+
272+ is_editing_template = false
265273 } else if (
266274 'template' in selected_template &&
267275 selected_template . template &&
268276 typeof selected_template . index == 'number'
269277 ) {
270- is_template_accepted = true
278+ is_entering_variables = true
271279 templates_quick_pick . hide ( )
272- is_disposed = true
273280
274281 // Move the selected template to the top of the list for easier access next time
275282 if ( selected_template . index > 0 ) {
@@ -300,13 +307,106 @@ export const handle_show_prompt_template_quick_pick = async (
300307 ] )
301308 ]
302309
310+ const variable_values : Record < string , string > = { }
311+ let cancelled = false
312+ let go_back_to_templates = false
313+
303314 if ( variables . length > 0 ) {
304- for ( const variable of variables ) {
305- const value = await vscode . window . showInputBox ( {
306- title : 'Enter Variable' ,
307- placeHolder : variable
315+ let i = 0
316+ while ( i < variables . length ) {
317+ const variable = variables [ i ]
318+
319+ const result = await new Promise < {
320+ value ?: string
321+ back : boolean
322+ cancel : boolean
323+ } > ( ( resolve ) => {
324+ const input = vscode . window . createInputBox ( )
325+ input . title = 'Enter Variable'
326+ input . placeholder = variable
327+ input . value = variable_values [ variable ] || ''
328+ input . buttons = [ vscode . QuickInputButtons . Back ]
329+
330+ let resolved = false
331+ const input_disposables : vscode . Disposable [ ] = [ ]
332+
333+ input_disposables . push (
334+ input . onDidTriggerButton ( ( button ) => {
335+ if ( button === vscode . QuickInputButtons . Back ) {
336+ resolved = true
337+ input . hide ( )
338+ resolve ( { back : true , cancel : false } )
339+ }
340+ } ) ,
341+ input . onDidAccept ( ( ) => {
342+ resolved = true
343+ const val = input . value
344+ input . hide ( )
345+ resolve ( { value : val , back : false , cancel : false } )
346+ } ) ,
347+ input . onDidHide ( ( ) => {
348+ if ( ! resolved ) {
349+ resolve ( { cancel : true , back : false } )
350+ }
351+ input_disposables . forEach ( ( d ) => d . dispose ( ) )
352+ input . dispose ( )
353+ } )
354+ )
355+
356+ input . show ( )
308357 } )
309358
359+ if ( result . cancel ) {
360+ cancelled = true
361+ break
362+ }
363+
364+ if ( result . back ) {
365+ if ( i === 0 ) {
366+ go_back_to_templates = true
367+ break
368+ } else {
369+ i --
370+ continue
371+ }
372+ }
373+
374+ if ( result . value !== undefined ) {
375+ variable_values [ variable ] = result . value
376+ i ++
377+ }
378+ }
379+
380+ if ( cancelled ) {
381+ is_entering_variables = false
382+ is_disposed = true
383+ prompt_view_provider . send_message ( {
384+ command : 'FOCUS_PROMPT_FIELD'
385+ } )
386+ disposables . forEach ( ( d ) => d . dispose ( ) )
387+ return
388+ }
389+
390+ if ( go_back_to_templates ) {
391+ is_entering_variables = false
392+ templates_quick_pick . items = create_template_items (
393+ prompt_templates ,
394+ templates_quick_pick . value
395+ )
396+
397+ const attempted_item = templates_quick_pick . items . find (
398+ ( i ) => i . template === selected_template . template
399+ )
400+ if ( attempted_item ) {
401+ templates_quick_pick . activeItems = [ attempted_item ]
402+ }
403+
404+ templates_quick_pick . show ( )
405+ return
406+ }
407+
408+ for ( const variable of variables ) {
409+ const value = variable_values [ variable ]
310410 if ( value ) {
311411 const double_regex = new RegExp (
312412 `\\{\\{\\s*${ variable . replace (
@@ -328,6 +428,10 @@ export const handle_show_prompt_template_quick_pick = async (
328428 }
329429 }
330430
431+ is_entering_variables = false
432+ is_template_accepted = true
433+ is_disposed = true
434+
331435 const current_text = prompt_view_provider . current_instruction
332436 const is_after_slash = current_text
333437 . slice ( 0 , prompt_view_provider . caret_position )
@@ -340,6 +444,7 @@ export const handle_show_prompt_template_quick_pick = async (
340444 prompt_view_provider . send_message ( {
341445 command : 'FOCUS_PROMPT_FIELD'
342446 } )
447+ disposables . forEach ( ( d ) => d . dispose ( ) )
343448 }
344449 } ) ,
345450 templates_quick_pick . onDidChangeValue ( ( value ) => {
@@ -459,9 +564,14 @@ export const handle_show_prompt_template_quick_pick = async (
459564 }
460565 } ) ,
461566 templates_quick_pick . onDidHide ( ( ) => {
462- if ( is_editing_template || notification_count > 0 ) {
567+ if (
568+ is_editing_template ||
569+ notification_count > 0 ||
570+ is_entering_variables
571+ ) {
463572 // We are editing a template, which involves showing input boxes that hide the quick pick.
464573 // Or we are showing a dialog (warning/info message) which also hides the quick pick.
574+ // Or we are filling out variables for the template which hides the quick pick.
465575 // We don't want to dispose of everything in these cases.
466576 return
467577 }
0 commit comments