Intellisense in SynEdit-Komponente

Rund um die LCL und andere Komponenten
Antworten
kirchfritz
Beiträge: 169
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Intellisense in SynEdit-Komponente

Beitrag von kirchfritz »

Hallo,

laut Wikipedia gilt:
"IntelliSense ist ein von Microsoft angebotenes Hilfsmittel zur automatischen Vervollständigung bei der Bearbeitung von Quellcode durch einen Programmierer."
Ich kenne dies vom Lazarus QuelltextEditor, wenn ich hinter dem Namen eines Objects einen Punkt "." eingebe, erscheint die Menge der möglichen Methoden oder Properties in einem Auswahlfenster.
Ich möchte so ein Verhalten jetzt in einer SynEditKomponente in meinem Programm verwenden.
Leider habe ich keine blasse Ahnung, wo man da ansetzen muss.
es gibt zwar ein Beispielprogramm zu SynEdit-AutoCompletion, aber daraus werde ich nicht schlau.
Kann mir mal jemand auf die Sprünge helfen?

Konkret sieht mein Problem so aus:
Ich habe in meinem SynEdit-Text verschiedenste Tags zum Beispiel
<NA>Mustermann<<VN>Max
<ST>Musterstrasse<HN>17
<PZ>12345<PO>Musterstadt

Dabei bedeutet <NA>=Name <VN>=Vorname <ST>=Strasse <HN>=Hausnummer <PZ>=Postleitzahl <PO>=Postort
Wenn man diesen Beispieltext mit dem SynXML-Highllighter im SynEdit-Kontroll darstellt, schaut er sogar super eingefärbt gut aus.

Nun soll der Texterfasser aber die einzelne Bestandteile dieses Adress-Satzes "verschönern"

<NA.s2.f17>Mustermann<VN.f35.s3>Max
<ST>Musterstrasse<HN>17
<PZ>12345<PO>Musterstadt

Die Bedeutung der ersten Zeile wäre dann etwa:
Der Name ist in der Schrift "s2" und in der farbe "f17" auszugeben, während der Vorname in der Schrift "s3" und der farbe "f35" auszugeben ist.
Wie dieser verschönerte Adress-Satz letzt endlich ausgegeben wird, spielt jetzt keine Rolle.

Konkret will ich eigentlich nur erreichen, dass der Erfasser <NA. tippt, und dann die Menge der gültigen Schriften und Farben zur Auswahl gestellt bekommt.

Wie geht das konkret? Jede Hilfe ist willkommen.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Intellisense in SynEdit-Komponente

Beitrag von Warf »

Erstmal, Intellisense ist einfach nur der Microsoft Name für Autovervollständigung. Aber die ist eigentlich ganz einfach.

Du benötigst eine Completion Komponente von der Syn Edit Seite. Die Completion hat zwei events, Execute und SearchPosition. Execute wird aufgerufen wenn die Completion liste gezeigt wird (z.B. Strg + Leer im editor drücken), SearchPosition sobland etwas verändert wird während der Dialog offen ist.

In diesen Events kannst du dann die ItemList der Completion bearbeiten. Den bereits getippten teil des Wortes kannst du mit CurrentString auslesen (um z.B. einen Filter zu machen).
Ein beispiel:

Code: Alles auswählen

 
Completion.ItemList.Clear;
for i := 0 to FCompletionList.Count - 1 do // FCompletionlist enthält alle möglichen vervollständigungen
  if Pos(LowerCase(Completion.CurrentString),
    LowerCase(FCompletionList[i])) >= 1 then // falls das aktuelle wort in dem eintrag vor kommt
      Completion.ItemList.Add(FCompletionList[i]); // Füge zur liste hinzu


Wenn du spaß dran hast kannst du auch im Paint Event syntax highlighting betreiben


Die Syntaxhighlight hingegen wird schon etwas schwieriger. Dafür musst eine neue Highlighter Klasse schreiben und das kann ich dir jetzt auf die schnelle nicht erklären. Dafür gibt es allerdings einen guten Wikieintrag: Link der mir damals sehr geholfen hat.

Ich habe mal eine kleine IDE geschrieben, die kannst du dir ansehen: Link ist allerdings wahrscheinlich schwer reinzukommen (Code schreiben ist immer einfacher als lesen). Aber für dich wären die Verzeichnisse Highlighter und Editor relevant

thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Re: Intellisense in SynEdit-Komponente

Beitrag von thosch »

Da wäre dann noch die Frage zu klären, wie die Completion List gefüllt wird?

kirchfritz
Beiträge: 169
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Intellisense in SynEdit-Komponente

Beitrag von kirchfritz »

Bitte der Reihe nach.

Ich habe jetzt mal ein kleines Demo-Programm erstellt und in der Execute-Methode einzig und allein mit

