osx: refactor plugin and add a few features (#9026)

Co-authored-by: Capybara <git.capybara@gmail.com>
Co-authored-by: drootang <drootang@users.noreply.github.com>
Co-authored-by: Augusto Souza <augustorsouza@gmail.com>
Co-authored-by: PatrBal <44707588+PatrBal@users.noreply.github.com>
This commit is contained in:
Marc Cornellà 2020-06-17 11:26:39 +02:00 committed by GitHub
parent 3f6e87df15
commit d47447a5e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 359 additions and 207 deletions

View file

@ -22,14 +22,17 @@ Original author: [Sorin Ionescu](https://github.com/sorin-ionescu)
| `pfs` | Return the current Finder selection |
| `cdf` | `cd` to the current Finder directory |
| `pushdf` | `pushd` to the current Finder directory |
| `pxd` | Return the current Xcode project directory |
| `cdx` | `cd` to the current Xcode project directory |
| `quick-look` | Quick-Look a specified file |
| `man-preview` | Open a specified man page in Preview app |
| `showfiles` | Show hidden files |
| `hidefiles` | Hide the hidden files |
| `itunes` | DEPRECATED. Use `music` from macOS Catalina on |
| `showfiles` | Show hidden files in Finder |
| `hidefiles` | Hide the hidden files in Finder |
| `itunes` | _DEPRECATED_. Use `music` from macOS Catalina on |
| `music` | Control Apple Music. Use `music -h` for usage details |
| `spotify` | Control Spotify and search by artist, album, track… |
| `rmdsstore` | Remove .DS\_Store files recursively in a directory |
| `btrestart` | Restart the Bluetooth daemon |
## Acknowledgements

90
plugins/osx/_security Normal file
View file

@ -0,0 +1,90 @@
#compdef security
local -a _1st_arguments
_1st_arguments=(
'help:Show all commands, or show usage for a command'
'list-keychains:Display or manipulate the keychain search list'
'default-keychain:Display or set the default keychain'
'login-keychain:Display or set the login keychain'
'create-keychain:Create keychains and add them to the search list'
'delete-keychain:Delete keychains and remove them from the search list'
'lock-keychain:Lock the specified keychain'
'lock-keychain:Unlock the specified keychain'
'set-keychain-settings:Set settings for a keychain'
'set-keychain-password:Set password for a keychain'
'show-keychain-info:Show the settings for keychain'
'dump-keychain:Dump the contents of one or more keychains'
'create-keypair:Create an asymmetric key pair'
'add-generic-password:Add a generic password item'
'add-internet-password:Add an internet password item'
'add-certificates:Add certificates to a keychain'
'find-generic-password:Find a generic password item'
'delete-generic-password:Delete a generic password item'
'find-internet-password:Find an internet password item'
'delete-internet-password:Delete an internet password item'
'find-certificate:Find a certificate item'
'find-identity:Find an identity certificate + private key'
'delete-certificate:Delete a certificate from a keychain'
'set-identity-preference:Set the preferred identity to use for a service'
'get-identity-preference:Get the preferred identity to use for a service'
'create-db:Create a db using the DL'
'export:Export items from a keychain'
'import:Import items into a keychain'
'cms:Encode or decode CMS messages'
'install-mds:MDS database'
'add-trusted-cert:Add trusted certificates:'
'remove-trusted-cert:Remove trusted certificates:'
'dump-trust-settings:Display contents of trust settings'
'user-trust-settings-enable:Display or manipulate user-level trust settings'
'trust-settings-export:Export trust settings'
'trust-settings-import:Import trust settings'
'verify-cert:Verify certificates:'
'authorize:Perform authorization operations'
'authorizationdb:Make changes to the authorization policy database'
'execute-with-privileges:Execute tool with privileges'
'leaks:Run /usr/bin/leaks on this process'
'error:Display a descriptive message for the given error codes:'
'create-filevaultmaster-keychain:"Create a keychain containing a key pair for FileVault recovery use'
)
_arguments '*:: :->command'
if (( CURRENT == 1 )); then
_describe -t commands "security command" _1st_arguments
return
fi
case "$words[1]" in
find-(generic|internet)-password)
_values \
'Usage: find-[internet/generic]-password [-a account] [-s server] [options...] [-g] [keychain...]' \
'-a[Match "account" string]' \
'-c[Match "creator" (four-character code)]' \
'-C[Match "type" (four-character code)]' \
'-D[Match "kind" string]' \
'-G[Match "value" string (generic attribute)]' \
'-j[Match "comment" string]' \
'-l[Match "label" string]' \
'-s[Match "service" string]' \
'-g[Display the password for the item found]' \
'-w[Display only the password on stdout]' ;;
add-(generic|internet)-password)
_values \
'Usage: add-[internet/generic]-password [-a account] [-s server] [-w password] [options...] [-A|-T appPath] [keychain]]' \
'-a[Specify account name (required)]' \
'-c[Specify item creator (optional four-character code)]' \
'-C[Specify item type (optional four-character code)]' \
'-d[Specify security domain string (optional)]' \
'-D[Specify kind (default is "Internet password")]' \
'-j[Specify comment string (optional)]' \
'-l[Specify label (if omitted, server name is used as default label)]' \
'-p[Specify path string (optional)]' \
'-P[Specify port number (optional)]' \
'-r[Specify protocol (optional four-character SecProtocolType, e.g. "http", "ftp ")]' \
'-s[Specify server name (required)]' \
'-t[Specify authentication type (as a four-character SecAuthenticationType, default is "dflt")]' \
'-w[Specify password to be added]' \
'-A[Allow any application to access this item without warning (insecure, not recommended!)]' \
'-T[Specify an application which may access this item (multiple -T options are allowed)]' \
'-U[Update item if it already exists (if omitted, the item cannot already exist) ]' \
'utils)]' ;;
esac

