3

Emacs: macOS sharing (DWIM style)

 1 year ago
source link: https://xenodium.com/emacs-macos-share-from-dired-dwim-style/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

12 October 2022 Emacs: macOS sharing (DWIM style)

A few days ago, I wrote dwim-shell-commands-macos-reveal-in-finder. While I've written a bunch of other dwim-shell-commands, what set this case apart was the use of Swift to glue an Emacs workflow.

(defun dwim-shell-commands-macos-reveal-in-finder ()
  "Reveal selected files in macOS Finder."
  (interactive)
  (dwim-shell-command-on-marked-files
   "Reveal in Finder"
   "import AppKit
    NSWorkspace.shared.activateFileViewerSelecting([\"<<*>>\"].map{URL(fileURLWithPath:$0)})"
   :join-separator ", "
   :silent-success t
   :shell-pipe "swift -"))

There is hardly any Swift involved, yet it scratched a real itch I couldn't otherwise reach (reveal multiple dired files in macOS's Finder).

divinedominion's reddit comment got me thinking of other use-cases, so I figured why not push this Swift-elisp beeswax a little further… Let's add macOS's sharing ability via dwim-shell-command, so I could invoke it from the comfort of my beloved dired or any 'ol Emacs buffer visiting a file.

(defun dwim-shell-commands-macos-share ()
  "Share selected files from macOS."
  (interactive)
  (let* ((position (window-absolute-pixel-position))
         (x (car position))
         (y (- (x-display-pixel-height)
               (cdr position))))
    (dwim-shell-command-on-marked-files
     "Share"
     (format
      "import AppKit

       _ = NSApplication.shared

       NSApp.setActivationPolicy(.regular)

       let window = InvisibleWindow(
         contentRect: NSRect(x: %d, y: %s, width: 0, height: 0),
         styleMask: [],
         backing: .buffered,
         defer: false)

       NSApp.activate(ignoringOtherApps: true)

       DispatchQueue.main.async {
         let picker = NSSharingServicePicker(items: [\"<<*>>\"].map{URL(fileURLWithPath:$0)})
         picker.delegate = window
         picker.show(
           relativeTo: .zero, of: window.contentView!, preferredEdge: .minY)
       }

       NSApp.run()

       class InvisibleWindow: NSWindow, NSSharingServicePickerDelegate, NSSharingServiceDelegate {
         func sharingServicePicker(
           _ sharingServicePicker: NSSharingServicePicker, didChoose service: NSSharingService?
         ) {
           if service == nil {
             print(\"Cancelled\")

             // Delay so \"More...\" menu can launch System Preferences
             DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
               NSApplication.shared.terminate(nil)
             }
           }
         }

         func sharingServicePicker(
           _ sharingServicePicker: NSSharingServicePicker,
           delegateFor sharingService: NSSharingService
         ) -> NSSharingServiceDelegate? {
           return self
         }

         func sharingService(
           _ sharingService: NSSharingService,
           didShareItems items: [Any]
         ) {
           NSApplication.shared.terminate(nil)
         }

         func sharingService(
           _ sharingService: NSSharingService, didFailToShareItems items: [Any], error: Error
         ) {
           let error = error as NSError
           if error.domain == NSCocoaErrorDomain && error.code == NSUserCancelledError {
             NSApplication.shared.terminate(nil)
           }
           exit(1)
         }
       }" x y)
     :silent-success t
     :shell-pipe "swift -"
     :join-separator ", "
     :no-progress t
     :utils "swift")))

Sure there is some trickery involved here (like creating an invisible macOS window to anchor the menu), but hey the results are surprisingly usable. Take a look…

share-done_x1.4.webp

I've pushed dwim-shell-commands-macos-share to dwim-shell-commands.el in case you'd like to give it a try. It's very much an experiment of sorts, so please treat it as such. For now, I'm looking forward to AirDropping more files and seeing if the flow sticks. Oh, and I just realised I can use this to send files to iOS Simulators. Win.

dwim-shell-command is available on melpa. What other uses can you find for it?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK