Page 1 of 3

sorting tables by v

Posted: 10 Aug 2019 21:32
by Ron Melby
I have the issue where I am trying to simplify that already used and done.

I have table.insert X tables

I want to sort by name, given as Last, first middle suffix and have all the other tables ride along with it.

if I go to the fhoutputcolumn I can sort.
but I want a sort and then I am going to print it to a file.
both things are trivial, but the sort to print those tables to a file sorted are not

as I read by indi, and look for all milt-attr in a record, i load up the tables.
So, my tables are set.
I now have a problem where I believe the tables are

[1] first record found with milt-attr
[2...n] all of his other milt attr.
(one to many relation)

i want to
prtlin = a...b..c..d
table.insert(prtfile, ptrlin)
sorted by table Name, as described above.

how to sort
integer key, value
by value

I am reasonably sure its one of those closures? (return a function result set)? not sure if have the wording right but...

"Name" "LNam" "S" "DRM" "Dates" "*" "AGE" "SVCDate" "War" "ARM" "Rank" "OTH" "Relation"
"AINCHAM, Dexter Charles " "" "M" "ff" "(1923 - 1992)" "111923" "69" "" "WWII" " US Army" " CPL" " " " 3rd cousin (x04) removed"
"AINCHAM, Kirk William " "" "M" "ff" "(1921 - 1993)" "111921" "72" "" "WWII" " US Army" " CPL" " " " 3rd cousin (x04) removed"
"AMES, Calvin Robert " "" "M" "ff" "(1897 - 1989)" "111897" "92" "" "WWI" " US Army" " PVT" " " ""
"AMES, Carl Edward " "" "M" "ff" "(1911 - 1972)" "111911" "61" "" "WWII" " US Navy" " CM3" " " ""
"AMES, Charles Carey " "" "M" "ff" "(1839 - 1917)" "111839" "78" "" "Civil War" " US Army" " " " Company B 5th WI Infantry" ""
"AMES, Jason Fenno " "" "M" "ff" "(1825 - 1906)" "111825" "81" "" "Civil War" " US Army" " " " Company K 45th MA Infantry" ""
"AMES, Thales Lucius " "" "M" "ff" "(1869 - 1945)" "111869" "76" "" " " " US Army" " COL" " " ""
"ANDERSON, Allen Junior " "" "M" "ff" "(1926 - 1992)" "111926" "66" "" "WWII" " US Navy" " RM3" " " " 4th cousin (x03) removed"
"ANDERSON, Robert James " "" "M" "ff" "(1929 - 2008)" "111929" "79" "" "Korea-Vietnam" " US Army" " SFC" " " " 4th cousin (x03) removed"
"ANDERSON, William Richard " "" "M" "ff" "(1939 - 2012)" "111939" "73" "" "Vietnam" " US Army" " SP4" " " " 4th cousin (x03) removed"
"ARENDT, Gary R. " "" "M" "ff" "(1947 - 1992)" "111947" "45" "" "Vietnam" " US Army" " SP5" " " " 4th cousin (x02) removed"
(formatted which I can do...)

Re: sorting tables by v

Posted: 11 Aug 2019 09:35
by tatewise
We covered the sorting techniques in Table Manners (16977).

You must use one tblX with record fields for Name, Sex, Dates, etc, etc.
i.e. table.insert( tblX, { Name=...; Sex=...; Dates=...; etc } )

table.sort(tblX, function(a, b) return a.Name < b.Name end) should work as long as it is a numerically indexed table.
for k, v in ipairs (tblX) do will traverse the table records in index order, which will also be sorted Name order.

Re: sorting tables by v

Posted: 11 Aug 2019 22:09
by Ron Melby
function matIXbyVAL(tbl, sortFN)
local keys = {}

