Sign in Join
Wiki copytemporary

SynEdit/pl

Deutsch · English · Español · Français · Polski · Русский · 中文(中国) · 日本語

SynEdit to pakiet edycji/notatek z podświetlaniem składni dostępny na karcie SynEdit obsługujący wiele języków/składni.

SynEdit zawarty w Lazarusie został utworzony na bazie SynEdit 1.0.3, i został w dużym stopniu zaadaptowany i rozszerzony. Zmiany są wymienione poniżej.

Pakiet Lazarus zawiera komponent edytora źródeł o nazwie TSynEdit, kilka podświetlaczy składni i inne komponenty używane do edycji źródeł.

Licencjonowany na tych samych warunkach, co oryginalny SynEdit (MPL lub GPL).

Wersja oryginalna a Lazarus

Wersją dla Lazarus opiekuje się głównie Martin Friebe. Martin napisał na forum, co zostało dodane do wersji Lazarusa od czasu pojawienia się tego forka:

Duże rzeczy dodane do wersji Lazarus:

Bazy kodu wersji Delphi/Lazarus zostały niezależnie przeprojektowane. Pozostało bardzo niewiele do zrobienia.

Port SynEdit 2.0

Istnieje alternatywny port wersji 2.0.x oryginalnego SynEdit. Nie jest aktywnie utrzymywany, ostatnie zatwierdzenie (obecnie jest marzec 2024) miało miejsce w 2023 roku, ale od 2011 roku ma on wersję 2.0.5.

SynEdit w IDE

SynEdit w Lazarusie jest pakietem wbudowanym, ponieważ samo IDE używa go do edycji kodów źródłowych. Z tego powodu nie można usunąć tego pakietu z listy instalacyjnej. Natomiast aby usunąć SynEdit z palety komponentów, można usunąć pakiet SynEditDsgn z instalacji.

Używanie SynEdit

Podświetlacze składni

Znaczniki

Znaczniki umożliwiają dodatkowe kolorowanie SynEdit Markup

Oznaczenia

Znaczniki zapewniają dodatkowe kolorowanie

Edycja istniejącego podświetlacza

Czasami możesz chcieć edytować istniejące podświetlacze składni (tak jak chciałem to zrobić kilka dni temu), które już istnieją. W tym przykładzie będziemy edytować podświetlacz dla kodu pascala (nazwa klasy: TSynPasSyn; pakiet: SynEdit V1.0; moduł: SynHighlighterPas.pas).

Powiedzmy, że chcemy osiągnąć to, aby nasza aplikacja (w tym przypadku Lazarus) rozróżniał trzy typy komentarzy, które istnieją w Pascalu:

pascal
  (* standardowe *)
  { klamry }
  // ukośniki

Może to być pomocne, jeśli chcesz rozróżnić różne typy swoich komentarzy (np. „Opis”, „Notatka”, „Referencja” itp.) i chcesz, aby każdy wyróżniony był innym kolorem.

Note: Na wypadek, gdybyś coś zepsuł, sugeruję dodanie kilku komentarzy „NEW” i „/NEW”, ale nie jest to konieczne

Np. pod deklaracją „tkTokenKind” napisz:

pascal
  {NEW}
  TtckCommentKind = (tckAnsi, tckBor, tckSlash);
  {/NEW}
pascal
  {NEW}
  FCommentID: TtckCommentKind;
  {/NEW}
  //Tworzy to nowe pole, w którym możemy zapisać informację, jakiego rodzaju mamy komentarz
pascal
  {NEW}
  fCommentAttri_Ansi: TSynHighlighterAttributes;
  fCommentAttri_Bor: TSynHighlighterAttributes;
  fCommentAttri_Slash: TSynHighlighterAttributes;
  {/NEW}
  //Dzięki temu możemy zwrócić różne atrybuty dla każdego typu komentarza
pascal
  (...)
  AddAttribute(fCommentAttri);
  {NEW}
  fCommentAttri_Ansi := TSynHighlighterAttributes.Create(SYNS_AttrComment+'_Ansi', SYNS_XML_AttrComment+'_Ansi'); //Ostatnie dwa ciągi to podpis i przechowywana nazwa
  //Jeśli chcesz mieć domyślne ustawienia swojego atrybutu, możesz np. dodać to:
  //fCommentAttri_Ansi.Background := clBlack; //Ustawiłoby to „Tło” na „clBlack” jako domyślne
  AddAttribute(fCommentAttri_Ansi);
  fCommentAttri_Bor := TSynHighlighterAttributes.Create(SYNS_AttrComment+'_Bor', SYNS_XML_AttrComment+'_Bor');
  AddAttribute(fCommentAttri_Bor);
  fCommentAttri_Slash := TSynHighlighterAttributes.Create(SYNS_AttrComment+'_Slash', SYNS_XML_AttrComment+'_Slash');
  AddAttribute(fCommentAttri_Slash);
  {/NEW}
  (...)
