@@ -395,7 +395,7 @@ class UI {
395395 const processedIdes = new Set ( ) ;
396396 const initialValues = [ ] ;
397397
398- // First, add previously configured IDEs at the top , marked with ✅
398+ // First, add previously configured IDEs, marked with ✅
399399 if ( configuredIdes . length > 0 ) {
400400 const configuredGroup = [ ] ;
401401 for ( const ideValue of configuredIdes ) {
@@ -447,42 +447,33 @@ class UI {
447447 } ) ) ;
448448 }
449449
450+ // Add standalone "None" option at the end
451+ groupedOptions [ ' ' ] = [
452+ {
453+ label : '⚠ None - I am not installing any tools' ,
454+ value : '__NONE__' ,
455+ } ,
456+ ] ;
457+
450458 let selectedIdes = [ ] ;
451- let userConfirmedNoTools = false ;
452-
453- // Loop until user selects at least one tool OR explicitly confirms no tools
454- while ( ! userConfirmedNoTools ) {
455- selectedIdes = await prompts . groupMultiselect ( {
456- message : `Select tools to configure ${ chalk . dim ( '(↑/↓ navigate, SPACE select, ENTER confirm)' ) } :` ,
457- options : groupedOptions ,
458- initialValues : initialValues . length > 0 ? initialValues : undefined ,
459- required : false ,
460- } ) ;
461459
462- // If tools were selected, we're done
463- if ( selectedIdes && selectedIdes . length > 0 ) {
464- break ;
465- }
460+ selectedIdes = await prompts . groupMultiselect ( {
461+ message : `Select tools to configure ${ chalk . dim ( '(↑/↓ navigates multiselect, SPACE toggles, A to toggles All, ENTER confirm)' ) } :` ,
462+ options : groupedOptions ,
463+ initialValues : initialValues . length > 0 ? initialValues : undefined ,
464+ required : true ,
465+ selectableGroups : false ,
466+ } ) ;
466467
467- // Warn that no tools were selected - users often miss the spacebar requirement
468+ // If user selected both "__NONE__" and other tools, honor the "None" choice
469+ if ( selectedIdes && selectedIdes . includes ( '__NONE__' ) && selectedIdes . length > 1 ) {
468470 console . log ( ) ;
469- console . log ( chalk . red . bold ( '⚠️ WARNING: No tools were selected!' ) ) ;
470- console . log ( chalk . red ( ' You must press SPACE to select items, then ENTER to confirm.' ) ) ;
471- console . log ( chalk . red ( ' Simply highlighting an item does NOT select it.' ) ) ;
471+ console . log ( chalk . yellow ( '⚠️ "None - I am not installing any tools" was selected, so no tools will be configured.' ) ) ;
472472 console . log ( ) ;
473-
474- const goBack = await prompts . confirm ( {
475- message : chalk . yellow ( 'Would you like to go back and select at least one tool?' ) ,
476- default : true ,
477- } ) ;
478-
479- if ( goBack ) {
480- // Re-display a message before looping back
481- console . log ( ) ;
482- } else {
483- // User explicitly chose to proceed without tools
484- userConfirmedNoTools = true ;
485- }
473+ selectedIdes = [ ] ;
474+ } else if ( selectedIdes && selectedIdes . includes ( '__NONE__' ) ) {
475+ // Only "__NONE__" was selected
476+ selectedIdes = [ ] ;
486477 }
487478
488479 return {
@@ -509,27 +500,6 @@ class UI {
509500 return { backupFirst, preserveCustomizations } ;
510501 }
511502
512- /**
513- * Prompt for module selection
514- * @param {Array } modules - Available modules
515- * @returns {Array } Selected modules
516- */
517- async promptModules ( modules ) {
518- const choices = modules . map ( ( mod ) => ( {
519- name : `${ mod . name } - ${ mod . description } ` ,
520- value : mod . id ,
521- checked : false ,
522- } ) ) ;
523-
524- const selectedModules = await prompts . multiselect ( {
525- message : `Select modules to add ${ chalk . dim ( '(↑/↓ navigate, SPACE select, ENTER confirm)' ) } :` ,
526- choices,
527- required : true ,
528- } ) ;
529-
530- return selectedModules ;
531- }
532-
533503 /**
534504 * Confirm action
535505 * @param {string } message - Confirmation message
@@ -697,20 +667,40 @@ class UI {
697667 * @param {Array } moduleChoices - Available module choices
698668 * @returns {Array } Selected module IDs
699669 */
700- async selectModules ( moduleChoices , defaultSelections = [ ] ) {
701- // Mark choices as checked based on defaultSelections
670+ async selectModules ( moduleChoices , defaultSelections = null ) {
671+ // If defaultSelections is provided, use it to override checked state
672+ // Otherwise preserve the checked state from moduleChoices (set by getModuleChoices)
702673 const choicesWithDefaults = moduleChoices . map ( ( choice ) => ( {
703674 ...choice ,
704- checked : defaultSelections . includes ( choice . value ) ,
675+ ... ( defaultSelections === null ? { } : { checked : defaultSelections . includes ( choice . value ) } ) ,
705676 } ) ) ;
706677
678+ // Add a "None" option at the end for users who changed their mind
679+ const choicesWithSkipOption = [
680+ ...choicesWithDefaults ,
681+ {
682+ value : '__NONE__' ,
683+ label : '⚠ None / I changed my mind - skip module installation' ,
684+ checked : false ,
685+ } ,
686+ ] ;
687+
707688 const selected = await prompts . multiselect ( {
708- message : `Select modules to install ${ chalk . dim ( '(↑/↓ navigate , SPACE select , ENTER confirm)' ) } :` ,
709- choices : choicesWithDefaults ,
710- required : false ,
689+ message : `Select modules to install ${ chalk . dim ( '(↑/↓ navigates multiselect , SPACE toggles, A to toggles All , ENTER confirm)' ) } :` ,
690+ choices : choicesWithSkipOption ,
691+ required : true ,
711692 } ) ;
712693
713- return selected || [ ] ;
694+ // If user selected both "__NONE__" and other items, honor the "None" choice
695+ if ( selected && selected . includes ( '__NONE__' ) && selected . length > 1 ) {
696+ console . log ( ) ;
697+ console . log ( chalk . yellow ( '⚠️ "None / I changed my mind" was selected, so no modules will be installed.' ) ) ;
698+ console . log ( ) ;
699+ return [ ] ;
700+ }
701+
702+ // Filter out the special '__NONE__' value
703+ return selected ? selected . filter ( ( m ) => m !== '__NONE__' ) : [ ] ;
714704 }
715705
716706 /**
@@ -1255,12 +1245,32 @@ class UI {
12551245 checked : m . checked ,
12561246 } ) ) ;
12571247
1248+ // Add "None / I changed my mind" option at the end
1249+ const choicesWithSkip = [
1250+ ...selectChoices ,
1251+ {
1252+ name : '⚠ None / I changed my mind - keep no custom modules' ,
1253+ value : '__NONE__' ,
1254+ checked : false ,
1255+ } ,
1256+ ] ;
1257+
12581258 const keepModules = await prompts . multiselect ( {
1259- message : `Select custom modules to keep ${ chalk . dim ( '(↑/↓ navigate , SPACE select , ENTER confirm)' ) } :` ,
1260- choices : selectChoices ,
1261- required : false ,
1259+ message : `Select custom modules to keep ${ chalk . dim ( '(↑/↓ navigates multiselect , SPACE toggles, A to toggles All , ENTER confirm)' ) } :` ,
1260+ choices : choicesWithSkip ,
1261+ required : true ,
12621262 } ) ;
1263- result . selectedCustomModules = keepModules || [ ] ;
1263+
1264+ // If user selected both "__NONE__" and other modules, honor the "None" choice
1265+ if ( keepModules && keepModules . includes ( '__NONE__' ) && keepModules . length > 1 ) {
1266+ console . log ( ) ;
1267+ console . log ( chalk . yellow ( '⚠️ "None / I changed my mind" was selected, so no custom modules will be kept.' ) ) ;
1268+ console . log ( ) ;
1269+ result . selectedCustomModules = [ ] ;
1270+ } else {
1271+ // Filter out the special '__NONE__' value
1272+ result . selectedCustomModules = keepModules ? keepModules . filter ( ( m ) => m !== '__NONE__' ) : [ ] ;
1273+ }
12641274 break ;
12651275 }
12661276
0 commit comments