for key in pairs(tbl) do
table.insert(keys, key)
table.sort(keys, function(a, b)
return sortFN(tbl[a], tbl)
return keys

local index = matIXbyVAL(tblName, function(a, b) return a < b end)

for _, key in ipairs(index) do
Name = tblName[key]
sex = tblSEX[key]
Dates = tblDates[key]
SVCDat = tblSVC[key]
WAR = tblWar[key]
ARM = tblARM[key]
RANK = tblRank[key]
OTH = tblOTH[key]

now my problem is one of generalization...

I need to determine if it is a table or an index upon entry
so that I can recursively sort records much like we do for place
reverse, sort by 5last, 4last, 3last, 2last, last
without a multiple key it is still not correct, but doable.
in this case, I would like to sort by war then name.

Re: sorting tables by v

Posted: 12 Aug 2019 09:25
by tatewise
I find it difficult to understand your method, but it is not the usual way of performing Lua table sorting.

Instead of all those separate tblName, tblSex, ... , tblOTH tables you should use just one table of records.
table.insert( tblRec, { Name=Name; Sex=sex; ... ; War=WAR; ... ; Other=OTH; } )

as you used before and shown in Table Manners Sun 21st Jul 2019 17:15

Then to sort into order use:

table.sort( tblRec, function(a, b) if a.War == b.War then return a.Name < b.Name end return a.War < b.War end )

or may be this is a bit clearer:

Code: Select all

function SortRec(a,b)
	if a.War == b.War then
		return a.Name < b.Name
	return a.War < b.War

table.sort( tblRec, SortRec )
That technique can be extended to sort as many record fields as required.

for i, Rec in ipairs (tblRec) do will then loop through records in sorted order.
Name = Rec.Name
Sex = Rec.Sex
War = Rec.War

and so on

Re: sorting tables by v

Posted: 12 Aug 2019 12:27
by Ron Melby
The issue is whether I build for sorting for a paper report, which will have a different layout altogether than a futputresultcolumn report, ie: single tables or a record style table. One vertically built, and one horizonally built.

Since I have been learning LUA, and FH, all my code has been vertically built, that is, single tables.
to retrofit the programs to build horizontally , that is a record like single table is doable, and I suppose I could just add to my standard routines a build a record table bit by bit. But then it is scattered thing and I am not sure if it is as facile and debug-able.

I have come up with a way that doesnt seem too hard to generalize. tbl can be an array, and glue up and sort the record numbers by the glued key.

But, it might not be that hard to convert from single table modules to build a record in bits and return tblRec.

it wili take some massive time though....
I'm gonna give that a long think...

Re: sorting tables by v

Posted: 12 Aug 2019 12:36
by ColeValleyGirl
Ron, while you're having a think, look at ...

Re: sorting tables by v

Posted: 12 Aug 2019 13:24
by Ron Melby
thanks, pretty techie, gonna have to give that a long long long think and far, greek to me.

I have realized my first problem in putting them in a record structure is, how do I know bit by bit to build this record from module to module, and when to start a new one, and how?

for some reason
matsomethingelse in the record
table.insert(RCD) ??
RCD = {} ??
something like that?
how do I write to this.RCD in bits and pieces
then create a new.RCD instance to do another loop?

Re: sorting tables by v

Posted: 12 Aug 2019 14:53
by tatewise
You can approach this two ways.

1) Keep your separate tables and just compose the sortable records to produce the printable output.

Code: Select all

local tblRec = { }
for i = 1, #tblName do
	table.insert( tblRec, { Name=tblName[i]; Sex=tblSEX[i]; War=tblWar[i]; }
table.sort( tblRec, function(a, b) if a.War == b.War then return a.Name < b.Name end return a.War < b.War end )
for i, Rec in ipairs (tblRec) do
	-- whatever to print to report
2) Retrofit the record field by field and create Result Set column tables when needed.
This is what you did in Table Manners (16977).

When you start creating a new set of field values then use:
table.insert( tblRec, { } ) to create an empty record.

