AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

AutoComplete mit SynEdit

Ein Thema von RWarnecke · begonnen am 26. Mai 2006 · letzter Beitrag vom 26. Jan 2010
Antwort Antwort
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#1

AutoComplete mit SynEdit

  Alt 26. Mai 2006, 13:03
Ich möchte gerne einen AutoComplete ala Delphi realisieren, wie kann ich das machen ? Wenn ich das richtige Kürzel eintrage und mein AutoComplete per Tastenkombination aufrufe, vervollständigt er meinen Code. Nur wenn ich jetzt einen Bruchteil davon eingebe und die Tastenkombination drücke kommt keine Auswahl, so wie in Delphi (s. Bild im Anhang).

Ich nehme als Ausgang die Demo AutoCompleteDemo von SynEdit.
Miniaturansicht angehängter Grafiken
autocomplete_161.jpg  
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.929 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: AutoComplete mit SynEdit

  Alt 26. Mai 2006, 13:09
Hi,

bei mir geht das ohne Probleme. Ich habe es nur schnell so gemacht:
SynEdit auf's Formular, TSynAutoComplete ebenfalls und mit dem SynEdit verknüpfen und habe bei TSynAutoComplete das eingegeben:

Zitat:
procedure
=procedure blabla
profi
=blubb
Tippe ich nun "pro" ins SynEdit und drücke Strg + Leertaste, kommt dieses Popupfenster.

Edit: Oder meinst du bei doppelten Einträgen? Da geht es bei mir auch nicht, sehe ich gerade.
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#3

Re: AutoComplete mit SynEdit

  Alt 26. Mai 2006, 13:27
Wenn ich es genau so mache wie Du, bekomme ich die folgene Zeile im SynEdit :

Zitat:
\style{+B}profi\style{-B}\column{}profi
Das will ich aber nicht. Wenn ich jetzt pro eingebe und dann aus dem Popup, den Wert profi auswähle, dann soll blubb erscheinen und nicht die Zeile aus dem Zitat.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.929 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: AutoComplete mit SynEdit

  Alt 26. Mai 2006, 13:41
Hi,

da musst du einfach unter "options" von TSynAutoComplete scoUseInsertList auf true stellen.
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#5

Re: AutoComplete mit SynEdit

  Alt 26. Mai 2006, 13:53
Danke Matthias. Das funktioniert schonmal soweit. Auch das mit den mehreren Zeilen habe ich jetzt hinbekommen. Dazu muss folgendes in die AutoCompleteList eingetragen werden :

Code:
arrayd
=array[0..|] of ;
arrayc
=array[0..|] of = ();
cases
=case | of
= : ;
= : ;
=end;
Damit wird der mehrzeilge Case-Befehl ins SynEdit eingetragen. Trotzdem bleibt es mit immer noch ein Rätsel, wie ich das Popup suaber hinbekomme, so wie es im ersten Beitrag im Bild zu sehen ist.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#6

Re: AutoComplete mit SynEdit

  Alt 26. Mai 2006, 21:23
So, habe es jetzt erstmal gelöst. Vielleicht nicht ganz elegant, aber es funktioniert.

Man füllt eine Datei mit folgenden Inhalt :
Code:
[select | Einfache Select-Anweisung]
select | from ;

[selectw | Select-Anweisung mit Where]
select | 
from | 
where |;

[created | Erstellen einer Datenbank]
create database |;

[createt | Erstellen einer Tabelle]
CREATE TABLE | (

);
Diese Datei speichert man als einfach Textfile ab. Dann lädt man dieses Textfile in die Komponente TSynAutoComplete. Danach wendet man noch den folgenden Code an :

Delphi-Quellcode:
  CompletionCmd.InsertList := fAutoComplete.Completions;
  for counter := 0 to fAutoComplete.CompletionComments.Count - 1 do
  begin
    CompletionCmd.ItemList.Add(fAutoComplete.Completions.Strings[counter] + ' | '
      + fAutoComplete.CompletionComments.Strings[counter]);
  end;