170
plugins/osx/music Normal file
View file

@ -0,0 +1,170 @@
#!/usr/bin/env zsh
function music itunes() {
local APP_NAME=Music sw_vers=$(sw_vers -productVersion 2>/dev/null)
autoload is-at-least
if [[ -z "$sw_vers" ]] || is-at-least 10.15 $sw_vers; then
if [[ $0 = itunes ]]; then
echo >&2 The itunes function name is deprecated. Use \'music\' instead.
return 1
fi
else
APP_NAME=iTunes
fi
local opt=$1 playlist=$2
(( $# > 0 )) && shift
case "$opt" in
launch|play|pause|stop|rewind|resume|quit)
;;
mute)
opt="set mute to true"
;;
unmute)
opt="set mute to false"
;;
next|previous)
opt="$opt track"
;;
vol)
local new_volume volume=$(osascript -e "tell application \"$APP_NAME\" to get sound volume")
if [[ $# -eq 0 ]]; then
echo "Current volume is ${volume}."
return 0
fi
case $1 in
up) new_volume=$((volume + 10 < 100 ? volume + 10 : 100)) ;;
down) new_volume=$((volume - 10 > 0 ? volume - 10 : 0)) ;;
<0-100>) new_volume=$1 ;;
*) echo "'$1' is not valid. Expected <0-100>, up or down."
return 1 ;;
esac
opt="set sound volume to ${new_volume}"
;;
playlist)
# Inspired by: https://gist.github.com/nakajijapan/ac8b45371064ae98ea7f
if [[ -n "$playlist" ]]; then
osascript 2>/dev/null <<EOF
tell application "$APP_NAME"
set new_playlist to "$playlist" as string
play playlist new_playlist
end tell
EOF
if [[ $? -eq 0 ]]; then
opt="play"
else
opt="stop"
fi
else
opt="set allPlaylists to (get name of every playlist)"
fi
;;
playing|status)
local currenttrack currentartist state=$(osascript -e "tell application \"$APP_NAME\" to player state as string")
if [[ "$state" = "playing" ]]; then
currenttrack=$(osascript -e "tell application \"$APP_NAME\" to name of current track as string")
currentartist=$(osascript -e "tell application \"$APP_NAME\" to artist of current track as string")
echo -E "Listening to ${fg[yellow]}${currenttrack}${reset_color} by ${fg[yellow]}${currentartist}${reset_color}"
else
echo "$APP_NAME is $state"
fi
return 0
;;
shuf|shuff|shuffle)
# The shuffle property of current playlist can't be changed in iTunes 12,
# so this workaround uses AppleScript to simulate user input instead.
# Defaults to toggling when no options are given.
# The toggle option depends on the shuffle button being visible in the Now playing area.
# On and off use the menu bar items.
local state=$1
if [[ -n "$state" && "$state" != (on|off|toggle) ]]; then
print "Usage: $0 shuffle [on|off|toggle]. Invalid option."
return 1
fi
case "$state" in
on|off)
# Inspired by: https://stackoverflow.com/a/14675583
osascript >/dev/null 2>&1 <<EOF
tell application "System Events" to perform action "AXPress" of (menu item "${state}" of menu "Shuffle" of menu item "Shuffle" of menu "Controls" of menu bar item "Controls" of menu bar 1 of application process "iTunes" )
EOF
return 0
;;
toggle|*)
osascript >/dev/null 2>&1 <<EOF
tell application "System Events" to perform action "AXPress" of (button 2 of process "iTunes"'s window "iTunes"'s scroll area 1)
EOF
return 0
;;
esac
;;
""|-h|--help)
echo "Usage: $0 <option>"
echo "option:"
echo "\t-h|--help\tShow this message and exit"
echo "\tlaunch|play|pause|stop|rewind|resume|quit"
echo "\tmute|unmute\tMute or unmute $APP_NAME"
echo "\tnext|previous\tPlay next or previous track"
echo "\tshuf|shuffle [on|off|toggle]\tSet shuffled playback. Default: toggle. Note: toggle doesn't support the MiniPlayer."
echo "\tvol [0-100|up|down]\tGet or set the volume. 0 to 100 sets the volume. 'up' / 'down' increases / decreases by 10 points. No argument displays current volume."
echo "\tplaying|status\tShow what song is currently playing in Music."
echo "\tplaylist [playlist name]\t Play specific playlist"
return 0
;;
*)
print "Unknown option: $opt"
return 1
;;
esac
osascript -e "tell application \"$APP_NAME\" to $opt"
}
function _music() {
local app_name
case "$words[1]" in
itunes) app_name="iTunes" ;;
music|*) app_name="Music" ;;
esac
local -a cmds subcmds
cmds=(
"launch:Launch the ${app_name} app"
"play:Play ${app_name}"
"pause:Pause ${app_name}"
"stop:Stop ${app_name}"
"rewind:Rewind ${app_name}"
"resume:Resume ${app_name}"
"quit:Quit ${app_name}"
"mute:Mute the ${app_name} app"
"unmute:Unmute the ${app_name} app"
"next:Skip to the next song"
"previous:Skip to the previous song"
"vol:Change the volume"
"playlist:Play a specific playlist"
{playing,status}":Show what song is currently playing"
{shuf,shuff,shuffle}":Set shuffle mode"
{-h,--help}":Show usage"
)
if (( CURRENT == 2 )); then
_describe 'command' cmds
elif (( CURRENT == 3 )); then
case "$words[2]" in
vol) subcmds=( 'up:Raise the volume' 'down:Lower the volume' )
_describe 'command' subcmds ;;
shuf|shuff|shuffle) subcmds=('on:Switch on shuffle mode' 'off:Switch off shuffle mode' 'toggle:Toggle shuffle mode (default)')
_describe 'command' subcmds ;;
esac
elif (( CURRENT == 4 )); then
case "$words[2]" in
playlist) subcmds=('play:Play the playlist (default)' 'stop:Stop the playlist')
_describe 'command' subcmds ;;
esac
fi
return 0
}
compdef _music music itunes