Wherever you currently use table.insert( tblName, Name ) or tblName[key] = Name use:
tblRec[#tblRec].Name = Name
and similarly for
tblRec[#tblRec].War = WAR

That allows tblRec to be sorted as required.

Then when you need Result Set column tables use:

Code: Select all

for i, Rec in ipairs (tblRec) do
	table.insert( tblName, Rec.Name )
	table.insert( tblWar = Rec.War )
	-- etc, repeated for each field

Re: sorting tables by v

Posted: 12 Aug 2019 16:57
by Ron Melby
that part about cutting apart I understand Mike.

fn matName(iptr)
tblGED(RCD = RCD or {})

fn matSEX(iptr)
tblGED(RCD = RCD or {})
sex = sex:substr(1, 1)

while indi is not null do
table.insert(tblGED, RCD)
why doesnt table.insert(tblGED, RCD{}) create a new empty record in the table between runs?
I am trying to figure out how to do a new record every indi, is that about the way to do it

Re: sorting tables by v

Posted: 12 Aug 2019 17:29
by tatewise
My option 2) explains all that.

I thought that when I say use "table.insert( tblRec, { } ) to create an empty record." could not be any clearer.
So use table.insert( tblGED, { } )

I have no idea what RCD is in your scripts. It is certainly not valid Lua.

Use tblGED[#tblGED].NAME = Name instead of tblGED(RCD{NAME=Name}) which is not valid Lua.

It would help if you could explain how key was determined in your Sunday posting, and how it is consistently used in every table?

Re: sorting tables by v

Posted: 12 Aug 2019 17:57
by Ron Melby
[1] FRED
[2] AL
[3] BEN
these are arrival order by doing a:
while ptrINDI is not null loop reading from first record to last
I sort the thing, giving me the index to the table in values of alpha order.

keys will return:

write out by key.

I am not near LUA at the moment so I am sort of psuedocoding the things I am writing. Hope you can catch on.
It is unclear to me when the table.insert is done with one record and starts on a new one, that is when each function writes a piece of the record (the actual fields in the record could be variable, for instance, I might not always write a RLT field for every plugin...
but I am unclear how #tblGED is incremented, is it known when I write an empty to autoincrement the record index? that is where I am confused, the rest is just a matter of typing in the actual real formal code.

did you get real confused by:
fn matSEX(iptr)
or did you grok that i shorthanded function....consider that i am shorthanding the code for this since I dont have any LUA stuff here right now, I am not at home.

again, it is unclear to me how the key is advanced.

Re: sorting tables by v

Posted: 12 Aug 2019 20:13
by tatewise
The key in your design is the record number.
That number must be consistent in all your separate tables, otherwise you cannot associate the table entries with each other.
Once you have worked out where the key is incremented, then that is where the empty tblGED record is created.

The questions to answer are...
Will you create a new data record for every Individual record?
Do you only create a new data record when a WAR is discovered for each Individual?
So each Individual may end up producing no record, or one record, or two records, up to the maximum number of WARs.

Until that design is clear, little progress can be made.

Re: sorting tables by v

Posted: 12 Aug 2019 20:38
by Ron Melby
there are two situations to generalize.
one record per indi (of whatever)
n records per indi while some attribute or fact exists
say -- census.
if it is necessary to make the code general -- in the case of a multiple record, the field in RCD as we have been discussing could be WAR{} (an array) and it could be torn apart at print or display time with a loop. (the tear apart routine is certainly not able to be generalized except in the main, as a

for k,v in pairs do
table insert(tblName, v.Name)
and so on

and the print optionally needs:
massaged data

and those both would be where most of the custom work would come in, provided I can generalize the common pieces
and those types of things I always have on my reports

tblGEN( RCD, {NAME=Roscoe; SEX='M'; DATES= '(1900 - 1890)'; GEN= -1; RLT='Brothers Cats Uncles Grandfather';)

in one program,
and might be
tblGEN( RCD, {NAME=Roscoe; SEX='M'; DATES= '(1900 - 1890)'; WAR{WW2, Korea, Vietnam};) in another
in another.

if it is less tortuous logic in the general modules it can be:

tblGEN( RCD, {NAME=Roscoe; SEX='M'; DATES= '(1900 - 1890)'; WAR=WW2;)
tblGEN( RCD, {NAME=Roscoe; SEX='M'; DATES= '(1900 - 1890)'; WAR=Korea;)
tblGEN( RCD, {NAME=Roscoe; SEX='M'; DATES= '(1900 - 1890)'; WAR=Vietnam;)

in this case I could set a level break sort of thing for the print, using say rcdid,
fn prtindi()
tbl.ins(ptrdoc, name)
tbl.ins(prtdoc, sex)
tbl.ins(prtdoc, dates)

fn prtwar()

for k, v in pairs(tblGEN) do
if v.rcdid == prvid then
if prvid ~= ''
table.insert(prtdoc, '\n'
prvid = rcdid
(or something very like that)

and the goal is customization confined to two modules:
prtDOC() in the case of a document file.

matTBLS() in the case of the display output.

right now, the display output is already a multiple set of records, in the case of MilSVC so thats an either or, easier in display to have it in 3 entries and not much difference either way in file out.

re the key thing,

most of my programs (there are about 21 right now)
do a loop
while ptrindi is not null do
matName (write name to table)
matSex(to table)
matDates(to table)

so sending in tblName to return keys in alphabetized order will bring the other ancillary tables in correctly (and will put roscoes 3 records together....(tho not sorted by war) your way would let me sort by war, then by name so I could sort downwind of several fields, which is handy for some things. by age, then by date, then by name for instance where name is surnamefirst. for example

Re: sorting tables by v

Posted: 13 Aug 2019 09:07
by tatewise
You are correct that the WAR={WW2, Korea, Vietnam}; structure in a record will complicate sorting by WAR.

Unfortunately, I don't have the time to solve your detailed design issues.

You have the Lua principles for constructing and sorting records, and used them successfully in Table Manners (16977), so should be able to find your own solution.

Re: sorting tables by v

Posted: 13 Aug 2019 12:10
by Ron Melby
the question I have and cannot solve and am asking is:

I insert an empty record, ok...then I fill in the parts. I am now at record key one, finished with my first indi. how do I write that record, or has it filled out the table entry, after the insert, and how is the record advanced to the next?

Re: sorting tables by v

Posted: 13 Aug 2019 12:12
by ColeValleyGirl
When you insert a new item, it advances to insert it.

Re: sorting tables by v

Posted: 13 Aug 2019 12:53
by Ron Melby
I thought that, and it sort of gums up the works (but maybe not)

function matID(varptr)
local rcdid = fhGetRecordId(varptr)
local cs = debug.getinfo(2, 'n')
if ~= 'rtvID' then
RCD[#RCD].RCDID = rcdid
cwrcd = 6
cwfam = 6
return rcdid
end -- fn matID

function matSEX(iptr)
local sex = string.sub(fhGetItemText(iptr,'~.SEX'), 1, 1)
if sex == '' then
sex = 'U'
local cs = debug.getinfo(2, 'n')
if ~= 'rtvSEX' then
RCD[#RCD].SEX = sex
cwsex = 6
return sex
end -- fn matSEX

function matNAME(iptr)
local Name = ''
local NameSfx = ''

Name = fhGetItemText(iptr,'~.NAME:SURNAME_FIRST')
NameSfx = fhGetItemText(iptr,'~.NAME.NSFX')
Name = (Name .. NameSfx)
if NameSfx > '' then
Name = Name .. ' '

local cs = debug.getinfo(2, 'n')
if ~= 'rtvNAME' then
cwnam = cwnam or 0
cwnam = math.max(cwnam, #Name)

RCD[#RCD].INDI = iptr:Clone()
cwptr = 0
return Name
end -- fn matNAME

local ptrINDI = fhNewItemPtr()
while ptrINDI:IsNotNull() do
table.insert(RCD, { })

so after one cycle and top of new cycle does my RCD contain:
[1] RCDID=1, NAME=AMES, Ada, INDI=(*ptr), SEX='F'
and is now set to

Re: sorting tables by v

Posted: 13 Aug 2019 13:39
by ColeValleyGirl
You need to stop thinking of 'a position' 'being set to anything'. There is not a pointer for the current position, or indeed any 'current position'.

There are only a set of entries that you can access via their key. And if you need to insert another, table.insert adds it -- but you can't know where, other than that it won't overwrite anything else, unless you specify a position!

Try a little documentation: Programming In Lua - Insert and Remove. There's a limit to what you can expect people here to do if you won't help yourself.

Re: sorting tables by v

Posted: 13 Aug 2019 13:47
by tatewise
Yes, that should work :)

Why not just run that experimental script and debug the RCD table contents?
BUT ensure you use local RCD = { } otherwise it is more difficult to find in the debug pane.

Not sure why Helen says "table.insert adds it -- but you can't know where".
table.insert(...) uses the next available integer key, and the current key is #RCD which is the size of the table.
So the first table.insert(...) creates entry RCD[1] and the second entry RCD[2] and so on.
( Unless the position parameter is used, but table.insert(...) still won't overwrite any existing entry. )
( It is only if you use RCD[n] = ... that it will overwrite the entry with key = n. )
( I suspect Helen may be thinking of textually indexed dictionary tables, that don't have a defined order. )

Re: sorting tables by v

Posted: 13 Aug 2019 14:03
by ColeValleyGirl
I suspect Helen may be thinking of textually indexed dictionary tables, that don't have a defined order.
Helen is thinking of the generic case for tables, as none of them have a defined order. If you use table.insert without specifying a position, it adds the new entry at the end of the table, but you can only access that using an integer key in the special case of a table indexed by integers. Admittedly, that's a frequent case, but it's misleading to imply that it's the only case. In all other cases you access it using a textual key.

I can't make head nor tail of Ron's requirement, but I suspect if he was indexing his table by (e.g.) the individual record id rather than an integer and each entry was a table of relevant values, he might find life easier. Was there a decent specification (saying what rather than how) I might make a stab at providing some example code, but I'm not hopeful.

Re: sorting tables by v

Posted: 13 Aug 2019 14:31
by tatewise
He needs to use the basic integer key technique.
He cannot use the Record Id as key, because some Individuals are involved in more than one War.
So in those cases the table needs an entry for each War with other details such as Name and Sex replicated.
That is because he wants to primarily sort by War and then by Name (and maybe other details).
So there must be consecutive integer key entries with a separate entry for each Individual and War combination, otherwise table.sort(...) won't work

Re: sorting tables by v

Posted: 13 Aug 2019 15:24
by ColeValleyGirl
Mike, you're assuming that your assumptions work ;)

Key the table on the concatenation of the individual+war (so unique, unless the individual served more than once in the same war, in which case there may be some way of distinguishing their service that Ron will know -- maybe add service dates?), with additional fields for the individual and the war (and dates) and all the other stuff like sex and all the rest.

The Penlight function for tablex.sort(t) (see Penlight table sorting) will let you sort on the key (Individual plus War plus perhaps Service Dates). And if you can refactor Name to be split out in the order you want in the key field and include table fields fore each element, are you done? You have one table entry per Individual per War plus Service Period and all the other 'stuff'

Re: sorting tables by v

Posted: 13 Aug 2019 15:37
by tatewise
I have tried the integer keyed table of records using table.insert(...) and table.sort(...), etc, and it works fine.

I see that using War + Name as the key, with the Penlight table sorting would work.
But that needs Ron to embrace the Penlight library.

Also, he is seeking a generalised solution that will work for whatever record fields he chooses to sort by, and where there may be multiple field values of particular data types for each Individual, similar to Wars, but also others.
So I suspect the War + Name + whatever key is too focussed and not general purpose enough.

Re: sorting tables by v

Posted: 13 Aug 2019 16:19
by ColeValleyGirl
So I suspect the War + Name + whatever key is too focussed and not general purpose enough.
There will (perhaps) be an analogy that works, given a particular dataset. But yes, if somebody does not want to extrapolate and use a helpful library, I'll bow out.

Re: sorting tables by v

Posted: 13 Aug 2019 17:41
by Ron Melby
my whole post disappeared.

bottom line I have hundreds of modules to revamp have read the documentation and want to check my understanding of how its going to work.

Dont count me out on penlight without checking with me, I will be studying it as time permits to understand it. So do not bow or curtsy on my account folks.

so, I will have two methods to do this fairly easily given an understanding of penlight.
once I understand penlight.tablex and the way we are talking about now....

the only issue I can forsee in upgrading my many modules is: --[[ Duplicate MML ]] that is a bit of code that is MikeTate, and I have never understood the magic, and have debugged the thing to death and still dont get it, and have to decide how to handle this so I get the dup in both [#RCD]

Code: Select all

function matCEM(varptr)
  local ptrSRC   = fhNewItemPtr()    -- Basing Pointer to SOUR
  local ptrRCD   = fhNewItemPtr()    -- Basing Pointer to INDI

  local ptrtype  = ''
  local OFS      = '~.'
  local ptrLBL   = fhNewItemPtr()
  local ptrLink  = fhNewItemPtr()
  local ptrRMN   = fhNewItemPtr()
  local ptrADDR  = fhNewItemPtr()
  local ptrWEB   = fhNewItemPtr()
  local ptrPLOT  = fhNewItemPtr()

  local rmn      = ''
  local CemAddr  = ''
  local WebPage  = ''
  local MML      = ''
  local DupMML   = ''
  local plot     = ''

  local function rslvMML()
    tblMML         = tblMML or {}
    cwmml          = cwmml or 0

    tblDup         = tblDup or {}
    cwwdp          = cwwdp or 0

--[[ memorial number ]]
    MML = WebPage:gsub('.-(%d+).*','%1')
    table.insert(tblMML, MML)
    cwmml = math.max(cwmml, #MML)

--[[ Duplicate MML ]]
    if WebPage ~= MML then
      if tblDup[MML] then
        DupMML = MML
        tblDup[tblDup[MML]] = DupMML
        cwwdp = math.max(cwwdp, #DupMML)
        duplicate = true
        tblDup[MML] = #tblMML
    table.insert(tblDup, DupMML)
  end --fn rslvMML

  local function rtvPtrFromSOUR()
    ptrRCD = varptr:Clone()                  -- Basing Pointer to INDI
    ptrSRC = varptr:Clone()                  -- Basing Pointer to SOUR
  end -- fn rtvPtrFromSOUR

  local function rtvPtrFromINDI()
    while ptrLBL:IsNotNull() do

      if fhGetTag(ptrLBL) == ptrtype then
        ptrLink = fhGetValueAsLink(ptrLBL)   -- link to this record
        if ptrLink:IsSame(ptrSOUR) then
          ptrRCD = varptr:Clone()            -- Basing Pointer to INDI
          ptrSRC = ptrLBL:Clone()            -- Basing Pointer to SOUR
      ptrLBL:MoveNextSpecial()               -- set to next TAG
      if not fhHasParentItem(ptrLBL) then
        ptrRCD  = varptr:Clone()             -- Basing Pointer to INDI
        ptrSRC  = ptrSOUR:Clone()            -- Basing Pointer to SOUR
        ptrLBL  = fhNewItemPtr()                 
        ptrLink = fhNewItemPtr()                 
  end -- fn rtvPtrFromINDI

  ptrtype = fhGetTag(varptr)
  if ptrtype == 'SOUR' then
    if not fhHasParentItem(varptr) then
      ptrRCD  = fhNewItemPtr()               -- Basing Pointer to INDI
      ptrSRC  = fhNewItemPtr()               -- Basing Pointer to SOUR
      ptrLBL  = fhNewItemPtr()                  
      ptrLink = fhNewItemPtr()                 
  elseif ptrtype == 'INDI' then
    ptrtype = 'SOUR'

  ptrRCD:MoveToRecordItem(varptr)           -- Basing Pointer to INDI
  ptrRMN:MoveToParentItem(ptrSRC)           -- Basing Pointer to BURI or CREM

  --[[ BURI or CREM ]] 
  rmn = string.sub(fhGetTag(ptrRMN), 1, 1)

  --[[ Cemetery Addr or disposition ]]
  OFS = OFS .. (fhGetTag(ptrRMN))           -- event offset
  CemAddr = (OFS.. '.ADDR')                 -- event address
  ptrADDR:MoveTo(ptrRCD, CemAddr)
  if ptrADDR:IsNull() then
    CemAddr = (OFS.. '.NOTE2')
    ptrADDR:MoveTo(ptrRCD, CemAddr)

  --[[ ]]
  WebPage = fhGetValueAsText(ptrWEB)


  --[[ Plot information ]]
  plot = fhGetValueAsText(ptrPLOT)

  local cs = debug.getinfo(2, 'n')
  if ~= 'rtvCEM' then
    --[[ BURI or CREM ]] 
    tblRMN         = tblRMN or {}
    table.insert(tblRMN, rmn)
    cwmin          = 6          

    --[[ Cemetery Addr or disposition ]]
    tblCEM = tblCEM or {}
    txtlen = fhGetValueAsText(ptrADDR)
    table.insert(tblCEM, ptrADDR:Clone())
    cwcem = cwcem or 0 
    cwcem = math.max(cwcem, #txtlen)

    --[[ ]]
    tblWEB = tblWEB or {}
    table.insert(tblWEB, WebPage)
    cwweb = cwweb or 0
    cwweb = math.max(cwweb,#WebPage)

    tblFaG = tblFaG or {}
    table.insert(tblFaG, ptrWEB:Clone())
    cwptr = cwptr or 0

    --[[ rslvMML mml# dupmml# unconditional ]]

    --[[ Plot information ]]
    tblPlot = tblPlot or {}
    table.insert(tblPlot, plot)
    cwgli = cwgli or 0
    cwgli = math.max(cwgli,#plot)            -- grave lot info

  return rmn, ptrADDR, WebPage, MML, DupMML, plot

end -- fn matCem
so I will do the modules this way, and I will (once all issues are resolved) learn how to do it the penlight way.
(what? you think I havent made a full backup of my working code?) Just because Calico Pie doesnt put additional folders in Plugins doesnt mean I don't. Melby is a very bad boy, oi? all my stuff starts out _ so that it appears first in any window. and the _STD modules are .lua instead of .fh_lua so they dont show up in FH plugins window but do show up in order in Zero Brane.

the idea is to learn techniques to have a full arsenal of methods to solve the problem, and slick up and out my programs so they shine.

Just doing the start of this upgrade, I have found 4 or 5 more modules I need to add to my repertoire.
this whole thing started because on memorail day, I want to post on facebook a list of my relatives who are veterans, the only way to line everything up is to make all lines the same length, or FB mangles it. So, normal save tables from display to text doesnt work, and its a pain to put into wordpad and line it all up and pad it out, so--- PROGRAM!!!!

and on the way I found I would like a key to read those tables:


that bit is RPG pseudocode, btw.

there are now two methods to do that, build by hand and penlight.
once the framework is built, the program to program differences are minor.