Recent

Author Topic: SynEdit Folding User's Selected Text in Code  (Read 3497 times)

PaulANormanNZ

  • Jr. Member
  • **
  • Posts: 93
SynEdit Folding User's Selected Text in Code
« on: May 04, 2014, 01:09:48 pm »
Hi,

I've had a look though the examples, other postings, and tried to get to grips with "La biblia del SynEdit" (Google translate help - best I can do is order a cup of coffee myself!), but I seem to have completely missed something, when the User has selected some text, or say placed their cursor to the left of an open bracket, I want to do something like this in a menu handler---

1.  editor.SelectToBrace; // selects text as expected
2.  editor.CopyToClipboard; // copies selected text as expected
3.  editor.FoldAll(1, false); // nothing happens
4.  // or
5.  editor.ExecuteCommand(EcFoldCurrent,'',nil); // nothing happens


 Steps 1 + 2 are all fine, neither 3 or 5 does anything, but form what I have seen in code in forum postings it looks like I need to do something with my selected text - mark it at each end BlockBegin BlockEnd(?) before I can fold, or is there a direct way of just folding selected text in code please?

I've also tried ---

procedure TprocessFiles.foldBraceClick(Sender: TObject);
 var selstart, selend : integer;
begin
  editor.SelectToBrace;
  editor.CopyToClipboard;
 //editor.SelStart
selend := editor.SelEnd;

  editor.BeginUpdate;
editor.BlockBegin := editor.LogicalCaretXY;
  editor.SelStart := selend;
editor.BlockEnd:=  editor.LogicalCaretXY;
editor.LogicalCaretXY := editor.BlockEnd;
editor.EndUpdate;

 //  editor.FoldAll(1, false); // doesn't work
   editor.ExecuteCommand(EcFoldCurrent,'',nil);  // doesn't work

end;
         

The caret ends up after the original selection as expected, but nothing gets folded (or is selected).

What should I be doing please?

Paul

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5576
    • wiki
Re: SynEdit Folding User's Selected Text in Code
« Reply #1 on: May 04, 2014, 03:57:17 pm »
Hi.

While the document you refer to, is probably the best document available in terms of current (Lazarus) SynEdit doc, it was written by observation. That is written by a user, not the maintainer of the code.

That still (or even more ) makes it a very good document. But it means the document may tend to describe the actual state (what currently is), rather than the intend (what should be).

What you describe is a bug, as in missing implementation.

The background is, that folding of selected text was written after all the other methods. And it turns out they do not work on it.

The difference is that the selection gets "hidden" rather than folded (Afaik, you can configure that, search FoldConfig, in the IDE folder).
Hiding means that all lines, including the very first, will be un-displayed.
Folding keeps the first line in view.

To fix this, you can edit SynEdit as follows (I will likely commit a similar fix sometime soon)

Find in SynEdit.pp line 3715 (SVN trunk / line may differ in 1.2) the function
   TCustomSynEdit.CodeFoldAction

The very last "IF" in this function is
Code: [Select]
  if FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)]
     * [cfFoldStart] <> []

Replace [cfFoldStart]
with [cfFoldStart, cfHideStart]

The entire procedure will then look like (you changed the 4th line from the bottom):
Code: [Select]
procedure TCustomSynEdit.CodeFoldAction(iLine: integer);
// iLine is 1 based as parameter
begin
  if (iLine<=0) or (iLine>FTheLinesView.Count) then exit;
  dec(iLine);
//DebugLn(['****** FoldAction at ',iLine,' scrline=',FFoldedLinesView.TextIndexToScreenLine(iLine), ' type ', SynEditCodeFoldTypeNames[FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)]],  '  view topline=',FFoldedLinesView.TopLine  ]);
  if FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)]
     * [cfCollapsedFold, cfCollapsedHide] <> []
  then
    FFoldedLinesView.UnFoldAtTextIndex(iLine)
  else
  if FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)]
     * [cfFoldStart, cfHideStart] <> []
  then
    FFoldedLinesView.FoldAtTextIndex(iLine);
end;

Then use
Code: [Select]
  Editor.CodeFoldAction(  Editor.BlockBegin.Y );

------------------
Editor.FoldAll
only works with primary folds form the code.
e.g If you use the Pascal Highlighter, it will fold Procedure, begin-end, class-end, ...

But it will not fold Ifdef, region, or selection. ifdef and region are secondary fold structures. (well there is no name for that, so I just call them secondary for now)

-------------------
EcFoldCurrent
will take some more time to fix.

In fact I am not sure if it is a good idea. It searches from the current line up (including on the current line) for the begin of a fold that include the current line.

That is, it searches the most inner fold, that includes the current line.

So if there was a selection, but a begin-end was closer to the caret, then it would still be begin end.

Maybe it can be made a configurable option.

And there should probably be
EcFoldSelection

You may want to report this on mantis, for I am not going to work on the EcFoldCurrent part right now, and it will get forgotten if there is no report,

PaulANormanNZ

  • Jr. Member
  • **
  • Posts: 93
Re: SynEdit Folding User's Selected Text in Code
« Reply #2 on: May 07, 2014, 08:06:24 am »
Dear Martin,

Thanks for that full answer, I'll implement that.

Meanwhile have written it up on Mantis http://bugs.freepascal.org/view.php?id=26119

Thanks again,
paul