Non-Scrivener Specific AppleScript Question

Hi All - hoping the bright minds here in the Scrivenerati might be able to help me with an appleScript problem that’s been driving me around the bend. My objective is to transfer the contents of the clipboard to another app - say the notes field of a new THL task or Mori document. The catch is that I want the clipboard contents to remain unaltered. I want graphics, fonts, colours, links, columns, etc. all preserved.

The other catch is that I don’t want to have to use system events and keystrokes to navigate into the app and its document and paste the clipboard in. It seems to me that there has to be another way - i.e. using something like ““tell App X to make new entry with properties {title:entryTitle, notes:the clipboard}”” but specifying, somehow, that the clipboard and its properties in their entirety are to populate the note, rather than just the clipboard’s rearranged text.

Am I drunk or does someone know of a way to do this? Or both? Thanks for any help.

in script editor look in the library, section StandardAdditions. The clipboard is in there.

You can add your app to the library and it should expose any apple scriptable (exposed by software) functions/objects. You’ll need to look there on how to create the new doc.

A rough guess would be

tell application x
  activate
  set myDoc to create document with properties of the clipboard
end tell

I highly suspect this is NOT what you want, but the idea is there. Provide a few more specifics and I am sure someone will offer a better solution.

Hi Jaysen - thanks very much for the reply and the assistance. I did go into the Script Editor app and opened the Dictionary (I’m assuming that’s what you meant by ‘library’). After having looked at the clipboard-related material in Standard Additions - and yet again all over the interwebs - I must say that I’m still stumped. (Disclaimer, I’m an appleScript novice.)

Using TextEdit as an example, I want to put the contents of the clipboard - unaltered - into a new TextEdit document (without using System Events and keystrokes). The following script achieves most of this, but alters the clipboard contents - it essentially pastes and matches style, rather than just pastes.

tell application “TextEdit”
activate
set myDoc to make new document
tell myDoc
make new paragraph at end with data (the clipboard)
end tell
end tell

I don’t know if it has to do with classes or properties or clipboard info or what-have-you, but it seems to me there must be a way to achieve my desired ends here.

Again, all in Scrivener-land, any help would be much appreciated.

Not sure that is possible. I think the default (meaning not using the low level api) for the clipboard is plain text.

That said, if you can stomach a little system event, the following works for me 100%

tell application "TextEdit"
	activate
	set myDoc to document 1
	tell application "System Events"
		key code 9 using {command down}
	end tell
end tell

Change text edit to app of choice.

Thanks again for your response, Jaysen. The reason I don’t want to use system events and keystrokes/keycodes if at all possible is that I want to send the clipboard contents to other apps in the background. For instance I might want to send the clipboard contents to the notes field in a Mori document, or the notes field in a The Hit List task, in the background. My understanding is that the system events method you’ve posted below will only work in the acitvated/frontmost app.

As you have alluded, I may be completely out of luck here, but I figured that if there’s a way to do what I’m looking for, yourself or some of the other folks on this forum would be likelier than the average bear to know of it.

True, but you can apple script who gets to be the frontmost when you are done. Dirty, but tested to work:

global myFrontApp

tell application "System Events"
	set myFrontApp to name of the first process whose frontmost is true
end tell

tell application "TextEdit"
	activate
	set myDoc to document 1
	tell application "System Events"
		key code 9 using {command down}
	end tell
end tell

tell application myFrontApp
	activate
end tell

Don’t like the last activate there, but I am not an applescript guy.

Maybe you can have your cake and eat it too?

Jaysen, that’s a great way to keep track of and get back to your initial app, so thanks, I hadn’t thought of that. I do have a workflow that activates the target app, then uses system events to keystroke cmd-v and then to keystroke cmd-tab to switch back to the original app (similar to what you’ve proposed here). More and more it is appearing that I can’t do what I was hoping, which was to do all of this quickly, quietly, and elegantly in the background.

For instance, again using TextEdit as an example, almost everything I want to achieve can be delivered with a single line of appleScript…
tell application “TextEdit” to tell document “Target Document” to make new paragraph at end with data (the clipboard)
Clean, quick, quiet, no app switching, no system events, no keystrokes - easy-peasy, lemon-squeezy.

Unfortunately, the one requirement that it does not meet - for me - is that it alters the clipboard contents, reducing them to text only, and unformatted at that. I assumed - it appears incorrectly - that there would be an easy way to let appleScript know to leave the clipboard contents alone. i.e make new paragraph at end with data (the clipboard, just as it’s content frickin’ appeared a moment ago whenst I copied it, for crissakes). Between the two of us, however, it looks like this is not a possibility.

If anyone else has an unexplored idea for me, please do chime in, otherwise I’ll assume that I’m beaten.

Thanks again.

[code]try
set rtf_data to the clipboard as «class RTF »

