Merge pull request #303 from olofhellman/master

more scriptable properties for feeds, accounts and authors
This commit is contained in:
Brent Simmons 2018-01-20 16:12:01 -08:00 committed by GitHub
commit 982b2d2d3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 206 additions and 4 deletions

View File

@ -138,6 +138,11 @@
D5907D972004B7EB005947E5 /* Account+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5907D962004B7EB005947E5 /* Account+Scriptability.swift */; };
D5907DB22004BB37005947E5 /* ScriptingObjectContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5907DB12004BB37005947E5 /* ScriptingObjectContainer.swift */; };
D5907DB32005F45D005947E5 /* AppleEventUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5558FD7200228B80066386B /* AppleEventUtils.swift */; };
D5A2678C20130ECF00A8D3C0 /* Author+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A2678B20130ECF00A8D3C0 /* Author+Scriptability.swift */; };
D5A2679C201312F900A8D3C0 /* testNameOfAuthors.applescript in Sources */ = {isa = PBXBuildFile; fileRef = D5A2679B201312F900A8D3C0 /* testNameOfAuthors.applescript */; };
D5A2679D201313A200A8D3C0 /* testNameOfAuthors.applescript in CopyFiles */ = {isa = PBXBuildFile; fileRef = D5A2679B201312F900A8D3C0 /* testNameOfAuthors.applescript */; };
D5A267C120131B8300A8D3C0 /* testFeedOPML.applescript in Sources */ = {isa = PBXBuildFile; fileRef = D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */; };
D5A267C220131BA000A8D3C0 /* testFeedOPML.applescript in CopyFiles */ = {isa = PBXBuildFile; fileRef = D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */; };
D5D1751220020B980047B29D /* Evergreen.sdef in Resources */ = {isa = PBXBuildFile; fileRef = D5D175012002039D0047B29D /* Evergreen.sdef */; };
D5F4EDB5200744A700B9E363 /* ScriptingObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB4200744A700B9E363 /* ScriptingObject.swift */; };
D5F4EDB720074D6500B9E363 /* Feed+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */; };
@ -439,6 +444,8 @@
dstPath = TestScripts;
dstSubfolderSpec = 7;
files = (
D5A267C220131BA000A8D3C0 /* testFeedOPML.applescript in CopyFiles */,
D5A2679D201313A200A8D3C0 /* testNameOfAuthors.applescript in CopyFiles */,
D5F4EDE920075C6700B9E363 /* testNameAndUrlOfEveryFeed.applescript in CopyFiles */,
D5F4EDEA20075C6700B9E363 /* testNameOfEveryFolder.applescript in CopyFiles */,
D5907CA2200232AD005947E5 /* testGenericScript.applescript in CopyFiles */,
@ -579,6 +586,9 @@
D5907D7E2004AC00005947E5 /* NSApplication+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSApplication+Scriptability.swift"; sourceTree = "<group>"; };
D5907D962004B7EB005947E5 /* Account+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Account+Scriptability.swift"; sourceTree = "<group>"; };
D5907DB12004BB37005947E5 /* ScriptingObjectContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptingObjectContainer.swift; sourceTree = "<group>"; };
D5A2678B20130ECF00A8D3C0 /* Author+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Author+Scriptability.swift"; sourceTree = "<group>"; };
D5A2679B201312F900A8D3C0 /* testNameOfAuthors.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = testNameOfAuthors.applescript; sourceTree = "<group>"; };
D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = testFeedOPML.applescript; sourceTree = "<group>"; };
D5D175012002039D0047B29D /* Evergreen.sdef */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = Evergreen.sdef; path = ../Resources/Evergreen.sdef; sourceTree = "<group>"; };
D5F4EDB4200744A700B9E363 /* ScriptingObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptingObject.swift; sourceTree = "<group>"; };
D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Feed+Scriptability.swift"; sourceTree = "<group>"; };
@ -1115,8 +1125,10 @@
isa = PBXGroup;
children = (
D5907C9D20023249005947E5 /* testGenericScript.applescript */,
D5A267B220131B8300A8D3C0 /* testFeedOPML.applescript */,
D5558FD1200223F60066386B /* testGetURL.applescript */,
D5F4EDE720075C1800B9E363 /* testNameAndUrlOfEveryFeed.applescript */,
D5A2679B201312F900A8D3C0 /* testNameOfAuthors.applescript */,
D5F4EDD720075C1300B9E363 /* testNameOfEveryFolder.applescript */,
);
path = scripts;
@ -1147,6 +1159,7 @@
isa = PBXGroup;
children = (
D5907D962004B7EB005947E5 /* Account+Scriptability.swift */,
D5A2678B20130ECF00A8D3C0 /* Author+Scriptability.swift */,
D5F4EDB620074D6500B9E363 /* Feed+Scriptability.swift */,
D5F4EDB820074D7C00B9E363 /* Folder+Scriptability.swift */,
D5907D7E2004AC00005947E5 /* NSApplication+Scriptability.swift */,
@ -1551,6 +1564,7 @@
84CC88181FE59CBF00644329 /* SmartFeedsController.swift in Sources */,
849A97661ED9EB96007D329B /* SidebarViewController.swift in Sources */,
849A97641ED9EB96007D329B /* SidebarOutlineView.swift in Sources */,
D5A2678C20130ECF00A8D3C0 /* Author+Scriptability.swift in Sources */,
84F2D5371FC22FCC00998D64 /* PseudoFeed.swift in Sources */,
845EE7C11FC2488C00854A1F /* SmartFeed.swift in Sources */,
84702AA41FA27AC0006B8943 /* MarkReadOrUnreadCommand.swift in Sources */,
@ -1626,6 +1640,8 @@
D5558FD5200225680066386B /* NSAppleEventDescriptor+UserRecordFields.swift in Sources */,
D5558FD9200228D30066386B /* AppleEventUtils.swift in Sources */,
D5907CA1200232A1005947E5 /* testGetURL.applescript in Sources */,
D5A267C120131B8300A8D3C0 /* testFeedOPML.applescript in Sources */,
D5A2679C201312F900A8D3C0 /* testNameOfAuthors.applescript in Sources */,
849C64761ED37A5D003D8FC0 /* EvergreenTests.swift in Sources */,
D5558FD32002245C0066386B /* ScriptingTests.swift in Sources */,
D5F4EDE820075C1800B9E363 /* testNameAndUrlOfEveryFeed.applescript in Sources */,

View File

@ -49,6 +49,9 @@
<cocoa key="contents"/>
<type type="account item" list="yes"/>
</property>
<property name="opml representation" code="OPML" type="text" access="r" description="OPML representation for the account">
<cocoa key="opmlRepresentation"/>
</property>
<element type="feed">
<cocoa key="feeds"/>
</element>
@ -62,7 +65,7 @@
<class name="feed" code="Feed" plural="feeds" description="An RSS feeds" inherits="account item">
<cocoa class="ScriptableFeed"/>
<property name="name" code="pnam" type="text" access="r" description="The name of the account">
<property name="name" code="pnam" type="text" access="r" description="The name of the feed">
<cocoa key="name"/>
</property>
<property name="id" code="id " type="text" access="r" description="The unique id of the account">
@ -71,6 +74,39 @@
<property name="url" code="URL " type="text" access="r" description="The type of the account">
<cocoa key="url"/>
</property>
<property name="homepage url" code="HpUr" type="text" access="r" description="url for the feed homepage (optional)">
<cocoa key="homePageURL"/>
</property>
<property name="icon url" code="IcUr" type="text" access="r" description="url for the feed icon (optional)">
<cocoa key="iconURL"/>
</property>
<property name="favicon url" code="FvUr" type="text" access="r" description="url for the feed favicon (optional)">
<cocoa key="faviconURL"/>
</property>
<property name="opml representation" code="OPML" type="text" access="r" description="OPML representation for the feed">
<cocoa key="opmlRepresentation"/>
</property>
<element type="author">
<cocoa key="authors"/>
</element>
</class>
<class name="author" code="Athr" plural="authors" description="A feed author">
<property name="name" code="pnam" type="text" access="r" description="The name of the author">
<cocoa key="name"/>
</property>
<property name="id" code="id " type="text" access="r" description="The unique id of the author">
<cocoa key="uniqueId"/>
</property>
<property name="url" code="URL " type="text" access="r" description="url for the author">
<cocoa key="url"/>
</property>
<property name="avatar url" code="AvUr" type="text" access="r" description="url for the author avatar (optional)">
<cocoa key="avatarURL"/>
</property>
<property name="email address" code="eMal" type="text" access="r" description="email address for the author avatar (optional)">
<cocoa key="emailAddress"/>
</property>
</class>
<class name="folder" code="fold" plural="folders" description="A folder for organizing feeds" inherits="account item">
@ -81,6 +117,9 @@
<property name="id" code="id " type="integer" access="r" description="The unique id of the account">
<cocoa key="uniqueId"/>
</property>
<property name="opml representation" code="OPML" type="text" access="r" description="OPML representation for the folder">
<cocoa key="opmlRepresentation"/>
</property>
</class>
</suite>

View File

@ -74,7 +74,12 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
}
return contentsArray as NSArray
}
@objc(opmlRepresentation)
var opmlRepresentation:String {
return self.account.OPMLString(indentLevel:0)
}
@objc(accountType)
var accountType:OSType {
var osType:String = ""

View File

@ -0,0 +1,71 @@
//
// Author+Scriptability.swift
// Evergreen
//
// Created by Olof Hellman on 1/19/18.
// Copyright © 2018 Olof Hellman. All rights reserved.
//
import Foundation
import Account
import Data
@objc(ScriptableAuthor)
class ScriptableAuthor: NSObject, UniqueIdScriptingObject {
let author:Author
let container:ScriptingObjectContainer
init (_ author:Author, container:ScriptingObjectContainer) {
self.author = author
self.container = container
}
@objc(objectSpecifier)
override var objectSpecifier: NSScriptObjectSpecifier? {
let scriptObjectSpecifier = self.container.makeFormUniqueIDScriptObjectSpecifier(forObject:self)
return (scriptObjectSpecifier)
}
// MARK: --- ScriptingObject protocol ---
var scriptingKey: String {
return "authors"
}
// MARK: --- UniqueIdScriptingObject protocol ---
// I am not sure if account should prefer to be specified by name or by ID
// but in either case it seems like the accountID would be used as the keydata, so I chose ID
var scriptingUniqueId:Any {
return author.authorID
}
// MARK: --- Scriptable properties ---
@objc(url)
var url:String {
return self.author.url ?? ""
}
@objc(uniqueId)
var uniqueId:String {
return self.author.authorID
}
@objc(name)
var name:String {
return self.author.name ?? ""
}
@objc(avatarURL)
var avatarURL:String {
return self.author.avatarURL ?? ""
}
@objc(emailAddress)
var emailAddress:String {
return self.author.emailAddress ?? ""
}
}

View File

@ -11,7 +11,7 @@ import Account
import Data
@objc(ScriptableFeed)
class ScriptableFeed: NSObject, UniqueIdScriptingObject {
class ScriptableFeed: NSObject, UniqueIdScriptingObject, ScriptingObjectContainer{
let feed:Feed
let container:ScriptingObjectContainer
@ -41,7 +41,13 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject {
var scriptingUniqueId:Any {
return feed.feedID
}
// MARK: --- ScriptingObjectContainer protocol ---
var scriptingClassDescription: NSScriptClassDescription {
return self.classDescription as! NSScriptClassDescription
}
// MARK: --- Scriptable properties ---
@objc(url)
@ -59,4 +65,30 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject {
return self.feed.name ?? ""
}
@objc(homePageURL)
var homePageURL:String {
return self.feed.homePageURL ?? ""
}
@objc(iconURL)
var iconURL:String {
return self.feed.iconURL ?? ""
}
@objc(faviconURL)
var faviconURL:String {
return self.feed.faviconURL ?? ""
}
@objc(opmlRepresentation)
var opmlRepresentation:String {
return self.feed.OPMLString(indentLevel:0)
}
@objc(authors)
var authors:NSArray {
let feedAuthors = feed.authors ?? []
return feedAuthors.map { ScriptableAuthor($0, container:self) } as NSArray
}
}

View File

@ -53,4 +53,9 @@ class ScriptableFolder: NSObject, UniqueIdScriptingObject {
return self.folder.name ?? ""
}
@objc(opmlRepresentation)
var opmlRepresentation:String {
return self.folder.OPMLString(indentLevel:0)
}
}

View File

@ -57,7 +57,11 @@ class ScriptingTests: XCTestCase {
}
XCTAssert(testResult.booleanValue == true, "test_result should be true")
if (testResult.booleanValue != true )
{
print("test_result was \(testResult)")
print("script_result was \(String(describing: usrfDictionary["script_result"]))")
}
return usrfDictionary["script_result"]
}
@ -85,5 +89,13 @@ class ScriptingTests: XCTestCase {
func testNameOfEveryFolderScript() {
_ = doIndividualScript(filename: "testNameOfEveryFolder")
}
func testNameOfAuthorsScript() {
_ = doIndividualScript(filename: "testNameOfAuthors")
}
func testNameOfAuthorsScript() {
_ = doIndividualScript(filename: "testFeedOPML")
}
}

View File

@ -0,0 +1,10 @@
-- this script just tests that no error was generated from the script
try
tell application "Evergreen"
opml representation of feed 1 of account 1
end tell
on error message
return {test_result:false, script_result:message}
end try
return {test_result:true}

View File

@ -0,0 +1,12 @@
-- this script just tests that no error was generated from the script
-- and that the returned list is greater than 0
try
tell application "Evergreen"
set namesResult to name of every author of every feed of every account
end tell
set test_result to ((count items of namesResult) > 0)
on error message
return {test_result:false, script_result:message}
end try
return {test_result:test_result}