Is there a way for a droplet to call the open handler by pressing Cmd+V and pass the clipboard content (files or text) to it. Currently, I’m watching the clipboard content with an idle handler which does not work well.
Not a good way, but there is a crufty way.
You can set the idle for a short time, like five seconds. Then every five seconds the script can look at the clipboard, figure out if it’s got what it’s looking for and if so execute. If not just wait another five seconds.
Thanks, that’s what I’m actually doing, but it’s clumsy. Idle will show repeatedly the Droplet window and it often can’t be closed with the mouse.
As it is possible to overwrite menu commands, I thought someone can tell me, how to call the open handler. I tried something like this:
-- …
on run
set appMenu to (current application's NSApp's mainMenu()'s itemAtIndex:2)'s submenu()
set menuItem to appMenu's itemAtIndex:5
menuItem's setTitle:"Paste"
menuItem's setAction:"useClipboard:"
menuItem's setTarget:me
end run
-- …
on useClipboard:sender
if current application's NSThread's isMainThread() then
my performUseClipboard:(missing value)
else
its performSelectorOnMainThread:"performUseClipboard:" withObject:(missing value) waitUntilDone:true
end if
end useClipboard:
on performUseClipboard:sender
open (the clipboard)
end performUseClipboard:
In this context it seems not to be possible to call the open handler.
Well, I don’t understand what the code does, I just use it.
Try this:
on performUseClipboard:sender
set clipboardContents to theClipboard
open clipboardContents
end performUseClipboard:
Thanks, I think you’re speaking of “the clipboard” instead of “theClipboard”, right?
Well, the problem is, that my open handler is displaying an alert dialog. If I use open from performUseClipboard, the dialog is not shown. Also the Applet can’t show error messages when I call open from a menubar command.
When calling the open handler from idle, it works as expected.
Interestingly, this lets the open handler show dialogs:
on performUseClipboard:sender
run script "set clipboardContents to the clipboard
open clipboardContents"
end performUseClipboard:
But then the Applet seems to crash and I have to force quit it.
You’ll need to show us more of your script for us to help.
To make things easy, here’s a simplified version:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"
on run
initialize()
end run
on initialize()
if name of current application is name of me then
set appMenu to (current application's NSApp's mainMenu()'s itemAtIndex:2)'s submenu()
set menuItem to appMenu's itemAtIndex:5
menuItem's setTitle:"Paste into Droplet"
menuItem's setAction:"pasteClipboard:"
menuItem's setTarget:me
set appMenu to (current application's NSApp's mainMenu()'s itemAtIndex:2)'s submenu()
set menuItem to (current application's NSMenuItem's alloc()'s initWithTitle:"Paste with “run script”" action:"alternativePasteClipboard:" keyEquivalent:"V")
menuItem's setTarget:me
appMenu's insertItem:menuItem atIndex:6
end if
end initialize
on open theFiles
beep
display alert "You've pasted/dropped:" message (item 1 of theFiles as string)
beep
end open
on pasteClipboard:sender
if current application's NSThread's isMainThread() then
my performpasteClipboard:(missing value)
else
its performSelectorOnMainThread:"performpasteClipboard:" withObject:(missing value) waitUntilDone:true
end if
end pasteClipboard:
on performpasteClipboard:sender
set clipboardContents to the clipboard
open clipboardContents
end performpasteClipboard:
on alternativePasteClipboard:sender
if current application's NSThread's isMainThread() then
my performalternativePasteClipboard:(missing value)
else
its performSelectorOnMainThread:"performalternativePasteClipboard:" withObject:(missing value) waitUntilDone:true
end if
end alternativePasteClipboard:
on performalternativePasteClipboard:sender
run script "set clipboardContents to the clipboard
open clipboardContents"
end performalternativePasteClipboard:
Save this as an Enhanced Applet with the option “stay open”.
When you drop a file into its window, you’ll hear a beep, see an alert with the filename and after pressing OK, you’ll hear a second beep.
Then try this:
- Copy a file from Finder into the clipboard
- Open the Droplet
- Perform: Edit > Paste
- Result:
- You’ll hear only one beep
- the code stops at “display alert”
- the Edit menu does not reset its highlight color, so it seems display alert caused a crash.
I’ve also integrated the alternative way:
- Copy a file from Finder into the clipboard
- Open the Droplet
- Perform: Edit > Paste with “run script”
- Result:
- You’ll hear only one beep.
- “display alert” is executed and shown
- The whole Applet is now frozen, you can’t press OK.
At some point you need to see what format and class the clipboard is that you’re sending to the open handler.
The variable: “theFiles” must be a list, and the list should consist of text or something automatically coerced into text by the display dialog command.
If you’re not using Script Debugger, add a “log theFiles” command at the start of your open handler, and run from script editor using the clipboard. This should tell you what’s going on.
The clipboard type doesn‘t matter. It even does not work with a simple handler with display alert "test"
.
Look at this sample. I selected two files in the Finder and did a command-c.
Then ran this appleScript.
The clipboard is text with two paragraphs, each with the name of one of the files.
When I run the script below I get too alerts. One from the run handler and one from the open handler.
The run handler alert has both files. The open handler alert only has the first file.
set myFiles to the clipboard
display alert myFiles
open myFiles
on open myFiles
set myFiles to paragraphs of myFiles
display alert item 1 of myFiles
end open
if I change the open handler to this the two alerts are identical:
on open myFiles
display alert myFiles
end open
Thanks Ed for your investigations. The clipboard handling is not of interest for me at this point. First I would like to know, how to call the open (or any other) handler from a menu command, so it behaves normally like in standard AppleScript with dialogs and real error messages. It seems that calling handlers from a menu command are running in a different context. I want the normal context.
Currently, my solution is to open a new instance of the App with “open -n” from shell and then quit the currently running process. But that looks like a bad hack and the behavior in the dock is irritating.
Maybe the Enhanced Applet could be enhanced(SIC!) with a pasteToWindow handler or something like that. That would be great and I don’t have to deal with workarounds and bugs (enhanced applet doesn’t like Idle handlers very much ).
Inspired by the docs, I’ve tried some stuff. When I use performSelectorInBackground:
I can call the open handler which is then be able to use display alert
. But now the progress bar does not work show up in the applet window. Any ideas?
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"
on run
initialize()
end run
on initialize()
if name of current application is name of me then
set appMenu to (current application's NSApp's mainMenu()'s itemAtIndex:2)'s submenu()
set menuItem to appMenu's itemAtIndex:5
menuItem's setTitle:"Paste 'Mail.app' into Droplet"
menuItem's setAction:"pasteClipboard:"
menuItem's setTarget:me
end if
end initialize
on open theFiles
beep
set progress total steps to -1
set progress description to "Description text"
display alert "You've pasted:" message (item 1 of theFiles as string)
beep
end open
on pasteClipboard:sender
if current application's NSThread's isMainThread() then
my performpasteClipboard:(missing value)
else
its performSelectorOnMainThread:"performpasteClipboard:" withObject:(missing value) waitUntilDone:true
end if
end pasteClipboard:
on performpasteClipboard:sender
my performSelectorInBackground:"backgroundHandler:" withObject:(missing value)
end performpasteClipboard:
on backgroundHandler:sender
open {"Macintosh HD:System:Applications:Mail.app"}
end backgroundHandler:
When I change the last handler to this, it seems to work:
on backgroundHandler:sender
run script "open {\"Macintosh HD:System:Applications:Mail.app\"}"
end backgroundHandler: