* Search and Replace Plugin - Calico

Homeless Posts from the old forum system
Locked
avatar
ikas
Platinum
Posts: 32
Joined: 02 Sep 2011 14:37
Family Historian: V7
Location: West Coast of Scotland

Search and Replace Plugin - Calico

Post by ikas » 29 Mar 2012 16:40

Hi,

I was hoping to use this plugin to replace all occurences of .tif with .jpg in a GEDCOM - previously used a text editor for this but it would be useful to run it within FH.

However it appears to replace all occurances of tif (without period at start) as well as .tif

Hence certified is changed to ce.jpgied

Can someone point me to the offending line in the plugin source - I cannot see it.

Thanks

ID:6058

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

Search and Replace Plugin - Calico

Post by PeterR » 29 Mar 2012 17:27

There is a clue in that 'rtif' was replaced by '.jpg'.  The dot '.' in the search string is a 'magic' character and stands for any character.  If you precede the dot '.' in the search string (only)  with a percent sign '%' it will escape the magic character and should find only the required occurrences.

I've tried '%.tif' as a search string and it works OK, with '.jpg' as a replace string.

avatar
ikas
Platinum
Posts: 32
Joined: 02 Sep 2011 14:37
Family Historian: V7
Location: West Coast of Scotland

Search and Replace Plugin - Calico

Post by ikas » 29 Mar 2012 17:32

Many thanks Peter. Did the trick.

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

Search and Replace Plugin - Calico

Post by tatewise » 29 Mar 2012 17:42

I think this may be a deficiency in the Plugin.
I would not expect a user to have to know about the Regular Expression 'Magic' characters, and work around them.

There is a straight-forward function that can be incorporated into the Plugin to ensure all user entered 'Magic' characters are automatically hidden by the % character.
See the Plugin Code Snippet called Plain Text Substitution.

avatar
ikas
Platinum
Posts: 32
Joined: 02 Sep 2011 14:37
Family Historian: V7
Location: West Coast of Scotland

Search and Replace Plugin - Calico

Post by ikas » 29 Mar 2012 20:13

Yes, agree. Knowledge of regular expressions should not be a pre-requistite to use this plug-in but can understand why it was missed.

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Search and Replace Plugin - Calico

Post by Jane » 19 Apr 2012 18:03

I have finally got around to the Search and Replace plugin

It now has 'whole word' and 'plain text' options.

Please could a few brave souls give it a go before I upload it to the plugin store

http://dl.dropbox.com/u/1367679/plugins ... ace.fh_lua

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

Search and Replace Plugin - Calico

Post by tatewise » 19 Apr 2012 20:43

Have not run any in depth tests, but here are a couple of suggestions.

(1) Whole Word Concept
Tried replacing munro with manro in Family Historian Sample Project.
With default Plugin settings it did not find /Munro/ nor Munro, because the slashes and comma prevents the Whole Words only match.
Maybe the strSearchFor needs to use more than just %s space separators for words, such as any punctuation perhaps.
[%s%p] worked well.

(2) Dialogue Tooltips
I am sure there was also posting asking for details about which fields each replacement Class related to.
This could be assisted by adding Tooltips to the iup.GetParam dialogue.
These would list the most popular actual field names for each Class.

Tooltips would also be useful on some of the other options.
In particular, explain that the alternative to Plain Text Search is Regular Expression Search & Replace.
For example, Search for ([0-9])([0-9]) and Replace with %2%1 will swap any pair of digits.

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

Search and Replace Plugin - Calico

Post by tatewise » 20 Apr 2012 10:35

Tooltips
Here are some suggestions for Tooltips in the iup.GetParam dialogue:

Code: Select all

'Replace in the following Classes %tn'..
'Text fields: %b{Title, Author, Type, Custom Id, Phone, E-mail, Website, Format, Keywords, etc.}n'..
'Long Text: %b{Address, Where Within Source, Text From Source, Note, etc.}n'..
'Names: %b{Name fields only.}n'..
'Places: %b{Place fields only.}n'..
'Key Words: %b{Word Lists??}n'..
'Extra Options %tn'..
'Whole Words only: %b{Whole words are delimited by spaces, tabs, and punctuation.}n'..
'Plain Text Search: %b{Plain Text or Regular Expression search & replace.}n'
I am not sure that the Text fields and Long Text tooltip lists are exhaustive.

I could not find any fields that matched the Key Words class. Certainly, the Multimedia Keywords are NOT in this class, but in the Text fields class.

Other Classes
Are there any pros or cons to adding the other classes such as:
enumword, enumlist, word, word2, rect, and age text types?
Also date and integer, which would need some specific processing?

Regular Expressions
Regular Expressions with (parenthesis) captures do NOT work in conjunction with the Whole Words only option.
I suggest that in Regular Expression Search mode, if the Search For string contains any (parenthesis) captures, then switch off the Whole Words only option.

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Search and Replace Plugin - Calico

Post by Jane » 20 Apr 2012 12:15

I have updated to use [%s%p] and to only do word if plain text is selected, same link as before.

I have also done the tool tips.

I am not sure about adding the other fields as they are not text. In some ways if you need to work on dates I would prefer to see a separate plugin to handle them.

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

Search and Replace Plugin - Calico

Post by tatewise » 20 Apr 2012 13:48

Do you know what fields match the Key Words class?

What about adding the text types of enumword, enumlist, word, word2, rect, and age?

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Search and Replace Plugin - Calico

Post by Jane » 20 Apr 2012 14:22

Do you know what fields match the Key Words class?
This is the wordlist value, but I don't know what fields return it.
What about adding the text types of enumword, enumlist, word, word2, rect, and age?
enumword a word (or short phrase) from a fixed choice of values text

This has fixed values so I would not want to replace items using a general plugin.


enumlist a comma-separated list of words (or short phrases) from a fixed choice of values text

This has fixed values so I would not want to replace items using a general plugin.


word a word (or short phrase) text
I am tempted to add this to the same value as text.

word2 a word (or short phrase), but more tightly restricted (e.g. brackets are not allowed) text
This needs special processing to make sure it can't have invalid data replaced into it.


rect a set of 4 coordinate values text
This is only used on ASIDs and again I can't see a good reason to want to search and replace this.


age age data (in months or years)
Again I can't see why you would want to search and replace this across a whole database.

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

Search and Replace Plugin - Calico

Post by tatewise » 21 Apr 2012 11:14

I agree with above explanations.

Perhaps wordlist as well as word should be lumped in with text.

I have done a fairly thorough search of GEDCOM fields with the following results:

Found NO wordlist class fields anywhere.

The only word class I found was the Multimedia Format field.

The revised tooltips based on the search results:

'Text fields: %b{Name Prefix/Suffix/Given/Nickname, Attribute values, Cause, Where Within Source, Title, Type, Custom Id, City, State, Postcode, Country, Phone, E-mail, Website, File, Format, Keywords, Sentence, etc.}n'..
'Long Text: %b{Note, Address, Author, Text From Source, Publication Info, Link/Note.}n'..

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Search and Replace Plugin - Calico

Post by Jane » 23 Apr 2012 17:19


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

Search and Replace Plugin - Calico

Post by tatewise » 23 Apr 2012 21:22

Two things I have spotted need correcting.

(1)

Code: Select all

     if pWhole == 1 then
    -- Special Case search for last word and first word
should be

Code: Select all

    if pWhole == 1 and pPlain == 1 then
    -- Special Case search for last word and first word
(2)

Code: Select all

'Text fields: %b{{Name Prefix ...
should be

Code: Select all

'Text fields: %b{Name Prefix ...
i.e. remove duplicated {

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

Search and Replace Plugin - Calico

Post by tatewise » 23 Apr 2012 22:35

Here is another refinement you might like in function srPrompt.

Code: Select all

        inp_from_string.multiline = 'YES'
        inp_from_string.size = '0x80'
        inp_from_string.wordwrap  = 'YES'
        inp_to_string.multiline = 'YES'
        inp_to_string.size = '0x80'
        inp_to_string.wordwrap  = 'YES'
becomes

Code: Select all

        local intLines = 1
        for strLine in string.gmatch(strFrom..'n','(.-)n') do
                intLines = intLines + math.ceil(string.len(strLine)/100)
        end
        inp_from_string.visiblelines = intLines
        inp_from_string.multiline = 'YES'
        inp_from_string.wordwrap  = 'YES'
        intLines = 1
        for strLine in string.gmatch(strTo..'n','(.-)n') do
                intLines = intLines + math.ceil(string.len(strLine)/100)
        end
        inp_to_string.visiblelines = intLines
        inp_to_string.multiline = 'YES'
        inp_to_string.wordwrap  = 'YES'
What this does is calculate how many visiblelines are needed to display the text.
It iterates over the text line by line, and guesses how many GUI lines each text line it will wrap over, assuming about 100 chars per GUI line.
The math.ceil function rounds up to next integer, so even short text lines will register as one GUI line.

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Search and Replace Plugin - Calico

Post by Jane » 23 Apr 2012 22:56

I'll think about the visible lines, as it won't work if there are very long notes as you could easily end up with a dialogue bigger than the viewport, so it needs more complex maths to work out the height of lines for the selected font to compare with the height of the available screen size.

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

Search and Replace Plugin - Calico

Post by tatewise » 23 Apr 2012 23:07

Fair point, so change as follows, so number of GUI lines is limited to 9 or whatever you think is a reasonable limit:

       inp_from_string.visiblelines = math.min(intLines,9)

       inp_to_string.visiblelines = math.min(intLines,9)

User avatar
Jane
Site Admin
Posts: 8440
Joined: 01 Nov 2002 15:00
Family Historian: V7
Location: Somerset, England
Contact:

Search and Replace Plugin - Calico

Post by Jane » 24 Apr 2012 13:57


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

Search and Replace Plugin - Calico

Post by tatewise » 24 Apr 2012 21:02

Further comments on function srPrompt().

(1) The following two statements need deleting, otherwise the visiblelines value has no effect:
       inp_from_string.size = '0x80'
       inp_to_string.size = '0x80'

(2) There is a snag with the statement dlg.minsize = dlg.size because minsize units are pixels whereas size units are fractions of character.
One solution is to use the actual screen size to set the GUI size.

Add this function:

-- Split a string into numbers using separators space or comma or x --
function string:SplitNumbers()
     local tblNum = {}
     self:gsub('([^%s,x]+)', function(c) tblNum[#tblNum+1] = c end)
     for i=1, #tblNum do
           tblNum = tonumber(tblNum)
     end
     return tblNum
end -- function string:SplitNumbers

In function srPrompt() remove ,minsize='150' from:

local inp_from_string = iup.text{expand='HORIZONTAL'}

Add the following statements just before local dlg = ....

     local tblScrn = iup.GetGlobal('VIRTUALSCREEN'):SplitNumbers()
     -- tblScrn[1] = origin x, tblScrn[2] = origin y, tblScrn[3] = width, tblScrn[4] = height
     local intWidth = tblScrn[3]

In local dlg = ... replace size='HALF' with rastersize=intWidth/2.

Later on replace dlg.minsize = dlg.size with dlg.minsize = dlg.rastersize.

(3) In function Replace(ptr) the second test is redundant in:

   if pConfirm  == 1 and strFromString ~= strToString then

because it is immediately preceded by:

 if strFromString ~= strToString then

Locked