Skip to main content
Inspiring
April 21, 2026
Pregunta

Debuging a plugin for lightroom 6.4

  • April 21, 2026
  • 3 respuestas
  • 32 visualizaciones
local LrDialogs = import 'LrDialogs'
local LrTasks = import 'LrTasks'
local LrApplication = import 'LrApplication'

local function getCollectionPath(collection)
local path = {}
local current = collection

while current do
table.insert(path, 1, current:getName())
current = current:getParent()
end
return path
end

local function createKeywordFromPath(path)
if #path==0 then
return ""
elseif #path==1 then
return path[1] -- just collection name
else
local keyword = ""
for i = 1, #path do
if i == 1 then
keyword = path[i]
else
keyword = keyword .. "|" .. path[i]
end
end
return keyword
end
end

local function processCollections(collections, progressScope)
for _, collection in ipairs(collections) do
if progressScope:isCanceled() then
return
end
if collection:type() == "LrCollectionSet" then
local childCollections = collection:getChildCollections()
local childCollectionSets = collection:getChildCollectionSets()

processCollections(childCollections, progressScope)
processCollections(childCollectionSets, progressScope)

else
progressScope:setCaption("Processing: " .. collection:getName())

if not collection:isSmartCollection() then
local photos = collection:getPhotos()
local collectionPath = getCollectionPath(collection)
local keyword = createKeywordFromPath(collectionPath)