Code: Alles auswählen

ShowMessage(SynCompletion1.CurrentString);


den Currentstring ausgegeben.
Dabei habe ich festgestellt, dass in der Execute-Methode der CurrentString "<NA" lautet, wenn der Cursor hinter "<NA" steht und ich CTRL+Space drücke. Das ist soweit in Ordnung.

Stelle ich aber den Cursor hinter "<NA." , dann ist beim Aufruf der Execute-Methode der CurrentString leer. Das ist aus meiner Sicht nicht erwünscht.

Ich hätte schon gerne, dass man einen Punkt "." eintippt, und dann mit CTRL-Space die Vorschlagsliste zu sehen bekommt.
Weiß jemand, was da gerade schiefläuft, dass der Punkt den CurrentString leert ??

Wozu die SearchPosition Methode gut sein soll erschliesst sich mir nicht.

Das Befüllen der Completion.ItemList sehe ich weniger als Problem. Das ist vielmehr von mir zu erbringende Fleissarbeit.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Intellisense in SynEdit-Komponente

Beitrag von Warf »

kirchfritz hat geschrieben:Bitte der Reihe nach.

Ich habe jetzt mal ein kleines Demo-Programm erstellt und in der Execute-Methode einzig und allein mit

Code: Alles auswählen

ShowMessage(SynCompletion1.CurrentString);


den Currentstring ausgegeben.
Dabei habe ich festgestellt, dass in der Execute-Methode der CurrentString "<NA" lautet, wenn der Cursor hinter "<NA" steht und ich CTRL+Space drücke. Das ist soweit in Ordnung.

Stelle ich aber den Cursor hinter "<NA." , dann ist beim Aufruf der Execute-Methode der CurrentString leer. Das ist aus meiner Sicht nicht erwünscht.

Ich hätte schon gerne, dass man einen Punkt "." eintippt, und dann mit CTRL-Space die Vorschlagsliste zu sehen bekommt.
Weiß jemand, was da gerade schiefläuft, dass der Punkt den CurrentString leert ??

Wozu die SearchPosition Methode gut sein soll erschliesst sich mir nicht.

Das Befüllen der Completion.ItemList sehe ich weniger als Problem. Das ist vielmehr von mir zu erbringende Fleissarbeit.


1. Die SynCompletion hat eine Eigenschaft EndOfTokenChr. Diese enthält die Charaktere die Tokens abtrennen. Standardmäßig sind das (, ), {, }, . Um punkte zu erlaube also einfach nur den . löschen (und eventuell < und > hinzufügen, da die ja nicht direkt zum token gehören)
2. Die Searchposition selbst (also den paramter) verwende ich in meiner IDE selbst auch nicht (ich glaube das ist der aktuelle ItemIndex, kann mich aber auch irren), das Event ist allerdings wichtig, da das immer gefeurt wird sobald sich irgendwas am currentString ändert, du also die Liste anpassen musst (z.B. du hast als vorschäge ABA und AAB. Wenn jemand jetzt A eintippt sollen beide gezeigt werden, wenn man als zweiten Buchstaben B oder A eintippt sollte die liste entsprechend angepasst werden, sodass das andere nicht mehr angezeigt wird)

kirchfritz
Beiträge: 169
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Intellisense in SynEdit-Komponente

Beitrag von kirchfritz »

Gut, das mit dem Punkt habe ich hinbekommen.
Der nächste Schritt wäre jetzt, das die ausgewählte Zeichenkette an den currentstring drangehängt wird und nicht bei Auswahl den currentstring ersetzt.
Wie geht das denn?

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Intellisense in SynEdit-Komponente

Beitrag von Warf »

Das ist auch ganz einfach, dafür gibt es das Event CodeCompletion mit der methodensignatur:

Code: Alles auswählen

CodeCompletion(var Value: string;
  SourceValue: string; var SourceStart, SourceEnd: TPoint; KeyChar: TUTF8Char;
  Shift: TShiftState);

Value ist dabei eine variable, und was du da reinschreibst wird dann ersetzt. SourceValue ist die original Value also der CurrentString (kann mich aber auch irren). SourceStart und SourceEnd geben dir die Position im SynEdit an (z.B. accessbar via TextBetweenPoints), Keyhar der Key mit dem Bestätigt wurde, shif enthält die modifikatoren (z.B. wenn strg beim bestätigen gedrückt wurde).

Einfaches Beispiel, hier wird der ausgewählte wert mit einem X vorne dran hingeschrieben statt der normal:

Code: Alles auswählen

CodeCompletion(var Value: string;
  SourceValue: string; var SourceStart, SourceEnd: TPoint; KeyChar: TUTF8Char;
  Shift: TShiftState);
begin
  Value := 'X' + Value;
end;

Antworten