Skip to main content
Inspiring
September 9, 2017
Answered

How to load a preset / LrTemplate file into a table variable

  • September 9, 2017
  • 1 reply
  • 961 views

Lightroom stores it's settings in preset file called xxx.lrtemplate.

Question: how to load such a file into a local table variable.

I know I can load a file with LrFileUtils.readFile ( path), but then it is just string.

But how can I load it in a table variable?

For example how to load a keyword lrtemplate file into a table variable

s = {
       id = "0427FE55-2BD3-4DF3-A68B-336D39F4AB9B",
       internalName = "Family",
      title = "Family",
      type = "KeywordSet",
      value = {
           shortcut1title = "John",
           shortcut2title = "Suzan",
           shortcut3title = "Peter",
           shortcut4title = "",
           shortcut5title = "",
           shortcut6title = "",
           shortcut7title = "",
           shortcut8title = "",
           shortcut9title = "",
      },
      version = 0,
}
This topic has been closed for replies.
Correct answer johnrellis

Call loadstring() on the string return by readFile(). That will compile the contents of the string and return a function, which when invoked will execute the Lua statements in the string.

LR uses the convention that its template files are Lua statements assigning to the global variable "s".  So after you execute the template file, the global "s" will be assigned to the table stored in the template.  Assigning to a global variable "s" isn't very polite, but that could be made completely safe by using Lua's setfenv(); but unfortunately, LR doesn't provide setfenv().  As a practical matter, copying the value of "s" immediately after executing the loadstring() function is safe enough, since the task scheduler is non-preemptive.

If you really wanted to be compulsive, you could strip off the "s = " and replace it with "return ". Then when you executed the loadstring() function, it would return the value in the string.  Some of my plugins store Lua constant expressions (e.g. tables) in files, and it uses this method to read them.  E.g.

--[[----------------------------------------------------------------------------

public any value, string errorMsg

stringToValue (string s)

Executes the string "s" (created by valueToString (v)) to return a value

equivalent to "v".  If no error occurs, returns <value, nil>; otherwise

returns <nil, errorMsg>.

------------------------------------------------------------------------------]]

function Util.stringToValue (s)

    local chunk, errorMsg = loadstring ("return " .. s)

    if not chunk then return nil, errorMsg end

    local success, v = pcall (chunk)

    if not success then return nil, v end

    return v, nil

    end

1 reply

johnrellis
johnrellisCorrect answer
Legend
September 9, 2017

Call loadstring() on the string return by readFile(). That will compile the contents of the string and return a function, which when invoked will execute the Lua statements in the string.

LR uses the convention that its template files are Lua statements assigning to the global variable "s".  So after you execute the template file, the global "s" will be assigned to the table stored in the template.  Assigning to a global variable "s" isn't very polite, but that could be made completely safe by using Lua's setfenv(); but unfortunately, LR doesn't provide setfenv().  As a practical matter, copying the value of "s" immediately after executing the loadstring() function is safe enough, since the task scheduler is non-preemptive.

If you really wanted to be compulsive, you could strip off the "s = " and replace it with "return ". Then when you executed the loadstring() function, it would return the value in the string.  Some of my plugins store Lua constant expressions (e.g. tables) in files, and it uses this method to read them.  E.g.

--[[----------------------------------------------------------------------------

public any value, string errorMsg

stringToValue (string s)

Executes the string "s" (created by valueToString (v)) to return a value

equivalent to "v".  If no error occurs, returns <value, nil>; otherwise

returns <nil, errorMsg>.

------------------------------------------------------------------------------]]

function Util.stringToValue (s)

    local chunk, errorMsg = loadstring ("return " .. s)

    if not chunk then return nil, errorMsg end

    local success, v = pcall (chunk)

    if not success then return nil, v end

    return v, nil

    end

Inspiring
September 10, 2017

Great! And thank you for your explanation and example code!