I just wrote the following script to get RTF content from the clipboard.
.
-- script: Get raw RTF content from the clipboard
-- written: by me, right now
clipboard_as_raw_RTF()
on clipboard_as_raw_RTF()
-- catch the hext text from the error message
try
(the clipboard as «class RTF ») as text
on error errorMessage
set hexRTFData to errorMessage
end try
-- clear the garbage text
set ATID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {"«data RTF ", "»"}
set hexRTFData to text item 2 of hexRTFData
set AppleScript's text item delimiters to ATID
-- convert hexadecimal text to ASCII text
do shell script "/bin/echo -n " & hexRTFData & " | xxd -r -p" without altering line endings
end clipboard_as_raw_RTF
.
It works, but I would like to know if there is a better way to accomplish this task. For example, to shorten the script without degrading the speed.
Shortened version:
.
-- script: Get raw RTF content from the clipboard
-- written: by me, right now
clipboard_as_raw_RTF()
on clipboard_as_raw_RTF()
try
(the clipboard as «class RTF ») as text
on error errorMessage -- catch HEX text from error message
set hexRTFData to text 22 thru -18 of errorMessage
end try
-- convert HEX text to ASCII text
do shell script "/bin/echo -n " & hexRTFData & " | xxd -r -p" without altering line endings
end clipboard_as_raw_RTF
.
Thanks for this link, but I’m not interested in a third-party utility, but in how I myself could program the simple task of getting raw RTF content from the clipboard using standard OSX tools. Also, pbpaste can’t pass the rich content inside the shell workflow, as I know.
Here is another such solution, which is shorter than my previous ones, but much slower:
.
do shell script "osascript -e 'the clipboard as «class RTF »' | perl -ne 'print chr foreach unpack(\"C*\",pack(\"H*\",substr($_,11,-3)))'"
.
As you can see, they work, but they work in a somewhat clumsy way.
In post #1 I’m catching content from an error message, and here
do shell script “osascript -e ‘the clipboard as «class RTF »’”
I’m executing Apple script inside osascript inside do shell script inside Apple script just to pass the hex text to perl command.
I don’t know if this will be of interest. It’s not shorter than your script, but it is a bit faster:
on clipboard_as_raw_RTF()
try
set RTFData to (the clipboard as «class RTF »)
on error errmsg
display dialog errmsg
return missing value
end try
set temporaryItemPath to (path to temporary items as text) & "RTFData.txt"
set fileRef to (open for access file temporaryItemPath with write permission)
try
write RTFData to fileRef
set RTFText to (read fileRef from 1 as «class utf8»)
close access fileRef
return RTFText
on error errmsg
close access fileRef
display dialog errmsg
end try
end clipboard_as_raw_RTF
clipboard_as_raw_RTF()
Edit: Or, come to think of it, there’s this:
use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
on clipboard_as_raw_RTF()
set pasteboard1 to current application's class "NSPasteboard"'s generalPasteboard()'s pasteboardItems()'s firstObject()
if ((pasteboard1's types()'s containsObject:("public.rtf")) as boolean) then
set RTFData to pasteboard1's dataForType:("public.rtf")
set RTFText to current application's class "NSString"'s alloc()'s ¬
initWithData:(RTFData) encoding:(current application's NSUTF8StringEncoding)
return RTFText as text
end if
return missing value
end clipboard_as_raw_RTF
clipboard_as_raw_RTF()
use framework "Foundation"
use framework "AppKit"
use scripting additions
set thePasteboard to current application's NSPasteboard's generalPasteboard()
set theData to (thePasteboard's dataForType:(current application's NSPasteboardTypeRTF)) -- or NSRTFPboardType prior to 10.14
return (current application's NSString's alloc()'s initWithData:(theData) encoding:(current application's NSUTF8StringEncoding)) as string
Yes, that’s briefer! Looking at the documentation again, I see that dataForType: acts on the first pasteboard item anyway and returns missing value if the requested data type isn’t there. So much of my code isn’t necessary. But I personally would prefer to return missing value rather than an empty string if there’s no RTF data:
use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
on clipboard_as_raw_RTF()
set thePasteboard to current application's NSPasteboard's generalPasteboard()
set theData to (thePasteboard's dataForType:(current application's NSPasteboardTypeRTF))
if (theData is missing value) then return theData -- If no RTF data.
return (current application's NSString's alloc()'s initWithData:(theData) encoding:(current application's NSUTF8StringEncoding)) as text
end clipboard_as_raw_RTF
clipboard_as_raw_RTF()
I liked the latest edit from @Nigel_Garvey. Unfortunately, I could only mark 1 post as a solution, and that post was by @ionah. This solution will come in handy as the best alternative to my 1st plain-Apple script in the original question.
COMMENT:
I noticed that my plain-AppleScript returns a result in which the newline character is RETURN, and in the AsObjC version it is LINEFEED. I wonder which of the 2 uses the original source symbol and which one modifies it. Maybe it doesn’t matter, I’m not sure.
The relevant code’s “0A” in the hexadecimal, so it’s a linefeed there. The returns are probably coming from do shell script, which renders line endings as returns unless without altering line endings is used.