While it turned out to be eminently doable, my recent query about flagging text in a document that would not be included in the document’s word count got me thinking about what kinds of AppleScript functions and properties might be useful. The pseudo-code below illustrates strawman approaches to:
- referring to a Scrivener project in different ways
- referring to documents in a project in different ways
- retrieving properties from a project
- retrieving and processing text in a document
- and extending the Outliner with a column named “AppleScript Results” that could contain the results of AppleScripts.
(The task itself is not the point.) Hope this is useful.
[code]-- strawman AppleScript pseudo-code that proposes ways of selecting documents, getting properties of a project, and processing text in documents,
– and proposes a custom column in the outliner that is dedicated to displaying the results of an AppleScript.
– the example task is counting the number of “manuscript words” in selected documents of a Scrivener project
– (“manuscript words”: the total number of words in the selected documents, less the total number of words that are in inline annotations).
– it’s just food for thought.
tell application “Scrivener”
– ==============================
– get a reference to a project. this could be done in a number of ways, such as:
– refer to the frontmost project:
set p to frontmost project
-- could also refer to a project by index:
set p to project 1
-- could also refer to a project by name, assuming that it is open:
set p to "My Great Novel"
-- could also refer to a project by path:
set p to "~/Library/Documents/My Great Novel/My Great Novel.scriv"
-- could also call up a Scrivener AppleScript dialog box to find and select a project (like calling "choose file" from standard additions):
set p to choose project "Select a project:"
-- ==============================
-- get the attributes that are used in the project to show inline annotations.
-- this is an example definition that uses color, background color, font, typeface (i.e., bold, etc.), and font size.
set attrs to {color, bgcolor, font, typeface, size} of inline annotations of p
-- an alternate way to get these attributes:
set attrs to attributes of inline annotations of p
-- ==============================
-- look in each of the selected documents in the target project,
-- and find the number of words that are formatted with the inline annotation's attributes. also, tally up the total number of words in the selected documents as we go.
-- refer to all of the currently selected documents:
set theSelection to selection of p
-- could also refer to them by their names:
set theSelection to {"Document 1", "Document 26", "Another document"} of manuscript folder of p
-- allow an arbitrary set of documents too, by using a parent/child structure of documents within folders.
-- ("manuscript folder" is a constant that can be used to refer to the manuscript folder, no matter what it is named):
set theSelection to {"Document 1", "Opening scene", "Another document"} of manuscript folder of p
set theSelection to theSelection & {"Some doc", "Theory of everything"} of folder "Notes" of project p
-- use collections, too, and allow selecting documents by index as well:
set theSelection to theSelection & document 2 of collection "My collection" of project p
-- or, could select all of the documents in a collection, folder, etc.
set theSelection to all of the documents in collection “My Collection”
set theSelection to all of the documents in folder “Folder 5”
-- a project browser would be useful, too -- this would call up a browser and
-- return a list of all of the documents selected by the user:
set theSelection to select documents of project p
-- count the manuscript words in each document.
set results to {}
repeat with ctr from 1 to count of documents in theSelection
set doc to document ctr of theSelection
set foundInDoc to 0
-- note that "words" would have to be returned from Scrivener, so that a script doesn't calculate
-- word count in some different way.
repeat with w from 1 to words in doc
set match to matchAttributes (attributes of w, attrs)
if match = true then
-- found a word in an inline annotation.
set foundIndoc to foundInDoc + 1
end if
end repeat
-- save the document name & counts.
set results to results & {name:name of doc, totalWords: count of words in doc, inlineWords: foundIndoc}
-- prepare the report.
set str to "Document: " & name of item ctr of results & return & ¬
tab & "Total words: " & (totalwords of item ctr of results as string)" & return & ¬
tab & "Inline annotated words: " & (inlineWOrds of item ctr of results as string) & return & ¬
tab & "Manuscript words: " & (totalwords of item ctr of results - inlineWords of item ctr of results as string) & return & return
set totalManuscriptWords to totalManuscriptWords + (totalwords of item ctr of results - inlineWords of item ctr of results)
end repeat
-- report the results.
display dialog str & return & return & "Grand total of manuscript words in " & name of p & ": " & manuscriptWords as string
-- if the outliner is being viewed, put the counts in the "AppleScript Results" column for all of the documents processed.
-- "outline" is a constant.
if current view = outline then
-- "AppleScript Results" is a constant
set name of column AppleScript Results of outline of project p to "Manuscript words"
repeat with ctr from 1 to count of items in results
repeat with outlineCtr from 1 to number of items in outline of project p
if name of item ctr of theSelection = name of item outlineCtr of outline of project p then
set text of column "Manuscript words" of outline of p to (totalwords of item ctr of results - inlineWords of item ctr of results as string)
else
set text of column "Manuscript words" to "(Not calculated)"
end if
end repeat
end repeat
end if
end tell
– ==============================
on matchAttributes (w, attrs)
– return true if the attributes of the passed word match the attributes contained in attr,
– return false if they do not match.
– this is just an example way of doing this. this function could also be a Scrivener function.
if color of w = color of attrs and bgcolor of w = bgcolor of attrs and font of w = font of attrs and typeface of w = typeface of attrs size of w = size of attrs then
set res to true
else
set res to false
end if
return res
end matchAttributes
[/code]