osx-trash icon indicating copy to clipboard operation
osx-trash copied to clipboard

Use ns-do-applescript instead of external binaries?

Open dsedivec opened this issue 4 years ago • 8 comments
trafficstars

Inspired by this Stack Exchange answer, I cooked up this:

(defun my:ns-move-file-to-trash (path)
  (ns-do-applescript
   (format
    "tell application \"Finder\" to move {the POSIX file \"%s\"} to trash"
    (replace-regexp-in-string (rx (group (any ?\\ ?\")))
                              "\\\\\\1"
                              (expand-file-name path)))))

This seems to work here. I think the AppleScript is equivalent to that of trashfile.AppleScript. And it seems to be as fast as calling out to the trash program, with the obvious benefit of not needing any external program. ns-do-applescript has been in Emacs since November 2008, if lisp/ChangeLog.14 is to be believed.

The only slightly weird thing I've seen is that macOS prompted me to let Emacs control Finder, something like that. That doesn't strike me as a problem.

Would you be interested at all in a PR that defaults to the above method for trashing files, or at least one that uses ns-do-applescript instead of calling out to osascript when trash isn't found?

dsedivec avatar May 02 '21 03:05 dsedivec

Hello @dsedivec

This looks interesting to me: getting rid of the third-party trash library and that emacs-foreign AppleScript file.

Have you incorporated this approach into your setup and still use it? Any drawbacks you noticed? Looking at the snippet you provided makes me think: why not simply add it to my init files 😄 reducing the quantity of the third-party packages in use. (But I haven't tested it yet.)

The only slightly weird thing I've seen is that macOS prompted me to let Emacs control Finder

The current implementation of the osx-trash package also prompts for the Finder control (after adding "-F" option that asks Finder to trash the files), so that's a norm. It seems System Preferences >> Security & Privacy >> Privacy >> Accessibility should influence this behavior.

yugaego avatar Jul 16 '21 15:07 yugaego

Have you incorporated this approach into your setup and still use it?

Yes.

Any drawbacks you noticed?

I wouldn't say I've used it a ton, but I have definitely used it (you can tell when the trash sound effect plays). No drawbacks I've witnessed yet, I'm quite liking it.

Looking at the snippet you provided makes me think: why not simply add it to my init files 😄

FYI here's what I'm using right now.

dsedivec avatar Jul 16 '21 17:07 dsedivec

FYI here's what I'm using right now.

Thank you, this looks good and seems to be resilient to oddly-named files too (I'm not sure about all possible cases, but that's not that important to me in this case).

In my opinion, the approach you suggested deserves to be PRed and considered as a replacement to the currently used one. A PR would add it more visibility anyway, IMO.

May I ask you what was the cause of changing path argument to paths?

move-file-to-trash documented to accept one file or directory name. When I testing the snippet in Dired - marking and removing several files in one run - system-move-file-to-trash indeed was called once per each file. Was that change caused by another use case?

Thanks, YE

yugaego avatar Jul 19 '21 18:07 yugaego

May I ask you what was the cause of changing path argument to paths?

move-file-to-trash documented to accept one file or directory name. When I testing the snippet in Dired - marking and removing several files in one run - system-move-file-to-trash indeed was called once per each file. Was that change caused by another use case?

I think this will be pretty slow if dired has to delete a lot of files, so I was entertaining the notion of patching my own dired to pass a long list of files to delete in just one function call. Modifying the trash function to accept multiple files to trash was easy, but I never got around to patching dired. I left the ability to accept multiple files here in case I needed it in the future.

dsedivec avatar Jul 20 '21 01:07 dsedivec

so I was entertaining the notion of patching my own dired to pass a long list of files to delete in just one function call.

Got it, thank you for the clarification.

BTW, I mentioned your solution on Stackexchange and EmacsWiki, so it should give some additional visibility to those who need it.

yugaego avatar Jul 20 '21 08:07 yugaego

Yep, the related bug got attention recently.

yugaego avatar Dec 07 '21 09:12 yugaego

I noticed that I did not have the Put Back option in the Finder menu when trying to restore a file I had deleted in emacs.

Unfortunately emacs has not followed the issues in other trash tools.

The problem is that the Apple Objective-C (and Swift) API is bugged and does not work. The only known way is to use Finder.app to do the trashing)

Thus the introduction of the -F to trash which then uses applescript. (I think there are other conversations about this but I can"t remember where)

The other complication is that oascript only works if you are running on the desktop ie using ssh into another machine will make oascript fail on that machine.

I am now using @dsedivec's solution except not doing (fboundp 'system-move-file-to-trash) as emacs now defines that. I don"t know if it works if not on the desktop.

bestlem avatar Jul 13 '23 12:07 bestlem