FIND popup dialog window appears slowly in IDE

I’m a big fan of Ctrl-F. I press it all the time. One of the things I noticed when first using Clarion 11 is that the Find window appeared a LOT faster in Clarion 11 (which was new) to Clarion 10 (which I’d been using for a long time.)

Today I had cause to go back to Clarion 10, and re-discovered the really slow Find window. But it also occurred to me that the Find window in my Clarion 11 had been going progressively slower to open as well. Which made me think that it’s a “degrade” issue - which it turn made me think of the “Find What” drop-down (which grows over time). So I went looking.

Turns out;
Close all your Clarion instances.
In an editor (not Clarion) Open C:\Users\bruce\AppData\Roaming\SoftVelocity\Clarion\11.0\ClarionProperties.xml
(aka %appdata%\SoftVelocity\Clarion\11.0\ClarionProperties.xml)

(you can replace 11.0 with whatever clarion you are using)

search for the line <FindPatterns
replace the whole line with
<FindPatterns value="" />
(in my file this line was over 72K long)

Restart IDE, test, and voila - Ctrl-F is now instant! yay!..

9 Likes

Fantastic tip Bruce! My Find was 100 KB. Can also get rid of the Replace strings which were right below FindPatterns, mine was 4kb. My file went from 150kb to 41kb.

<FindPatterns value="" />
<ReplacePatterns value="" />

Someone (me?) should make a little utility “CwFindClean” to make it easy to zap. I rarely can use the drop list, it never seems to be in MRU order or any order that I can see. The XML Value= seems to be LIFO (last in first). If I was making a utility I might keep the last 20. The C3h byte seems to be the delimiter. Maybe with a reasonable number of entries the drop list will be LIFO. Seems to be that way now that I cleared it.

While we are talking about Find one that I like is “Find Selected” where you Select text and then press Ctrl+F3. This does not open the Find dialog, it just jumps to the next. Press Ctrl+_F3 again for the next. If you select text and press Ctrl+F that will appear in the Find Dialog, as long as it was not open.

Find_Selected

