@@ -12,7 +12,7 @@ brew_menu() {
1212 crumb_push " Homebrew"
1313 while true ; do
1414 clear
15- set_title " macrift > brew "
15+
1616 local choice
1717 choice=$( show_menu " Homebrew" \
1818 " Development" \
@@ -29,13 +29,13 @@ brew_menu() {
2929 " Back" )
3030
3131 case " $choice " in
32- 1) install_bundle " Brewfile.dev" ;;
33- 2) install_bundle " Brewfile.utils" ;;
34- 3) install_bundle " Brewfile.browsers" ;;
35- 4) install_bundle " Brewfile.comm" ;;
36- 5) install_bundle " Brewfile.media" ;;
37- 6) install_bundle " Brewfile.games" ;;
38- 7) install_bundle " Brewfile.fonts" ;;
32+ 1) install_bundle " Brewfile.dev" " Development " ;;
33+ 2) install_bundle " Brewfile.utils" " Utilities " ;;
34+ 3) install_bundle " Brewfile.browsers" " Browsers " ;;
35+ 4) install_bundle " Brewfile.comm" " Communication " ;;
36+ 5) install_bundle " Brewfile.media" " Media " ;;
37+ 6) install_bundle " Brewfile.games" " Games " ;;
38+ 7) install_bundle " Brewfile.fonts" " Fonts " ;;
3939 8) install_all_bundles ;;
4040 9) brewbak_menu ;;
4141 0) break ;;
@@ -49,7 +49,7 @@ brewbak_menu() {
4949 crumb_push " Backup"
5050 while true ; do
5151 clear
52- set_title " macrift > brew > backup "
52+
5353 local choice
5454 choice=$( show_menu " Backup (.brewbak)" \
5555 " Import from .brewbak" \
@@ -68,6 +68,7 @@ brewbak_menu() {
6868
6969install_bundle () {
7070 local brewfile=" $1 "
71+ local label=" ${2:- $brewfile } "
7172 local path=" $MACRIFT_DIR /config/$brewfile "
7273
7374 if [[ ! -f " $path " ]]; then
@@ -97,36 +98,20 @@ install_bundle() {
9798 continue
9899 fi
99100 had_items= true
100- local name= " " label = " "
101+ local name= " "
101102 if [[ " $line " =~ ^brew[[:space:]]+\" ([^\" ]+)\" ]]; then
102103 name=" ${BASH_REMATCH[1]} "
103- label=" $name "
104104 elif [[ " $line " =~ ^cask[[:space:]]+\" ([^\" ]+)\" ]]; then
105105 name=" ${BASH_REMATCH[1]} "
106- label=" $name "
107- elif [[ " $line " =~ ^mas[[:space:]]+\" ([^\" ]+)\" ,[[:space:]]* id:[[:space:]]* ([0-9]+) ]]; then
108- name=" ${BASH_REMATCH[1]} "
109- local mas_id=" ${BASH_REMATCH[2]} "
110- label=" $name "
111- if mas list 2> /dev/null | awk ' {print $1}' | grep -qx " $mas_id " ; then
112- installed_count=$(( installed_count + 1 ))
113- else
114- new_lines+=(" $line " )
115- new_labels+=(" $label " )
116- fi
117- continue
118106 else
119107 continue
120108 fi
121109 if echo " $installed " | grep -qxF " $name " ; then
122- # For casks, verify the .app actually exists in /Applications
123110 if [[ " $line " =~ ^cask ]]; then
124- # || true prevents set -e from triggering if find exits non-zero
125111 app_path=$( find " $( brew --prefix) /Caskroom" /" $name " -name " *.app" -maxdepth 3 2> /dev/null | head -1) || true
126112 if [[ -n " $app_path " ]]; then
127113 appname=$( basename " $app_path " )
128114 if [[ ! -e " /Applications/$appname " ]]; then
129- # Registered in brew but .app is missing — queue for silent reinstall
130115 broken_casks+=(" $name " )
131116 continue
132117 fi
@@ -135,33 +120,56 @@ install_bundle() {
135120 installed_count=$(( installed_count + 1 ))
136121 else
137122 new_lines+=(" $line " )
138- new_labels+=(" $label " )
123+ new_labels+=(" $name " )
139124 fi
140125 done < " $path "
141126
142- # Clean up separators: remove leading, trailing, and consecutive
143- local clean_lines= () clean_labels= ()
144- local prev_sep= true
145- for (( i= 0 ; i< ${# new_labels[@]} ; i++ )) ; do
146- if [[ " ${new_labels[$i]} " == " ---" ]]; then
147- $prev_sep && continue
148- prev_sep=true
149- else
150- prev_sep=false
127+ # Nothing new — handle broken casks if any, otherwise skip silently
128+ if [[ ! ${new_labels[*]+x} || ${# new_labels[@]} -eq 0 ]]; then
129+ if [[ ${broken_casks[*]+x} && ${# broken_casks[@]} -gt 0 ]]; then
130+ log_warn " ${# broken_casks[@]} app(s) are missing from Applications"
131+ for cask in " ${broken_casks[@]} " ; do
132+ printf ' %b· %s%b\n' " $DIM " " $cask " " $RESET "
133+ done
134+ printf " \n"
135+ if [[ " $MACRIFT_DRY_RUN " != true ]] && confirm " Fix them now?" ; then
136+ local cask_idx=0
137+ for cask in " ${broken_casks[@]} " ; do
138+ (( cask_idx++ ))
139+ show_progress " $cask_idx " " ${# broken_casks[@]} " " $cask "
140+ if brew reinstall --cask " $cask " & > /dev/null; then
141+ log_ok " $cask reinstalled"
142+ else
143+ log_warn " Failed to reinstall $cask "
144+ fi
145+ done
146+ fi
147+ wait_enter
151148 fi
152- clean_lines+=(" ${new_lines[$i]} " )
153- clean_labels+=(" ${new_labels[$i]} " )
154- done
155- # Remove trailing separator
156- while [[ ${# clean_labels[@]} -gt 0 && " ${clean_labels[-1]} " == " ---" ]]; do
157- unset ' clean_lines[-1]'
158- unset ' clean_labels[-1]'
159- done
160- new_lines= (" ${clean_lines[@]} " )
161- new_labels= (" ${clean_labels[@]} " )
149+ return 0
150+ fi
162151
163- if [[ $installed_count -gt 0 ]]; then
164- log_ok " $installed_count already installed"
152+ # Clean up separators: remove leading, trailing, and consecutive
153+ if [[ ${# new_labels[@]} -gt 0 ]]; then
154+ local clean_lines=() clean_labels=()
155+ local prev_sep=true
156+ for (( i= 0 ; i< ${# new_labels[@]} ; i++ )) ; do
157+ if [[ " ${new_labels[$i]} " == " ---" ]]; then
158+ $prev_sep && continue
159+ prev_sep=true
160+ else
161+ prev_sep=false
162+ fi
163+ clean_lines+=(" ${new_lines[$i]} " )
164+ clean_labels+=(" ${new_labels[$i]} " )
165+ done
166+ # Remove trailing separator
167+ while [[ ${# clean_labels[@]} -gt 0 && " ${clean_labels[${#clean_labels[@]} -1]}" == " ---" ]]; do
168+ unset " clean_lines[${# clean_lines[@]} -1]"
169+ unset " clean_labels[${# clean_labels[@]} -1]"
170+ done
171+ new_lines=(${clean_lines[@]+" ${clean_lines[@]} " } )
172+ new_labels=(${clean_labels[@]+" ${clean_labels[@]} " } )
165173 fi
166174
167175 # Handle missing apps separately — ask user once, then fix silently
@@ -205,8 +213,10 @@ install_bundle() {
205213 fi
206214
207215 # Multiselect for new packages only
216+ local ms_title= " $label "
217+ [[ $installed_count -gt 0 ]] && ms_title= " $label · $installed_count installed"
208218 local selected
209- selected= $( show_multiselect " $brewfile " " ${new_labels[@]} " )
219+ selected= $( show_multiselect " $ms_title " " ${new_labels[@]} " )
210220
211221 if [[ -z " $selected " ]]; then
212222 return 0
@@ -216,15 +226,10 @@ install_bundle() {
216226 local tmp
217227 tmp= $( mktemp /tmp/macrift_brew_XXXXXX)
218228
219- local mas_install_lines= ()
220229 for (( i= 0 ; i< ${# new_labels[@]} ; i++ )) ; do
221230 [[ " ${new_labels[$i]} " == " ---" ]] && continue
222231 if echo " $selected " | grep -qxF " ${new_labels[$i]} " ; then
223- if [[ " ${new_lines[$i]} " =~ ^mas[[:space:]] ]]; then
224- mas_install_lines+=(" ${new_lines[$i]} " )
225- else
226- echo " ${new_lines[$i]} " >> " $tmp "
227- fi
232+ echo " ${new_lines[$i]} " >> " $tmp "
228233 fi
229234 done
230235
@@ -233,11 +238,6 @@ install_bundle() {
233238 [[ -s " $tmp " ]] && while IFS= read -r line; do
234239 printf ' %b· %s%b\n' " $DIM " " $line " " $RESET "
235240 done < " $tmp "
236- for mas_line in " ${mas_install_lines[@]} " ; do
237- if [[ " $mas_line " =~ ^mas[[:space:]]+\" ([^\" ]+)\" ]]; then
238- printf ' %b· %s (App Store)%b\n' " $DIM " " ${BASH_REMATCH[1]} " " $RESET "
239- fi
240- done
241241 rm -f " $tmp "
242242 wait_enter
243243 return 0
@@ -251,27 +251,6 @@ install_bundle() {
251251 fi
252252 rm -f " $tmp "
253253
254- local mas_idx= 0 mas_total= ${# mas_install_lines[@]}
255- for mas_line in " ${mas_install_lines[@]} " ; do
256- (( mas_idx++ ))
257- if [[ " $mas_line " =~ ^mas[[:space:]]+\" ([^\" ]+)\" ,[[:space:]]* id:[[:space:]]* ([0-9]+) ]]; then
258- local mas_name=" ${BASH_REMATCH[1]} "
259- local mas_id=" ${BASH_REMATCH[2]} "
260- [[ $mas_total -gt 1 ]] && show_progress " $mas_idx " " $mas_total " " $mas_name "
261- local mas_out
262- if mas_out=$( mas install " $mas_id " 2>&1 ) ; then
263- log_ok " $mas_name installed"
264- elif echo " $mas_out " | grep -qi " Redownload Unavailable" ; then
265- log_warn " $mas_name : not purchased with this account — opening App Store"
266- open " https://apps.apple.com/app/id$mas_id "
267- all_ok=false
268- else
269- log_warn " Failed to install $mas_name "
270- all_ok=false
271- fi
272- fi
273- done
274-
275254 if $all_ok ; then
276255 log_ok " All packages installed"
277256 else
@@ -280,14 +259,29 @@ install_bundle() {
280259 wait_enter
281260}
282261
262+ _bundle_label () {
263+ case " $1 " in
264+ Brewfile.dev) echo " Development" ;;
265+ Brewfile.utils) echo " Utilities" ;;
266+ Brewfile.browsers) echo " Browsers" ;;
267+ Brewfile.comm) echo " Communication" ;;
268+ Brewfile.media) echo " Media" ;;
269+ Brewfile.games) echo " Games" ;;
270+ Brewfile.fonts) echo " Fonts" ;;
271+ * ) echo " $1 " ;;
272+ esac
273+ }
274+
283275install_all_bundles () {
284276 if ! confirm " Install all bundles? (select packages in each)" ; then
285277 return
286278 fi
287279
288280 for brewfile in " $MACRIFT_DIR " /config/Brewfile.* ; do
289281 if [[ -f " $brewfile " ]]; then
290- install_bundle " $( basename " $brewfile " ) "
282+ local name
283+ name=$( basename " $brewfile " )
284+ install_bundle " $name " " $( _bundle_label " $name " ) "
291285 fi
292286 done
293287
0 commit comments