Und dann erzeugt man noch die folgende Procedure :
Delphi-Quellcode:
procedure TMainEditForm.CompletionCmdAfterCodeCompletion(Sender: TObject;
  const Value: String; Shift: TShiftState; Index: Integer; EndToken: Char);
begin
  fAutoComplete.ExecuteCompletion(CompletionCmd.InsertItem(Index),SynEditMemo);
end;
Nun wird der Insert-Wert aus der Komponente TSynCompletionProposol (hier mit CompletionCmd bezeichnet) an die Komponete TSynAutoComplete übergeben und der dazugehörige Code im SynEditMemo eingefügt.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
schöni

Registriert seit: 23. Jan 2005
Ort: Dresden
445 Beiträge
 
Delphi 7 Personal
 
#7

Re: AutoComplete mit SynEdit

  Alt 26. Jan 2010, 13:48
Hallo!

Kann mir wirklich niemend helfen bei der Codevervollständigung des SynEdit Projektes?

Hier ist das Demo Beispiel. Das funktioniert.

Warum aber funktioniert dann mein Lösung nicht? Die ist im Quellcode mit der Methode
Assign

Delphi-Quellcode:
unit frmMain1;

{$I SynEdit.inc}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  SynEditHighlighter, SynHighlighterPas, SynEdit, SynEditKeyCmds,
  SynEditAutoComplete, Menus;

type
  TForm1 = class(TForm)
    SynEdit1: TSynEdit;
    SynPasSyn1: TSynPasSyn;
    MainMenu1: TMainMenu;
    miNewForm: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure miNewFormClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    fAutoComplete: TSynAutoComplete;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  if Application.MainForm = nil then begin
    fAutoComplete := TSynAutoComplete.Create(Self);
    fAutoComplete.Editor := SynEdit1;
    fAutoComplete.AutoCompleteList.LoadFromFile('Delphi32.dci');
  end else
    Form1.fAutoComplete.AddEditor(SynEdit1);
  SynEdit1.AddKey(ecAutoCompletion, word('J'), [ssCtrl], 0, []);
end;

procedure TForm1.miNewFormClick(Sender: TObject);
begin
  with TForm1.Create(Application) do
    Show;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

end.

//Schöni-Lösung:
//Diese wird bei jedem Öffnen eines neuen Editors aufgerufen
procedure TfpasIDE.AssignCodeCompletion(AEditor: TSynEdit);
begin
  if Assigned(AutoCompleter) then
  begin
    if AutoCompleter.AutoCompleteList.Count = 0 then AutoCompleter.LoadFromFile('fp.dci');
    //Damit die Datei mit den Codevervollständigungen nur einmal beim ersten Aufruf der
   //Methode gelesen und später nur noch verwendet wird.
    AutoCompleter.Editor := AEditor;
    //AddEditor wird intern aufgerufen und Editor ist der aktuelle Editor
    if Assigned(AutoCompleter.Editor) then
    AutoCompleter.Editor.AddKey(ecAutoCompletion, word('J'), [ssCtrl], 0, []);
    //Der Editor wird nicht zugewiesen, was ich daran sehe, das ich ohne die "If Assigned() Abfrage
    //eine Exception erhalte und zwar eine EAccessViolation. Der Debugger springt dann in AddKey von
    //TCustomSynEdit.
    //Warum aber wird der Editor nicht zugewiesen?
  end;
end;

//Mein AutoCompleter sieht so aus:
unit CompleteManager;

interface

uses
  Sysutils, Classes, SynEditAutoComplete, SynCompletionProposal, SynEdit;