if keyword ~= "" and #photos > 0 then
progressScope:setCaption("Adding keyword'" .. keyword .. "' to " .. #photos .. "photos")

for _, photo in ipairs(photos) do
if progressScope:isCanceled() then
return
end
local currentKeywords = photo:getFormattedMetadata('keywordTags') or ""
local keywords = {}
if currentKeywords ~= "" then
for kw in string.gmatch(currentKeywords, "[^,]+") do
local trimmed = string.match(kw, "%s*(.-)%s*$")
if trimmed ~= "" then
table.insert(keywords, trimmed)
end
end
end

local keywordExists = false
for _, existingKeyword in ipairs (keywords) do
if existingKeyword == keyword then
keywordExists = true
break
end
end

if not keywordExists then
table.insert(keywords, keyword)
photo:setPropertyForPlugin(_PLUGIN, "tempKeywords", table.concat(keywords, ", "))
local success, errorMessage = pcall(function()
photo:setRawMetadata("keywordTags", table.concat(keywords, ", "))
end)
if not success then
local catalog = LrApplication.activeCatalog()
catalog:setKeywordStringForPhoto(photo, table.concat(keywords, ", "))
end
end
end
end
end
end
end
end

local function collectionToKeyword()
LrTasks.startAsyncTask(function()
local catalog = LrApplication.activeCatalog()

local collections = catalog:getChildCollections()
local collectionSets = catalog:getChildCollectionSets()

local allCollections = {}
for _, collection in ipairs (collections) do
table.insert(allCollections, collection)
end
for _, collectionSet in ipairs (collectionSets) do
table.insert(allCollections, collectionSet)
end

if #allCollections == 0 then
LrDialogs.message ("no collections Found", "no collections in the catalog", "info")
return
end

local result = LrDialogs.confirm(
"Add Collection Keywords",
"This will add collection hierarchy as keywordss to all photos in non -smart collections.\n\n do you want to continue",
"Continue",
"Cancel"
)

if result == "Cancel" then
return
end

local progressScope = LrDialogs.showModalProgressDialog({
title = "Adding Collection Keywords",
functionContext = function(progressScope)
local catalog = LrApplication.activeCatalog()
catalog:withWriteAccessDo("Add collection Keyword", function()
processCollections(allCollections, progressScope)
end)
if not progressScope:isCanceled() then
LrDialogs.message("Complete", "Collection to keywords done successfully!", "info")
end
end
})

end)
end

collectionToKeyword()

my plugin is functional, when I launch it I have the confirmation message (LrDialogs.confirm) but then I get an error ?:0: attempt to index a function value

stuck here.
Goal of my plugin is to auto add keywords to all photos in my collections (couldn’t find any other plugin to do it, i have enough collections so that it’s worth trying to get the plugin working...)

I use Lightroom 6.4 on windows 10, yes I now, old one… classic indeed

 

Thanks for any help

3 respuestas

Inspiring
April 22, 2026

I should I named this thread “Collections to Keyword” but can’t edit the first post.
What I wan’t to achieve is : 

  • for each photos in each collection / sub collection (except dyanmic collection) 
  • add keyword (grandfather_coll_name|)(parent_coll_name|)collname to the photo

I tryied to simplify and verify as I could the syntax here and there. 

I have the first message ok (keyword is collection1, fine), 

 the 

createKeywordFromPath

looks ok

Then I have MSG 4 ok
then “assertion failed on 

photo:addKeyword(keyword)
that function have been called just the line before : 
local function getOrCreateKeyword(catalog, name)
-- search all existing keywords
for _, kw in ipairs(catalog:getKeywords()) do
if kw:getName() == name then
return kw
end
end
-- not found, so create
return catalog:createKeyword(name, {}, false, nil)
end

still, I don’t see the keyword in my catalog keywords.

Here is the code as now
 

local LrDialogs = import 'LrDialogs'
local LrTasks = import 'LrTasks'
local LrApplication = import 'LrApplication'

-- Helper: manually find or create a keyword by name
local function getOrCreateKeyword(catalog, name)
-- search all existing keywords
for _, kw in ipairs(catalog:getKeywords()) do
if kw:getName() == name then
return kw
end
end
-- not found, so create
return catalog:createKeyword(name, {}, false, nil)
end

local function getCollectionPath(collection)
local path = {}
local current = collection

while current do
table.insert(path, 1, current:getName())
current = current:getParent()
end
return path
end

local function createKeywordFromPath(path)
if #path==0 then
return ""
elseif #path==1 then
return path[1] -- just collection name
else
local keyword = ""
for i = 1, #path do
if i == 1 then
keyword = path[i]
else
keyword = keyword .. "|" .. path[i]
end
end
return keyword
end
end

local function processCollections(collections, catalog)

for _, collection in ipairs(collections) do

if collection:type() == "LrCollectionSet" then
local childCollections = collection:getChildCollections()
local childCollectionSets = collection:getChildCollectionSets()

processCollections(childCollections, catalog)
processCollections(childCollectionSets, catalog)

else

if not collection:isSmartCollection() then
local photos = collection:getPhotos()
local collectionPath = getCollectionPath(collection)
local keyword = createKeywordFromPath(collectionPath)

if keyword ~= "" and #photos > 0 then

for _, photo in ipairs(photos) do
local currentKeywords = photo:getFormattedMetadata('keywordTags') or ""
local keywords = {}
if currentKeywords ~= "" then
for kw in string.gmatch(currentKeywords, "[^,]+") do
local trimmed = string.match(kw, "%s*(.-)%s*$")
if trimmed ~= "" then
table.insert(keywords, trimmed)
end
end
end

local keywordExists = false
for _, existingKeyword in ipairs (keywords) do
if existingKeyword == keyword then
keywordExists = true
break
end
end

if not keywordExists then
LrDialogs.message("DEBUG", "keyword = " .. keyword, "info")
getOrCreateKeyword(catalog, keyword)
LrDialogs.message("DEBUG", "MSG 4 " .. keyword, "info")
photo:addKeyword(keyword)
LrDialogs.message("DEBUG", "MSG 5 ", "info")
end
end
end
end
end
end
end

local function collectionToKeyword()
LrTasks.startAsyncTask(function()
local catalog = LrApplication.activeCatalog()

local collections = catalog:getChildCollections()
local collectionSets = catalog:getChildCollectionSets()

local allCollections = {}
for _, collection in ipairs (collections) do
table.insert(allCollections, collection)
end
for _, collectionSet in ipairs (collectionSets) do
table.insert(allCollections, collectionSet)
end

if #allCollections == 0 then
LrDialogs.message ("no collections Found", "no collections in the catalog", "info")
return
end

local result = LrDialogs.confirm(
"Add Collection Keywords",
"This will add collection hierarchy as keywordss to all photos in non -smart collections.\n\n do you want to continue",
"Continue",
"Cancel"
)

if result == "Cancel" then
return
end


catalog:withWriteAccessDo("Add Collection Keyword", function()
processCollections(allCollections, catalog)
end)

end)
end

collectionToKeyword()

 

 

 

Legend
April 22, 2026

@ppphotos 

 

Line 125 result is “cancel” or “ok”, not “Cancel”, so this test is never true.

 

Line 129 your use of LrDialogs.showModalProgressDialog is incorrect. The functionContext is an LrFunctionContext object, not a lua function.

Inspiring
April 22, 2026

thanks, I got rid of progressdialog but still have issue on how to write the keyword….
I’ll keep on trying

johnrellis
Legend
April 22, 2026

[View this post in your web browser. It contains formatting and images that don't appear in email.]

 

Two options for debugging plugins: 

 

- My Debugging Toolkit provides a rudimentary very lightweight debugger that understands LR’s task architecture and provides pretty printing of nested objects.

 

- The Zerobrane IDE provides a more capable external debugger that doesn’t understand LR’s task architecture as well and doesn’t provide (or least didn’t years ago) pretty printing of nested objects.

Inspiring
April 22, 2026

Thanks jhon. I tried both.
I’m not up to the requirements….  debuging toolkit lost me here :
 

  Wrap all functions passed to the SDK API and your main showDialog function with Debug.showErrors. For example:

viewFactory:edit_field {validate = Debug.showErrors (myValidate)}
LrTask.startAsyncTask (Debug.showErrors (function () ...))

the other one here.

Already spend too much time on that. I’ll probably do it by mannually...