* Using Penlight

For users to report plugin bugs and request plugin enhancements; and for authors to test new/new versions of plugins, and to discuss plugin development (in the Programming Technicalities sub-forum). If you want advice on choosing or using a plugin, please ask in General Usage or an appropriate sub-forum.
Post Reply
User avatar
ColeValleyGirl
Megastar
Posts: 5465
Joined: 28 Dec 2005 22:02
Family Historian: V7
Location: Cirencester, Gloucestershire
Contact:

Using Penlight

Post by ColeValleyGirl »

Once somebody (Mike, inevitably) explains, this will be blindingly obvious, but I don't mind being the dumb one in the room.

I'm trying to use the Penlight library as follows:

Code: Select all

if not fhloadrequire("pl","pl.init") then return end -- Load required Penlight modules using the snippet from FHUG wiki
pl = require("pl.import_into")
dir = require ("pl.dir")

pluginDir = fhGetPluginDataFileName("LOCAL_MACHINE",true)

function SetDatFileLists() --populate a list
    tblDatList= dir.getfiles(pluginDir, ".*\\(.-)\.dat") --get list of .dat files in the plugin data directory
    if tblDatList ~= nil then
        iup.SetAttribute (listX, "REMOVEITEM", "ALL") 
        for i = 1,#tblDatList do 
            iup.SetAttribute (listX, "APPENDITEM", tblDatList[i])
        end
    end
end
There are 2 .dat files in the relevant directory.

It's passing the test (as expected)

Code: Select all

    if tblDatList ~= nil then
but not executing the loop

Code: Select all

 for i = 1,#tblDatList do 

What stupid thing am I doing wrong?
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Using Penlight

Post by tatewise »

fhGetPluginDataFileName(...) does not return a directory, but a full path such as:
C:\ProgramData\Calico Pie\Family Historian\Plugin Data\PluginName.dat
So it is not a valid 1st parameter for dir.getfiles(...) which will expect to find a directory named PluginName.dat

If the filename & type is removed to leave just:
C:\ProgramData\Calico Pie\Family Historian\Plugin Data\
then dir.getfiles(pluginDir, ".dat") produces a list of .dat files in tblDatList.

When dir.getfiles(...) finds no matching files it returns an empty table which is not nil but has length 0.
So use if #tblDatList > 0 then to test for a non-empty table.

If you use local tblDatList = dir.getfiles(...) it is easy to see its contents in the Plugin debug pane lower right.
Otherwise, it is a global table which is not shown in that pane by default.

Another way to get that global Plugin Data folder is:
local pluginDir = fhGetContextInfo("CI_APP_DATA_FOLDER").."\\Plugin Data\\"

You cannot use dir.getfiles(pluginDir, "...") to extract the filename parts using the 2nd parameter shell mask, so use:
for _, strFile in ipairs (tblDatList) do
strFile = strFile:match("^.*\\(.-)%.dat$")
iup.SetAttribute(listX, "APPENDITEM", strFile)
end
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Using Penlight

Post by tatewise »

You don't need to use Penlight to obtain a list of files in a directory.
Use lfs instead:

Code: Select all

require "lfs"

local pluginDir = fhGetContextInfo("CI_APP_DATA_FOLDER").."\\Plugin Data\\"

for strFile in lfs.dir(pluginDir) do
	local strMode = lfs.attributes(pluginDir..strFile,"mode")
	local strName = strFile:match("^(.-)%.dat$")
	if strMode == "file" and strName then
		iup.SetAttribute(listX, "APPENDITEM", strName)
	end
end
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
ColeValleyGirl
Megastar
Posts: 5465
Joined: 28 Dec 2005 22:02
Family Historian: V7
Location: Cirencester, Gloucestershire
Contact:

Re: Using Penlight

Post by ColeValleyGirl »

Mike, the path returned by

Code: Select all

pluginDir = fhGetPluginDataFileName("LOCAL_MACHINE",true)
is a directory, with a name ending in .dat, so that isn't the problem.

The problem was the shell pattern to identify what files are returned -- I now have the following code working.

Code: Select all

if not fhloadrequire("pl","pl.init") then return end						-- Load required Penlight modules
pl = require("pl.import_into")
dir = require ("pl.dir")
path = require("pl.path")

function SetDatFileLists()    
    local tblDatList = dir.getfiles(pluginDir, "*.dat") --get list of the .dat files within the plugindir directory
    if #tblDatList > 0 then
        iup.SetAttribute (listX, "REMOVEITEM", "ALL")
        for i = 1,#tblDatList do
            local filename, _ = path.splitext(tblDatList [i]) --returns the file name including path and the extension (which is discarded)
            local filebase = path.basename(filename) --splits off the path and returns just the name
            iup.SetAttribute (listX, "APPENDITEM", filebase)
        end
    end
end
I know there are ways of doing it without Penlight, but I prefer the readability of this.
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Using Penlight

Post by tatewise »

The Plugin Name ending in .dat as a directory is unconventional but perfectly OK.
Not knowing that, meant I could not replicate your scenario on my PC, hence my comments about removing it.

FYI: The Penlight shell mask pattern only offers two wild card characters:
* represents any multiple characters.
? represents any single character.
All other characters represent themselves.

I thought you would have used the technique from Handling filenames without extensions (16310) to split out path, filename, and extension.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
Post Reply