mirror of
https://github.com/tw93/Mole.git
synced 2026-02-16 13:31:12 +00:00
Well-structured output
This commit is contained in:
@@ -2048,7 +2048,8 @@ interactive_drill_down() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " ${GRAY}Press ${NC}${GREEN}ENTER${NC}${GRAY} to confirm, ${NC}${YELLOW}ESC/Q${NC}${GRAY} to cancel${NC}"
|
echo -e " ${PURPLE}☛${NC} Press ${GREEN}Enter${NC} to delete, ${GRAY}ESC${NC} to cancel"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Read confirmation
|
# Read confirmation
|
||||||
local confirm
|
local confirm
|
||||||
@@ -2087,8 +2088,7 @@ interactive_drill_down() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$delete_success" == "true" ]]; then
|
if [[ "$delete_success" == "true" ]]; then
|
||||||
echo " ${GREEN}✓ Deleted successfully${NC}"
|
echo " ${GREEN}✓ Deleted successfully (freed $human_size)${NC}"
|
||||||
echo " ${GRAY}Freed: $human_size${NC}"
|
|
||||||
sleep 0.8
|
sleep 0.8
|
||||||
|
|
||||||
# Clear cache to force rescan
|
# Clear cache to force rescan
|
||||||
|
|||||||
57
bin/clean.sh
57
bin/clean.sh
@@ -363,23 +363,30 @@ start_cleanup() {
|
|||||||
|
|
||||||
if [[ -t 0 ]]; then
|
if [[ -t 0 ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo -ne "${BLUE}${ICON_SETTINGS}${NC} ${BLUE}System cleanup?${NC} ${GRAY}Enter to continue, any key to skip${NC} "
|
echo -ne "${PURPLE}☛${NC} System caches need sudo — ${GREEN}Enter${NC} continue, other key skip: "
|
||||||
|
|
||||||
# Use IFS= and read without -n to allow Ctrl+C to work properly
|
# Use IFS= and read without -n to allow Ctrl+C to work properly
|
||||||
IFS= read -r -s -n 1 choice
|
IFS= read -r -s -n 1 choice
|
||||||
local read_status=$?
|
local read_status=$?
|
||||||
echo ""
|
|
||||||
|
|
||||||
# If read was interrupted (Ctrl+C), exit cleanly
|
# If read was interrupted (Ctrl+C), exit cleanly
|
||||||
if [[ $read_status -ne 0 ]]; then
|
if [[ $read_status -ne 0 ]]; then
|
||||||
|
echo ""
|
||||||
exit 130
|
exit 130
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Enter or y = yes, do system cleanup
|
if [[ "$choice" == $'\e' ]]; then
|
||||||
if [[ -z "$choice" ]] || [[ "$choice" == $'\n' ]] || [[ "$choice" =~ ^[Yy]$ ]]; then
|
echo -e " ${GRAY}Cancelled${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enter = yes, do system cleanup
|
||||||
|
if [[ -z "$choice" ]] || [[ "$choice" == $'\n' ]]; then
|
||||||
|
printf "\r\033[K" # Clear the prompt line
|
||||||
if request_sudo_access "System cleanup requires admin access"; then
|
if request_sudo_access "System cleanup requires admin access"; then
|
||||||
SYSTEM_CLEAN=true
|
SYSTEM_CLEAN=true
|
||||||
echo -e "${GREEN}✓${NC} Admin access granted"
|
echo -e "${GREEN}✓${NC} Admin access granted"
|
||||||
|
echo ""
|
||||||
# Start sudo keepalive with error handling
|
# Start sudo keepalive with error handling
|
||||||
(
|
(
|
||||||
local retry_count=0
|
local retry_count=0
|
||||||
@@ -404,9 +411,10 @@ start_cleanup() {
|
|||||||
echo -e "${YELLOW}Authentication failed${NC}, continuing with user-level cleanup"
|
echo -e "${YELLOW}Authentication failed${NC}, continuing with user-level cleanup"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Any other key = no system cleanup
|
# ESC or other key = no system cleanup
|
||||||
SYSTEM_CLEAN=false
|
SYSTEM_CLEAN=false
|
||||||
echo -e "${BLUE}${ICON_EMPTY}${NC} Skipped system cleanup, user-level only"
|
echo ""
|
||||||
|
echo -e "${GRAY}Skipped system cleanup, user-level only${NC}"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
SYSTEM_CLEAN=false
|
SYSTEM_CLEAN=false
|
||||||
@@ -1350,7 +1358,7 @@ perform_cleanup() {
|
|||||||
local summary_heading=""
|
local summary_heading=""
|
||||||
local summary_status="success"
|
local summary_status="success"
|
||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
if [[ "$DRY_RUN" == "true" ]]; then
|
||||||
summary_heading="Dry run complete"
|
summary_heading="Dry run complete - no changes made"
|
||||||
else
|
else
|
||||||
summary_heading="Cleanup complete"
|
summary_heading="Cleanup complete"
|
||||||
fi
|
fi
|
||||||
@@ -1362,45 +1370,31 @@ perform_cleanup() {
|
|||||||
freed_gb=$(echo "$total_size_cleaned" | awk '{printf "%.2f", $1/1024/1024}')
|
freed_gb=$(echo "$total_size_cleaned" | awk '{printf "%.2f", $1/1024/1024}')
|
||||||
|
|
||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
if [[ "$DRY_RUN" == "true" ]]; then
|
||||||
summary_details+=("Potential reclaimable space: ${GREEN}${freed_gb}GB${NC}")
|
# Build compact stats line for dry run
|
||||||
summary_details+=("No changes were made in this mode.")
|
local stats="Potential space: ${GREEN}${freed_gb}GB${NC}"
|
||||||
|
[[ $files_cleaned -gt 0 ]] && stats+=" | Files: $files_cleaned"
|
||||||
|
[[ $total_items -gt 0 ]] && stats+=" | Categories: $total_items"
|
||||||
|
[[ $whitelist_skipped_count -gt 0 ]] && stats+=" | Protected: $whitelist_skipped_count"
|
||||||
|
summary_details+=("$stats")
|
||||||
|
summary_details+=("Use ${GRAY}mo clean --whitelist${NC} to protect caches")
|
||||||
else
|
else
|
||||||
summary_details+=("Space freed: ${GREEN}${freed_gb}GB${NC}")
|
summary_details+=("Space freed: ${GREEN}${freed_gb}GB${NC}")
|
||||||
fi
|
|
||||||
summary_details+=("Free space now: $(get_free_space)")
|
summary_details+=("Free space now: $(get_free_space)")
|
||||||
|
|
||||||
if [[ $files_cleaned -gt 0 && $total_items -gt 0 ]]; then
|
if [[ $files_cleaned -gt 0 && $total_items -gt 0 ]]; then
|
||||||
local stats
|
local stats="Files cleaned: $files_cleaned | Categories: $total_items"
|
||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
|
||||||
stats="Files to clean: $files_cleaned | Categories: $total_items"
|
|
||||||
else
|
|
||||||
stats="Files cleaned: $files_cleaned | Categories: $total_items"
|
|
||||||
fi
|
|
||||||
[[ $whitelist_skipped_count -gt 0 ]] && stats+=" | Protected: $whitelist_skipped_count"
|
[[ $whitelist_skipped_count -gt 0 ]] && stats+=" | Protected: $whitelist_skipped_count"
|
||||||
summary_details+=("$stats")
|
summary_details+=("$stats")
|
||||||
elif [[ $files_cleaned -gt 0 ]]; then
|
elif [[ $files_cleaned -gt 0 ]]; then
|
||||||
local stats
|
local stats="Files cleaned: $files_cleaned"
|
||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
|
||||||
stats="Files to clean: $files_cleaned"
|
|
||||||
else
|
|
||||||
stats="Files cleaned: $files_cleaned"
|
|
||||||
fi
|
|
||||||
[[ $whitelist_skipped_count -gt 0 ]] && stats+=" | Protected: $whitelist_skipped_count"
|
[[ $whitelist_skipped_count -gt 0 ]] && stats+=" | Protected: $whitelist_skipped_count"
|
||||||
summary_details+=("$stats")
|
summary_details+=("$stats")
|
||||||
elif [[ $total_items -gt 0 ]]; then
|
elif [[ $total_items -gt 0 ]]; then
|
||||||
local stats
|
local stats="Categories: $total_items"
|
||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
|
||||||
stats="Categories to review: $total_items"
|
|
||||||
else
|
|
||||||
stats="Categories: $total_items"
|
|
||||||
fi
|
|
||||||
[[ $whitelist_skipped_count -gt 0 ]] && stats+=" | Protected: $whitelist_skipped_count"
|
[[ $whitelist_skipped_count -gt 0 ]] && stats+=" | Protected: $whitelist_skipped_count"
|
||||||
summary_details+=("$stats")
|
summary_details+=("$stats")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
|
||||||
summary_details+=("Protect specific caches anytime with: mo clean --whitelist")
|
|
||||||
else
|
|
||||||
if [[ $(echo "$freed_gb" | awk '{print ($1 >= 1) ? 1 : 0}') -eq 1 ]]; then
|
if [[ $(echo "$freed_gb" | awk '{print ($1 >= 1) ? 1 : 0}') -eq 1 ]]; then
|
||||||
local movies
|
local movies
|
||||||
movies=$(echo "$freed_gb" | awk '{printf "%.0f", $1/4.5}')
|
movies=$(echo "$freed_gb" | awk '{printf "%.0f", $1/4.5}')
|
||||||
@@ -1420,6 +1414,7 @@ perform_cleanup() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_summary_block "$summary_status" "$summary_heading" "${summary_details[@]}"
|
print_summary_block "$summary_status" "$summary_heading" "${summary_details[@]}"
|
||||||
|
printf '\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -501,7 +501,6 @@ uninstall_applications() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Show final summary
|
# Show final summary
|
||||||
echo ""
|
|
||||||
echo -e "${PURPLE}▶ Uninstallation Summary${NC}"
|
echo -e "${PURPLE}▶ Uninstallation Summary${NC}"
|
||||||
|
|
||||||
if [[ $total_size_freed -gt 0 ]]; then
|
if [[ $total_size_freed -gt 0 ]]; then
|
||||||
@@ -527,6 +526,11 @@ cleanup() {
|
|||||||
leave_alt_screen
|
leave_alt_screen
|
||||||
unset MOLE_ALT_SCREEN_ACTIVE
|
unset MOLE_ALT_SCREEN_ACTIVE
|
||||||
fi
|
fi
|
||||||
|
if [[ -n "${sudo_keepalive_pid:-}" ]]; then
|
||||||
|
kill "$sudo_keepalive_pid" 2>/dev/null || true
|
||||||
|
wait "$sudo_keepalive_pid" 2>/dev/null || true
|
||||||
|
sudo_keepalive_pid=""
|
||||||
|
fi
|
||||||
show_cursor
|
show_cursor
|
||||||
exit "${1:-0}"
|
exit "${1:-0}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,23 +87,36 @@ batch_uninstall_applications() {
|
|||||||
local remaining=$((file_count - max_files))
|
local remaining=$((file_count - max_files))
|
||||||
echo -e " ${GRAY} ... and ${remaining} more files${NC}"
|
echo -e " ${GRAY} ... and ${remaining} more files${NC}"
|
||||||
fi
|
fi
|
||||||
echo ""
|
|
||||||
done
|
done
|
||||||
|
|
||||||
# Show summary and get batch confirmation first (before asking for password)
|
# Show summary and get batch confirmation first (before asking for password)
|
||||||
local app_total=${#selected_apps[@]}
|
local app_total=${#selected_apps[@]}
|
||||||
local app_text="app"
|
local app_text="app"
|
||||||
[[ $app_total -gt 1 ]] && app_text="apps"
|
[[ $app_total -gt 1 ]] && app_text="apps"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
local removal_note="Remove ${app_total} ${app_text}"
|
||||||
|
[[ -n "$size_display" ]] && removal_note+=" (${size_display})"
|
||||||
if [[ ${#running_apps[@]} -gt 0 ]]; then
|
if [[ ${#running_apps[@]} -gt 0 ]]; then
|
||||||
echo -n "${BLUE}${ICON_CONFIRM}${NC} Remove ${app_total} ${app_text} | ${size_display} | Force quit: ${running_apps[*]} | Enter=go / ESC=q: "
|
removal_note+=" - will force quit: ${running_apps[*]}"
|
||||||
else
|
|
||||||
echo -n "${BLUE}${ICON_CONFIRM}${NC} Remove ${app_total} ${app_text} | ${size_display} | Enter=go / ESC=q: "
|
|
||||||
fi
|
fi
|
||||||
|
echo -ne "${PURPLE}☛${NC} ${removal_note}. Press ${GREEN}Enter${NC} to confirm, ${GRAY}ESC${NC} to cancel: "
|
||||||
|
|
||||||
IFS= read -r -s -n1 key || key=""
|
IFS= read -r -s -n1 key || key=""
|
||||||
case "$key" in
|
case "$key" in
|
||||||
$'\e'|q|Q) echo ""; return 0 ;;
|
$'\e'|q|Q)
|
||||||
""|$'\n'|$'\r'|y|Y) echo "" ;;
|
echo ""
|
||||||
*) echo ""; return 0 ;;
|
echo ""
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
""|$'\n'|$'\r'|y|Y)
|
||||||
|
printf "\r\033[K" # Clear the prompt line
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo ""
|
||||||
|
echo ""
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# User confirmed, now request sudo access if needed
|
# User confirmed, now request sudo access if needed
|
||||||
@@ -117,19 +130,9 @@ batch_uninstall_applications() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
(while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null) &
|
(while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null) &
|
||||||
local sudo_keepalive_pid=$!
|
sudo_keepalive_pid=$!
|
||||||
local _trap_cleanup_cmd="kill $sudo_keepalive_pid 2>/dev/null || true; wait $sudo_keepalive_pid 2>/dev/null || true"
|
|
||||||
for signal in EXIT INT TERM; do
|
|
||||||
local existing_trap; existing_trap=$(trap -p "$signal" | awk -F"'" '{print $2}')
|
|
||||||
if [[ -n "$existing_trap" ]]; then
|
|
||||||
trap "$existing_trap; $_trap_cleanup_cmd" "$signal"
|
|
||||||
else
|
|
||||||
trap "$_trap_cleanup_cmd" "$signal"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
|
||||||
if [[ -t 1 ]]; then start_inline_spinner "Uninstalling apps..."; fi
|
if [[ -t 1 ]]; then start_inline_spinner "Uninstalling apps..."; fi
|
||||||
|
|
||||||
# Force quit running apps first (batch)
|
# Force quit running apps first (batch)
|
||||||
@@ -183,8 +186,23 @@ batch_uninstall_applications() {
|
|||||||
|
|
||||||
if [[ $success_count -gt 0 ]]; then
|
if [[ $success_count -gt 0 ]]; then
|
||||||
local success_list="${success_items[*]}"
|
local success_list="${success_items[*]}"
|
||||||
summary_details+=("Removed: ${GREEN}${success_list}${NC}")
|
local success_text="app"
|
||||||
summary_details+=("Freed space: ${GREEN}${freed_display}${NC}")
|
[[ $success_count -gt 1 ]] && success_text="apps"
|
||||||
|
local success_line="Removed ${success_count} ${success_text}"
|
||||||
|
if [[ -n "$freed_display" ]]; then
|
||||||
|
success_line+=", freed ${GREEN}${freed_display}${NC}"
|
||||||
|
fi
|
||||||
|
if [[ -n "$success_list" ]]; then
|
||||||
|
local -a formatted_apps=()
|
||||||
|
for app_name in "${success_items[@]}"; do
|
||||||
|
formatted_apps+=("${GREEN}${app_name}${NC}")
|
||||||
|
done
|
||||||
|
if [[ ${#formatted_apps[@]} -gt 0 ]]; then
|
||||||
|
local IFS=', '
|
||||||
|
success_line+=": ${formatted_apps[*]}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
summary_details+=("$success_line")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $failed_count -gt 0 ]]; then
|
if [[ $failed_count -gt 0 ]]; then
|
||||||
@@ -216,6 +234,7 @@ batch_uninstall_applications() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_summary_block "$summary_status" "Uninstall complete" "${summary_details[@]}"
|
print_summary_block "$summary_status" "Uninstall complete" "${summary_details[@]}"
|
||||||
|
printf '\n'
|
||||||
|
|
||||||
if [[ ${#dock_cleanup_paths[@]} -gt 0 ]]; then
|
if [[ ${#dock_cleanup_paths[@]} -gt 0 ]]; then
|
||||||
remove_apps_from_dock "${dock_cleanup_paths[@]}"
|
remove_apps_from_dock "${dock_cleanup_paths[@]}"
|
||||||
@@ -225,6 +244,7 @@ batch_uninstall_applications() {
|
|||||||
if [[ -n "${sudo_keepalive_pid:-}" ]]; then
|
if [[ -n "${sudo_keepalive_pid:-}" ]]; then
|
||||||
kill "$sudo_keepalive_pid" 2>/dev/null || true
|
kill "$sudo_keepalive_pid" 2>/dev/null || true
|
||||||
wait "$sudo_keepalive_pid" 2>/dev/null || true
|
wait "$sudo_keepalive_pid" 2>/dev/null || true
|
||||||
|
sudo_keepalive_pid=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
((total_size_cleaned += total_size_freed))
|
((total_size_cleaned += total_size_freed))
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ readonly ICON_ERROR="✗" # Error
|
|||||||
readonly ICON_EMPTY="○" # Empty state
|
readonly ICON_EMPTY="○" # Empty state
|
||||||
readonly ICON_LIST="-" # List item
|
readonly ICON_LIST="-" # List item
|
||||||
readonly ICON_MENU="▸" # Menu item
|
readonly ICON_MENU="▸" # Menu item
|
||||||
readonly ICON_SYSTEM="☯︎" # System/Architecture info
|
readonly ICON_SYSTEM="❤︎" # System/Architecture info
|
||||||
readonly ICON_SETTINGS="⚙" # Settings/Configuration
|
readonly ICON_SETTINGS="⚙" # Settings/Configuration
|
||||||
|
|
||||||
# Spinner character helpers (ASCII by default, overridable via env)
|
# Spinner character helpers (ASCII by default, overridable via env)
|
||||||
@@ -741,7 +741,37 @@ clean_tool_cache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Confirmation prompt abstraction (Enter=confirm ESC/q=cancel)
|
# Unified confirmation prompt with consistent style
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# Unified action prompt
|
||||||
|
# Usage: prompt_action "action" "cancel_text" -> returns 0 for yes, 1 for no
|
||||||
|
# Example: prompt_action "enable" "quit" -> "☛ Press Enter to enable, ESC to quit: "
|
||||||
|
prompt_action() {
|
||||||
|
local action="$1"
|
||||||
|
local cancel="${2:-cancel}"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -ne "${PURPLE}☛${NC} Press ${GREEN}Enter${NC} to ${action}, ${GRAY}ESC${NC} to ${cancel}: "
|
||||||
|
IFS= read -r -s -n1 key || key=""
|
||||||
|
|
||||||
|
case "$key" in
|
||||||
|
$'\e') # ESC
|
||||||
|
echo ""
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
""|$'\n'|$'\r') # Enter
|
||||||
|
printf "\r\033[K" # Clear the prompt line
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo ""
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Legacy confirmation prompt (kept for compatibility)
|
||||||
# confirm_prompt "Message" -> 0 yes, 1 no
|
# confirm_prompt "Message" -> 0 yes, 1 no
|
||||||
confirm_prompt() {
|
confirm_prompt() {
|
||||||
local message="$1"
|
local message="$1"
|
||||||
|
|||||||
@@ -262,6 +262,14 @@ EOF
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [[ ${#selected_indices[@]} -eq 0 ]]; then
|
||||||
|
local default_idx=$((top_index + cursor_pos))
|
||||||
|
if [[ $default_idx -ge 0 && $default_idx -lt $total_items ]]; then
|
||||||
|
selected[default_idx]=true
|
||||||
|
selected_indices=("$default_idx")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
local final_result=""
|
local final_result=""
|
||||||
if [[ ${#selected_indices[@]} -gt 0 ]]; then
|
if [[ ${#selected_indices[@]} -gt 0 ]]; then
|
||||||
local IFS=','
|
local IFS=','
|
||||||
|
|||||||
@@ -179,7 +179,6 @@ manage_whitelist_categories() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo -e "${PURPLE}Whitelist Manager${NC}"
|
echo -e "${PURPLE}Whitelist Manager${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GRAY}Select caches to protect from cleanup.${NC}"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Load currently enabled patterns from both sources
|
# Load currently enabled patterns from both sources
|
||||||
@@ -248,7 +247,7 @@ manage_whitelist_categories() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
MOLE_SELECTION_RESULT=""
|
MOLE_SELECTION_RESULT=""
|
||||||
paginated_multi_select "Select caches to protect" "${menu_options[@]}"
|
paginated_multi_select "Whitelist Manager – Select caches to protect" "${menu_options[@]}"
|
||||||
unset MOLE_PRESELECTED_INDICES
|
unset MOLE_PRESELECTED_INDICES
|
||||||
local exit_code=$?
|
local exit_code=$?
|
||||||
|
|
||||||
@@ -283,6 +282,7 @@ manage_whitelist_categories() {
|
|||||||
print_summary_block "success" \
|
print_summary_block "success" \
|
||||||
"Protected ${#selected_patterns[@]} cache(s)" \
|
"Protected ${#selected_patterns[@]} cache(s)" \
|
||||||
"Saved to ${WHITELIST_CONFIG}"
|
"Saved to ${WHITELIST_CONFIG}"
|
||||||
|
printf '\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user