There are several components to this posting.
(1) Function loadrequire()
I have had to amend this to cope with certain
require(module) errors.
Example Scenario:-
A loaded module
"ABC" uses
require("XYZ") but module
"XYZ" no longer exists.
When
loadrequire("ABC") invokes
require(module) it returns
false.
So a download and install is attempted, which does not resolve the problem.
Thus, the associated
require(module) error message needs to be examined to determine the correct action.
So I have replaced the original line (which erroneously declares the global
res):
with the lines [Edited 19-Oct]:
Code: Select all
local res, err = pcall(requiref,extended) -- was: res = pcall(requiref,extended)
if not(res) then
if err:match("module '"..extended:gsub("(%W)","%%%1").."' not found") then
... { existing code to download extended/module goes here } ...
else
fhMessageBox('Error from require("'..module..'") command:\n'..err)
return false
end
This only tries a download if the error message is of the form:
...alico Pie\Family Historian\Plugins\ABC.lua:22: module 'ABC.lua' not found: ...
It should cope with all other error messages, including when
module 'XYZ.lua' not found is NOT the required module.
(2) FH Module Naming
I have decided to put the FH Modules in the
\Plugins\fh\ sub-folder.
This is short, similar to the FH Icon, and to the
fh prefix on LUA API functions, but otherwise rarely occurs in code.
I have added version suffixes such as
_v1 and
_v2 to module filenames to identify their version.
e.g.
\fh\stringx_v1.lua
I assume version control will be exercised on each individual module rather than on the
fh library as a whole.
Any version suffix would be OK, providing the resulting name is also a valid LUA variable name, so that the
Penlight loading and
lazy table techniques can be used.
(3) FH Module Library Files
The following module files are available from my SkyDrive
fh folder.
Tick the modules you want, then right-click to
Download a zip file of them all.
Alternatively, simply right-click and
Download the files individually.
encoder_v1.lua
encoder_v2.lua
general_v1.lua
iterate_v1.lua
iup_gui_v1.lua
loadreq_v1.lua
progbar_v1.lua
stringx_v1.lua
tablex_v1.lua
These can be loaded and called in the conventional ways:
[EDIT 19-Oct] This has all been updated - see (5) [EDIT UPDATE 19-Oct] later.
Code: Select all
if not loadrequire("fh.encoder_v1") then return end
require "fh.general_v1"
require("fh.stringx_v1").import()
require("fh.tablex_v1")
tablex.import()
strText = encoder.StrCP1252_XML(strText)
general.SaveStringToFile(strText,strFile)
strText = strText:split()
table.save(tblData,strFile)
But
require "fh.encoder_v1" and
require "fh.encoder_v2" cannot be used in same Plugin, because both utilise the same module name and table
encoder. [EDIT - This is no longer a restriction.]
Note that
fh.general_v1 uses:
Code: Select all
require "fh.loadreq_v1" -- To access loadrequire() function
if not loadreq.loadrequire("pl","pl.init") then return end
local pl = require("pl.import_into")() -- To access Penlight packages
(4) [EDIT UPDATE 18-Oct]
All modules updated Friday 18 Oct ~ 19:00 pm with relatively minor changes.
You may be interested in the way I developed these modules:-
They all start as
.fh_lua modules, with names such as
+fh+encoder_v1 and
+fh+stringx_v1.
This allows them to be edited directly from the
Plugins window, and the
+fh+... lists them at the top.
They are tested using
require "+fh+encoder_v1" etc, and have exactly the same content as a module.
I have a Plugin whose purpose is to assess & copy each
+fh+{module_ver}.fh_lua to its
fh\{module_ver}.lua.
The assessments are confidence checks that firstly the
.lua and then the
.fh_lua modules work consistently.
If all the assessments pass, then any updated/new
+fh+{module_ver}.fh_lua is copied to its
fh\{module_ver}.lua.
I am looking at how
Penlight loads the whole
pl library, yet supports individual
require "pl.{module}" commands, and the
lazy table technique.
I presume something like
loadrequire("fh","fh.init") would load all versions of all modules, yet support individual
require "fh.{module_ver}" commands for any single version of each module.
What is not clear, is how a new version of one module gets incorporated into the
fh library and downloaded.
Alternatively, we could simply use
loadrequire("fh.{module_ver}") for each module version.
(5) [EDIT UPDATE 19-Oct]
All modules updated Saturday 19 Oct ~ 19:00 pm with additional files:
library_v1.lua
library_v2.lua
modules_v1.lua
modules_v2.lua
stringx_v2.lua
These implement a
Penlight style of loading as follows.
For library version 1 set of modules, all at version 1:
Code: Select all
if not loadrequire("fh.library_v1") then return end
local fh = require("fh.modules_v1")()
For library version 2 set of modules, all at version 1 plus some at version 2:
Code: Select all
if not loadrequire("fh.library_v2") then return end
local fh = require("fh.modules_v2")()
"fh.library_v1/2" combines the Penlight
"pl","pl.init" function into one file.
"fh.modules_v1/2" performs the Penlight
"pl.import_into" &
"pl.utils" function in one file.
The idea is that
"fh.library_v1" downloads all the
fh\{module}.lua files for
V1, and calls
"fh.modules_v1", which
lazy loads all the required modules.
Later on
"fh.library_v2" downloads all the
fh\{module}.lua files for
V1 &
V2, and calls
"fh.modules_v2", which
lazy loads all the required
V1 &
V2 modules.
For the moment
"fh.modules_v1/2" does NOT use the List, Map, Set, MultiMap classes from
pl.import_into as I could not see where they got used, and everything seems to work OK without them.
loadrequire would be more efficient if it only downloaded files NOT already existing in the
Plugins folder.
e.g. Just before
Get file down and install it insert:
Code: Select all
if lfs.attributes(storein..filename,"mode") == "file" then return true end
All the library modules now start with the following style of code:
Code: Select all
local fh = {} -- Local environment table
package.seeall(fh) -- Enable all globals
module(...,package.seeall) -- Create matching module name
setfenv(1,fh) -- All public names are added to local fh table
This no longer pollutes the global space with a table name ( e.g.
encoder = fh ).
This also allows multiple versions of the same module to be used at the same time.
e.g.
A library module could use
local encoder = require "fh.encoder_v1"
while main Plugin can use
local encoder = require "fh.encoder_v2"
both can then use
encoder.StrUTF8_Encode() but with different results, because this function has been updated from V1 to V2.
Also, I have realised that the
lazy table technique creates a
Global table for each module, with the same name as the module file.
So,
\fh\encoder_v1.lua would utilise Global table
encoder_v1,
and
\fh\encoder_v2.lua would utilise Global table
encoder_v2, and so on.
This offers another way that items from different versions can be used at the same time.
It also virtually guarantees no name clashes with libraries such as
Penlight, because the version suffixes are quite unusual.