Recent

Author Topic: [SynEdit] how to force a highlighter to rescan complete file and wait  (Read 5923 times)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Hello,

i wrote a Cobol highlighter which prepares data for a Cobol parser. The highlighter does a full scan if i set the Highlighter property of my synedit or if i do Lines.LoadFromFile. But both functions return immediately and the scan seems to be run in the backgound. When i run the parser in an OnTimer event started by the OnChange event of the SynEdit the data is not prepared by the highlighter.
How can i wait for the highlighters initial scan or force a rescan which returns after everything is done?

Regards
Pascal
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9794
  • Debugger - SynEdit - and more
    • wiki
Re: [SynEdit] how to force a highlighter to rescan complete file and wait
« Reply #1 on: February 17, 2015, 06:47:53 pm »
If SynEdit has not got a handle yet, it will scan in the background (on idle in small steps).

This is useful if you have many SynEdit, like the IDE does. Then at startup, you do not need to wait for all highlighters to finish. (see TCustomSynEdit.IdleScanRanges line 4890 in SynEdit.pp)

Any visible SynEdit will scan all (in future maybe: to the last visible line).

Before a SynEdit interacts with a highlighter it always does:
Code: [Select]
FHighlighter.CurrentLines := FLines;
Then it calls:
Code: [Select]
FHighlighter.ScanRanges;This will scan all lines, that have changed since the last scan.

ScanRanges will only return if all is done.

The highlighter attaches a "ranges" object to the lines. The lines will inform the ranges about changes.
See TSynHighlighterRangeList  NeedsReScanStartIndex / NeedsReScanEndIndex
Code: [Select]
  TSynHighlighterRangeList = class(TSynManagedStorageMem)
    procedure ClearReScanNeeded;
    procedure AdjustReScanStart(ANewStart: Integer);
    procedure InvalidateAll;
    property NeedsReScanStartIndex: Integer read FNeedsReScanStartIndex;
    property NeedsReScanEndIndex: Integer read FNeedsReScanEndIndex;
    property NeedsReScanRealStartIndex: Integer read GetNeedsReScanRealStartIndex;
  end;
The highlighter may continue past NeedsReScanEndIndex, as long as the new "range" value for a line differs from the stored one. (See the highlighter tutorial on the wiki)


From memory/not tested, to force a full rescan (must probably subclass synedit)
Code: [Select]
FHighlighter.CurrentLines := FLines;
FHighlighter.CurrentRanges.InvalidateAll;
FHighlighter.ScanRanges;


Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: [SynEdit] how to force a highlighter to rescan complete file and wait
« Reply #2 on: February 17, 2015, 09:48:42 pm »
Thanks Martin,

that seems to work.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9794
  • Debugger - SynEdit - and more
    • wiki
Re: [SynEdit] how to force a highlighter to rescan complete file and wait
« Reply #3 on: February 17, 2015, 10:19:31 pm »
I wonder why you need that though?

Normally SynEdit, and the base classes decide correctly what to scan.

If it is for debugging, no prob. If it is for production, then there may be something else wrong.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: [SynEdit] how to force a highlighter to rescan complete file and wait
« Reply #4 on: February 18, 2015, 06:13:17 am »
The Problem is the first parse. When i setup a new editor with highlighter and set the text an OnEditorChange event starts a timer (500 ms) and the timer does a scan of the Cobol parser but the highlighter didn't prepare the basic TCobloToken, which the parser needs, until this time. So the parsing only delivers a correct result after the first manual change to the editor. Therefore i want to make sure that the editor file is fully scanned before the parser starts. Or is there something like an OnRangescanEnd event in the highlighter?
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9794
  • Debugger - SynEdit - and more
    • wiki
Re: [SynEdit] how to force a highlighter to rescan complete file and wait
« Reply #5 on: February 18, 2015, 03:47:06 pm »
SynEdit does not have an OnEditorChange event? It has OnChange and OnStatusChange.

Anyway the behaviour you describe happens if the text is set before the editor has a handle. (which would also be in FormCreate and other places).

In which method of your highlighter is the TCobloToken prepared? (What is it?)

When a scan finishes the highlighter does
  CurrentLines.SendHighlightChanged(1based_startline, cnt)
which send "senrHighlightChanged"

Anywhere where you have access to the internal lines of SynEdit (either the HL, or inherited SynEdit) you can do

Code: [Select]
SynEdit.TextBuffer .AddChangeHandler(senrHighlightChanged, @DoHighlightChanged);
HL.CurrentLines .AddChangeHandler(senrHighlightChanged, @DoHighlightChanged);
 
procedure TFoo.DoHighlightChanged(Sender: TSynEditStrings; AIndex,  ACount: Integer);







Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: [SynEdit] how to force a highlighter to rescan complete file and wait
« Reply #6 on: February 18, 2015, 08:36:19 pm »
Thanks Martin,

your sample, a little modified, works as expected and solves the problem.
Code: [Select]
procedure TsusEdit.RescanRanges;
begin
  if not Assigned(Highlighter) then exit;
  Highlighter.CurrentLines := GetTextBuffer;
  TsusEditHighlighterCobol(Highlighter).CurrentRanges.InvalidateAll;
  Highlighter.ScanRanges;
end;
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9794
  • Debugger - SynEdit - and more
    • wiki
Re: [SynEdit] how to force a highlighter to rescan complete file and wait
« Reply #7 on: February 18, 2015, 09:32:18 pm »
It would be better to move the OnChangeEvent to senrHighlightChanged

There is no guarantee that Editor OnChange event will always fire after the HL was updated.


The only issue with senrHighlightChanged is: If you use shared textbuffer between 2 edits, then you may need to register the event again, after setting up the share. This is because the event is on the textbuffer, and when start sharing, that changes the textbuffer.
« Last Edit: February 18, 2015, 09:34:14 pm by Martin_fr »

 

TinyPortal © 2005-2018