AppleScript equivalent to Finder->Edit->Show Clipboard?

I think the answer to this question is No, but I hope it 's OK to ask anyway.

Is there any way an AppleScript (or a shell script running from an AppleScript) can open the same window that opens when you use Edit->Show Clipboard from the Finder’s menubar? I am looking for a solution that doesn’t need assistive access, so solutions that click the menu won’t be suitable.

Many thanks for any help.

The simplest way is using TextEdit window. Run following script in the Script Editor, or save and run it as application:


tell application "TextEdit"
	activate
	make new document with properties {text:(the clipboard as text)}
end tell

The same using display dialog:


display dialog (the clipboard as text) with title "Clipboard" buttons {"OK"}

The same using display alert:


display alert "Clipbord" & return message (the clipboard as text)

If you want the window to belong to the Finder, put dialog inside tell block:


set clipboardContents to (the clipboard as text)

tell application "Finder"
	activate
	display dialog clipboardContents with title "Clipboard" buttons {"OK"}
end tell

That’s excellent - thank you! But I should have specified that I also need to be able to display images in the Finder->Edit->Show Clipboard window. Is there a way to display graphics that matches the way you displayed text? I see that Preview can display New from Clipboard - but is there a way to display that simple read-only window that appears with Finder->Edit->Show Clipboard?

Thank you again!

At least on my Mac the Finder’s menu Show Clipboard doesn’t show selected item’s icons inside its own clipboard window. It shows only the names of selected items, and only when the view is not icon view.

I think, you can achieve adding the images inside empty NSWindow using AsObjC. But this is very complex task.

Thank you. If I have a graphic image in the clipboard (not a file - an image selected from Preview or some other graphics app), the Edit->Show Clipboard window shows the graphic. I’ll look into the AsObjC method. Thanks again!

Hi. Again.

Here is AsObjC solution. To use it, save following script as stay-open application. It is start point, but already works.

You can add some button and its action to quit app when need. Or, you can add quitting on window minimizing and so on.

This script can display images with a size not exceeding 1280x800 pixels. My window sizes are set 1280x800, but you can make them more flexible - bind the window sizes to the image sizes. You can do it yourself.

For images that do not fit in 1280x800, you can add a multiple reduction (scaling on the fly). I have no time to do all this myself.


use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"

property NSWindow : a reference to current application's NSWindow
property NSImage : a reference to current application's NSImage
property NSImageView : a reference to current application's NSImageView
property NSWindowStyleMaskTitled : a reference to 1
property NSWindowStyleMaskClosable : a reference to 2

set theWindow to createWindowWithRect(0, 0, 1280, 800)
my performSelectorOnMainThread:"showTheWindow:" withObject:theWindow waitUntilDone:true

--------------------------------------------------  The Handlers  ------------------------------------------------
on createWindowWithRect(xMin, yMin, xLen, yLen)
	set windowSize to {{xMin, yMin}, {xLen, yLen}}
	set winStyle to NSWindowStyleMaskTitled + NSWindowStyleMaskClosable
	set aWindow to NSWindow's alloc()'s initWithContentRect:windowSize styleMask:winStyle backing:2 defer:yes
	aWindow's setTitle:"Clipboard"
	return aWindow
end createWindowWithRect

on showTheWindow:theWindow
	set theImage to my getClipboardASImage()
	set theImageView to NSImageView's alloc()'s initWithFrame:{{0, 0}, {1280, 800}}
	theWindow's contentView()'s addSubview:theImageView
	theImageView's setImage:theImage
	theWindow's makeKeyAndOrderFront:me
end showTheWindow:

