Lightroom SDK: replace _G.dofile with one that works with non-ascii characters

  • 3
  • Idea
  • Updated 6 years ago
********* WARNING TO ALL PLUGIN AUTHORS: dofile will fail if there are any non-ascii characters in the path, e.g. as is possible with the Swedish version of Windows.

I noticed LrFileUtils.readFile was provided in a dot release of SDK 2.2, which solves the problem for reading files, but any lua code that attempts to access files via paths will fail, not just read-file.

Examples:

- lua logger (printing to file)
- writing files.
- dofile

Doesn't look like Lua 5.2 is fixing this problem (?) so maybe Adobe should.

Please replace all lua built-in functions that will choke on non-ascii characters in paths or filenames.

This will solve some problems some plugin authors may not even know they have, or know they have but can't fathom why some few users report strange problems...

Example solution - put this in LrInitPlugin module:

-- step 0: replace load-file/do-file with versions that will work with non-ascii characters in path.
local LrPathUtils = import 'LrPathUtils'
local LrFileUtils = import 'LrFileUtils'
_G.loadfile = function( file )
-- Note: file is optional, and if not provided means stdin.
-- Shouldn't happen in Lr env(?) but just in case...
if file == nil then
return nil, "load-file from stdin not supported in Lr env."
end
local status, contents = pcall( LrFileUtils.readFile, file ) -- lr-doc says nothing about throwing errors, or if contents returned could be nil: best to play safe...
if status then
if contents then
local chunkname
if file:len() > 63 then -- dunno if same on Mac ###1
chunkname = file:sub( -63 )
else
chunkname = file
end
local func, err = loadstring( contents, chunkname ) -- returns nil, errm if any troubles: no need for pcall (short chunkname required for debug).
if func then
return func
else
--return nil, "loadstring was unable to load contents returned from: " .. tostring( file or 'nil' ) .. ", error message: " .. err -- lua guarantees a non-nil error message string.
if err:len() > 77 then -- dunno if same on Mac ###1
err = err:sub( -77 )
end
return nil, err -- return *short* error message
end
else
-- return nil, "Unable to obtain contents from file: " .. tostring( file ) -- probably also too long.
local filename = LrPathUtils.leafName( file )
return nil, "No contents in: " .. filename
end
else
-- return nil, "Unable to read file: " .. tostring( file ) .. ", error message: " .. tostring( contents or 'nil' ) -- probably also too long.
local filename = LrPathUtils.leafName( file )
return nil, "Unable to read file: " .. filename
end
end
_G.dofile = function( file )
local func, err = loadfile( file ) -- returns nil, errm if any problems.
if func then
local result = {}
result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15], result[16], result[17], result[18], result[19], result[20], result[21] = func() -- throw error, if any.
if result[21] ~= nil then
error( "Modified dofile only supports 20 return values" )
else
return unpack( result )
end
else
error( err ) -- error message guaranteed.
end
end


I have no idea how to solve the problem of writing files - not even sure there is one(?!) - I'll check, unless somebody else beats me to it.

PS - This could easily be considered a "Problem Report" instead of an "Idea", since as it stands, all plugins that use lua code for accessing files will fail if target paths have non-ascii characters - not good, no not good at all, especially since the malfliction (I invented that word just now) may not be reproducible by the plugin author.
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 372 Reply Likes
  • suggesting this be fixed in next release, and fix documented so it doesn't have to be rechecked each release...

Posted 7 years ago

  • 3
Photo of John R. Ellis

John R. Ellis, Champion

  • 3385 Posts
  • 854 Reply Likes
Ack, I just got bit by this with Any Filter. I remember reading this at the time, but then promptly forgot and used "dofile" to read saved data from a file.
Photo of John R. Ellis

John R. Ellis, Champion

  • 3385 Posts
  • 854 Reply Likes
I think this line:

result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15], result[16], result[17], result[18], result[19], result[20], result[21] = func()

could be simplified to this:

result = {func()}

and it would handle an arbitrary number of return results. This is the idiom for "pack", the dual of "unpack".
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 372 Reply Likes
Perfect. Thanks John - I knew there had to be a better way ;-)

I don't guess this was fixed in Lr4.0 was it???
Photo of jdv

jdv, Champion

  • 728 Posts
  • 55 Reply Likes
Thanks, John. I knew my hacky use of LrDate.timestampToComponents() to get a weekday was wrong.
Photo of John R. Ellis

John R. Ellis, Champion

  • 3385 Posts
  • 854 Reply Likes
Here's what I learned about LR 3 and LR 4: The Lua function io.open() handles non-ASCII characters in pathnames properly. But dofile() and loadfile() don't, so you have to reimplement them, as Rob did above.
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 372 Reply Likes
I can confirm that behavior. Seems strange that io.open is OK but do/load-file not. Thanks again John.