Skip to main content
TheRat1956
Participating Frequently
November 21, 2022
Answered

Variable visibility inside a LUA plugin function.

  • November 21, 2022
  • 1 reply
  • 1135 views

I am new to lua and am trying to create a plugin to assist my use of keywords in Lightroom Classic.  I am creating my own UI for this tool and intend to include buttons to activate certain functions.  However I am having problems getting a keyword variable to be visible inside a function attached as an action to a button.  I can get a string variable passed in no problem, but not a keyword variable.

Here is the code, the variable KeywordIn is one of the top level kewwords in my catalog -

 

local function show_Dialog(KeywordIn)
local kw_In_Name = KeywordIn:getName()
outputToLog("in show_Dialog, input keyword - " .. kw_In_Name )
LrFunctionContext.callWithContext( "show_Dialog", function( context )
local props = LrBinding.makePropertyTable( context )
props.myObservedString = "Birds (Aves)"
local f = LrView.osFactory()
local staticTextValue = f:static_text {
title = props.myObservedString,
}
local updateField = f:edit_field {
immediate = true,
value = props.myObservedString -- "Birds (Aves)"
}
local c = f:column {
spacing = f:dialog_spacing(),
f:row {
f:static_text {
alignment = "right",
width = LrView.share "label_width",
title = "Class to be Searched: "
},
updateField,
f:push_button {
title = "Run",
-- When the 'Run' button is clicked.
action = function()
outputToLog( "Run button clicked." )
staticTextValue.text_color = LrColor ( 0, 0, 0)
props.myObservedString = updateField.value
local kwClassName = updateField.value
outputToLog("Data from Field - " .. kwClassName)
outputToLog("keyword Inputted, name passed as string - " .. kw_In_Name)
outputToLog("keyword Inputted, name from getName - " .. KeywordIn:getName() )
end
},
}, -- end of row
} -- end of column
LrDialogs.presentModalDialog {
title = "Trial Dialog",
contents = c
}

end)
end

When I run this plugin it works fine until I click on the run button.  All works apart from the line outputting the keyword name using getName, which is not printed to the debug viewer.

Can anyone tell me what I am doing wrong please?

 

Pete Rowland

This topic has been closed for replies.
Correct answer johnrellis

This code is just a trial to get the button code working, I'm using your debugger on other codes to get my head around it.  I'm working around the original problem by using the dialog to just return string data and then running the active code in the main task, using LrTasks.startAsyncTask.


Sorry, thinko on my part.  The task should be created inside the action function:

action = function() LrTasks.startAsyncTask (function ()
    outputToLog( "Run button clicked." )
    staticTextValue.text_color = LrColor ( 0, 0, 0)
    props.myObservedString = updateField.value
    local kwClassName = updateField.value
    outputToLog("Data from Field - " .. kwClassName)
    outputToLog("keyword Inputted, name passed as string - " .. kw_In_Name)
    outputToLog("keyword Inputted, name from getName - " .. KeywordIn:getName() )
    end) end

 

1 reply

johnrellis
Legend
November 21, 2022

[This post contains formatting and embedded images that don't appear in email. View the post in your Web browser.]

 

The callback functions passed to LrView methods are generally called from the main task, including the "action" function of an f:push_button().  But most of the methods of LrKeyword (and many other SDK objects) must be called from what the API documentation calls an "asynchronous" task"

An "asynchronous" task is simply one created by LrTask.

 

When one of these methods is executed on the main task, you'll get this mysterious runtime error:

 

You're not seeing that because LR silently stops execution of the task and doesn't display an error message.  If you want errors to be trapped and an error message to be display, you'll need to use this idiom to wrap the body of every tasks and callback function:

LrFunctionContext.callWithContext ("", function (context)
    LrDialogs.attachErrorDialogToFunctionContext (context)
    ...your code...
    end)

  

Pretty tedious. Or you can use my lightweight debugging toolkit, which provides the more concise Debug.showErrors() that does the same thing.  For example:

action = showErrors (function()
    outputToLog( "Run button clicked." )
    ...                   
    end)}}}

 

In general, it's very difficult to develop LR plugins with just print statements. I recommend you either use my toolkit or the Zerobrane IDE.  My toolkit better understands LR's particular task architecture and will give better stack traces, error handling, and pretty-printing of nested tables.  But the Zerobrane is a full-fledged IDE used with many apps that include Lua.

 

To get back to the original problem, the easiest way to implement that action function is run it as a separate task:

action = LrTasks.startAsyncTask (showErrors (function()
    outputToLog( "Run button clicked." )
    ...
    end))

 

johnrellis
Legend
November 21, 2022

Note that with both my toolkit and Zerobrane, you'll need to annotate your code with showErrors() or Zerobrane's equivalent.