on getClipboardASImage()
	set theNSPasteboard to (current application's NSPasteboard)'s generalPasteboard()
	set anArray to theNSPasteboard's readObjectsForClasses:({NSImage}) options:(missing value)
	if anArray = missing value or (anArray as list) = {} then return false
	set aRes to anArray's objectAtIndex:0
	return aRes
end getClipboardASImage

That is wonderful! And it’s an education for me in AsObjC. Thank you!

This is basically exactly what I needed - I want to be able to show the user that an image was correctly copied to the clipboard. So I reduced the size of the window, added a delay of a few seconds and then a command to quit. This does exactly what I hoped for.

My next job is to teach myself how to specify the location of the window (which now opens in the lower left corner of the screen) and how to add a cancel button. I think this should be relatively easy, now that I know the basics.

Thank you again for this extremely generous help.

EDIT: I see that I can set the position of the window with something like this:

theWindow’s setFrame:{{300, 300}, {640, 480}} display:true

but of course I have to replace 300, 300 with variables based on calculating the dimensions of the screen that contains the window…

Here is a very slightly modified version of the code above. It uses a small window, centered on the main display, and closes down after five seconds. Of course this is only for my own use, but maybe it can be of use to someone else. With thanks again to KniazidisR for doing all the work!

Warning: I don’t understand how much of the code works, so my modifications may have made nonsense of the original code. I hope some expert will offer corrections of my nonsense.

use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions

property NSWindow : a reference to current application's NSWindow
property NSImage : a reference to current application's NSImage
property NSImageView : a reference to current application's NSImageView
property NSWindowStyleMaskTitled : a reference to 1
property NSWindowStyleMaskClosable : a reference to 2

set clipContents to (clipboard info) as text

if clipContents contains "TIFF" then
	showImage()
else
	display dialog "No image in clipboard." buttons {"OK"} giving up after 2
end if
error number -128

on showImage()
	set {width, height, scale} to words of (do shell script "system_profiler SPDisplaysDataType | awk '/Main Display: Yes/{found=1} /Resolution/{width=$2; height=$4} /Retina/{scale=($2 == \"Yes\" ? 2 : 1)} /^ {8}[^ ]+/{if(found) {exit}; scale=1} END{printf \"%d %d %d\\n\", width, height, scale}'")
	set winX to (((width as integer) / 2) - 320)
	set winY to ((((height as integer) / 2)) - 240)
	set theWindow to createWindowWithRect(winX, winY, 640, 480)
	my performSelectorOnMainThread:"showTheWindow:" withObject:theWindow waitUntilDone:true
	delay 5
	tell me to quit
end showImage

--------------------------------------------------  The Handlers  ------------------------------------------------
on createWindowWithRect(xMin, yMin, xLen, yLen)
	set windowSize to {{xMin, yMin}, {xLen, yLen}}
	set winStyle to NSWindowStyleMaskTitled + NSWindowStyleMaskClosable
	set aWindow to NSWindow's alloc()'s initWithContentRect:windowSize styleMask:winStyle backing:2 defer:yes
	aWindow's setTitle:"Clipboard"
	return aWindow
end createWindowWithRect

on showTheWindow:theWindow
	set theImage to my getClipboardASImage()
	set theImageView to NSImageView's alloc()'s initWithFrame:{{0, 0}, {640, 480}}
	theWindow's contentView()'s addSubview:theImageView
	theImageView's setImage:theImage
	theWindow's makeKeyAndOrderFront:me
	theWindow's setFrame:{{winX, winY}, {640, 480}} display:true -- change this to match height and width
end showTheWindow:

on getClipboardASImage()
	set theNSPasteboard to (current application's NSPasteboard)'s generalPasteboard()
	set anArray to theNSPasteboard's readObjectsForClasses:({NSImage}) options:(missing value)
	if anArray = missing value or (anArray as list) = {} then return false
	set aRes to anArray's objectAtIndex:0
	return aRes
end getClipboardASImage

You should check not existence of string “TIFF”, but existence of TIFF picture class. And error throwing should be placed inside the if block.

Anyway, I would check the existence of the image data in the clipboard this way:


try
	the clipboard as TIFF picture -- this will throw error only when no image in the clipboard
on error
	display dialog "No image in clipboard." buttons {"OK"} giving up after 2
	error number -128
end try

my showImage()

REMEMBER: you should save and run the entire script only as application.

Perfect! Thank you again!

Here is a solution that you may be interested in. Basically, if your clipboard contains TIFF picture data, a temporary file will be created on your desktop with the image from your clipboard. Then a Quick Look preview will be generated… showing the image in the temp file (which is the same as the image on your clipboard). After the Quick Look preview is closed, the temp file will automatically be deleted.

try
	TIFF picture of (the clipboard) 
on error
	display dialog "The clipboard doesn't contain image data" buttons {"Cancel", "OK"} ¬
		default button "OK" giving up after 3
	return
end try

set tempFile to writeTiffImageToTempFile("clipboard.tiff")

do shell script "/usr/bin/qlmanage -p " & quoted form of tempFile & " ; rm " & quoted form of tempFile

on writeTiffImageToTempFile(fileName)
	set tempFile to POSIX path of (path to desktop as text) & fileName
	try
		set writeToFile to open for access tempFile with write permission
		write TIFF picture of (the clipboard) to writeToFile starting at 0
		close access writeToFile
		return tempFile
	on error errMsg number errNum
		close access writeToFile
	end try
end writeTiffImageToTempFile

That is a very elegant solution, and works extremely quickly. I’ve been spending a lot of time trying to figure out how to use Esc or a button to close the window in the previous solution, but Esc works perfectly in this one. Thank you!

Question: on my system the window title is “[DEBUG] clipboard.tiff”. Is it possible to change that? This is a cosmetic issue, not a serious one.

There are rare cases when AsObjC code is inferior to plain AppleScript code.

As I checked, the latter is 2x slower than the AsObjC code. In addition, it will repeatedly write / erase the file to disk, wearing it out. Also, I only see a minus while waiting for ESC to be pressed, instead of closing itself after a quick glance at the clipboard.

So what’s so elegant about it? Of course, your tastes are up to you. I wrote this comment for novice users. So that they are not mistaken about the “improvement”.


use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions
property NSWindow : a reference to current application's NSWindow
property NSImage : a reference to current application's NSImage
property NSImageView : a reference to current application's NSImageView
property NSWindowStyleMaskTitled : a reference to 1
property NSWindowStyleMaskClosable : a reference to 2

try
	the clipboard as TIFF picture -- this will throw error only when no image in the clipboard
on error
	display dialog "No image in clipboard." buttons {"OK"} giving up after 2
	error number -128
end try
my showImage()

on showImage()
	set {width, height, scale} to words of (do shell script "system_profiler SPDisplaysDataType | awk '/Main Display: Yes/{found=1} /Resolution/{width=$2; height=$4} /Retina/{scale=($2 == \"Yes\" ? 2 : 1)} /^ {8}[^ ]+/{if(found) {exit}; scale=1} END{printf \"%d %d %d\\n\", width, height, scale}'")
	set winX to ((width as integer) / 2) - 320
	set winY to ((height as integer) / 2) - 240
	set theWindow to my createWindowWithRect(winX, winY, 640, 480)
	my performSelectorOnMainThread:"showTheWindow:" withObject:theWindow waitUntilDone:true
	delay 5
	tell me to quit
end showImage

-------------------------------------------------- The Handlers ------------------------------------------------
on createWindowWithRect(xMin, yMin, xLen, yLen)
	set windowSize to {{xMin, yMin}, {xLen, yLen}}
	set winStyle to NSWindowStyleMaskTitled + NSWindowStyleMaskClosable
	set aWindow to NSWindow's alloc()'s initWithContentRect:windowSize styleMask:winStyle backing:2 defer:yes
	aWindow's setTitle:"Clipboard"
	return aWindow
end createWindowWithRect

on showTheWindow:theWindow
	set theImage to my getClipboardASImage()
	set theImageView to NSImageView's alloc()'s initWithFrame:{{0, 0}, {640, 480}}
	theWindow's contentView()'s addSubview:theImageView
	theImageView's setImage:theImage
	theWindow's makeKeyAndOrderFront:me
	theWindow's setFrame:{{winX, winY}, {640, 480}} display:true -- change this to match height and width
end showTheWindow:

on getClipboardASImage()
	set theNSPasteboard to (current application's NSPasteboard)'s generalPasteboard()
	set anArray to theNSPasteboard's readObjectsForClasses:({NSImage}) options:(missing value)
	if anArray = missing value or (anArray as list) = {} then return false
	set aRes to anArray's objectAtIndex:0
	return aRes
end getClipboardASImage

Yes - I see your point. My reason for calling it “elegant” was that it used only a very few lines of code to provide the Esc closing that I haven’t been able to figure out for your much more customizable solution. If I could figure out how to add an Esc and OK button to the window in the AsObJ solution, I would certainly use it!

Wait, wait a minute. I had a terrible suspicion that you are saving my script in post #13 as a stay-open application … And therefore, the application does not self-close for you.

And that’s why you are so glued to the ESC key, which is not meant to quit Cocoa applications at all. This is what Command+Q is for. You can also add a button, but this will complicate the code and slow down the speed.

You apparently did not understand me. Just save the script from post #13 as a regular application (not a stay-open application), and everything will close by itself, like a clock.

I do not regret my time to help someone, but I do regret it for the deterioration of the script.

NOTE: the script in the post #6, which I recommend to save as stay-open app, was a start point. You can use it as well, and quit application using Command+Q. Although, I see automated approach from #13 best.

Yes, you are right! I did save the app as a stay-open app: I misinterpreted something in an earlier message, but that was very foolish of me. Everything in your code is now working perfectly. Thank you again!