Question

My first post…

I am using a python script to get the text from the clipboard on Mac OS X Lion.

I set the clipboard with the following function:

def setClip (text):
    pb = NSPasteboard.generalPasteboard()
    pb.clearContents()
    a = NSArray.arrayWithObject_(text)
    return pb.writeObjects_(a)

where text = "some text"

I retrieve the clipboard with the following:

def getClip():
    pb = NSPasteboard.generalPasteboard()
    pbstring = pb.stringForType_(NSString *)dataType
    return pbstring

The output is prepended with a "u" with the text surrounded in quotation marks as follows:

In [224]: setClip('some text')
Out[224]: True

In [225]: getClip()
Out[225]: "u'some text'"

How do I retrieve the text as it was supposedly entered to the clipboard?

I know nothing about NSPasteboard. I found these snippets of code on stackoverflow.

Thanks in advance.

Addendum: my actual code

    from AppKit import *
    def setClip (text):
        pb = NSPasteboard.generalPasteboard()
        pb.clearContents()
        a = NSArray.arrayWithObject_(text)
        return pb.writeObjects_(a)

    def getClip():
        pb = NSPasteboard.generalPasteboard()
        pbstring = pb.stringForType_(NSString *)dataType
        return pbstring

And this is what happens when I run it in ipython:

The output is prepended with a "u" with the text surrounded in quotation marks as follows:

In [224]: setClip('some text')
Out[224]: True

In [225]: getClip()
Out[225]: "u'some text'"

tried a suggestion from the answer***

def getClip():
    pb = NSPasteboard.generalPasteboard()
    return pb.stringForType_("public.utf8-plain-text")

In [332]: getClip()
Out[332]: u"some text"

No go. :-(

YES. I just needed to do this:

print getClip()

And I now have

"some text"
Was it helpful?

Solution

If you know nothing about NSPasteboard, you should skim the Pasteboard Programming Guide, and look at the NSPasteboard Class Reference for details.

The code you've given us cannot possibly be the code you're running, because:

pbstring = pb.stringForType_(NSString *)dataType

This is not valid Python. It's somewhere half-way between ObjC and Python. So it'll just raise a SyntaxError. And even if I turn it into something sensible:

pbstring = pb.stringForType_(dataType)

Or, if you want to be explicit:

pbstring = pb.stringForType_(NSString.stringWithString_(dataType))

This will just be a NameError, because you haven't defined dataType anywhere.

So, where do you get dataType from? Well, the reference for stringForType: makes that pretty clear:

You must send types or availableTypeFromArray: before invoking stringForType:.

So, what if we call pb.types()? We get back a list of strings, something like this:

Out[153]: 
(
    "NeXT smart paste pasteboard type",
    "com.apple.webarchive",
    "NeXT Rich Text Format v1.0 pasteboard type",
    "public.utf8-plain-text",
    NSStringPboardType,
    …
)

A few of the built-in types won't come back as string literals like u"public.utf8-plain-text", but as string constants from one of the Cocoa libraries, likeNSStringPboardType. If you've donefrom AppKit import *,from Cocoa import *, or similar, you can just refer to it asNSStringPboardType`.

Anyway pick something that looks reasonable and use it:

In [156]: pb.stringForType_(NSStringPboardType)
Out[156]: u'some text'

Everything is fine!

So, why are you getting "u'some text'" instead of just u'some text'? My guess is that, in your real code, either setClip or getClip is doing an extra repr(s) somewhere. For example:

In [165]: s=u'some text'

In [166]: repr(s)
Out[166]: "u'some text'"

In [167]: s
Out[167]: u'some text'

Out[166] may look familiar to you. Most likely, you've done the equivalent in your code. But since you haven't done it in the code you showed us, we can't guess where.

The right way to write getClip() is to make a list of types in your order of preference, then do something like this:

def getClip():
    pb = NSPasteboard.generalPasteboard()
    best_type = pb.availableTypeFromArray_(myFavoriteTypes)
    if best_type:
        return pb.stringForType_(best_type)

This may seem like a pain, and unnecessary. Can't you just do return pb.stringForType_(best_type[0]) and skip that whole availableTypeFromArray_ nonsense? In practice, if the type you want is NSStringPboardType, you will get away with it with every version of OS X so far, with probably every program in the universe, because it just doesn't make sense to put text on the clipboard and not make it available in that format. But it's still wrong, and a bad habit to get into. (Besides, maybe you'd actually prefer to get UTF-8 bytes instead of a Unicode string, which may be easier to deal with in Python 2.x, or more efficient in 3.3.)

When you do things right, if you just type getClip() at the console, you will see u'some text' instead of 'u"some text"'. "But hold on", you say, "there's still a 'u' and a pair of quotes there, even if there aren't two pairs of quotes anymore, so it's still broken!" No, it's not. Take a look at this:

In [182]: s=u'some text'

In [183]: s
Out[183]: u'some text'

In [184]: print s
some text

Or this:

In [185]: s='some text'

In [186]: s
Out[186]: 'some text'

In [187]: print s
some text

Whenever you just type a string (or a function that returns a string) at the interactive console, it prints out the string with quotes. But the quotes aren't actually in the string—as you can see when you use the print statement explicitly.

So, if you see this:

In [332]: getClip()
Out[332]: u"some text"

That's actually correct. It's the same as the s=u'some text' example above. There are no quotes, or u characters, in your string; that's just the way the interactive interpreter shows strings that you type at the command line. To verify it, just print the result:

In [332]: print getClip()
some text

Or store it in a file:

In [188]: with open('test.txt', 'w') as f:
   .....:     f.write(getClip())
   .....:

Now open test.txt in your text editor—no quotes, no u.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top