* Plugin Help

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

Plugin Help

Post by Ron Melby » 17 Feb 2018 01:32

I am struggling to learn LUA and the FH API.
I code by debug.

All three of these tools are woefully inadequate, the first two in documentation and the last in features and variable display.

I have the situation in my file (a new file) repeatedly:

1 FAMC @F24@
2 PEDI Adopted
1 NICK Marcus
2 SOUR @@S1467382439@@

or any variation thereof. not too many of them have the source problem and I can fix those by hand in the UDF List Plugin

I have plagiarized and stripped UDF List down to its bare bones, and that works as the original without the progress screen.

the gravamen of the issue is this:
Where I have the case, and the only case in a list of UDFs...
INDI.NICK

I want to take the item (nickvalue) and put it in the %indi.nick% whatever field and delete the UDF itemav


since I have left the table output and the table output will lead me to the field it must be inherent in the field that there are actual pointers to the record and place. it should be straightforward.

Now the question I have, is that true, and secondarily why couldnt I have just read with pointer (I am not up on the white coat language but if you are not too pedantic or obtuse... something like this, in psuedocode :
for _,sType in ipairs ('INDI'}) do
indiptr = the indi record
udfptr = 'INDI.NICK'
if udfptr != null
move item to %Ind.nick%
delitem pter(item)
enddo
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 27078
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Plugin Help

Post by tatewise » 17 Feb 2018 11:25

Regarding the Plugin advice, have you seen the plugins:index#developer_guide|> FH V5+ Plugins > Developer Guide?
(It is one of the topics in how_to:key_features_for_newcomers|> Key Features for Newcomers.)
There in plugins:getting_started|> Getting Started Writing Plugins there are links to FH advice and Lua Language References.
Did you find all those? What advice are they lacking?
The Tools > Plugins > More > How to Write Plugins > Sample Plugin Scripts have examples of similar copy data code.

When run in debug mode then at a break point the screen shows each Variable and its Value.
(You can also 'print' variables that appear in the pane lower left.)
PluginDebug.png
PluginDebug.png (27.45 KiB) Viewed 12539 times
The Plugin script that should perform as you requested is:

Code: Select all

	local ptrItem = fhNewItemPtr()
	ptrItem:MoveToFirstRecord("INDI")
	while ptrItem:IsNotNull() do							-- loop through all Individual records
		local ptrUDF = fhGetItemPtr(ptrItem,"~.NICK") 
		if ptrUDF:IsNotNull() then						-- found NICK UDF
			local ptrName = fhGetItemPtr(ptrItem,"~.NAME")
			if ptrName:IsNull() then						-- ensure NAME sub-field exists
				ptrName = fhCreateItem("NAME",ptrIndi)
			end
			local ptrNick = fhGetItemPtr(ptrName,"~.NICK")
			if ptrNick:IsNull() then						-- ensure NICK sub-field is not already used
				ptrNick = fhCreateItem("NICK",ptrName) 	-- create and set NICK value from UDF
				fhSetValueAsText(ptrNick,fhGetValueAsText(ptrUDF))
				fhDeleteItem(ptrUDF)					-- delete UDF
			end
		end
		ptrItem:MoveNext()
	end
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 17 Feb 2018 12:21

thank you for the code snippets I think I sort of understand them. Fairly straightforward method, as I thought there should be. With a few little decorations, what I had imagined it should be. Having spent over 3 years on UDF related things, I can confidently say that nearly 90% of udfs are items in the wrong place and or level. and some ETL one-off snippets should care for a lot of them which would be rather simple if one could use the up down arrows on the ALL screen, move instead of copy (with intelligence). I have a bunch of sources on records without the @S9999@ pointer on them but the note, page, data, text all correct placement, so my next one off will be to put a conforming source in them. I may make the source record MikeTate in honor of your help in lua plugins.

type fhDeleteItem into help. type data assistant into help. or DAR. perhaps fhDeleteItem is in functions(all)..............uh.........nope
I do not see the list of fh functions and their pararmeters and arguments detailed anywhere.
while editing a plugin to see the apis and the data access...........that would be minimal. not there, replete with hyperlinks.
as discussed the PSPeditor could be used but totally unconnected to FH. already do to much handwork for simple stuff.

