@@ -261,7 +261,7 @@ function runSandboxTask(sender, { pm, action, args, stdinScript, appName }) {
261261 }
262262 let settled = false ;
263263 let output = '' ;
264- const passwordRegex = / m o t d e p a s s e .* : | p a s s w o r d .* : / i;
264+ const passwordRegex = / \[ s u d o \] | m o t d e p a s s e .* : | p a s s w o r d .* : / i;
265265 const send = ( payload ) => {
266266 if ( ! sender ) return ;
267267 try {
@@ -528,7 +528,7 @@ ipcMain.handle('am-action', async (event, action, software) => {
528528 } ) ;
529529 child . onData ( ( txt ) => {
530530 output += txt ;
531- if ( / m o t d e p a s s e .* : | p a s s w o r d .* : / i. test ( txt ) ) {
531+ if ( / \[ s u d o \] | m o t d e p a s s e .* : | p a s s w o r d .* : / i. test ( txt ) ) {
532532 // Demander le mot de passe au renderer via IPC
533533 if ( event . sender ) event . sender . send ( 'password-prompt' , { id } ) ;
534534 }
@@ -613,7 +613,7 @@ ipcMain.handle('install-start', async (event, name) => {
613613 const txt = chunk . toString ( ) ;
614614 output += txt ;
615615 // Détection du prompt mot de passe sudo
616- if ( / m o t d e p a s s e .* : | p a s s w o r d .* : / i. test ( txt ) ) {
616+ if ( / \[ s u d o \] | m o t d e p a s s e .* : | p a s s w o r d .* : / i. test ( txt ) ) {
617617 // Demander le mot de passe au renderer via IPC
618618 wc . send ( 'password-prompt' , { id } ) ;
619619 // Attendre la réponse avant d'envoyer le mot de passe au process
@@ -770,7 +770,7 @@ ipcMain.handle('updates-start', async (event) => {
770770 child . onData ( ( txt ) => {
771771 output += txt ;
772772 send ( { kind : 'data' , chunk : txt } ) ;
773- if ( / m o t d e p a s s e .* : | p a s s w o r d .* : / i. test ( txt ) ) {
773+ if ( / \[ s u d o \] | m o t d e p a s s e .* : | p a s s w o r d .* : / i. test ( txt ) ) {
774774 try { wc . send ( 'password-prompt' , { id } ) ; }
775775 catch ( _ ) { }
776776 }
@@ -885,39 +885,61 @@ ipcMain.handle('list-apps-detailed', async () => {
885885 / ^ T O T A L / i,
886886 / ^ \* h a s / i
887887 ] ;
888+ // curEntry tracks the current ◆ entry so continuation lines can be
889+ // appended to its description (descriptions can span multiple lines).
890+ let curName = null ;
891+ let curDesc = null ;
892+ let curInCatalog = false ;
893+ const flushEntry = ( ) => {
894+ if ( ! curName ) return ;
895+ if ( ! curInCatalog ) {
896+ installedFromCatalog . add ( curName ) ;
897+ if ( curDesc ) installedDesc . set ( curName , curDesc ) ;
898+ } else {
899+ catalogSet . add ( curName ) ;
900+ if ( curDesc ) catalogDesc . set ( curName , curDesc ) ;
901+ }
902+ diamondSet . add ( curName ) ;
903+ curName = null ;
904+ curDesc = null ;
905+ } ;
906+
888907 for ( const raw of lines ) {
889908 const line = raw . trim ( ) ;
890909 if ( line === '' ) {
891910 // blank line: if we've already scanned at least one ◆ entry and
892911 // we're not yet in the catalog, switch to catalog mode. Subsequent
893912 // ◆ entries will then be catalog items.
894913 if ( seenAppEntry && ! inCatalog ) {
914+ flushEntry ( ) ;
895915 inCatalog = true ;
916+ } else {
917+ flushEntry ( ) ;
896918 }
897919 continue ;
898920 }
899- if ( ! line . startsWith ( '\u25c6' ) ) continue ; // ignore non-◆ lines
900- const rest = line . slice ( 1 ) . trim ( ) ;
901- const colonIdx = rest . indexOf ( ':' ) ;
902- let desc = null ;
903- let left = rest ;
904- if ( colonIdx !== - 1 ) {
905- left = rest . slice ( 0 , colonIdx ) . trim ( ) ;
906- desc = rest . slice ( colonIdx + 1 ) . trim ( ) ;
907- if ( desc === '' ) desc = null ;
908- }
909- const name = left . split ( / \s + / ) [ 0 ] . trim ( ) ;
910- if ( ignoreNamePatterns . some ( re => re . test ( name ) ) ) continue ;
911- if ( ! inCatalog ) {
912- installedFromCatalog . add ( name ) ;
913- if ( desc ) installedDesc . set ( name , desc ) ;
914- } else {
915- catalogSet . add ( name ) ;
916- if ( desc ) catalogDesc . set ( name , desc ) ;
921+ if ( line . startsWith ( '\u25c6' ) ) {
922+ flushEntry ( ) ;
923+ const rest = line . slice ( 1 ) . trim ( ) ;
924+ const colonIdx = rest . indexOf ( ':' ) ;
925+ let left = rest ;
926+ let desc = null ;
927+ if ( colonIdx !== - 1 ) {
928+ left = rest . slice ( 0 , colonIdx ) . trim ( ) ;
929+ desc = rest . slice ( colonIdx + 1 ) . trim ( ) || null ;
930+ }
931+ const name = left . split ( / \s + / ) [ 0 ] . trim ( ) ;
932+ if ( ignoreNamePatterns . some ( re => re . test ( name ) ) ) continue ;
933+ curName = name ;
934+ curDesc = desc ;
935+ curInCatalog = inCatalog ;
936+ seenAppEntry = true ;
937+ } else if ( curName && curInCatalog ) {
938+ // continuation line: append to current catalog entry description
939+ curDesc = curDesc ? curDesc + ' ' + line : line ;
917940 }
918- diamondSet . add ( name ) ;
919- seenAppEntry = true ;
920941 }
942+ flushEntry ( ) ; // flush the last entry
921943 } catch ( e ) {
922944 // ignore parse errors from catalog
923945 }
@@ -982,6 +1004,16 @@ ipcMain.handle('list-apps-detailed', async () => {
9821004 }
9831005 }
9841006
1007+ // Build bundle-child map: apps whose description says
1008+ // "This script installs the full 'X' suite" are children of X.
1009+ // When X is installed the child should be hidden from the catalog.
1010+ const bundleChildOf = { } ;
1011+ const suitePattern = / i n s t a l l s t h e f u l l " ( [ ^ " ] + ) " s u i t e / i;
1012+ for ( const [ name , desc ] of catalogDesc ) {
1013+ const m = suitePattern . exec ( desc ) ;
1014+ if ( m ) bundleChildOf [ name ] = m [ 1 ] . toLowerCase ( ) ;
1015+ }
1016+
9851017 const allSet = new Set ( [ ...catalogSet , ...installedSet ] ) ;
9861018 const all = Array . from ( allSet ) . map ( name => ( {
9871019 name,
@@ -997,7 +1029,7 @@ ipcMain.handle('list-apps-detailed', async () => {
9971029 version : installedDesc . get ( name ) || null ,
9981030 desc : catalogDesc . get ( name ) || null
9991031 } ) ) ;
1000- return resolve ( { installed, all, pmFound : true } ) ;
1032+ return resolve ( { installed, all, pmFound : true , bundleChildOf } ) ;
10011033 } catch ( e ) {
10021034 return resolve ( { installed : [ ] , all : [ ] , pmFound : true , error : 'Erreur interne lors du parsing.' } ) ;
10031035 }
0 commit comments