pascal
procedure TSynPasSyn.BorProc;
(...)
  fTokenID := tkComment;
  {NEW}
  FCommentID:=tckBor;
  {/NEW}
  if rsIDEDirective in fRange then
(...)
pascal
procedure TSynPasSyn.AnsiProc;
begin
  fTokenID := tkComment;
  {NEW}
  FCommentID:=tckAnsi;
  {/NEW}
(...)
pascal
procedure TSynPasSyn.RoundOpenProc;
(...)
        fTokenID := tkComment;
        {NEW}
        FCommentID:=tckAnsi;
        {/NEW}
        fStringLen := 2; // długość "(*"
(...)
pascal
procedure TSynPasSyn.SlashProc;
begin
  if fLine[Run+1] = '/' then begin
    fTokenID := tkComment;
    {NEW}
    FCommentID:=tckSlash;
    {/NEW}
    if FAtLineStart then begin
(...)
pascal
procedure TSynPasSyn.SlashContinueProc;
(...)
    fTokenID := tkComment;
    {NEW}
    FCommentID:=tckSlash;
    {/NEW}
    while not(fLine[Run] in [#0, #10, #13]) do
(...)
pascal
function TSynPasSyn.GetTokenAttribute: TSynHighlighterAttributes;
begin
  case GetTokenID of
    tkAsm: Result := fAsmAttri;
    {OLD
    tkComment: Result := fCommentAttri; //To jest komentarz i stanowi kopię zapasową, więc zostanie zignorowany
    /OLD}
    {NEW}
    tkComment: begin
      if (FCommentID = tckAnsi) then
        Result := fCommentAttri_Ansi //To jest typ standardowy AnsiComment
      else
        if (FCommentID = tckBor) then
          Result := fCommentAttri_Bor //To jest typ klamrowy BorComment
        else
          if (FCommentID = tckSlash) then 
            Result := fCommentAttri_Slash //To jest typ ukośnikowy SlashComment
          else
            Result := fCommentAttri //Jeśli nasz kod w jakiś sposób zawiódł, przywróć ustawienia domyślne
    end;
    {/NEW}
    tkIDEDirective: begin
(...)

Jeśli używasz lazarusa, po prostu zainstaluj ponownie pakiet SynEdit, jeśli nie, przekompiluj swój projekt/pakiet.

GOTOWE ! Mówię poważnie! Twój kod jest teraz gotowy na rozróżnianie różnych typów komentarzy.

Lazarus-IDE automatycznie wykrywa, jakie atrybuty istnieją i pokazuje je w opcjach, na przykład zapisuje je, jeśli je zmienisz. Jeśli Twoja aplikacja/IDE tego nie robi, będziesz musiał ustawić Kolor/Czcionkę/itp. nowych atrybutów gdzieś ręcznie (np. w konstruktorze TSynPasSyn)

Realizacja wtyczek

Istnieją 3 wtyczki uzupełniające dla SynEdit:

TSynCompletion

Przykładowy kod wywołujący programowo wyskakujące okienko uzupełniania (tj. bez naciskania skrótu klawiaturowego):

pascal
YourSynEdit.CommandProcessor(YourSynCompletion.ExecCommandID, '', nil)

TSynAutoComplete

TSynEditAutoComplete

Todo: Należy udokumentować różnice pomiędzy 2. i 3. poziomem. Może uda się je połączyć.

Logiczna/fizyczna pozycja karetki

SynEdit oferuje położenie karetki (migającego kursora tekstowego) w 2 różnych formach:

Obydwa są oparte na 1. Obecnie współrzędne Y są zawsze takie same. To może się zmienić w przyszłości.

Współrzędna fizyczna
To pozycja w siatce wyświetlania (pomijająca przewijanie). Przy czym:

litera „a” i „â” zajmują JEDNĄ komórkę w siatce, zwiększając fizyczne x o 1. Mimo że w utf8 kodowanie „a” zajmuje jeden bajt, a „â” zajmuje kilka bajtów.

jednakże znak tabulacji (#9), poza tym, że jest tylko jednym bajtem i jednym znakiem, może zająć kilka komórek w siatce, zwiększając fizyczne x o więcej niż jeden. Istnieją również znaki w językach chińskim i wschodnim, które zajmują 2 pozycje siatki (znak Google o pełnej szerokości i o połowie szerokości)

Współrzędna logiczna
To przesunięcie bajtu w ciągu znaków przechowującym linię.

litera „a” ma 1 bajt i zwiększa się o 1

litera „â” ma 2 (lub 3) bajty i zwiększa się o tą wartość

tab ma 1 bajt i zwiększa się o 1.

Żaden z tych współrzędnych nie podaje pozycji w znakach/punktach kodowych UTF8 (tak jak np. Utf8Copy czy Utf8Length).

Fizyczna współrzędna X jest zawsze liczona od lewej strony tekstu, nawet jeśli jest on przewijany. Aby uzyskać grid-x aktualnie przewijanej kontrolki, wykonaj:

grid-X-in-visible-part-of-synedit := PhysicalX - SynEdit.LeftChar + 1

grid-y-in-visible-part-of-synedit := SynEdit.RowToScreenRow(PhysicalY); // obejmuje zwijanie bloków

użyj ScreenRowToRow do odwrotnych wyliczeń

Zmiana tekstu za pomocą kodu

Warning: Zmiana tekstu za pomocą właściwości SynEdit.Lines nie działa w przypadku funkcji cofnij/ponów.

Dostęp do tekstu można uzyskać za pośrednictwem SynEdit.Lines. Jest to właściwość oparta na TStrings oferująca dostęp do odczytu/zapisu dla każdej linii. Pierwszy wiersz ma index 0.

pascal
  SynEdit.Lines[0] := 'Text'; // pierwsza line

Za pomocą SynEdit.Lines można ustawić początkową wersję tekstu (np. wczytaną z pliku). Należy pamiętać, że SynEdit.Lines.Add/SynEdit.Lines.Append nie obsługuje podziału wierszy wewnątrz dodanych ciągów. Należy dodawać linie jedna po drugiej.

Aby zmodyfikować zawartość SynEdit i pozwolić użytkownikowi na cofnięcie akcji, użyj następujących metod:

pascal
    procedure InsertTextAtCaret(aText: String; aCaretMode: TSynCaretAdjustMode = scamEnd);
    property TextBetweenPoints[aStartPoint, aEndPoint: TPoint]: String // Logiczna pozycja
      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:

pascal
  // Wstaw tekst w miejscu karetki
  SynEdit.InsertTextAtCaret('Tekst');
  // Zamień tekst od punktu (x=2,y=10) do punktu (x=4,y=20) na Str
  SynEdit.TextBetweenPoints[Point(2,10), Point(4,20)] := Str;
pascal
  // Usuń/zamień pojedynczy znak w pozycji karetki
  var
    p1, p2: TPoint;
  begin
    p1 := SynEdit.LogicalCaretXY;
    p2 := p1;
    // Oblicz pozycję bajtu następnego znaku
    p2.x := p2.x + UTF8CharacterLength(@SynEdit.LineText[p2.x]);
    // p1 wskazuje pierwszy bajt znaku, który ma zostać zastąpiony
    // p2 wskazuje pierwszy bajt znaku po ostatnim znaku, który można zastąpić
    // Zamień na „Tekst” (lub użyj pustego ciągu, aby usunąć)
    SynEdit.TextBetweenPoints[p1, p2] := 'Tekst';

Zwiń/rozwiń za pomocą kodu

Metody zwijania kodu:

1) TSynEdit.CodeFoldAction

Pasuje na podanej linii. Jeśli jest więcej niż jeden, zwija najbardziej do środka (najbardziej po prawej). Uwaga: to nie działa w przypadku zaznaczania ani w przypadku zakładek, które całkowicie się ukrywają / Wymagają przetestowania dla innych operacji zwijania.

2) TSynEdit.FindNextUnfoldedLine

3) TSynEdit.FoldAll / TSynEdit.UnfoldAll

Zakładki

Więcej informacji

Dyskusje na forum, które zawierają informacje o SynEdit:

Przykładowe aplikacje

Przykładowe zastosowania znajdziesz w folderze "lazarus/examples/synedit".

Dodawanie skrótów klawiszowych do wycinania/kopiowania/wklejania/itp

Skróty klawiszowe można wdrożyć za pomocą poleceń SynEdit.

pascal
uses
  SynEdit, SynEditKeyCmds;

procedure TForm1.SynEdit1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Shift = [ssCtrl]) then
    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;

Dalszy rozwój, dyskusje

Zobacz także


From the Free Pascal wiki, page "SynEdit/pl", as it stood on 2024-03-12 after a change by Slawek, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 2, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.