set leFiche to "volume:Users:username:Desktop:clipboard contents.rtf"
set file_ID to open for access leFiche with write permission
write rtf_data to file_ID
close access file_ID

on error errMsg number errNum
if errMsg = “Can’t make some data into the expected type.” then
display dialog “The clipboard does not contain rich text”
error number -128
else
display dialog “Houston, we have a problem.” & return & errNum & return & errMsg
end if
end try[/code]

It is possible that your clipboard does not contain the information that you think it does. For example, if you are copying some text and pictures from a Word document, it is quite possible that your Clipboard contains only unicode text and not the pictures.

So, when working on this and trying to get the rich stuff out, you need to make sure that some rich stuff is actually on the clipboard.

In Script Editor:

set k to the clipboard return class of k

If you run this with the Event Log active, you can see a representation of what is on the clipboard (be prepared for a wait if you have picture data on there, as you will get a numerical dump of the pic data), and the Result tab will show you the class of the clipboard contents.

Examples: A copy from Preview of a picture yields a clipboard of class Record containing one record whose type is picture and whose value is the pic data. A copy from Word of some text with an embedded picture yields a clipboard of class Unicode Text. The contents in this case include only the text with a gap where the picture should be.

The real challenge in what you are trying to do is that the clipboard can contain basically anything. So, when a Paste operation is called for in a given application, that app has some real work to do to figure out what to do with what is on the clipboard. This process is not likely made Applescript accessible by the app. What you are typically given is something lower down–like how to insert some content of a known and appropriate type into a content area.

–Greg

P.S. I am finding TextEdit a problematic test case. Pasting mixed text and graphics from Word does not work under any circumstances. Pasting a picture copied out of Preview works, but the Applescript dictionary of TextEdit is very spotty. Documents contain a (rich) text object. Text objects contain paragraphs, but paragraphs lack a contents property. So, it seems that about all you can do is directly set the text of a document–but this gives you no obvious way to insert a picture object (or record containing on) like you get from Preview.

From “AppleScript: The Comprehensive Guide to Scripting and Automation on Mac OS X” by Hanaan Rosenthal (a book I recommend highly), page 446:

Understanding How the Mac Clipboard Works

The Mac clipboard is a clever piece of software; it’s simple to use but surprisingly sophisticated beneath the surface.

When a user copies some data from an application, the clipboard has no idea what kind of application the user is going to paste that data into next. To provide as much flexibility as possible when copying and pasting between applications, the clipboard doesn’t just get the data in the native format used by that application; it gets it in as many different formats as the application can provide. This gives the clipboard a sort of “backup plan” when pasting the data into other applications. Less sophisticated formats may not contain as much of the original data as the native format, but they are likely to be understood by a greater number of applications–and something is better than nothing.

For example, when you copy text from a rich-text document in TextEdit, the Mac clipboard obtains this text in as many formats as it can, from the basic (string) to the richest (RTF).

It does this so that when you paste this text into another application, the receiving application can pick whichever format is best for it. For example, Microsoft Word can understand RTF data, so it will ask the clipboard for this because RTF contains not only character data but also lots of valuable style information that Word can put to good use. An application such as Terminal would take the UTF 8–encoded character data, since that’s the richest format it can understand and use. An elderly, Carbon-based, plain-text editor that doesn’t support Unicode text would make do with the basic string data.

Finding Out What’s on the Clipboard

The clipboard info command returns some information about the contents of the clipboard, as shown in the following example:

set the clipboard to "Paste me!" clipboard info --> {{string, 9}}
The result shows that the clipboard contains a string of 9 bytes. Next, here’s an example of the clipboard information after copying text from TextEdit:

clipboard info --> {{Unicode text, 1142}, {scrap styles, 62}, {string, 571}, ➥ {uniform styles, 564}, {«class ut16», 1144}, {«class utf8», 575}, ➥ {«class RTF», 914}}
The result is a list containing all the formats TextEdit used to place the same data on the clipboard. It shows that the basic character information is available in any of four formats: string and three Unicode encodings (Unicode text, «class ut16», and «class utf8»). Also, some separate style information is available (scrap stylesand uniform styles) for applications that know how to combine this with one of the previous character-only formats. Finally, the data is available in RTF («class RTF»), which combines both character and style information in a single format.

I’ve moved this to the Developers & Code section as it isn’t really relevant to Scrivener technical support.

@flow and @gr: Thanks very much to both of you for your help. The class stuff is something that I had been looking at before, but I had been missing a couple of crucial pieces of information that I now have, thanks to you . The first had to do with those chevron-y/arrow-y symbols bracketing the “class RTF”, and the second had to do with only being able to write the rtf data to a closed file, rather than being able to append it to an open document.

Anyhoo, @flow’s script definitely accomplishes what I’d requested in my original post, but now, if I may be so bold, I have two additional questions I’m hoping someone could help me with:

  1. How do I make those symbols surrounding “class RTF”?

  2. Once I’ve got the rtf clipboard contents into my TextEdit document, how do I change the font/font family to Helvetica without losing the typeface attributes?

