* Map Life Facts coding question

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
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Map Life Facts coding question

Post by Ron Melby »

miketate,

some time ago, we exchanged some emails regarding MLF recognizing the right Berks, and other subtle improvements, one of the improvements was cutting up both ,, and , , parts, equivalently. this is not done in fh.split() but somewhere else, insofar as I can tell, and I cannot find that bit of code in 5.1 MLF which is what I have, mostly because I do not know what I am looking for... can you give me the line numbers where you operate on both ,, and , , because I need my code to work with both situations, and it currently does not.

(example of military attributes:

1. Civil War, US Army,, Company A 16th Army Corps MN Regiment
2. Civil War, US Army, , Company A 16th Army Corps MN Regiment

-- Split a string into fields using sep or dft ','
function rtvFields(str, sep)

local otbl = {}
local pattern = ('([^%s]+)'):format(sep or ',')

str = tostring(str or ' ')
str:gsub(pattern,
function(field)
otbl[#otbl + 1] = (field or ' ')
end
)
return #otbl, otbl
end -- fn rtvFields

this will miss the .. (obvs) in 1, but 2 works.
I need to make it work for both (that is, placeholders; void or spaced are important.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Map Life Facts coding question

Post by tatewise »

The code is within the function StrGeocodeLocation(strLocName) about line 3740:

Code: Select all

strLoc = strLoc:gsub('%-',' ')	-- Replace each hyphen with space to fix Stoke-upon-Trent
strLoc = strLoc:gsub(", -, -",", "):gsub(", -, -",", "):gsub("^[, ]+",""):gsub("[, ]+$","") -- Purge blank comma parts
gsub(", -, -",", ") replaces a comma with any or no spaces and another comma with any or no spaces with one comma & space.
( Note that , - matches a comma followed by any number of spaces including none. )
That gsub is repeated to cater for multiple adjacent comma space sequences.
gsub("^[, ]+","") removes all leading commas and spaces.
gsub("[, ]+$","") removes all trailing commas and spaces.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Map Life Facts coding question

Post by Ron Melby »

mike, dont know why I don't see these things in my mind right off...but I do not.

local ATTR = fhGetValueAsText(aptr)
ATTR = ATTR:gsub('^,', ' ,'):gsub(',,,,', ', , , ,'):gsub(',,,', ', , ,'):gsub(',,', ', ,')

so I don't know if there is a shorter way to say this, but it appears that gsub does not allow coincidental overlap.

that is, unless I explicitly state it, i.e.: ,,, it will find the ,, and fix it but will not see the last , so a ,,, = , ,,
if I only use the first and 4th gsub.
and since I have 4 fields possible, I also check for ,,,, (but I don't probably need to do that.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Map Life Facts coding question

Post by tatewise »

The explanation is that gsub(...) works strictly left to right, so once it has replaced ,, with , , it resumes from that point and does not back track.

If I understand correctly, you want a leading comma prefixed with a space and all other commas followed by just one space.
This should do that:
ATTR = ATTR:gsub( '^,', ' ,' )
ATTR = ATTR:gsub( ',', ', ' )
ATTR = ATTR:gsub( ', +', ', ' )

gsub( '^,', ' ,' ) replaces a leading comma '^,' with space comma ' ,'

gsub( ',', ', ' ) ensures every comma ',' is followed by at least one space ', '

gsub( ', +', ', ' ) replaces each comma followed by one or more spaces ', +' with a comma and one space ', '
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Map Life Facts coding question

Post by Ron Melby »

no, I do not think I want that, but it comes to the same thing perhaps.
if there is a comma including at the start that has no space: (let us call the existing but no value: (void)

void, void, void, void,
would be the minimal text
void, US Army, void, Company B,
WWII,void, CPT,void,
I need all void values to have the value (space)
as you can see I cannot address the nth (in this case 4th field), without a comma in the *generalized* (I say this with a laugh) function to retrieve fields from a text line.


-- Split a string into fields using sep or dft ','
function rtvFields(str, sep)

local otbl = {}
local pattern = ('([^%s]+)'):format(sep or ',')

str = tostring(str or ' ')
str:gsub(pattern,
function(field)
otbl[#otbl + 1] = (field or ' ')
end
)
return #otbl, otbl
end -- fn rtvFields

each field I will get is positionally dependent, and it may contain a space or a void

local ATTR = fhGetValueAsText(aptr)
ATTR = ATTR:gsub('^,', ' ,'):gsub(',,,,', ', , , ,'):gsub(',,,', ', , ,'):gsub(',,', ', ,')

local _, tbl = rtvFields(ATTR, ',')
for i = 1, flds do
if not tbl then
tbl = ' ' (this is to insure all fields exist. that is a space)
else
tbl = trime(tbl) (this trims leading and trailing spaces. trim ends as opposed to trimi (trim multispaces inside the string)
end
end

local war = tbl[1]
cw.war = math.max(cw.war, #war)
local arm = tbl[2]
cw.arm = math.max(cw.arm, #arm)
local rank = tbl[3]
cw.rnk = math.max(cw.rnk, #rank)
local oth = tbl[4]
cw.oth = math.max(cw.oth, #oth)
>> those cw (column width) fields are used for later spacing in the print file.

if not __rtv then
GEDRCD[#GEDRCD].pATTR = aptr:Clone()
GEDRCD[#GEDRCD].SVCDAT = svcdat
GEDRCD[#GEDRCD].sSVC = dsf
GEDRCD[#GEDRCD].WAR = war
GEDRCD[#GEDRCD].ARM = arm
GEDRCD[#GEDRCD].RANK = rank
GEDRCD[#GEDRCD].OTH = oth
end

_cs =
{
svcdat = svcdat,
war = war,
arm = arm,
rank = rank,
oth = oth,
}

return _cs
end -- fn matMILSVC


now having that I add _cs to my record of other GEDCOM info...for that (in this case...MilSvc attribute.)

later, I will print those records,

Code: Select all


  Name                                                             S      Era             SVCDate     War                    ARM                                  Rank                                                         
* Aincham (Dayton), Laura Alice                F (1895 - 1994)                                             US Army                              PVT                                                                                                                  
* Aincham, Dexter Charles                        M (1923 - 1992)                     WWII                   US Army                              CPL   
* Austin, Humphrey                                      M (     - 1864) 12 Jan 1864  Civil War                 US Army                            >>  (this does not wrap in the printfile) >>                                                Company K 9th MI Infantry Volunteers                               
* Ayres, DeWitt Clinton                              M (1838 - 1921)  1862-1865  Civil War              US Army                              PVT                                               Company H 30th WI Infantry                                         
since I am already handling the record, I fix the voids, and the print statement becomes

for k, _ in ipairs(GEDRCD) do
recno = k -- used by inlvl function
local g = GEDRCD[k]

if IIDLVL(g.iID) == true then
dtl1 = ('%s %s%s%s'):format(g.isrlt, movl(trim(g.NAME), cw.nam), movc(g.SEX, cw.sex), movl(g.ERA, cw.era))
else
dtl1 = string.format('%s', _BLANKS((2 + cw.nam + cw.sex + cw.era)))
end
print(g.iID)
print('"' .. movc(g.SVCDAT, cw.era) .. '"')
local dtl2 = string.format('%s%s%s%s%s', movc(g.SVCDAT, cw.era), movl(g.WAR, cw.war), movl(g.ARM, cw.arm), movl(g.RANK, cw.rnk), movl(g.OTH, cw.oth))

local DTL = ('%s%s%s'):format(dtl1, dtl2,
_BLANKS(__linlen - (UTF8len(dtl1) + UTF8len(dtl2))))
__PRTF[#__PRTF + 1] = DTL
end

where movl moves the field left justified in the longest space allocated for (in this case name) trim removes any multiple spaces in the name (when I build name I put 2 spaces before Sr suffix so that Sr and Jr sort right, I remove the extra space at print movc centers a field under the same type of conditions.
if the field in any of my formatting is '' I return as is, if it is anything else (including a blank) I pad whichever way movl movr movc so that print is always aligned.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Map Life Facts coding question

Post by tatewise »

In what way does the script I offered not do what you want?

Have you tried it?

As far as I can tell it does exactly what you asked for.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Map Life Facts coding question

Post by Ron Melby »

mike, it does work, in fact, just fine, but your explanation of left to right and continue got me to set up a little test and test run to see if I could watch the 'animation' of it in debug. I must say, visually, yours looks cooler. I know its sort of off-beat, but gotta take your amusements where you can find them. Your code has also found some pretty arcane bugs in my movl and trim, that are so 'edgy' I have never run across them before in all my runs of all my plugins, so those got fixed, but now I am back to your gsub code on the string and cutting up fields again. thank you.

But it is why I said: 'but it comes to the same thing perhaps.'

I want a space before every void comma. << this is how I thought of it. >> yours puts a space after some commas which is the exact same effect, as you know. semantics only, you say boot and I say trunk,
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Map Life Facts coding question

Post by tatewise »

No, my script ensures one and only one space appears immediately after every comma whether 'void' exists or not.
e.g.

Code: Select all

,Civil War, ,         US Army,,Company A
becomes

Code: Select all

 , Civil War, , US Army, , Company A
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 917
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Map Life Facts coding question

Post by Ron Melby »

ATTR = ATTR:gsub('^,', ' ,'):gsub(',,', ', ,'):gsub(',,', ', ,')

having thought about it, it seems like this would be the most efficient.
1. fix any first voids: gsub('^,', ' ,')
2. fix every other void: gsub(',,', ', ,')
3. fix remaining voids: gsub(',,', ', ,')
FH V.6.2.7 Win 10 64 bit
Post Reply