Issues with "On Open" Applescript handler in Yosemite - applescript

In using Applescript in OSX 10.10 (Yosemite), it seems Apple has changed some of the default behavior.
on open dropped_files
display dialog (count of dropped_files)
end open
This very basic Applescript highlights the problem. If I select a group of 6 files from the Finder, and drop/drop onto a compiled version of this script, I get the response "2" and then the response "4". It should be responding "6"... but it's almost as if Finder is parsing the files into smaller groups. If I do this again, I get a different combination of numbers, so it does not seem to be consistent.
This is not the desired behavior for my application, any ideas for a solution? I never saw this behavior with older versions of Applescript.

This bizarre effect is due to quarantined files. Quarantined files can be checked with the command:
xattr -p com.apple.quarantine *
Depending on the sort order of the quarantined/non-quarantined files, it will separately execute the "on open" handler for each group (be it quarantined or non-quarantined): e.g., 1 - quarantined, 4 - non-quarantined, 3 - quarantined. You'll notice there are two groups of quarantined files being submitted in this example, and that's because of how that particular list was sorted and submitted to the on open handler.
This behavior is rather surprising, and I've submitted it as a bug report to Apple. The quarantine attribute can be removed with this command:
sudo xattr -dr com.apple.quarantine *
to show the correct number of files. Also, see the Applescript trick above by regulus6633 for a clever workaround.

Wow, that's strange. This workaround seems to work. We can take advantage of properties and the "on quit" handler which is automatically run after the "on open" handler. So just run your normal code in the "on quit" handler using dFiles. Remember to set dFiles to {} at the very end else dFiles will not work properly the next time you drop files.
property dFiles : {}
on open dropped_files
set dFiles to dFiles & dropped_files
end open
on quit
display dialog (count of dFiles)
set dFiles to {}
continue quit
end quit

Related

How do I make NeoVim my default text/code editor?

