Here's a proposal for making a small change to LrKeyword that could relieve pressure from users to improve LR's keywording functionality.
LR 3 and LR 4 have garnered a fair amount of user feedback about keywording issues. Some of the recurrent themes include: a user interface that makes it hard to rearrange large hiearchies, the inability to batch edit keyword attributes, changes in the export behavior of ancestor keywords between versions, lack of spelling correction.
It's pretty clear that Adobe is limited in the resources its willing to devote to the library functionality of LR. Given that constraint, perhaps a more effective way of addressing users' needs is to make a small enhancement to the SDK, providing plugins with complete and fast access to keywords. Plugin authors could then provide the missing functionality, meeting the more specialized needs of different users (e.g. those with large controlled vocabularies).
While plugins rarely work as well as built-in functionality, they usually get the job done. And if the choice is not having the functionality at all, or having it via a plugin...
The changes needed are small -- returning all the attributes of a keyword, allowing all of the attributes of a keyword to be changed, and providing batch access. These changes are backward compatibile and could be introduced in 4.1 or 4.2.
Here's a detailed proposal:
* keyword:getAttributres () [change to return all attributes]
Returns a table with these fields:
- keywordName (string) The name of the keyword.
- synonyms (array of string) The names of synonyms.
- includeOnExport (boolean) True to include the keyword on export.
- exportContainingKeywords (boolean) True to export the keyword's ancestors.
- localIdentifier (integer) The identifier of this keyword, unique within the catalog.
- parent (LrKeyword) The parent of this keyword.
- children (array of LrKeyword) The children of this keyword.
* keyword:setAttributes (keywordInfo) [change to allow all attributes to be set]
Sets the fields of the keyword with the fields from "keywordInfo", a table containing the same fields as returned by keyword:getAttributes(). If a field's value is nil, the field value is not changed. Returns true on success; false if there's another keyword with the same name and parent, if "parent" is currently a descendent of this keyword, or if one of the keywords in "keywordInfo.children" is an ancestor of this keyword. [The current setAttributes() ignores attempted changes to "keywordName".]
(If LR were to allow the SDK to make arbitrary changes to "includeOnExport" in the hierarchy and respect those values on export, while enforcing its "privacy" constraints in the user interface, LR users could have their cake and eat it too. The typical user would get the privacy constraints Adobe thinks are important, while sophisticated users with large hierarchies could use hidden mid-level keywords.)
* catalog:createKeyword (args) [change to allow all attributes to be set]
Args is a table with the same fields as returned by keyword:getAttributes(). (The current signature of createKeyword() is also allowed for backward compatibility.)
* catalog:batchGet (keyword) [new]
Returns a table whose keys are LrKeywords, representing "keyword" and all of its descendants. The value of each key is a table, the result of keyword:getAttributes(). If "keyword" is nil, then the entire set of keywords in the catalog is returned.
* catalog:batchSet (table) [new]
"table" is a table whose keys are LrKeywords. The value of each key is a table "keywordInfo", as described in getAttributes(). Invokes keyword:setAttributes (table [keyword]) for each of the keywords in "table". Returns true on success, false if any of the "keywordInfo" values are invalid (see setAttributes()).
The batch operations are essential for working with large controlled vocabularies, which can have more than 70,000 keywords. LR 4 made a low-level change to its Windows event-loop processing, so that on both Windows and Mac, plugins can now access the full keyword attributes via the :get() methods at a rate of about 600 keywords/second. This is still way too slow for working with the large vocabularies. In comparison, catalog:batchGetRawMetadata () can return information on several thousand photos per second.