Skip to content

Commit

Permalink
fs-rm, setup-util-trash: fix macos support
Browse files Browse the repository at this point in the history
- choose: add `--default-all`
- command-working: add `rmtrash`
- fs-rm: only support `/usr/bin/trash` on macos, and `trash-put` on linux
- setup-util: fix and improve generic rm
  • Loading branch information
balupton committed Jan 2, 2025
1 parent cf10395 commit cca8f9b
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 35 deletions.
38 changes: 24 additions & 14 deletions commands/choose
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,9 @@ function choose_() (
--defaults-fuzzy=<newline separated values>
Pre-select <value>s by fuzzy matching.
--[no-]default-all=[yes|NO]
If provided, select everything as a default.
--[no-]skip-solo=[YES|no] | --[no-]confirm-solo=[NO|yes]
If a selection is required, and there is only a single item, the solo item will be selected. This option skips the prompt for the required solo item, sending it without doing the prompt. Defaults to disabled.
Expand Down Expand Up @@ -553,7 +556,7 @@ function choose_() (
local item='' inputs=() tmp=()
local option_question=()
local option_label='no' option_visual='' option_return='$VALUE'
local defaults_exact=() defaults_fuzzy=() option_confirm_solo='yes' option_confirm_default='yes' option_confirm_input='no' option_confirm_cancel='yes'
local defaults_exact=() defaults_fuzzy=() option_default_all='' option_confirm_solo='yes' option_confirm_default='yes' option_confirm_input='no' option_confirm_cancel='yes'
local option_required='no' option_multi='no'
local option_linger='no' option_timeout='' option_truncate_body='no'
while [[ $# -ne 0 ]]; do
Expand All @@ -579,6 +582,9 @@ function choose_() (
mapfile -t tmp <<<"${item#*=}"
defaults_fuzzy+=("${tmp[@]}")
;;
'--no-default-all'* | '--default-all'*)
option_default_all="$(get-flag-value --affirmative --fallback="$option_default_all" -- "$item")"
;;
'--no-skip-solo'* | '--skip-solo'*)
option_confirm_solo="$(get-flag-value --non-affirmative --fallback="$option_confirm_solo" -- "$item")"
;;
Expand Down Expand Up @@ -751,19 +757,23 @@ function choose_() (
fi

# enable if default
if [[ ${#defaults_exact[@]} -ne 0 ]]; then # bash v3 compat
for item in "${defaults_exact[@]}"; do
if [[ $VALUE == "$item" ]]; then
defaults[INDEX]='yes'
fi
done
fi
if [[ ${#defaults_fuzzy[@]} -ne 0 ]]; then # bash v3 compat
for item in "${defaults_fuzzy[@]}"; do
if __string_has_case_insensitive_substring "$VALUE" "$item"; then
defaults[INDEX]='yes'
fi
done
if [[ $option_default_all == 'yes' ]]; then
defaults[INDEX]='yes'
else
if [[ ${#defaults_exact[@]} -ne 0 ]]; then # bash v3 compat
for item in "${defaults_exact[@]}"; do
if [[ $VALUE == "$item" ]]; then
defaults[INDEX]='yes'
fi
done
fi
if [[ ${#defaults_fuzzy[@]} -ne 0 ]]; then # bash v3 compat
for item in "${defaults_fuzzy[@]}"; do
if __string_has_case_insensitive_substring "$VALUE" "$item"; then
defaults[INDEX]='yes'
fi
done
fi
fi

# generate what is used
Expand Down
1 change: 1 addition & 0 deletions commands/command-working
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ function command_working() (
local failures=() exceptions=(
dash
ksh
rmtrash
rpi-update
ssh-askpass
sshd
Expand Down
18 changes: 15 additions & 3 deletions commands/fs-rm
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,24 @@ function fs_rm() (
fi
fi

# handle macos trash support, which is only properly supported with the builtin trash command in macOS 14.0 and up
# adjust options with warnings, and feature detection
local trash_bin
if [[ $option_trash != 'no' ]]; then
if [[ -z $option_trash && $option_delete != 'yes' ]] && __command_missing -- trash; then
if [[ -z $option_trash && $option_delete != 'yes' ]]; then
# no trash/delete preference set, so provide it
setup-util-trash --quiet --optional --no-fallback
fi
if __command_missing -- trash; then
if is-mac; then
if [[ -x '/usr/bin/trash' ]]; then
trash_bin='/usr/bin/trash'
else
trash_bin=''
fi
elif is-linux; then
trash_bin="$(type -P 'trash-put' 2>/dev/null || :)"
fi
if [[ -z $trash_bin ]]; then
if [[ $option_trash == 'yes' ]]; then
echo-style --dim='Moving to trash is not available, falling back to immediate deletion for: ' --code="${option_inputs[*]}" >/dev/stderr
option_trash='no'
Expand Down Expand Up @@ -410,7 +422,7 @@ function fs_rm() (
}
;;
'trash')
__wrap trash "$path" || {
__wrap "$trash_bin" "$path" || {
had_failure='yes'
}
;;
Expand Down
5 changes: 5 additions & 0 deletions commands/setup-environment-commands
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,11 @@ if [[ -n ${HOMEBREW_PREFIX-} && -x "${HOMEBREW_PREFIX-}/bin/brew" ]]; then
PATH="$HOMEBREW_PREFIX/opt/gettext/bin:$PATH"
fi

# trash-cli: don't uncomment this, as trash-cli doesn't support macos, and macos has its own trash bin now
# if [[ -d "$HOMEBREW_PREFIX/opt/trash-cli/bin" ]]; then
# PATH="$HOMEBREW_PREFIX/opt/trash-cli/bin:$PATH"
# fi

# Ruby
if [[ -n ${HOMEBREW_RUBY_VERSION-} ]]; then
p=''
Expand Down
62 changes: 56 additions & 6 deletions commands/setup-util
Original file line number Diff line number Diff line change
Expand Up @@ -659,18 +659,68 @@ function setup_util() (
# prefer moving to trash
# because trash allows invocations to continue
# otherwise active invocations will crash (such as setup-util-bash uninstalling the bash it was invoked with)
if [[ $# -ne 0 ]]; then
fs-rm --quiet --no-confirm --trash --sudo="$option_sudo" -- "$@"
local options=() item
if [[ $# -eq 0 ]]; then
return 0
fi

# check they exist, with support for broken symlinks
for item in "$@"; do
if is-present -- "$item"; then
options+=("$item")
fi
done

# if none of the paths exist, then we don't need to remove anything
if [[ ${#options[@]} -eq 0 ]]; then
return 0
fi

# remove them
fs-rm --quiet --no-confirm --trash --delete --sudo="$option_sudo" -- "${options[@]}"
return
}
function rm_helper_confirm {
local selection=()
local selection=() options=() item _item
if [[ $# -eq 0 ]]; then
return 0
fi

# remove duplicates
for item in "$@"; do
# check they exist, with support for broken symlinks
if is-present -- "$item"; then
continue
fi
if [[ ${#options[@]} -eq 0 ]]; then
options+=("$item")
else
for _item in "${options[@]}"; do
if [[ $item == "$_item" ]]; then
continue
else
options+=("$item")
fi
done
fi
done

# if none of the paths exist, then we don't need to remove anything
if [[ ${#options[@]} -eq 0 ]]; then
return 0
fi

# fetch which files to remove
mapfile -t selection < <(
choose --linger --confirm --multi --question='Which files to remove?' -- "$@"
choose --linger --confirm --multi --default-all --question='Which files to remove?' -- "${options[@]}"
)
if [[ $# -ne 0 ]]; then
rm_helper -- "${selection[@]}"

# ask
if [[ ${#selection[@]} -eq 0 ]]; then
return 0
fi
rm_helper -- "${selection[@]}"
return
}

# prepare fallbacks, for when the package could not be installed without installing a package system first
Expand Down
127 changes: 115 additions & 12 deletions commands/setup-util-trash
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
#!/usr/bin/env bash

# brew/macos version
# https://github.com/ali-rantakari/trash
# only provides [trash] binary
# basic version:
# https://apple.stackexchange.com/a/335164/15131

# apple provides an official tool now: First appeared in macOS 14.0
# https://apple.stackexchange.com/a/476506/15131

# applescript options:
# https://apple.stackexchange.com/a/310084/15131
# https://apple.stackexchange.com/a/421264/15131

# macOS: this one is the best, but it still doesn't support native put back
# https://github.com/russelldavis/trash101

# debian/ubuntu version
# macOS: doesn't support unix conventions for avoiding a common bug: https://github.com/macmade/trash/issues/6
# https://github.com/macmade/trash

# macOS: not maintained
# https://github.com/morgant/tools-osx

# macOS: not maintained
# https://github.com/reklis/recycle

# macOS: not maintained: https://superuser.com/questions/116703/move-file-to-trash-on-snow-leopard-from-terminal#comment882991_116788
# http://www.dribin.org/dave/osx-trash/

# Debian, Ubuntu: no macOS: https://github.com/andreafrancia/trash-cli/issues/323#issuecomment-1848345186
# https://github.com/andreafrancia/trash-cli
# https://packages.debian.org/sid/amd64/trash-cli/filelist
# /usr/bin/trash
Expand All @@ -14,19 +35,101 @@
# /usr/bin/trash-restore
# /usr/bin/trash-rm

# superior but dead: https://github.com/oberblastmeister/trashy/issues/126
# https://github.com/oberblastmeister/trashy
# https://github.com/oberblastmeister/trashy/releases/tag/v2.0.0
# trash-x86_64-pc-windows-msvc.exe
# trash-x86_64-unknown-linux-gnu.tar.gz
# options=(
# --cli='trashy'
# --optional
# --no-fallback
# "$@"
# CARGO='trashy'
# AUR='trashy'
# )
# setup-util "${options[@]}"

# macOS, Windows, Linux: but cannot use macos system trash
# https://github.com/umlx5h/gtrash

# doesn't actually send to the system trash
# https://github.com/nivekuil/rip

# macOS: poorly maintained: https://github.com/sindresorhus/macos-trash/issues
# doesn't support any put back: https://github.com/sindresorhus/macos-trash/issues/1
# https://github.com/sindresorhus/macos-trash
# https://github.com/sindresorhus/macos-trash/releases/latest
# https://github.com/sindresorhus/macos-trash/releases/download/v1.2.0/trash.zip
# options=(
# --cli='trash'
# --optional
# --no-fallback
# "$@"
# BREW='macos-trash'
# # MINT='sindresorhus/macos-trash'
# )
# setup-util "${options[@]}"

# macOS: code seems too simple to support trash properly
# https://github.com/changkun/rmtrash
# GO='changkun.de/x/rmtrash'
# options=(
# --cli='rmtrash'
# --optional
# --no-fallback
# "$@"
# GO='changkun.de/x/rmtrash'
# )
# setup-util "${options[@]}"

# macOS: poorly maintained: https://github.com/ali-rantakari/trash/issues
# https://github.com/ali-rantakari/trash
# https://hasseg.org/trash/
# only provides [trash] binary

# macOS, Windows, Linux: poorly maintained: https://github.com/sindresorhus/trash-cli/issues/24
# https://github.com/sindresorhus/trash-cli
# options=(
# --cli='trash'
# --optional
# --no-fallback
# "$@"
# NPM='trash-cli'
# )
# setup-util "${options[@]}"

# ubuntu also has [gio trash ...]

function setup_util_trash() (
source "$DOROTHY/sources/bash.bash"
local options

# uninstall poorly maintained or conflictual options
if __command_exists -- rmtrash || __command_exists -- trashy || __command_exists -- trash-put; then # __command_exists -- trash
setup-util --quiet --uninstall --optional --cli='rmtrash' GO='changkun.de/x/rmtrash'
setup-util --quiet --uninstall --optional --cli='trashy' CARGO='trashy'
if is-mac; then
setup-util --quiet --uninstall --optional --cli='trash-put' APT='trash-cli' AUR='trash-cli' BREW='trash-cli' DNF='trash-cli' PIP='trash-cli' PIPX='trash-cli'
setup-util --quiet --uninstall --optional --cli='trash' BREW='macos-trash' NPM='trash-cli'
fi
fi

# setup
local options=(
--cli='trash'
"$@"
APT='trash-cli' # UBUNTU
BREW='trash'
)
setup-util "${options[@]}"
if is-linux; then
# https://github.com/andreafrancia/trash-cli
# installs on macos, but only supports linux
options=(
--cli='trash-put'
"$@"
APT='trash-cli'
AUR='trash-cli'
# BREW='trash-cli' <-- has brew, but does not actually support macos
DNF='trash-cli'
PIP='trash-cli'
PIPX='trash-cli'
)
setup-util "${options[@]}"
fi
)

# fire if invoked standalone
Expand Down
3 changes: 3 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
"cascadia",
"ccache",
"certutil",
"changkun",
"charmbracelet",
"chattr",
"chcon",
Expand Down Expand Up @@ -837,6 +838,7 @@
"rmcup",
"rmesg",
"rmsn",
"rmtrash",
"rnano",
"Roadmap",
"rogueamoeba",
Expand Down Expand Up @@ -931,6 +933,7 @@
"SIGXFSZ",
"silenceremove",
"simonarcher",
"sindresorhus",
"skipcrossduplicates",
"skyapps",
"slabtop",
Expand Down

0 comments on commit cca8f9b

Please sign in to comment.