The other one I use a lot is the Incremental Search. Press the hot key Ctrl+L (I changed to Ctrl+I the #Develop default) and start typing text. it appears in the Status bar and the Editor locates. Because the editor text is selected you can press ctrl+F3 to find the next.

Find_Inc

Edit 1/23: My C10 was still on Ctrl + L so to change to the #Develop default of Ctrl + I open Options to Menu Shortcuts

1 Like

I use Ctrl-F3 all the time, too!

Yes, ReplacePatterns could be trimmed as well. Although mine, like yours, is a tiny fraction of the FindPatterns.

Like you I also never really use the drop-down on the search text button - and clearly 170K of drop-downs is particularly useless.

A utility would be nice, but frankly it takes years to accumulate enough to run slow, so I’d likely only run this every year or so…but hey, I know you’re bored so…

I searched my FindPatterns for the C3h delimiter and found 7,600. Replace had 385.

I’m most interested in keeping the Drop list in LIFO order so I can repeat recent searches using the Drop List. It seems to be LIFO since I cleared it. I’ll start using it more and watch it. Maybe I’ll test putting back 20 to 200 of the FindPatterns I had to find a breaking point. I see no point in having more than 50.

Would be good to have a global option “Max number of entries in Find dialog” in the IDE.

2 Likes

Carl I think the delimiter is (hex) C3 BF

This looks to be UTF-8 encoding of a high values byte (FFh). In fact you can see the EF BB BF (hex) first three characters in the file which are the UTF-8 byte order mark.

Someone (me?) should make a little utility “CwFindClean” to make it easy to zap.

OK then, never one to shirk a challenge when it involves string manipulation I have knocked up function to do this using StringTheory (my favourite third party tool).

As always there are numerous ways to do these things - you might, for example, think to do a split on the entries then delete excess entries from the lines queue and then join the remaining entries. While Split and Join are fast, they are not needed in this case.

TrimProperty         PROCEDURE  (STRING pFileName,STRING pProperty,STRING pDelim,LONG pEntriesToRetain=20) 
st     StringTheory
lStart Long
lEnd   Long

  CODE
  if ~st.loadFile(pFileName) then stop('failed to load file'  & clip(pFileName) & '<13,10>Error: ' & st.LastError); return.

  st.findBetweenPosition('<' & clip(pProperty) & ' value="','" />', lStart, lEnd)
  if lStart <= 0 or lStart > lEnd then return.
 
  loop pEntriesToRetain times
    lStart = st.findChars(pDelim,lStart+1,lEnd)
    if ~lStart then break.
  end
  if lStart   ! if more entries than desired, make a backup then remove extra entries
    st.saveFile(TimeStampFileName(pFileName))
    st.removeFromPosition(lStart, lEnd - lStart + 1)  ! remove extra entries
    st.saveFile(pFileName)
  end

I put the time-stamping of the file name (used above to create a backup) into a separate procedure as it is likely to be reusable:

TimeStampFileName    PROCEDURE  (STRING pFileName)    
st StringTheory
  CODE
  if ~pFileName then return ''.
  st.setvalue(st.PathOnly(pFileName))
  st.append(st.FileNameOnly(pFileName,false) & ' on ' & format(today(),@d12) & |
            ' at ' & format(clock(),@T05) & format(clock()%100,@N02) & |
            '.' & st.ExtensionOnly(pFileName),,'\')
  return st.getValue()

as I always say, with ST you can accomplish a lot with just a few lines of code.

OK to use it:
TrimProperty(‘C:\Users\Geoff\AppData\Roaming\SoftVelocity\Clarion\11.0\ClarionProperties.xml’,‘FindPatterns’,’<0C3h,0BFh>’)

or

  myFile = 'C:\Users\Geoff\AppData\Roaming\SoftVelocity\Clarion\11.0\ClarionProperties.xml'
  TrimProperty(myFile,'FindPatterns','<0C3h,0BFh>') 

that will retain the default 20 entries.

what if I want to retain 50 entries?

TrimProperty(myFile,‘FindPatterns’,’<0C3h,0BFh>’,50)

what if I want to clear it out completely?

TrimProperty(myFile,‘FindPatterns’,’<0C3h,0BFh>’,0)

and clear out ReplacePatterns?

TrimProperty(myFile,‘ReplacePatterns’,’<0C3h,0BFh>’,0)

anyway hopefully that will be of use

cheers

Geoff R

3 Likes

Nice! I would prefer to do Find and Replace together (so one backup) so suggest:

  • Refactor truncating the value into separate function
  • Return True to know that Value was changed else no need to Write file
  • Return Count found as *LONG Out so can display to see effect.
  • Suggest also * Return bytes to see it was 100k. Show Bytes/Count-2 = Average Find string.
  • Use Copy() to make backup so original is not touched
  • Name backup ‘Claxxx.xml.YYMMDD-HHMMSS.xmlB4’ so easy to rename to undo, and to purge YYYY*.xmlb4 Creates too many old files that need clean up
  • Name backup 'Claxxx.xml.B4clean and .B4clean2 so just 2 backups

Here is some mocked up code (I am not an ST pro):

CleanFind   PROCEDURE(STRING pFileName,LONG pEntriesToRetain=20) 

   if ~st.loadFile(pFileName) then 
       Message('Failed to load file: '  & clip(pFileName) &' |Error: '& st.LastError ,'Find Clean')
       return
   end    

   if  ~TrimPatterns(st,'FindPatterns',pEntriesToRetain,FindCnt,FindBytes) |
   and ~TrimPatterns(st,'ReplacePatterns',pEntriesToRetain,ReplCnt,ReplBytes) THEN 
        Message('Only found ' & FindCnt &' FindPatterns' & |
               ' and ' & ReplCnt &' ReplacePatterns.' & 
               '||Require ' & pEntriesToRetain &' to act.||' & pFileName ,'Find Clean')
        return 
   end
    
   !no: SaveB4FN=clip(pFileName) &'.'& format(today(),@d12) &'-' & format(clock(),@T05) & ' .xmlB4'
   SaveB4FN=clip(pFileName) &'.B4clean'
   Copy(SaveB4FN,clip(SaveB4FN) & '2')  !keep 2 backups
   Copy(pFileName,SaveB4FN)
   if errorcode() then 
      message('Copy to save B4 XML fail....')
      return
   end 

   if ~st.saveFile(pFileName) then
      message('Error Saving... ' &pFileName ,'Find Clean' )
      return 
   end  

   Message('Found ' & FindCnt &' FindPatterns' & |
           ' and ' & ReplCnt &' ReplacePatterns.' & 
           '||Reduced to ' & pEntriesToRetain &' Patterns.||' & pFileName ,'Find Clean')
   return 

Function to just find the value and remove excess:

TrimPatterns PROCEDURE(StringTheory st,STRING pProperty, LONG pEntriesToRetain=20, *LONG OutFoundCount, *LONG OutBytes)!,BOOL
pDelim  Equate('<0C3h,0BFh>') 
lStart Long
lEnd   Long
  CODE
  OutFoundCount=0
  OutBytes=0
  st.findBetweenPosition('<<' & clip(pProperty) & ' value="','" />', lStart, lEnd)
  if lStart <= 0 or lStart > lEnd then return FALSE.
  OutFoundCount = st.count(pDelim,1,lStart+1,lEnd) + 1  !Correct?
  OutBytes=lEnd-lStart+1                                                        !Correct?
  !rest of your ST code
  loop pEntriesToRetain times
    lStart = st.findChars(pDelim,lStart+1,lEnd)
    if ~lStart then break.
  end
  if lStart   ! if more entries than desired, make a backup then remove extra entries
     st.removeFromPosition(lStart, lEnd - lStart + 1)  ! remove extra entries
  end
  Return CHOOSE(lStart<>0)   !True if removed stuff

Probably safer to not assume perfect and consistent xml that may have been altered in manual editing. Suggest first Find Between ‘<FindPatterns<32>’ and ‘/>’, then between those FindBetween ‘value="’ and ‘"’. That way if extra white space got in, or another attribute=, it would still find just the value=“findme” attribute.

1 Like

thanks Carl for your great suggestions/improvements… and your “mocked up” code is close to being usable as it is.

personally I like lots of backups so I preferred your original version rather than just keeping the last two copies - but that is just personal preference.

When adding a time-stamp I generally like to keep the hundredths of seconds too in case you are outputting several files within a second so they are much less likely to overwrite each other.

I was originally aiming for something more general so originally had the delimiters as parameters but given you are going to have them hard-coded, I would go with a String rather than an equate as you are passing them to methods that expect a string parameter. You would think it wouldn’t matter (and maybe it doesn’t these days) but I was bitten doing this back last century and have avoided it ever since.

so anyway a couple of tweaks and this compiles (and hopefully works too )

CleanFind            PROCEDURE  (STRING pFileName,LONG pEntriesToRetain=20) 
st        StringTheory
lStart    Long
lEnd      Long
lClock    Long,auto
SaveB4FN  String(FILE:MaxFileName)
FindCnt   Long
FindBytes Long
ReplCnt   Long
ReplBytes Long

  CODE
   if ~st.loadFile(pFileName) then 
       Message('Failed to load file: '  & clip(pFileName) &'||Error: '& st.LastError ,'Find Clean')
       return
   end    

   if not (TrimPatterns(st,'FindPatterns',pEntriesToRetain,FindCnt,FindBytes) + |
           TrimPatterns(st,'ReplacePatterns',pEntriesToRetain,ReplCnt,ReplBytes)) THEN 
        Message('Only found ' & FindCnt &' FindPatterns' & |
               ' and ' & ReplCnt &' ReplacePatterns.' & |
               '||Require more than ' & pEntriesToRetain &' to act.||' & pFileName ,'Find Clean')
        return 
   end

   !no <g>: SaveB4FN=clip(pFileName) &'.'& format(today(),@d12) &'-' & format(clock(),@T05) & ' .xmlB4'
   lClock = clock() 
   SaveB4FN=clip(pFileName) &'.'& format(today(),@d12) & |
                   '-' & format(lClock,@T05) & format(lClock%100,@N02) & '.xmlB4'
   Copy(pFileName,SaveB4FN)
   if errorcode() then 
      message('Copy to save B4 XML failed....' & |
              '||from : ' & clip(pFileName) & |
              '||to   : ' & clip(SaveB4FN) & |
              '||error: ' & error(),'Find Clean')  
      return
   end 

   if ~st.saveFile(pFileName) then
       Message('Failed to save file: ' & clip(pFileName) &'||Error: '& st.LastError ,'Find Clean')
       return
   end  

   Message('Found ' & FindCnt &' FindPatterns with length ' & FindBytes & |
           ' and '  & ReplCnt &' ReplacePatterns with length ' & ReplBytes & |
           '||Reduced to ' & pEntriesToRetain &' Patterns.||' & pFileName ,'Find Clean')
   return 

Function to just find the value and remove excess:

TrimPatterns         PROCEDURE  (StringTheory st,STRING pProperty, LONG pEntriesToRetain=20, *LONG OutFoundCount, *LONG OutBytes) !,BOOL ! Declare Procedure
lDelim String('<0C3h,0BFh>') 
lStart Long
lEnd   Long

  CODE
  OutFoundCount=0
  OutBytes=0
  st.findBetweenPosition('<<' & clip(pProperty) & ' value="','" />', lStart, lEnd)
  if lStart <= 0 or lStart > lEnd then return FALSE.
  OutFoundCount = st.count(lDelim,1,lStart,lEnd) + 1 
  OutBytes=lEnd-lStart+1
  if pEntriesToRetain > 0
    lStart -= size(lDelim)
    loop pEntriesToRetain times
      lStart = st.findChars(lDelim,lStart+size(lDelim),lEnd)
      if ~lStart then return FALSE.
    end
  end
  st.removeFromPosition(lStart, lEnd - lStart + 1)  ! remove extra entries
  Return TRUE   !True if removed stuff

Probably safer to not assume perfect and consistent xml that may have been altered in manual editing. Suggest first Find Between ‘<FindPatterns<32>’ and ‘/>’, then between those FindBetween ‘value="’ and ‘"’. That way if extra white space got in, or another attribute=, it would still find just the value=“findme” attribute.

yes I don’t disagree but it is turning midnight here so will have to wait for another day :sunglasses:

cheers

2 Likes

why all that if C11 support it already?

What’s “all that”?

Supports what?

Can you expand on your post? There are 11 posts, to which are you referring?

Hi Diego and welcome!

I think the point of this post is that C11 and older versions DON’T have any support for reducing the slowness of Ctrl-F over time.

There seem to be a lot of things like this in Clarion, as I am discovering.

Could it be this?

image