For example…
tell application “TextEdit”
tell document 1
set font to “Helvetica”
end tell
end tell

This script - against my wishes - strips all bold and oblique attributes, converting everything to Helvetica regular typeface. Even, for instance, if the document’s contents are already in Helvetica (which I tried as a test case). Sizes, colours and links are all preserved, but bold and oblique typefaces are not. Any ideas for me?

@edmo

  1. It’s actually «class RTF », with a space between the ‘F’ and the right pointing double angle quotation. (Script Editor will want that space.) Option-\ for the left pointing double angle quotation and option-shift-\ for the right one.

  2. I wasn’t able to delve into this question deeply. I did paste some rich text into TextEdit, then changed the font using your script and ran into the same problem. Then I used “get properties of paragraph 1” and got the following as the result: {size:14.0, color:{65535, 0, 0}, font:"Calibri-BoldItalic", class:text} The bold and italic attributes are considered part of the font (at least for TextEdit). Helvetica, Helvetica-Bold, Helvetica-Italic, and Helvetica-BoldItalic are four different fonts. Didn’t come up with an easy solution right off the bat. I’ll look into it more when I have more time and report back.

TextEdit recognizes ‘attribute run’ objects within a document. An attribute run is a run of text with all the same styling. Seems like you might accomplish what you want by looping through all the attribute runs in the document and changing the italic ones to Helv-italic and the bold ones to Helv-bold, the bold-italic ones to Helv-bolditalic, and the rest to Helvetica.

–Greg

P.S. It will be worth it to you to find some sites dedicated to Applescript and look for relevant scripts to download and examine. Someone out there has spent time figuring out how to do tricks with TextEdit, for example, and seeing how they did what they did is probably your quickest route to getting where you are going. (You will no doubt find some helpful forums there, too!)

@flow & @gr - Thanks again to both of you for the further assistance. The info you provided helped me to cobble together an acceptable solution in the following form:

set font of every attribute run whose (font does not start with “Helvetica” and (font contains “BoldOblique” or font contains “BoldItalic”)) to “Helvetica-BoldOblique”
set font of every attribute run whose (font does not start with “Helvetica” and (font contains “Oblique” or font contains “Italic”)) to “Helvetica-Oblique”
set font of every attribute run whose (font does not start with “Helvetica” and font contains “Bold”) to “Helvetica-Bold”
set font of every attribute run whose (font does not start with “Helvetica”) to “Helvetica”

It seems to work quite a bit faster than a looped find & replace on attribute runs.

@flow - If you do end up looking any further into this and finding a better way to do it, I’m all ears. It’s one of those things to me that feels like there ought to be a quick and easy way to do this via applescript, given how easy it is to do it in a document (select all, go to the Format>Font>Show Fonts menu, select Helvetica, et voila).

@gr - Thanks for the tip re. finding appleScript sites and forums. I have done much googling and bookmarking, though so far I have refrained from joining any additional forums. FWIW to know, I have only asked these questions in the Scriv forum as a next-to-last resort, after much research and many failed attempts. Don’t want to impose on yourself and other busy writers, but since this is a place where so many bright (and helpful) lights hang out…

Thanks again, all.

Wow. Just took a look at this, and … wow. I was expecting some challenges with this, but there were more than I imagined. A lot of the fonts have different naming conventions, which made for an interesting brain teaser this afternoon.

Your script seems to be the best solution. The only thing I’d note is that, as written, your script would not change fonts like “HelveticaCY” or “HelveticaNeue” to “Helvetica”, but if you don’t have those fonts on your system, then that’s not an issue.

It is funny how system events would make this a piece of cake, but to change fonts in the background makes it a … challenge.

@flow - thanks much for chiming back in on this and for letting me know about the “Helvetica Neue/CY” omissions, which I have now fixed.

For my further edification, if you feel like posting the “piece of cake” system events method of changing the font family to love to know it (I can see how to activate the font palette using keystrokes, but if that’s the start of the method you’re alluding to, I have no idea what to do next). Don’t bother if your too busy or otherwise disinclined, though - I’ve already taken up a lot of your time with this.

Again, much appreciated.

Oops. Earlier in the conversation, when we were working with keeping the color, I was experimenting with Tex-Edit Plus as well TextEdit. In Tex-Edit Plus, the fonts are listed in the Font menu (and the “Show Fonts” option is there as well), and I was able to simply select the text and change the font without changing any of the other attributes. Tex-Edit Plus is more AppleScript-friendly than TextEdit.

By the way, instead of adding special clauses for Helvetica versions, why not just drop the exclusion clauses:

font does not start with "Helvetica" 

The amount of overkill this would result in would probably be negligible.

–Greg