to view a variable as actual data rather than table[#1] or array[14] in many cases would be handy. or to inspect the variable on the screen with a click.
spent half a day trying to figure out why buildDR was equal to Nick:Ollie and not Ollie. WYSIWYG.

BTW this file had the FTM to FH plugin strangled for over an hour before I killed it, dont know if it was on this or something else.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 27078
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Plugin Help

Post by tatewise » 17 Feb 2018 13:25

Ron, I suspect you are not taking enough time to study the advice provided.
As explained in the the plugins:index#developer_guide|> FH V5+ Plugins > Developer Guide the Help for Plugins is in Tools > Plugins > More > How to Write Plugins and that is where all the API such as fhDeleteItem() are described.
( They are NOT in the main FH Help pages, because non-programmers don't need it. )

Also in the Plugin Debug screen shown earlier, the Help command at the top provides what you requested:
Plugin Help
Current Function Help
Family Historian API
Lua Online Reference Manual

etc...
I am always amazed how many users do not click the Help command/button provided, or don't click the F1 key.
So while editing a Plugin all the Help you requested was there all the time.

Also Edit > Insert Data Reference provides the Data Ref Assistant you requested.

You can inspect any Variable by double-clicking it in lower right-hand pane, and all table elements are shown.
You may need to use Debug > Options to Display Global Types for some variables.
That is why it is a good idea to use local variables everywhere, as they are all displayed by default.

Also you can include print(...) commands in the Plugin script to display variables in lower left-hand pane.
That can include all elements of a table or array.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 17 Feb 2018 13:42

I will go to the quick link index and go to knowledge base. Uh, no
I will back out all the way from this forum and go to a screen and go to knowledge base and... in. Uh, no.

I hear ya, but if the idea is to demonstrate usability and intuitive interfaces, we are in #EpicFail;

I guess the print thing will help. So I can inspect the elements. I know about the variables in the lower left of the screen, used them as much as I am able, note that part where I was talking about Nick:Ollie instead of Ollie in a field.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 27078
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Plugin Help

Post by tatewise » 17 Feb 2018 13:53

There is no debug plugin, what my screenshot shows is the Plugin Editor screen that has debugging built in.

Please, please, please read the help in Tools > Plugins > More > How to Write Plugins.
In the How to Write Plugins sub-section it has 2. Getting Started - Hello World and 6. Debugging.
Initially use the New button, and thereafter you use the Edit button.

If you know about the variables in the lower left of the screen, then that is the editor/debugger as shown in my screenshot.
That is where the Help for Plugins I mentioned is available.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 17 Feb 2018 15:29

cool...right? while I am in the editor working on my program I will open a file of code snippets or another plugin to reuse code from ............uh, no.

So I went to the line in the debugger I wanted and hit F1............uh, no.
I went to the variable window and hit f1 on a variable....it never ceases to amaze me the number of people that tell you to hit F1, to demonstrate additional #EpicFail :lol:
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 27078
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Plugin Help

Post by tatewise » 17 Feb 2018 15:55

Yes, sorry, you can only have one Plugin Editor window open at a time.

Clicking F1 on a Variable in Variables pane won't display variable values, because that is nothing to do with displaying help advice, which is what the standard Windows F1 key is all about.

If you randomly choose any line in the Plugin script, and hit F1 you get the general Family Historian Plugin Help page, because it does not know which part of that line you want help with.

If you select a specific API function such as fhGetItemText then F1 will open that function help page.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 17 Feb 2018 21:35

Code: Select all

local ptrItem = fhNewItemPtr()
ptrItem:MoveToFirstRecord("INDI")
while ptrItem:IsNotNull() do                     -- loop through all Individual records
   local ptrUDF = fhGetItemPtr(ptrItem,"INDI.NICK") 
   if ptrUDF:IsNotNull() then                  -- found NICK UDF
     local ptrTemp = fhNewItemPtr()
     ptrTemp = fhHasChildItem(ptrUDF) --has kids  **
     if not fhHasChildItem(ptrUDF) then  --not now read next **
       local ptrName = fhGetItemPtr(ptrItem,"INDI.NAME")
       if ptrName:IsNull() then                  -- ensure NAME sub-field exists
         ptrName = fhCreateItem("NAME",ptrIndi)
      end
      local ptrNick = fhGetItemPtr(ptrName,"~.NICK")
      if ptrNick:IsNull() then                  -- ensure NICK sub-field is not already used
         ptrNick = fhCreateItem("NICK",ptrName)    -- create and set NICK value from UDF
         fhSetValueAsText(ptrNick,fhGetValueAsText(ptrUDF))
         fhDeleteItem(ptrUDF)               -- delete UDF
       end
    end
 end
 ptrItem:MoveNext()
 end
 
I added a line or two because in the NICK UDFs (I think as shown originally) I have child sources that I do not want to go away, they probably will go to whole record sources, and I am unsure about how to do that yet, where they are presently (but wrongly) children of 1 NICK, if I fix that until that code is in there then I will lose them according to documentation. So, I have just debugged all the way thru, and rolled back for the instant But a little plan here will cure two bits of problem in one fell swoop (can a swoop be actually considered executed unless it is indeed fell one wonders?) with slight coding differences,

I have this in the data item for nick occasionally and this in the source occasionally since it is UDF
"Ollie"
@@S12345@@
seems to me:
something like this bit of code idea:

arr{] = fhgetvalueastest(ptrUDF)
o =1
for q= 1 to len do
if NICK then
if arr(q] != """
out[o]= arr[q]
o += 1
end
fhSetValueAsText(ptrNick,fhGetValueAsText(out))

in the case of source
'@' + out + @ (in the case of where the source doesnt exist will FH let me create it or does it check? because I do have a few cases where the source record no longer exists somehow in the file I have. And if it goes back in @@S12345@ its ok, I can ask my cousin, what is that? although here is what I believe happened to mostof them (I merged sources and where those were already UDF at the time.......) well it may be in the standard to @@ them and ignore them, but here is the problem FH has actually now lost information IN MY FILE when they incorrectly merged without taking these into account, they deleted records for which the UDFS could have at one time been fixed.

so, is there a way cuz I dont see it yet to grab the udfs as a bunch,
2 SOUR
3 PAGE
3 NOTE and'/or DATA TEXT
and number them
1 SOUR
2 PAGE
2 NOTE
directly without moving the object versions about?
get the line once I know its a udf of that type
and read into text, string.gmatch or something, or read it into a ?structure? change the level and write it back out in place?
FH V.6.2.7 Win 10 64 bit

User avatar
DavidNewton
Superstar
Posts: 462
Joined: 25 Mar 2014 11:46
Family Historian: V7

Re: Plugin Help

Post by DavidNewton » 17 Feb 2018 22:12

tatewise wrote:Yes, sorry, you can only have one Plugin Editor window open at a time
Sorry Mike. It is not possioble via the Plugin Editor file menu but it is possible via the Tools>Plugins dialog box. Using the More>> button you can open as many as you like, or create new ones, without closing the existing ones.

David

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 17 Feb 2018 22:25

little lost here. lets make 'tend' that I am in writing my plugin, and I need to reference something in say UDF list, slosh around and copy a bunch of code to where my cursor is in this one. so edit, click, edit, click, edit, click.....uh do they even window and cascade then? oh, I see, that is gruesome
FH V.6.2.7 Win 10 64 bit

User avatar
DavidNewton
Superstar
Posts: 462
Joined: 25 Mar 2014 11:46
Family Historian: V7

Re: Plugin Help

Post by DavidNewton » 17 Feb 2018 22:51

Not quite sure what is gruesome. I frequently work with two plugin editor windows open and cut and paste from one to the other. I use Windows to split the screen like so.
TwoWindows.png
TwoWindows.png (57.94 KiB) Viewed 12435 times
David

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 17 Feb 2018 23:00

Tabbed editors on mainframes even since about 2000. but the editor doesnt remember its position, so many other things that dont do or remember it wrongly.

Ok, it can be done.
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 17 Feb 2018 23:41

Code: Select all

str = fhGetValueAsText(ptrUDF)
o = 1 
for i = 1, string.len(str) do
   if str(i) ~= '"' then
     out(o) = str(i)
     o = o + 1
   end
end  


error: out(o) = str(I) unexpected symbol near =

lost.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 27078
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Plugin Help

Post by tatewise » 18 Feb 2018 00:13

The solution is almost given to you on a plate in the Tools > Plugins > More > How to Write Plugins > Sample Plugin Scripts.
The Christening-Baptism Conversion has the two copy functions you need.

The the code you need is :-
CopyChildren_FromTo(ptrUDF,ptrName)

That will add the SOUR structure to the NAME field.

If you want it added to the whole record then use :-
CopyChildren_FromTo(ptrUDF,ptrIndi)
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 18 Feb 2018 01:30

I have seen that in the meantime, thank you. that will be the loop after if ghgetchild:is Null
I will then have a loopif fhgetchil:Isnotnull


current problem is stripping characters, in this case > " from a field.

Turning "Ollie" into Ollie
FH V.6.2.7 Win 10 64 bit

User avatar
DavidNewton
Superstar
Posts: 462
Joined: 25 Mar 2014 11:46
Family Historian: V7

Re: Plugin Help

Post by DavidNewton » 18 Feb 2018 07:24

Check out the Lua Online Reference Manual

http://www.lua.org/manual/5.1/manual.html#5.4

the string.gsub should do what you want
str=string.gsub(str,'"','')

David

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 18 Feb 2018 12:17

i Had looked at that and tried it

if ptrNick:IsNull() then
str = fhGetValueAsText(ptrUDF)
str = string.gsub(str,""","")
end


str = string.gsub(str,""","")
19: ')' expected near '","'

couldnt figure out how to make it work
FH V.6.2.7 Win 10 64 bit

User avatar
DavidNewton
Superstar
Posts: 462
Joined: 25 Mar 2014 11:46
Family Historian: V7

Re: Plugin Help

Post by DavidNewton » 18 Feb 2018 12:51

Ron you need to use both type of inverted commas so that the interpreter recognises the string delimiters - looks confusing on the forum. An alternative would be to use double square parentheses as string delimiters

str=string.gsub(str,[["]],[[]])

David

User avatar
PeterR
Megastar
Posts: 1129
Joined: 10 Jul 2006 16:55
Family Historian: V7
Location: Northumberland, UK

Re: Plugin Help

Post by PeterR » 18 Feb 2018 13:14

The original is clearer if posted as CODE:

Code: Select all

str=string.gsub(str,'"','')
In other words:
2nd parameter is two primes ' enclosing one string quote " i.e. '"'
3rd parameter is just two primes ' i.e. ''
Peter Richmond (researching Richmond, Bulman, Martin, Driscoll, Baxter, Hall, Dales, Tyrer)

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 18 Feb 2018 14:08

took awhile, but I did figure that out. I am now trying to fix those records where source is subsequent to NICK udf.


Code: Select all

if fhHasChildItem(ptrUDF) then   
    CopyChildren_FromTo(ptrUDF,ptrINDI)  
    fhSetValueAsLink(ptrINDI,ptrNew)
end

f I have understood miketate correctly, this should do it with the functions from the sample change christening to baptism

if I havent, Ill be back
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 18 Feb 2018 14:24

Yeah, no. ok, looking at the loop.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 27078
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Plugin Help

Post by tatewise » 18 Feb 2018 14:36

Yes, those functions will copy the Source and its sub-fields, but will not convert into a linked Source record.

What you have is a Source Note with plain text @@S12345@@.
The double @ is the way GEDCOM represents a single @ character to prevent being mistaken as a link @S12345@ that links to a Source record with Record Id = 12345.

It is possible for the Plugin script to convert the Source Note into a Source Link within the copy functions.
Again Lua patterns will help.
strRecId = string.match( strSour, "@@S(%d+)@@" )

local ptrRec = fhNewItemPtr()
ptrRec:MoveToRecordById( "SOUR", strRecId)


Then use:
local ptrNew = fhCreateItem( "SOUR", ptrParent )
fhSetValueAsLink( ptrNew, ptrRec)


So assuming actual Source Records exist with the Record Id the copy function becomes:

Code: Select all

function CopyChildBranch(ptrSrc, ptrTargParent)
    local strTag = fhGetTag(ptrSrc)
    if strTag == "SOUR2" then                                                     -- Found a Source Note
        strSour2 = fhGetValueAsText(ptrSrc)
        strRecId = string.match( strSour2, "@@S(%d+)@@" )   -- Extract Rec Id from Source Note
        local ptrRec = fhNewItemPtr()
        ptrRec:MoveToRecordById( "SOUR", strRecId)               -- Obtain pointer to Source Record
        local ptrNew = fhCreateItem( "SOUR", ptrTargParent )    -- Create the Source Link
        fhSetValueAsLink( ptrNew, ptrRec)
    else
        local ptrNew = fhCreateItem( strTag, ptrTargParent)        -- Otherwise just copy original tag
        fhSetValue_Copy(ptrNew, ptrSrc)
    end
    CopyChildren_FromTo(ptrSrc, ptrNew)
end
If Source Records do not exist with matching Record Id then you will have to create them, before saving the link.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 18 Feb 2018 17:07

Code: Select all

---------------------------------------
-- Function: CopyChildBranch
---------------------------------------
 function CopyChildBranch(ptrSrc, ptrTargParent)
 local ptrNew = fhCreateItem(fhGetTag(ptrSrc), ptrTargParent)
 fhSetValue_Copy(ptrNew, ptrSrc)
 CopyChildren_FromTo(ptrSrc, ptrNew)
 end
 
---------------------------------------
-- Function: CreateCopyChildren_FromTo
---------------------------------------
 function CopyChildren_FromTo(ptrFrom, ptrTo)
 local ptrF = fhNewItemPtr()
 ptrF = ptrFrom:Clone()
 ptrF:MoveToFirstChildItem(ptrF)
 while ptrF:IsNotNull() do
   CopyChildBranch(ptrF, ptrTo)
   ptrF:MoveNext()
 end
 end

--main

 local ptrINDI = fhNewItemPtr()
 ptrINDI:MoveToFirstRecord("INDI")
 while ptrINDI:IsNotNull() do                     
   local ptrUDF = fhGetItemPtr(ptrINDI,"INDI.NICK") 
   if ptrUDF:IsNotNull() then                     
     local ptrTemp = fhNewItemPtr()
     local ptrName = fhGetItemPtr(ptrINDI,"INDI.NAME")
     if ptrName:IsNull() then                    
       ptrName = fhCreateItem("NAME",ptrINDI)
     end
     local ptrNick = fhGetItemPtr(ptrName,"~.NICK")
     if ptrNick:IsNull() then                    
       str = fhGetValueAsText(ptrUDF)
       str = string.gsub(str,'"','')
       ptrNick = fhCreateItem("NICK",ptrName)    
       fhSetValueAsText(ptrNick,str)
        local ptrTemp = fhHasChildItem(ptrUDF) 
       if fhHasChildItem(ptrUDF) then   
         local ptrInsert = fhNewItemPtr()
         CopyChildren_FromTo(ptrUDF, ptrInsert) 
         print(ptrInsert)
         fhSetValueAsLink(ptrInsert, ptrINDI)  
       end
       fhDeleteItem(ptrUDF)               -- delete UDF
     end
   end
   ptrINDI:MoveNext()
 end
print(ptrInsert) at this point is null. I would expect it to have the value (and there is one) from CopyChildren_FromTo's ptrto what am I missing?
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 878
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: Plugin Help

Post by Ron Melby » 18 Feb 2018 17:58

well, zeroing in on the problem it is an @@ source, the debugger doesnt show that. it shows the field as @S1234567890@ (normal)
FH V.6.2.7 Win 10 64 bit

Post Reply