mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 19:44:44 +00:00
Fix search problems and best practices
This commit is contained in:
@@ -456,7 +456,10 @@ safe_clean() {
|
||||
}
|
||||
|
||||
start_cleanup() {
|
||||
clear
|
||||
if [[ -t 1 ]]; then
|
||||
# Avoid relying on TERM since CI often runs without it
|
||||
printf '\033[2J\033[H'
|
||||
fi
|
||||
printf '\n'
|
||||
echo -e "${PURPLE_BOLD}Clean Your Mac${NC}"
|
||||
echo ""
|
||||
|
||||
@@ -73,11 +73,12 @@ scan_applications() {
|
||||
local cache_dir="$HOME/.cache/mole"
|
||||
local cache_file="$cache_dir/app_scan_cache"
|
||||
local cache_ttl=86400 # 24 hours
|
||||
local force_rescan="${1:-false}"
|
||||
|
||||
mkdir -p "$cache_dir" 2> /dev/null
|
||||
|
||||
# Check if cache exists and is fresh
|
||||
if [[ -f "$cache_file" ]]; then
|
||||
if [[ $force_rescan == false && -f "$cache_file" ]]; then
|
||||
local cache_age=$(($(date +%s) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(date +%s) ]] && cache_age=86401 # Handle missing file
|
||||
if [[ $cache_age -lt $cache_ttl ]]; then
|
||||
@@ -405,11 +406,15 @@ trap cleanup EXIT INT TERM
|
||||
# Main function
|
||||
main() {
|
||||
# Parse args
|
||||
local force_rescan=false
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
"--debug")
|
||||
export MO_DEBUG=1
|
||||
;;
|
||||
"--force-rescan")
|
||||
force_rescan=true
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -425,7 +430,7 @@ main() {
|
||||
# (scan_applications handles cache internally)
|
||||
local needs_scanning=true
|
||||
local cache_file="$HOME/.cache/mole/app_scan_cache"
|
||||
if [[ -f "$cache_file" ]]; then
|
||||
if [[ $force_rescan == false && -f "$cache_file" ]]; then
|
||||
local cache_age=$(($(date +%s) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(date +%s) ]] && cache_age=86401 # Handle missing file
|
||||
[[ $cache_age -lt 86400 ]] && needs_scanning=false
|
||||
@@ -444,7 +449,7 @@ main() {
|
||||
|
||||
# Scan applications
|
||||
local apps_file=""
|
||||
if ! apps_file=$(scan_applications); then
|
||||
if ! apps_file=$(scan_applications "$force_rescan"); then
|
||||
if [[ "${MOLE_ALT_SCREEN_ACTIVE:-}" == "1" ]]; then
|
||||
printf "\033[2J\033[H" >&2
|
||||
leave_alt_screen
|
||||
|
||||
@@ -73,3 +73,93 @@ update_via_homebrew() {
|
||||
# Clear update cache
|
||||
rm -f "$HOME/.cache/mole/version_check" "$HOME/.cache/mole/update_message" 2> /dev/null || true
|
||||
}
|
||||
|
||||
# Remove apps from Dock
|
||||
# Args: app paths to remove
|
||||
remove_apps_from_dock() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local plist="$HOME/Library/Preferences/com.apple.dock.plist"
|
||||
[[ -f "$plist" ]] || return 0
|
||||
|
||||
if ! command -v python3 > /dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Execute Python helper to prune dock entries for the given app paths
|
||||
python3 - "$@" << 'PY' 2>/dev/null || return 0
|
||||
import os
|
||||
import plistlib
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib.parse
|
||||
|
||||
plist_path = os.path.expanduser('~/Library/Preferences/com.apple.dock.plist')
|
||||
if not os.path.exists(plist_path):
|
||||
sys.exit(0)
|
||||
|
||||
def normalise(path):
|
||||
if not path:
|
||||
return ''
|
||||
return os.path.normpath(os.path.realpath(path.rstrip('/')))
|
||||
|
||||
targets = {normalise(arg) for arg in sys.argv[1:] if arg}
|
||||
targets = {t for t in targets if t}
|
||||
if not targets:
|
||||
sys.exit(0)
|
||||
|
||||
with open(plist_path, 'rb') as fh:
|
||||
try:
|
||||
data = plistlib.load(fh)
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
|
||||
apps = data.get('persistent-apps')
|
||||
if not isinstance(apps, list):
|
||||
sys.exit(0)
|
||||
|
||||
changed = False
|
||||
filtered = []
|
||||
for item in apps:
|
||||
try:
|
||||
url = item['tile-data']['file-data']['_CFURLString']
|
||||
except (KeyError, TypeError):
|
||||
filtered.append(item)
|
||||
continue
|
||||
|
||||
if not isinstance(url, str):
|
||||
filtered.append(item)
|
||||
continue
|
||||
|
||||
parsed = urllib.parse.urlparse(url)
|
||||
path = urllib.parse.unquote(parsed.path or '')
|
||||
if not path:
|
||||
filtered.append(item)
|
||||
continue
|
||||
|
||||
candidate = normalise(path)
|
||||
if any(candidate == t or candidate.startswith(t + os.sep) for t in targets):
|
||||
changed = True
|
||||
continue
|
||||
|
||||
filtered.append(item)
|
||||
|
||||
if not changed:
|
||||
sys.exit(0)
|
||||
|
||||
data['persistent-apps'] = filtered
|
||||
with open(plist_path, 'wb') as fh:
|
||||
try:
|
||||
plistlib.dump(data, fh, fmt=plistlib.FMT_BINARY)
|
||||
except Exception:
|
||||
plistlib.dump(data, fh)
|
||||
|
||||
# Restart Dock to apply changes
|
||||
try:
|
||||
subprocess.run(['killall', 'Dock'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False)
|
||||
except Exception:
|
||||
pass
|
||||
PY
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ read_key() {
|
||||
case "$key" in
|
||||
$'\n' | $'\r') echo "ENTER" ;;
|
||||
' ') echo "SPACE" ;;
|
||||
'/') echo "FILTER" ;;
|
||||
'q' | 'Q') echo "QUIT" ;;
|
||||
'R') echo "RETRY" ;;
|
||||
$'\x03') echo "QUIT" ;;
|
||||
$'\x7f' | $'\x08') echo "DELETE" ;;
|
||||
$'\x1b')
|
||||
|
||||
@@ -11,16 +11,25 @@ source "$_MOLE_MANAGE_DIR/../ui/menu_simple.sh"
|
||||
|
||||
# Config file paths
|
||||
readonly WHITELIST_CONFIG_CLEAN="$HOME/.config/mole/whitelist"
|
||||
readonly WHITELIST_CONFIG_OPTIMIZE="$HOME/.config/mole/whitelist_checks"
|
||||
readonly WHITELIST_CONFIG_OPTIMIZE="$HOME/.config/mole/whitelist_optimize"
|
||||
readonly WHITELIST_CONFIG_OPTIMIZE_LEGACY="$HOME/.config/mole/whitelist_checks"
|
||||
|
||||
# Default whitelist patterns defined in lib/core/common.sh:
|
||||
# - DEFAULT_WHITELIST_PATTERNS
|
||||
# - FINDER_METADATA_SENTINEL
|
||||
|
||||
# Save whitelist patterns to config
|
||||
# Save whitelist patterns to config (defaults to "clean" for legacy callers)
|
||||
save_whitelist_patterns() {
|
||||
local mode="$1"
|
||||
shift
|
||||
local mode="clean"
|
||||
if [[ $# -gt 0 ]]; then
|
||||
case "$1" in
|
||||
clean | optimize)
|
||||
mode="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
local -a patterns
|
||||
patterns=("$@")
|
||||
|
||||
@@ -170,13 +179,21 @@ load_whitelist() {
|
||||
local mode="${1:-clean}"
|
||||
local -a patterns=()
|
||||
local config_file
|
||||
local legacy_file=""
|
||||
|
||||
if [[ "$mode" == "optimize" ]]; then
|
||||
config_file="$WHITELIST_CONFIG_OPTIMIZE"
|
||||
legacy_file="$WHITELIST_CONFIG_OPTIMIZE_LEGACY"
|
||||
else
|
||||
config_file="$WHITELIST_CONFIG_CLEAN"
|
||||
fi
|
||||
|
||||
local using_legacy="false"
|
||||
if [[ ! -f "$config_file" && -n "$legacy_file" && -f "$legacy_file" ]]; then
|
||||
config_file="$legacy_file"
|
||||
using_legacy="true"
|
||||
fi
|
||||
|
||||
if [[ -f "$config_file" ]]; then
|
||||
while IFS= read -r line; do
|
||||
# shellcheck disable=SC2295
|
||||
@@ -210,6 +227,11 @@ load_whitelist() {
|
||||
unique_patterns+=("$pattern")
|
||||
done
|
||||
CURRENT_WHITELIST_PATTERNS=("${unique_patterns[@]}")
|
||||
|
||||
# Migrate legacy optimize config to the new path automatically
|
||||
if [[ "$mode" == "optimize" && "$using_legacy" == "true" && "$config_file" != "$WHITELIST_CONFIG_OPTIMIZE" ]]; then
|
||||
save_whitelist_patterns "$mode" "${CURRENT_WHITELIST_PATTERNS[@]}"
|
||||
fi
|
||||
else
|
||||
CURRENT_WHITELIST_PATTERNS=()
|
||||
fi
|
||||
|
||||
@@ -399,7 +399,7 @@ paginated_multi_select() {
|
||||
for ((i = 0; i < items_per_page; i++)); do
|
||||
printf "${clear_line}\n" >&2
|
||||
done
|
||||
printf "${clear_line}${GRAY}Type to filter | Delete | Enter | / Exit | ESC${NC}\n" >&2
|
||||
printf "${clear_line}${GRAY}Type to filter | Delete | Enter Confirm | ESC Cancel${NC}\n" >&2
|
||||
printf "${clear_line}" >&2
|
||||
return
|
||||
else
|
||||
@@ -480,9 +480,8 @@ paginated_multi_select() {
|
||||
local -a _segs_filter=(
|
||||
"${GRAY}Filter: ${filter_status}${NC}"
|
||||
"${GRAY}Delete${NC}"
|
||||
"${GRAY}Enter${NC}"
|
||||
"${GRAY}/ Exit${NC}"
|
||||
"${GRAY}ESC${NC}"
|
||||
"${GRAY}Enter Confirm${NC}"
|
||||
"${GRAY}ESC Cancel${NC}"
|
||||
)
|
||||
_print_wrapped_controls "$sep" "${_segs_filter[@]}"
|
||||
else
|
||||
@@ -668,15 +667,8 @@ paginated_multi_select() {
|
||||
CHAR:*)
|
||||
if [[ "$filter_mode" == "true" ]]; then
|
||||
local ch="${key#CHAR:}"
|
||||
# Special handling for /: exit filter mode
|
||||
if [[ "$ch" == "/" ]]; then
|
||||
filter_mode="false"
|
||||
unset MOLE_READ_KEY_FORCE_CHAR
|
||||
filter_query=""
|
||||
applied_query=""
|
||||
rebuild_view
|
||||
# avoid accidental leading spaces
|
||||
elif [[ -n "$filter_query" || "$ch" != " " ]]; then
|
||||
if [[ -n "$filter_query" || "$ch" != " " ]]; then
|
||||
filter_query+="$ch"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -113,7 +113,6 @@ batch_uninstall_applications() {
|
||||
local -a sudo_apps=()
|
||||
local total_estimated_size=0
|
||||
local -a app_details=()
|
||||
local -a dock_cleanup_paths=()
|
||||
|
||||
# Analyze selected apps with progress indicator
|
||||
if [[ -t 1 ]]; then start_inline_spinner "Scanning files..."; fi
|
||||
@@ -315,7 +314,6 @@ batch_uninstall_applications() {
|
||||
((files_cleaned++))
|
||||
((total_items++))
|
||||
success_items+=("$app_name")
|
||||
dock_cleanup_paths+=("$app_path")
|
||||
else
|
||||
((failed_count++))
|
||||
failed_items+=("$app_name:$reason")
|
||||
@@ -406,8 +404,22 @@ batch_uninstall_applications() {
|
||||
print_summary_block "$summary_status" "Uninstall complete" "${summary_details[@]}"
|
||||
printf '\n'
|
||||
|
||||
if [[ ${#dock_cleanup_paths[@]} -gt 0 ]]; then
|
||||
remove_apps_from_dock "${dock_cleanup_paths[@]}"
|
||||
# Clean up Dock entries for uninstalled apps
|
||||
if [[ $success_count -gt 0 ]]; then
|
||||
local -a removed_paths=()
|
||||
for detail in "${app_details[@]}"; do
|
||||
IFS='|' read -r app_name app_path _ _ _ _ <<< "$detail"
|
||||
# Check if this app was successfully removed
|
||||
for success_name in "${success_items[@]}"; do
|
||||
if [[ "$success_name" == "$app_name" ]]; then
|
||||
removed_paths+=("$app_path")
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
if [[ ${#removed_paths[@]} -gt 0 ]]; then
|
||||
remove_apps_from_dock "${removed_paths[@]}" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean up sudo keepalive if it was started
|
||||
|
||||
Reference in New Issue
Block a user