Difference between revisions of "SynEdit"

From Lazarus wiki
Jump to navigationJump to search
Line 140: Line 140:
 
== Fold/Unfold from code ==
 
== Fold/Unfold from code ==
  
* This is still under construction
+
* This is still under construction.
 +
* This only works if current highlighter supports folding (details at [[SynEdit_Highlighter]]).
 +
* Also note that some highlighters support several independent fold-trees. E.g. in Pascal you have folding on keywords (begin, end, class, procedure, etc) which is the primary fold, and folding on $ifdef or $region which is secondary.
 +
* Folding of current selection is also different from folding on keywords.
  
This only works if the Highlighter in use supports folding [[SynEdit_Highlighter]].
+
Methods for folding:
  
Also node that some Highlighter support several independent fold-trees. E.g. In Pascal you have folding on keywords (begin,end,class,procedure,...) which is the primary fold, and folding on $Ifdef or $region which are secondary.
+
1) TSynEdit.CodeFoldAction
  
Folding current selection is also different from folding on keywords.
+
Folds at the given Line. If there are more than one, folds the inner most (right most). 
 +
Note: This does not work with selection, nor with Folds that hide entirely / Need testing for 2ndary folds.
  
=== SynEdit.CodeFoldAction ===
+
2) TSynEdit.FindNextUnfoldedLine
  
SynEdit.CodeFoldAction(Line)
+
3) TSynEdit.FoldAll / TSynEdit.UnfoldAll
Folds at the given Line. If there are more than one, folds the inner most (right most)  
 
 
 
;Note: This does not work with selection, nor with Folds that hide entirely / Need testing for 2ndary folds. May be extended
 
 
 
=== TSynEdit.FindNextUnfoldedLine ===
 
 
 
=== TSynEdit.FoldAll / TSynEdit.UnfoldAll ===
 
 
 
Works on primary folds
 
  
 
== Bookmarks ==
 
== Bookmarks ==

Revision as of 00:58, 12 June 2014

Deutsch (de) English (en) español (es) français (fr) 日本語 (ja) polski (pl) русский (ru) 中文(中国大陆)‎ (zh_CN)

General

SynEdit is a syntax highlighting edit control with support for many languages/syntaxes.

The SynEdit contained in Lazarus is based on on SynEdit 1.0.3 [[1]], and was adapted and extended quite a lot. For example UTF-8 support and code folding were added.

The package contains a source editor component named TSynEdit, several syntax highlighters and other components used for source editing.

It is licensed under the same terms as the original SynEdit (MPL or GPL)

Diffs between original and Lazarus versions

Lazarus version is maintained mostly by Martin Friebe. Martin wrote at forum, what has been added to Lazarus version since fork appeared:

Big things added to the Lazarus version:

  • folding
  • configurable gutter / gutter-parts
  • shared text between several editors
  • utf-8 support
  • sync-editing plugin
  • basic RTL/LTR support
  • mouse config via MouseActions
  • rewrite of various highlight/markup modules

Codebases of Delphi/Lazarus versions were independently refactored. There is very few overlap left.

SynEdit 2.0 port

An alternative port of the 2.0.x version of the original SynEdit exists. It's not actively maintained, last commit (now is Jun 2014) was at 2011.

SynEdit in the IDE

The SynEdit in Lazarus is a built-in package, because the IDE uses it itself. Therefore the package can not be removed from the installation list. To remove the entries from the component palette, the SynEditDsgn package can be removed from installation.

Using SynEdit

Highlighting

(Auto-)Completion

There are 3 completion plug-ins for SynEdit:

  • TSynCompletion
    • Offers a list of words in a drop-down.
    • Used in the IDE for identifier completion.
    • Included in examples.
    • Only available in the component palette since 0.9.31
  • TSynAutoComplete
    • Replaces the current token (if known) with a piece of text. Not interactive. No drop-down
    • Included in examples.
    • Available in the component palette.
  • TSynEditAutoComplete
    • Basic template module. No drop-down.
    • Used by the IDE for code-templates. The IDE contains additional code extending the features. (drop-down and syncro macros are added by IDE only)
    • Not Included in examples.

See examples for more info.

Todo: The differences between 2nd and 3pd need to be documented. Maybe they can be merged

"CaretXY" Logical versus Physical Caret Pos

SynEdit offers the position of the Caret (Text-Cursor) in 2 different Forms.

  • Physical: Correspondents to the visual position
  • Logical: Correspondents to byte position in the text.

Both are 1 based. Currently the Y co-ordinate is always the same. This may change in future.

The Physical coordinate is the position in the display grid (ignoring any scrolling) That is:

the letter "a" and "â" take both ONE cell on the grid, increasing physical x by 1. Even though in utf8 encoding "a" takes one byte, and "â" takes several bytes.
however the tab char (#9), besides being just one byte and one char, can take several cells in the grid, increasing the physical x by more than one. There are also some chars in Chinese and eastern languages, that take 2 grid positions (google full-width vs half-width char)

The Logical coordinate is the byte position in the string holding the line.

the letter "a" has 1 byte and increases by 1
the letter "â" has 2 (or 3) bytes, and increases by that
tab has 1 byte and increases by that.

Neither of the 2 give the position in utf8 chars/code-points (eg. for Utf8Copy or Utf8Length).

The physical X is always counted from the left of the text, even if this is scrolled out. To get the grid-x of the currently scrolled SynEdit do:

grid-X-in-visible-part-of-synedit := PhysicalX - SynEdit.LeftChar + 1
grid-y-in-visible-part-of-synedit := SynEdit.RowToScreenRow(PhysicalY); // includes folding
// ScreenRowToRow for reverse

Change text from code

Warning-icon.png

Warning: Changing text via the SynEdit.Lines property does not work with undo/redo

Text can be accessed via SynEdit.Lines. This is a TStrings based property offering read write access to each line. It is 0 based.

  SynEdit.Lines[0] := 'a'; // first line

SynEdit.Lines can be used to set the initial version of the text (e.g. loaded from file). Note that Synedit.Lines.Add/Synedit.Lines.Append does not support line breaks inside the added strings. You could add the lines one by one.

To modify the content of a SynEdit, and allow the user to undo the action use the following methods:

    procedure InsertTextAtCaret(aText: String; aCaretMode : TSynCaretAdjustMode = scamEnd);
    property TextBetweenPoints[aStartPoint, aEndPoint: TPoint]: String              // Logical Points
      read GetTextBetweenPoints write SetTextBetweenPointsSimple;
    property TextBetweenPointsEx[aStartPoint, aEndPoint: TPoint; CaretMode: TSynCaretAdjustMode]: String
      write SetTextBetweenPointsEx;
    procedure SetTextBetweenPoints(aStartPoint, aEndPoint: TPoint;
                                   const AValue: String;
                                   aFlags: TSynEditTextFlags = [];
                                   aCaretMode: TSynCaretAdjustMode = scamIgnore;
                                   aMarksMode: TSynMarksAdjustMode = smaMoveUp;
                                   aSelectionMode: TSynSelectionMode = smNormal
                                  );

Examples:

  SynEdit.InsertTextAtCaret('A');

or to delete/replace text

  var p1,p2: TPoint;
  begin
    p1 := SynEdit.LogicalCaretXY;
    p2 := SynEdit.LogicalCaretXY;
    p2.x := p2.x + UTF8CharacterLength(@SynEdit.LineText[p2.x]); // byte len of char AFTER current caret
    SynEdit.TextBetweenPoints[p1,p2] := '';

Fold/Unfold from code

  • This is still under construction.
  • This only works if current highlighter supports folding (details at SynEdit_Highlighter).
  • Also note that some highlighters support several independent fold-trees. E.g. in Pascal you have folding on keywords (begin, end, class, procedure, etc) which is the primary fold, and folding on $ifdef or $region which is secondary.
  • Folding of current selection is also different from folding on keywords.

Methods for folding:

1) TSynEdit.CodeFoldAction

Folds at the given Line. If there are more than one, folds the inner most (right most). Note: This does not work with selection, nor with Folds that hide entirely / Need testing for 2ndary folds.

2) TSynEdit.FindNextUnfoldedLine

3) TSynEdit.FoldAll / TSynEdit.UnfoldAll

Bookmarks

More info

Discussions on the forum, which contain info about SynEdit:

Examples

Examples can be found in the folder lazarus/examples/synedit

How to add keys for Copy, Paste, Cut etc

Hotkeys can be implemented by using SynEdit commands.

uses
  SynEdit, SynEditKeyCmds;

procedure TForm1.SynEdit1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Shift = [ssCtrl]) then
  begin
    case Key of
    VK_C: SynEdit1.CommandProcessor(TSynEditorCommand(ecCopy), ' ', nil);
    VK_V: SynEdit1.CommandProcessor(TSynEditorCommand(ecPaste), ' ', nil);
    VK_X: SynEdit1.CommandProcessor(TSynEditorCommand(ecCut), ' ', nil);
    end;
  end;
end;

Further development, discussions

  • RTL (right-to-left): started by Mazen (partly implemented on Windows)
  • SynEdit only uses UTF8; an ASCII/ANSI version no longer exists. A font is pre-selected depending on the system. The user can choose another font, but must then take care to choose a monospaced ont.
    OLD:
    • automatic monospace font selection: At the moment SynEdit starts with a font 'courier'. December 2012/BigChimp: but Courier *is* monospace!!?!? But it would be better, if SynEdit would start with a monospace font (meaning: every character has the same width). At the moment the LCL TFont does not provide such a property. At the moment the user has to choose the right font.
    • automatic UTF-8 font selection: Same as above monospace, but also with an UTF-8 font, so that for example umlaute are shown correctly. At the moment the user has to choose the right font.
  • Dead keys. Most keyboards support typing two or more keys to create one special character (like accented or umlaut characters). (This is handled by LCL widgedset)
  • Redesign of the SynEdit component. The primary goal is more reliable display and navigation in the text. A more modular approach also allows for better integration of extensions, and for specialized controls, for use outside of Lazarus.

See also