type
//Der TAutoCompleteManager ist entstanden, weil ich mir auch die Demos von
//TSynCompletionProposal angeguckt habe und dort die Codes und die Vervollständigungen
//in 2 verschidenen Listen verwaltet werden und ich eine Vereinfachung des resultierenden
//Codes haben will.

  TAutoCompleteManager = class(SynCompletionProposal.TSynCompletionProposal)
  private
  public
   //Hier kann ich die AutoCompleteList aus dem AutoCompleter zuweisen
    procedure Assign(AList: TStrings);
    //Hier weise ich die beiden gtrennten Listen zu, wie das im Demobeispiel
    //vorgeführt wird, allerdings ohne diese Klasse. Dort passiert das einfach
    //im Quellcode unter Nutzung der Originalklasse TSynCompletionProposal
    procedure AssignList(AList: TStrings; Separator: String; AComments: TStrings);
  end;

//Hier ist nun eine verbesserte AutoComplete Klasse
  TAutoCompleter = class(SynEditAutoComplete.TSynAutoComplete)
  private
    FCompleteManager: TAutoCompleteManager;
  public
    procedure Assign(AList: TStrings);
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
   procedure LoadFromFile(Filename: String);
   
   //Falls ich in der Finalversion die Funktionalitäten beider Kompnenten
   //zusammenfassen muss, um ein optimales Ergebnis zu erhalten.
    property CompleteManager: TAutoCompleteManager read FCompleteManager;
  end;

var
  AutoCompleter: TAutoCompleter;
  AutoCompleteManager: TAutoCompleteManager;

implementation

type
  TManagerContainer = class(SynCompletionProposal.TSynAutoComplete)
  private
  public
  end;
//Diese Klasse TSynAutoComplete ist namensgleich mit TSynAutoComplete in
//TSynEditAutoComplete. Deshalb habe ich auch die Unitnamen vor den Namen
//der Vorfahrklasse gesetzt. Die namensgleiche Klasse in der Unit mit dem
//Namen TSynCompletionProposal ist jedoch anders inmlementiert, als die
//gleichnamige Klasse in der Unit SynEditAutoComplete, die ich für die
//Codevervollständigung verwende. Falls die TSynAutoComplete-Klasse des
//hiesigen Imlementationsteils zur Unterstützung des AutoComplete-Managers,
//abgeleitet von TSynCompltionProposal, benötigt wird, ist sie hier als
//Typdefinition vorhanden. Sollte sie hier nicht gebraucht werden in der
//Finalversion dieser Unit, werde ich sie später entfernen.



{ TAutoCompleteManager }

procedure TAutoCompleteManager.Assign(AList: TStrings);
begin
  ItemList.Assign(AList);
end;

procedure TAutoCompleteManager.AssignList(AList: TStrings; Separator: String; AComments: TStrings);
var Counter: Integer;
begin
  InsertList.Assign(AList);
  for Counter := 0 to AComments.Count - 1 do
       ItemList.Add(AList[Counter]+Separator+AComments[Counter]);
end;


{ TAutoComplete }

procedure TAutoCompleter.Assign(AList: TStrings);
begin
  AutoCompleteList.Assign(AList);
end;

constructor TAutoCompleter.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCompleteManager := TAutoCompleteManager.Create(AOwner);
  AutoCompleteManager := FCompleteManager;
  AutoCompleter := self;
end;

destructor TAutoCompleter.Destroy;
begin
  FCompleteManager.Free;
  inherited Destroy;
end;

procedure TAutoCompleter.LoadFromFile(FileName: String);
begin
  AutoCompleteList.LoadFromFile(FileName);
end;

end.
Warum wird mein Editor nicht korrekt zugewiesen. Im übergeordneten Programm habe ich bereits meinen zuzuweisenden Editor auf NIL getestet. Mein zuzuweisender Editor ist gültig, das heißt er ist nicht NIL und ich erhalten den Quelltext des Editors, für den ich die Codevervollständigung realisieren will. Der AutoCompleter ist auch zugewiesen. Nur der Editor lässt sich aus mir rätselhaftem Grund nicht an die Editoreigenschaft des AutoCompleters zuweisen.

Wer kann mir hier helfen?
Damit der Topf nicht explodiert, lässt man es ab und zu mal zischen.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz