* Map Life Facts coding question
Map Life Facts coding question
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.
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
- tatewise
- Megastar
- Posts: 28341
- Joined: 25 May 2010 11:00
- Family Historian: V7
- Location: Torbay, Devon, UK
- Contact:
Re: Map Life Facts coding question
The code is within the function StrGeocodeLocation(strLocName) about line 3740:
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.
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
( 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
Re: Map Life Facts coding question
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.
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
- tatewise
- Megastar
- Posts: 28341
- Joined: 25 May 2010 11:00
- Family Historian: V7
- Location: Torbay, Devon, UK
- Contact:
Re: Map Life Facts coding question
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 ', '
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
Re: Map Life Facts coding question
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,
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.
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
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
- tatewise
- Megastar
- Posts: 28341
- Joined: 25 May 2010 11:00
- Family Historian: V7
- Location: Torbay, Devon, UK
- Contact:
Re: Map Life Facts coding question
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.
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
Re: Map Life Facts coding question
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,
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
- tatewise
- Megastar
- Posts: 28341
- Joined: 25 May 2010 11:00
- Family Historian: V7
- Location: Torbay, Devon, UK
- Contact:
Re: Map Life Facts coding question
No, my script ensures one and only one space appears immediately after every comma whether 'void' exists or not.
e.g.
becomes
e.g.
Code: Select all
,Civil War, , US Army,,Company A
Code: Select all
, Civil War, , US Army, , Company A
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
Re: Map Life Facts coding question
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(',,', ', ,')
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