2016-08-31 12 views
18

Często używam aktywnych szablonów w Delphi, ale próbowałem wymyślić rozwiązanie, aby dodać GUIDS do szablonów. Czy ktoś wie, jak to zrobić?Jak utworzyć identyfikator GUID podczas wywoływania aktywnego szablonu w Delphi?

Poniżej szablonu, który mam teraz z identyfikatorem GUID, jako słowo, które należy zastąpić ręcznie.

<?xml version="1.0" encoding="utf-8" ?> 
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" 
      version="1.0.0"> 
<template name="iacc" surround="false" invoke="manual"> 
    <point name="name"> 
     <text> 
      IntfAccessors 
     </text> 
     <hint> 
      Accessors name 
     </hint> 
    </point> 
    <description> 
     accessor declaration 
    </description> 
    <author> 
     PMH 
    </author> 
    <code language="Delphi" context="methoddecl" delimiter="|"> <![CDATA[I|name|Accessors = interface(IInterface) 
GUID <-- here I want a GUID 
end; 


I|name| = interface(I|name|Accessors) 
GUID <-- here I want a GUID 
end; 
    ]]> 
     </code> 
    </template> 
</codetemplate> 
+0

+100, co za świetne pytanie! – Johan

+0

W większości przypadków szablony na żywo są statyczne. Chociaż istnieją pewne zdarzenia skryptowe, które są uruchamiane podczas wywoływania szablonu, a jest kilka funkcji, które takie skrypty mogą wywoływać w celu dynamicznego generowania treści, generowanie identyfikatora GUID nie jest jedną z dostępnych funkcji. Aby uzyskać więcej informacji, zobacz [Informacje techniczne szablonów aktywnych] (http://delphi.wikia.com/wiki/Live_Templates_Technical_Info). –

+0

Czytałem informacje techniczne szablonów aktywnych, a także czytałem w skrypcie silnikowym, ale miałem nadzieję na rozwiązanie, które nie wymagało ode mnie utworzenia silnika skryptowego. –

Odpowiedz

22

Można rozszerzyć IDE, pisząc do tego niestandardowy silnik skryptowy. (Here to artykuł napisany przez Nicka Hodgesa z podobnym przykładem, który wstawia aktualną datę.)

Zakładam, że dwa różne interfejsy z przykładowego szablonu wymagają dwóch różnych IID, więc napisałem silnik skryptowy, aby załadować nazwy punktów od "skryptu" (jest to po prostu lista par nazwa = wartość, gdzie nazwa jest nazwą punktu, a wartość musi być wartością NewGuid, w przeciwnym razie zostanie zignorowana), dzięki czemu można tworzyć szablony z wieloma punktami, z których każdy otrzymuje oddzielne nowe IID.

Przykład szablon intf.xml:

<?xml version="1.0" encoding="utf-8" ?> 
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0"> 
<template name="iacc" surround="false" invoke="manual"> 
    <point name="name"> 
     <text> 
      Accessor 
     </text> 
     <hint> 
      Accessors name 
     </hint> 
    </point> 
    <point name="guid1"/> 
    <point name="guid2"/> 
    <description> 
     accessor declaration 
    </description> 
    <author> 
     PMH 
    </author> 
    <script language="NewGuidScript" onvalidate="true"> 
     guid1=NewGuid 
     guid2=NewGuid 
    </script> 
    <code language="Delphi" context="any" delimiter="|"> <![CDATA[I|name|Accessors = interface(IInterface) 
|*||guid1| 
end; 

I|name| = interface(I|name|Accessors) 
|*||guid2| 
end;]]> 
    </code> 
    </template> 
</codetemplate> 

NewGuidScriptEngine.pas:

unit NewGuidScriptEngine; 

interface 

uses 
    Classes, SysUtils, 
    ToolsApi, CodeTemplateApi, DesignEditors; 

type 
    TNewGuidScriptEngine = class(TNotifierObject, IOTACodeTemplateScriptEngine) 
    public 
    procedure Execute(const ATemplate: IOTACodeTemplate; const APoint: IOTACodeTemplatePoint; const ASyncPoints: IOTASyncEditPoints; const AScript: IOTACodeTemplateScript; var Cancel: Boolean); 
    function GetIDString: WideString; 
    function GetLanguage: WideString; 
    end; 

procedure Register; 

implementation 

uses 
    ActiveX, 
    ComObj; 

procedure Register; 
begin 
    (BorlandIDEServices as IOTACodeTemplateServices).RegisterScriptEngine(TNewGuidScriptEngine.Create); 
end; 

procedure TNewGuidScriptEngine.Execute(const ATemplate: IOTACodeTemplate; const APoint: IOTACodeTemplatePoint; 
    const ASyncPoints: IOTASyncEditPoints; const AScript: IOTACodeTemplateScript; var Cancel: Boolean); 
var 
    I: Integer; 
    Guid: TGUID; 
    P: IOTACodeTemplatePoint; 
    Points: TStringList; 
begin 
    Cancel := False; 
    if not Assigned(ATemplate) then 
    Exit; 

    Points := TStringList.Create; 
    try 
    Points.Text := AScript.Script; 
    for I := 0 to Points.Count - 1 do 
     Points.Strings[I] := Trim(Points[I]); 

    for I := 0 to Points.Count - 1 do 
     if Points.ValueFromIndex[I] = 'NewGuid' then 
     begin 
     P := ATemplate.FindPoint(Points.Names[I]); 
     if Assigned(P) then 
     begin 
      OleCheck(CoCreateGuid(Guid)); 
      P.Editable := False; 
      P.Value := '[''' + GUIDToString(Guid) + ''']'; 
     end; 
     end; 
    finally 
    Points.Free; 
    end; 
end; 

function TNewGuidScriptEngine.GetIDString: WideString; 
begin 
    Result := 'OndrejKelle.NewGuidScriptEngine'; 
end; 

function TNewGuidScriptEngine.GetLanguage: WideString; 
begin 
    Result := 'NewGuidScript'; 
end; 

end. 

umieścić to urządzenie do opakowania designtime tylko dodać odniesienie do designide.dcp jego requires klauzuli i zainstaluj pakiet w IDE.

Inną użyteczną, podobnie szablon może wyglądać następująco:

<?xml version="1.0" encoding="utf-8" ?> 
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0"> 
<template name="iacc" surround="false" invoke="manual"> 
    <point name="name"> 
     <text> 
     </text> 
     <hint> 
      Accessors name 
     </hint> 
    </point> 
    <point name="guid1"/> 
    <point name="guid2"/> 
    <description> 
     accessor declaration 
    </description> 
    <author> 
     PMH 
    </author> 
    <script language="NewGuidScript" onvalidate="true"> 
     guid1=NewGuid 
     guid2=NewGuid 
    </script> 
    <code language="Delphi" context="any" delimiter="|"> <![CDATA[const 
    SIID_I|name|Accessors = |guid1|; 
    IID_I|name|Accessors: TGUID = SIID_I|name|Accessors; 
    SIID_I|name| = |guid2|; 
    IID_I|name|: TGUID = SIID_I|name|; 

type 
    I|name|Accessors = interface 
    [SIID_I|name|Accessors] 
    end; 

    I|name| = interface(I|name|Accessors) 
    [SIID_I|name|] 
    end;]]> 
    </code> 
    </template> 
</codetemplate> 

Byłoby to zadeklarować ciąg, jak również TGUID stałych, a także używać ich w deklaracji interfejsu. W takim przypadku wstawione wartości GUID nie powinny być ujęte w nawiasy kwadratowe. Masz kilka opcji, aby dostosować silnik skryptowy, aby to zrobić:

  1. zmodyfikować kod, aby po prostu nie używać nawiasów kwadratowych
  2. wprowadzić nowy oddzielne NewGuidNoBrackets funkcyjnych i używać go w szablonie
  3. wprowadzić kilka prostych Składnia taka jak NewGuid (false), którą silnik może przeanalizować i użyć wartości parametru, aby określić, czy należy użyć nawiasów kwadratowych, czy nie.
+2

Wow, to świetnie. – Johan

+1

Dzięki za pracę, ona działa tak jak jest. –