Search code examples
macoscocoaapplescriptcocoa-scripting

Support "styled text" in a scriptable Mac application (Cocoa Scripting)


My app supports being scripted with Applescript.

I am trying to make styled text content, stored in NSAttributedString objects, available to an Applescript user.

I thought I could simply deliver styled text with the NSAttributedString class, just like I deliver plain text with the NSString class, but that does not work - Cocoa Scripting then reports that it cannot convert or coerce the data.

I wonder if I'm missing something or if this is just plain impossible with the standard classes supported by Cocoa Scripting?

AppleScript does know the "styled text" type, as seen in this example:

set stxt to "foo" as styled text

So, if AppleScript knows this type by default, shouldn't the Cocoa Scripting engine support it as well somehow?


Solution

  • As always there are many choices for solving an AS problem. In my scriptable text editor (Ted), I implemented the Text Suite, which is based on rich text (NSTextStorage, a subclass of NSMutableAttributedString). I wanted to be able to script tabs in my paragraphs, so I added a style record, which contains all the paragraph style information. This lets me write scripts like this:

    tell application "Ted"
        set doc1 to make new document at beginning with properties {name:"Document One"}
        tell doc1
            set p1 to make new paragraph at end with data "Paragraph One" with properties {size:24, color:maraschino}
            set p2 to make new paragraph at end with data "Paragraph Two" with properties {style:style of paragraph 1}
            set color of paragraph 1 to blue
        end tell
    
        set doc2 to make new document at beginning with properties {name:"Document Two"}
        copy p1 to beginning of doc2
        properties of paragraph 1 of doc2       
    end tell
    

    Since p1 is rich text, the second document ends up with both the text and formatting of the first paragraph of the first document.

    You can also ask for the properties of a piece of text, where I have implemented the usual Text Suite properties, as well as a "style" property for paragraph style (backed by NSParagraphStyle, since I wanted to be able to script the tab stops):

    properties of paragraph 1 of doc2       
    

    Result: {height:60.0, italic:false, size:24, style:{paragraph spacing after:0.0, head indent:0.0, line break mode:0, alignment:4, line spacing:0.0, minimum line height:0.0, first line head indent:0.0, paragraph spacing before:0.0, tabs:{"28L", "56L", "84L", "112L", "140L", "168L", "196L", "224L", "252L", "280L", "308L", "336L"}, tail indent:0.0, maximum line height:0.0, line height multiple:0.0, default tab interval:0.0}, color:blue, width:164.109375, font:"Helvetica", bold:false, class:attribute run}

    This works well for passing rich text within my application, but may not be as useful for passing styled text to other applications, which may be what you wanted to do. I think adding a "style" property (of type record) is probably the best way to convey style info for use in other scriptable apps. Then in the second app, the scripter can make use of any properties in the style record that the second app understands.