Is there a way to make NeoVim as default text/code editor (without any bad side effects) ?Trust me, I looked to lots of StackOverflow question/answers and tried a few things but nothing worked for me.
Note: I'm on macOS Big Sur (version 11.2.1). What I want is when I click on files to open in NeoVim.
--> For example, in ~/.zshrc (and added to ~/.bash_profile also just in case) I have:
Note: zsh is my default shell
alias nvim=$HOME/nvim-osx64/bin/nvim
export EDITOR="nvim"
export VISUAL="nvim"
When I do set in Terminal it shows:
EDITOR=nvim
VISUAL=nvim
And yes, I quit and started the terminal (I'm using iTerm2). I even reboot.
--> I will place my $PATH here just in case it has anything to do it that. When I do echo $PATH it shows:
--> And, just in case someone suggests:
I can't Select a File > Open With... and select NeoVim as default text editor, since that option doesn't show and I can't do Choose Other since I can't select NeoVim in that way.
If anyone needs more information, please say and I will edit the question with that info. Thanks!
Setting variables in the terminal will not affect the GUI file associations. To do that you have to change the OS's file associations.
Though it appears to be a small project and unsupported, I've had a good experience using duti. It's a wrapper around the Apple file extension API. The configuration did take me a minute to figure out. I'll post it if I can find it.
After a while I found the answer to my own question, here it is how you can set NeoVim in Mac as the default text editor. Now, you will be able click on files and opening them in NeoVim:
Some people recommended me to have a look at the follow links:
https://gist.github.com/Huluk/5117702
https://superuser.com/questions/139352/mac-os-x-how-to-open-vim-in-terminal-when-double-click-on-a-file
That didn't work for me but it served as a reference to look up related topics (automator + neovim).
After a while, I discover this blog:
https://blog.schembri.me/post/neovim-everywhere-on-macos/
Go and have a look at the blog, but here it is how you do it:
Launch Automator (Finder -> Applications -> Automator)
New Document -> Choose a type for your document: Application
In Actions search for Run AppleScript and drag that to where it says something like "Drag actions here..."
Delete the default example of AppleScript
Copy and Paste the code in the blog (where it says NeoVim.app) to where it previous had the default code
Save the new Automator app (save as aplicattion format). Save it in the Applications folder
Right-Click a file type you wish to open every time you click on them (e.g. .php file). Select Get Info or do cmd + i, it will open informations about that file. Scroll to wher it says Open With and select Other. Then just go to Aplicattions folder and select your new NeoVim "app".
Do the same to other file types if you wish.
You can now double click on your PHP files (or others if you did the same) and open them in NeoVim. Enjoy!
Note: You really need to do Right-Click, Get Info and look for Open With to change in all files with that extension. If you skip Get Info and just Right-Click + Open With, it will only work for that specific file...
This is the code from the blog:
on run {input, parameters}
set cmd to "nvim"
if input is not {} then
set filePath to POSIX path of input
set cmd to "nvim \"" & filePath & "\""
end if
tell application "iTerm"
create window with default profile
tell the current window
tell the current session to write text cmd
end tell
end tell
end run
This would open a new window even if you already had one open.
I change it so that it would open in a tab:
on run {input, parameters}
set cmd to "nvim"
if input is not {} then
set filePath to POSIX path of input
set cmd to "nvim \"" & filePath & "\""
end if
tell application "iTerm"
tell the current window
create tab with default profile
tell the current session to write text cmd
end tell
end tell
end run
Note: I'm using iTerm2. If you are using another Terminal Emulator, change where it says iTerm to the name of your terminal...
For anyone using Kitty on MacOS, I found a pretty simple way to accomplish this using the remote control feature.
First you need the following set in your kitty.conf:
allow_remote_control yes
listen_on unix:/tmp/mykitty
Using Automator like in #DGF's answer, I created an Application with the "Run Shell Script" action, and this is the script:
if [ -z "$(pgrep kitty)" ]
then
open /Applications/kitty.app
sleep 3 # allow ample time to startup and start listening
fi
/usr/local/bin/kitty # --to=unix:/tmp/mykitty-$(pgrep kitty) launch --type=os-window nvim "$#"
Save that as an application somewhere, and select it from "Open with"!
Note: to be honest, the logic to handle starting up kitty if it's not already running is a little flaky. But it seems to work great when kitty is already running, which of course it is most of the time for me. Also, it doesn't work at all if kitty is running but has no windows. :\
Choose nvim as the default application by means of a txt file sub-menu like here with Preview for PDFs:

Path to me returning incorrect value on unzipped AppleScript application

So here's a peculiar situation. I created an AppleScript application that relies on the path to me command. After saving as AppleScript Application it runs perfectly. However, if you archive/zip the file, then unzip and run again after downloading/emailing or on another computer, the path to me is incorrect.
For example, I created a super simple app to test this:
set myPath to (path to me as text)
display dialog "myPath: " & myPath
Save the application and run it from the Finder by double clicking it.
Mine reports correctly: myPath: Sierra:Users:joshbooth:Desktop:Test.app:
Zip/Unzip the file on my other laptop and run again.
The result is myPath: 429EF755-2646-4249-A428-666D454E9DAD:d:Test.app:
Option + click and drag to create a new copy in the same directory then run again:
result: myPath: Macintosh HD:Users:joshbooth:Downloads:Test 2.app:
Any ideas what is happening or how to prevent it?
I've no real "answer", but my info is too big for comments (and no one else has chimed in)...
While there may be other cases, at least one cause is a downloaded zip being marked "quarantined" which results in OS X expanding it into a temp "/private/var/folders" location (with the complex folder name you see, as well as the expanded item being quarantined and actually on a read only file system).
So, it is the "download" biting us, which we can see in the "com.apple.quarantine" attribute of the app, and zip, in a terminal window with "xattr -l /Users/johndoe/Downloads/Test.app" (like "com.apple.quarantine: 0083;5f20ce0e;Safari;BFABF751-2ACD-4B6F-9952-9A87D45AC9D4"), and remove it with "xattr -d com.apple.quarantine /Users/johndoe/Downloads/test.app".
Getting (POSIX path of (path to me as string)) within the expanded app would have shown something like /private/var/folders/lh/9hl01d1n2knckzj0bxdb22lr0000gn/T/AppTranslocation/429EF755-2646-4249-A428-666D454E9DAD/d/Test.app before removing the quarantine flag.
Unfortunately, given the temp path is locked, the app itself can't remove the flag with "xattr -d com.apple.quarantine /private/var/folders...", getting "xattr: [Errno 30] Read-only file system", so idea what we can do with this info, but these are my findings.
One good note: moving or copying the expanded app to another folder leaves the quarantine flag set, but updates the "path to me" resolution, which is a bit inconsistent, and confusing, by OS X in my opinion (debatably defeating this quarantine flag pattern if it was intentional), but a useful workaround.

How to get clang format for Xcode 8?

After Xcode update to version 8. The very useful Alcatraz PlugIn Manager is locked out and superb utilities like clang-format, or highlight selected word occurrences, or resize the font by use of a shortcut are gone.
How can I reenable clang-format to format my current source code file on save with a template .clang-format in any parent directory of the source file?
You could create a shell script that is added to Xcode 8 as a behavior: Xcode > Behaviors > +(to create new one) > Run script: (select file here), add shortcut like Cmd+Shift+S.
The script asks Xcode to save the current document. Then it extracts its filepath and calls clang-format to format that file in-place. Clang-format has to be available e.g. by using brew as the package manager to download it and having its path published for command line access. As usual the style guide used by clang-format must have the name .clang-format and must be in any parent folder of the source file.
Here is the script:
#!/bin/bash
CDP=$(osascript -e '
tell application "Xcode"
activate
tell application "System Events" to keystroke "s" using {command down}
--wait for Xcode to remove edited flag from filename
delay 0.3
set last_word_in_main_window to (word -1 of (get name of window 1))
set current_document to document 1 whose name ends with last_word_in_main_window
set current_document_path to path of current_document
--CDP is assigned last set value: current_document_path
end tell ')
LOGPATH=$(dirname "$0")
LOGNAME=formatWithClangLog.txt
echo "Filepath: ${CDP}" > ${LOGPATH}/${LOGNAME}
sleep 0.6 ### during save Xcode stops listening for file changes
/usr/local/bin/clang-format -style=file -i -sort-includes ${CDP} >> ${LOGPATH}/${LOGNAME} 2>&1
# EOF
Please exchange the path /usr/local/bin to the one where your clang-format executable resides.
Happy coding!
The mapbox/XcodeClangFormat extension looks like a promising way to get clang format working with Xcode8.
Due to the limitations of source editor extensions, unfortunately you can only specify one .clang-format file for all your projects. "Format on save" also is not available.
Found a viable solution in this blog - code-beautifier-in-xcode
Basically, we can have clang-format running as a service by automator and invoke it through Xcode whenever we need to format the code. Refer the blog for more details.
Unfortunately your little script often does not update the formatted file in Xcode because it stops listening to file updates when saving. Increasing the sleep durations in the script does not make it more reliable and introduces a lot of waiting time for the common file-save & file-format action.
What I did in your situation was to get my mac backup and restore macOS and Xcode to the last version where all the productivity plugins from Alcatraz work fine again. This boosted my productivity.
It looks like Alcatraz plug-ins get be back to work in Xcode 8+ when unsigning them. Because I am not in the situation to try that, I can only point you to that resource:
Examine the header Installation on that github page ClangFormat-Xcode.

Mute Macbook pro when computer is shutting down

I'm thinking of using the Mac's applescript to make a program that mutes the system when it is shutting down.
Though I'm new to applescript and I don't know how to use the IF-statement to determine if the system is shutting down. I've done some googling and I've found that the finder app is the app that is "controlling" the shutdown, but i don't know how to check if the state is "shut down". Can anybody assist me in this matter?
AppleScript has no direct mechanism for detecting a shutdown/logout.
It does have a mechanism for creating applications that can react to themselves being quit.
Thus, you can:
use AppleScript to create a stay-open application (.app bundle) with a standard on quit handler, in which you perform the desired action (
make sure that the application is launched on login - in the simpler case as a Login Item (via System Preferences, see below), or, with more flexibility but complexity, as a launch agent (see https://stackoverflow.com/a/22872222/45375).
Instructions:
Open Script Editor and open a new script window.
Paste the following code:
# This standard handler is called when the application quits.
on quit
# Mute the system volume.
# !! See caveat below.
set volume with output muted
continue quit # signal to the system that it's OK to quit
end quit
Save the script as a stay-open application:
with File Format Application
check Stay open after run handler
Open System Preferences > Users & Groups > Login Items, drag the newly saved *.app bundle into the list, and check the checkbox next to it, so as to make it launch hidden.
The final step is to hide the new application's Dock icon, as there's no reason for it to have one:
From Terminal, run the following:
defaults write /full/path/to/newApp.app/Contents/Info.plist LSUIElement 1
Note: You could use LSBackgroundOnly too, but the advantage of LSUIElement is that you can still display UI elements if you want to, such as for debugging.
Important: Substitute the full path of your new app for /full/path/to/newApp.app; the command will only work if you specify the full path to the Info.plist file.
To test, start the new app interactively, and make sure that no Dock icon appears. (You can quit the app via Activity Monitor).
CAVEAT: If the intent is to suppress the system startup sound, set volume with output muted has two drawbacks:
it will not work if headphones happened to be plugged at the time of shutdown
you will have to unmute the volume on startup (however, you could do that in an on on run handler in the same app).
Consider the alternative approach below, which requires admin privileges to set up and invokes nvram SystemAudioVolume=%80 with root privileges, which bypasses the above drawbacks.
You could run do shell script "nvram SystemAudioVolume=%80" user name "someAdminUsername" password "matchingAdminPassword" with administrator privileges from the above AppleScript app, but you'd have to hard-code the password, which is not advisable for security reasons.
Alternative approach, using a system-wide logout hook via com.apple.loginwindow.
There's a deprecated mechanism for running a script on logout that, however, still works as of OSX 10.10; given that there's no direct non-deprecated equivalent, it may continue to be supported.
Note that you do need admin privileges:
sudo defaults write com.apple.loginwindow LogoutHook <yourScript>
<yourScript> must be an executable, such as a shell script; note that the executable is run in the context of the root user.
In case you're thinking of muting the startup sound, invoke the following shell command from that script:
nvram SystemAudioVolume=%80 # to try this interactively, prepend `sudo `
This will mute sounds until after a reboot, effectively muting the startup sound, without keeping the sound muted.
Note that the nvram command requires root privileges, which are by definition in effect in a script run via the com.apple.loginwindow logout hook.; by contrast, to try the command interactively, use sudo nvram SystemAudioVolume=%80 - otherwise, you'll get the following, unhelpful error message: nvram: Error setting variable - 'SystemAudioVolume': (iokit/common) general error
Honestly, it is better to make a deterministic solution. What I mean is, is that you make a script that:
Mutes your computer.
Shuts it down.
Then you take your script and create an Automator service, that you can assign to some shortcut, to make it easier for you to use it. ctrl-opt-cmd-eject or something. :)
This is just how I would have solved it, if I have the need, it is short and sweet to make work, and should work reasonably well.
If you want to use the LogoutHook mentioned in #mklement0's answer.
You can use the normal Applescript command set volume with output muted.
You just need to add the osascript shebang to the top of the Applescript document
i.e
#!/usr/bin/osascript
set volume with output muted
And then save the file as applescript text file.
In the save dialogue use : file format: Text )
It will get the extension .applescript
Once it is saved, use Terminal.app to chmod the script as you would a normal shell script which in effect it is.
i.e
/bin/chmod +x foo.applescript
Then add it to the loginwindows LogoutHook.
sudo defaults write com.apple.loginwindow LogoutHook foo.applescript
I Know this is an old post but for anyone still looking how to do this(like I was) I have a simple method.
Before I started Scripting I created a new folder in my home folder called toolbar scripts.(this is optional)
With the desktop showing Finder click on Go >Utilities >Script Editor.
In the window that opens type in or copy and paste the code
set volume with output muted
tell application "finder"
shut down
end tell
Click on the last button above the script you added - it should be compile. If you cannot find that button then on the top click on Script >Compile
Click on File >Save in the save as I called mine shutdown and chose the script folder (this is optional)
Down the bottom of the dialog box at file format click on the arrow and change the format to application and click on save.
Open the folder you saved it in and drag the icon to the dock. Click on the icon you just put in the dock.
now if all is right this should mute the volume and shutdown the computer.
This will not shutdown the computer if you still have anything open.
Cheers
Peter
first, you should create a sound-off script (with terminal)
sudo nano /Library/Scripts/sound-off.sh
after filling it with these lines:
#!/bin/bash
osascript -e ‘set volume output muted 1’
and make a sound-on script like that
sudo nano /Library/Scripts/sound-on.sh
and fill it with:
#!/bin/bash
osascript -e ‘set volume 4’
then access them as executing files
sudo chmod u+x /Library/Scripts/sound-off.sh
sudo chmod u+x /Library/Scripts/sound-on.sh
and the last part is set them when the mac device is turn off and on:
sudo defaults write com.apple.loginwindow LogoutHook /Library/Scripts/sound-off.sh
sudo defaults write com.apple.loginwindow LoginHook /Library/Scripts/sound-on.sh

Applescript application hangs on 10.9 when executing a shell command with administrator privileges

I'm executing the following line in an Applescript application.
set POSIX_path to "/Applications/iPhoto.app"
do shell script "sudo rm -rfv " & quoted form of POSIX_path with administrator privileges
The authentification screen pops up as it should but after authenticating the application just freezes upon executing this command. This problems only occurs in 10.9.
When I set the permissions of the folder to be delete to "everyone can read & write" it works.
Does anyone have a clue what has been changed?
EDIT: When I repeat the execution of this script by checking du -shx /Applications/iMovie.app it manages to delete a few more files with every try.
$ open compiled-applescript.app/
$ du -shx /Applications/iMovie.app
1.4G /Applications/iMovie.app
-- force quit AppleScript --
$ open compiled-applescript.app/
$ du -shx /Applications/iMovie.app
1.3G /Applications/iMovie.app
-- force quit AppleScript --
$ open compiled-applescript.app/
$ du -shx /Applications/iMovie.app
1.0G /Applications/iMovie.app
Its working fine on OS X 10.9 (13A603)
set POSIX_path to "/Users/paragbafna/Desktop/untitled folder"
do shell script "sudo rm -rfv " & quoted form of POSIX_path with administrator privileges
Does anyone have a clue what has been changed?
Well yes.. Gatekeeper has changed, that may be the cause..
When I set the permissions of the folder to be delete to "everyone can read & write" it works.
Did you do this from Finder or from the command line with chmod 0777? The latter may delete some attributes that Finder does not remove.
What setting is selected here, on your computer?
If you have a restrictive setting, try "Anywhere" to see if it solves the problem. If this is the cause you may:
Have custom command line tools installed, (e.g. MacPorts) or something you compiled yourself (since this is happening on 3 but not all computers and obviously you are not a "generic" user).
Your applescript is not being trusted, you can try signing it if possible, otherwise this may work:
If the user wants to run an application blocked by Gatekeeper, they have several options. Gatekeeper could, in effect, be turned off by letting it run all applications. A power user may opt to remove the quarantine attribute or use the spctl command to add a new policy in the security assessment policy subsystem. - TrendMicro - about Gatekeeper
Last resort idea.. Check your disk permissions, re-install Xcode if you use that, maybe the signatures are corrupted.
Write a shell script instead, I don't know if it is just about deleting a few files, then you can definitely do it in shell script, or comment to let me know what you're trying to achieve.
After days of trying everything to sort out this problem I finally found what was causing this issue.
It's the verbose-option (-v) of the rm-command. Leaving it out makes the application work flawless again.
Maybe Apple accidently introduced a buffer overflow. I will report this under the problem ID 15309626 I created at Apple's bugtracker. Maybe they'll fix it until the first 10.10 DP :D

Resources