View file

@ -1,15 +1,22 @@
# Open the current directory in a Finder window
alias ofd='open_command $PWD'
# Show/hide hidden files in the Finder
alias showfiles="defaults write com.apple.finder AppleShowAllFiles -bool true && killall Finder"
alias hidefiles="defaults write com.apple.finder AppleShowAllFiles -bool false && killall Finder"
# Bluetooth restart
function btrestart() {
sudo kextunload -b com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
sudo kextload -b com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
}
function _omz_osx_get_frontmost_app() {
local the_app=$(
osascript 2>/dev/null <<EOF
tell application "System Events"
name of first item of (every process whose frontmost is true)
end tell
osascript 2>/dev/null <<EOF
tell application "System Events"
name of first item of (every process whose frontmost is true)
end tell
EOF
)
echo "$the_app"
}
function tab() {
@ -27,7 +34,6 @@ function tab() {
end tell
tell application "Terminal" to do script "${command}" in front window
EOF
elif [[ "$the_app" == 'iTerm' ]]; then
osascript <<EOF
tell application "iTerm"
@ -41,32 +47,29 @@ EOF
end tell
end tell
EOF
elif [[ "$the_app" == 'iTerm2' ]]; then
osascript <<EOF
tell application "iTerm2"
tell current window
create tab with default profile
tell current session to write text "${command}"
end tell
osascript <<EOF
tell application "iTerm2"
tell current window
create tab with default profile
tell current session to write text "${command}"
end tell
end tell
EOF
elif [[ "$the_app" == 'Hyper' ]]; then
osascript >/dev/null <<EOF
tell application "System Events"
tell process "Hyper" to keystroke "t" using command down
end tell
delay 1
tell application "System Events"
keystroke "${command}"
key code 36 #(presses enter)
end tell
tell application "System Events"
tell process "Hyper" to keystroke "t" using command down
end tell
delay 1
tell application "System Events"
keystroke "${command}"
key code 36 #(presses enter)
end tell
EOF
else
echo "tab: unsupported terminal app: $the_app"
false
echo "$0: unsupported terminal app: $the_app" >&2
return 1
fi
}
@ -79,7 +82,6 @@ function vsplit_tab() {
if [[ "$the_app" == 'iTerm' ]]; then
osascript <<EOF
-- tell application "iTerm" to activate
tell application "System Events"
tell process "iTerm"
tell menu item "Split Vertically With Current Profile" of menu "Shell" of menu bar item "Shell" of menu bar 1
@ -89,37 +91,33 @@ function vsplit_tab() {
keystroke "${command} \n"
end tell
EOF
elif [[ "$the_app" == 'iTerm2' ]]; then
osascript <<EOF
tell application "iTerm2"
tell current session of first window
set newSession to (split vertically with same profile)
tell newSession
write text "${command}"
select
end tell
osascript <<EOF
tell application "iTerm2"
tell current session of first window
set newSession to (split vertically with same profile)
tell newSession
write text "${command}"
select
end tell
end tell
EOF
elif [[ "$the_app" == 'Hyper' ]]; then
osascript >/dev/null <<EOF
tell application "System Events"
tell process "Hyper"
tell menu item "Split Vertically" of menu "Shell" of menu bar 1
click
end tell
end tell
delay 1
keystroke "${command} \n"
end tell
EOF
elif [[ "$the_app" == 'Hyper' ]]; then
osascript >/dev/null <<EOF
tell application "System Events"
tell process "Hyper"
tell menu item "Split Vertically" of menu "Shell" of menu bar 1
click
end tell
end tell
delay 1
keystroke "${command} \n"
end tell
EOF
else
echo "$0: unsupported terminal app: $the_app" >&2
false
return 1
fi
}
@ -142,44 +140,40 @@ function split_tab() {
keystroke "${command} \n"
end tell
EOF
elif [[ "$the_app" == 'iTerm2' ]]; then
osascript <<EOF
tell application "iTerm2"
tell current session of first window
set newSession to (split horizontally with same profile)
tell newSession
write text "${command}"
select
end tell
osascript <<EOF
tell application "iTerm2"
tell current session of first window
set newSession to (split horizontally with same profile)
tell newSession
write text "${command}"
select
end tell
end tell
EOF
elif [[ "$the_app" == 'Hyper' ]]; then
osascript >/dev/null <<EOF
tell application "System Events"
tell process "Hyper"
tell menu item "Split Horizontally" of menu "Shell" of menu bar 1
click
end tell
end tell
delay 1
keystroke "${command} \n"
end tell
EOF
elif [[ "$the_app" == 'Hyper' ]]; then
osascript >/dev/null <<EOF
tell application "System Events"
tell process "Hyper"
tell menu item "Split Horizontally" of menu "Shell" of menu bar 1
click
end tell
end tell
delay 1
keystroke "${command} \n"
end tell
EOF
else
echo "$0: unsupported terminal app: $the_app" >&2
false
return 1
fi
}
function pfd() {
osascript 2>/dev/null <<EOF
tell application "Finder"
return POSIX path of (target of window 1 as alias)
return POSIX path of (insertion location as alias)
end tell
EOF
}
@ -205,6 +199,21 @@ function pushdf() {
pushd "$(pfd)"
}
function pxd() {
dirname $(osascript 2>/dev/null <<EOF
if application "Xcode" is running then
tell application "Xcode"
return path of active workspace document
end tell
end if
EOF
)
}
function cdx() {
cd "$(pxd)"
}
function quick-look() {
(( $# > 0 )) && qlmanage -p $* &>/dev/null &
}
@ -218,133 +227,13 @@ function vncviewer() {
open vnc://$@
}
# iTunes control function
function itunes music() {
local APP_NAME=Music
autoload is-at-least
if is-at-least 10.15 $(sw_vers -productVersion); then
if [[ $0 = itunes ]]; then
echo >&2 The itunes function name is deprecated. Use \`music\' instead.
return 1
fi
else
APP_NAME=iTunes
fi
local opt=$1
local playlist=$2
shift
case "$opt" in
launch|play|pause|stop|rewind|resume|quit)
;;
mute)
opt="set mute to true"
;;
unmute)
opt="set mute to false"
;;
next|previous)
opt="$opt track"
;;
vol)
local new_volume volume=$(osascript -e "tell application \"$APP_NAME\" to get sound volume")
if [[ $# -eq 0 ]]; then
echo "Current volume is ${volume}."
return 0
fi
case $1 in
up) new_volume=$((volume + 10 < 100 ? volume + 10 : 100)) ;;
down) new_volume=$((volume - 10 > 0 ? volume - 10 : 0)) ;;
<0-100>) new_volume=$1 ;;
*) echo "'$1' is not valid. Expected <0-100>, up or down."
return 1 ;;
esac
opt="set sound volume to ${new_volume}"
;;
playlist)
# Inspired by: https://gist.github.com/nakajijapan/ac8b45371064ae98ea7f
if [[ ! -z "$playlist" ]]; then
osascript -e "tell application \"$APP_NAME\"" -e "set new_playlist to \"$playlist\" as string" -e "play playlist new_playlist" -e "end tell" 2>/dev/null;
if [[ $? -eq 0 ]]; then
opt="play"
else
opt="stop"
fi
else
opt="set allPlaylists to (get name of every playlist)"
fi
;;
playing|status)
local state=`osascript -e "tell application \"$APP_NAME\" to player state as string"`
if [[ "$state" = "playing" ]]; then
currenttrack=`osascript -e "tell application \"$APP_NAME\" to name of current track as string"`
currentartist=`osascript -e "tell application \"$APP_NAME\" to artist of current track as string"`
echo -E "Listening to $fg[yellow]$currenttrack$reset_color by $fg[yellow]$currentartist$reset_color";
else
echo "$APP_NAME is" $state;
fi
return 0
;;
shuf|shuff|shuffle)
# The shuffle property of current playlist can't be changed in iTunes 12,
# so this workaround uses AppleScript to simulate user input instead.
# Defaults to toggling when no options are given.
# The toggle option depends on the shuffle button being visible in the Now playing area.
# On and off use the menu bar items.
local state=$1
if [[ -n "$state" && ! "$state" =~ "^(on|off|toggle)$" ]]
then
print "Usage: $0 shuffle [on|off|toggle]. Invalid option."
return 1
fi
case "$state" in
on|off)
# Inspired by: https://stackoverflow.com/a/14675583
osascript 1>/dev/null 2>&1 <<-EOF
tell application "System Events" to perform action "AXPress" of (menu item "${state}" of menu "Shuffle" of menu item "Shuffle" of menu "Controls" of menu bar item "Controls" of menu bar 1 of application process "iTunes" )
EOF
return 0
;;
toggle|*)
osascript 1>/dev/null 2>&1 <<-EOF
tell application "System Events" to perform action "AXPress" of (button 2 of process "iTunes"'s window "iTunes"'s scroll area 1)
EOF
return 0
;;
esac
;;
""|-h|--help)
echo "Usage: $0 <option>"
echo "option:"
echo "\tlaunch|play|pause|stop|rewind|resume|quit"
echo "\tmute|unmute\tcontrol volume set"
echo "\tnext|previous\tplay next or previous track"
echo "\tshuf|shuffle [on|off|toggle]\tSet shuffled playback. Default: toggle. Note: toggle doesn't support the MiniPlayer."
echo "\tvol [0-100|up|down]\tGet or set the volume. 0 to 100 sets the volume. 'up' / 'down' increases / decreases by 10 points. No argument displays current volume."
echo "\tplaying|status\tShow what song is currently playing in Music."
echo "\tplaylist [playlist name]\t Play specific playlist"
echo "\thelp\tshow this message and exit"
return 0
;;
*)
print "Unknown option: $opt"
return 1
;;
esac
osascript -e "tell application \"$APP_NAME\" to $opt"
}
# Spotify control function
source ${ZSH}/plugins/osx/spotify
# Show/hide hidden files in the Finder
alias showfiles="defaults write com.apple.finder AppleShowAllFiles -bool true && killall Finder"
alias hidefiles="defaults write com.apple.finder AppleShowAllFiles -bool false && killall Finder"
# Remove .DS_Store files recursively in a directory, default .
function rmdsstore() {
find "${@:-.}" -type f -name .DS_Store -delete
find "${@:-.}" -type f -name .DS_Store -delete
}
# Music / iTunes control function
source "${0:h:A}/music"
# Spotify control function
source "${0:h:A}/spotify"