But...
the MarkupWordGroup seem as wrong on Node.LogXEnd, mean conflict with my idea.
See the "food"~"/food" vs "repeat"~"until" screengrab.
IIRC (need to check) end is the begin of next token.
Think of the pos as pointing between two chars, not the start of a char.
foo starts at 1
last char of foo is (starts at) 3
foo ends at 4
space starts at 4
IIRC that is common on many parts of SynEdit.
Keep MWG, by above logic.
Btw, this is also where the caret would be, if it was at the end of foo.
please ignore my previous question
too late
Now, the problem is when text/line trailing with tab. The vertical lines drawn improperly.
Either:
1) they are past end of line. But selection (in column mode) can do it, so there must be a way.
2) logical vs physical
http://wiki.lazarus.freepascal.org/SynEdit#Logical.2FPhysical_caret_positionif there are #9, or multybyte utf8 (umlauts äüö, accents, Chinese, ....)
You need to store the phys pos, as that is the same in all lines. logical changes.
Need to check later
Hey, I currently face a real problem ... !
This messy visual effect, can be solved by drawing all vertical lines, straight to "end;" keyword vertically.
We can see how CnPack solves the same problem. (see attachment II )
relates how to the quote of mine that you posted before?
see my comment above.
It should work with the frame for now. There may be shlight changes, but they would still need to go line by line
cnpack probably paints on top of all (and I have seen pictures where the yellow "begin" was painted with an offset to the original....)
But in Lazarus SynEdit composes colors by priority. A user can define another markup (eg selection) to have higher priority. All other markups are evaluated per line, so yours must be too.
... plus : if it still in 3th depth of folds, comparison will be repeated 3 times again.
That is why this code (searching end line) should be added to nested fold list. there known info can be cached and reused.
For honest, the longest procedure AFAIK would be only 200 lines including off-of-screen lines. (sorry for 10K abuse).
But, couldn't we make this real solution more efficient?
Yes, but not by storing on the range.
see above: cache in the list.
I have some ideas there, but I need more time to evaluate and explain.
In the nested list, if you change the line, it can still keep the previous data as cache, and only calculate until it can use the cache.
This cache would be per module, It will work well just for your markup, and it will work well for other markup, but it will not add synergy between markups. For that another cache may be needed, but that can be done later.
But, because MarkupColorFold will operate per sourcecode's line basis,
the next sourcecode-line will repeat comparing the left most pair of that begin~end (that have already proir calculated)
... plus : if it still in 3th depth of folds, comparison will be repeated 3 times again.
Not if cached in the nested list. Also I have to look at your code again. I need to see if the invalidate issue was truly fixed.
And depending on this other changes may make this partly obsolete.
Assumed that System.pas has 10K lines, it should have 10K states stored, right? because 1line = 1 states.
As I wrote a few posts back: No.
Example pas HL, it will probably have 1500 range objects for the 10k lines. (and the ratio gets better, if you have 100k lines).
For each line it has a pointer entry, that points to one of those objects.
And that is the reason they must be immutable, because several lines use them, if you changed it, that has side effects on other lines.
Hence, on file loading, when a 'begin' of procedure block founded, I can store that begin postion.
when 'end' of that procedure founded, I stored that in the shared-folding-block (whatever Range / CodeFoldBLock?).
See above, you need a lot more range objects (and folding blocks, the 2 go together)
You would also need to fix, that very long ago (maybe even before synedit was added to Lazarus) someone decided that range objects are only freed when the HL is freed. They are kept, even if they no longer apply to any line.
Currently this is at best a very minor issue, but the more of them are created, the bigger it gets.
You still may need to find the end line. it could contain an "invalid flag" or other info. Unless you store a copy of the entire node info record on the fold block. But that would be a lot of data, AND also mean you have to calculate all this data during every scan, even for lines that are currently not visible.
Not tested, but try (forward declaration):
type TFoo = class
// 10 lines
;
An maybe also "class of".
If the search is improved correctly, then you do only one scan independent on nesting depth, and the data is re-used for the next (and further) line(s).
And all the search will be abstracted in the nested list. So any optimization can be done now or later, it does no longer affect your code. Your code asks the list. the list can get it whatever way, and the way can even be changed.
If this concept is negative, how can an HL rescan (reparsing) a line randomly?
For rescanning the x pos is not needed. The xpos is only needed outside the HL.
But it most probably impossible, when range (or foldblock?) is reused rewriten unpredicably.
it is re-used (not unpredictable though).
Overall, I do see what you mean. I don't currently think it is the way to go.
In any case if the problem can be abstracted into a few re-usable helper functions, then it can be changed later if indeed needed.
--------
EDIT
Also adding more data to the HL, one needs to look at who/what benefits.
Some users use the HL only for highlight, no fold, no markup. Then the data is wasted.
Of course then for some HL the fold level is wasted too. But that would be all the more reason not to add to it (pascal needs parts of the fold info, because some symbols change. For examle "of" looks at the foldtype, "case of" means a label is next, but only in a case block. Also "Cdecl", "final" and others need them.
-----
EDIT2:
I am NOT asking you to write the cache code etc. (you are welcome, but it would be a separate project)
Just add to the TLazSynEditNestedFoldsList:
property EndNodeLine[Index: Integer]: Integer read GetEndNodeLine;
that does the loop on the foldlevel.
So that EndNodeLine[n] returns the line that matches the open-node in NodeLine[n]
Ideally, if EndNodeLine[n-x] is known, continue from there.
then maybe also add
same as HLNode just the closing.