Delphi Programming
Advertisement

Delphi 2006 introduced a feature called "Live Templates" that allows one to write macro type templates that expand from a keyword and are parameterized, i.e. you can tab through the parameters and supply them one by one. This is a great productivity aid. The best part is that you can provide your own and it is relatively simple to do so.

How to use live templates[]

To use these "live templates," all you need to do is copy the XML snippet provided and save it in

D2006: c:\Program Files\Borland\BDS\4.0\ObjRepos\Code_Templates\Delphi\
D2009: c:\Program Files\CodeGear\RAD Studio\6.0\ObjRepos\Code_Templates\Delphi\

with an xml extension.

Alternate places to put them are

D2006: c:\Documents and Settings\<username>\Local Settings\Application Data\Borland\BDS\4.0\code_templates\
D2009: c:\Users\<username>\Documents\RAD Studio\code_templates\ 

Note that you need to restart BDS if you just copy the file. Alternatively you can use the IDE to create a new template, delete all the automatically filled in stuff, copy and paste the template from below and use the IDE to save it. In that case the template will be immediately available.

A suggested file name is provided above the snippet but you can use whatever you like.

Live Templates for Developers Coming from VB[]

MsgBox[]

Just typing "msgbox" following by a space (or tab) will invoke this live template and generate the Delphi equivalent (with the ability to tab between the parameters you need to supply):

 MessageDlg('Hello', mtInformation, [mbOK], 0);

This script was adapted from Bob Swart's blog posting.


TEMPLATE FILE NAME: vb_live_template_msgbox.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0">
 <template name="msgbox" invoke="auto">
   <description>MessageDlg live template</description>
   <author>Bob Swart</author>
   <point name="Message">
      <text>Hello</text>
      <hint>Message</hint>
   </point>
   <point name="MessageType">
      <text>mtInformation</text>
      <hint>Message Type</hint>
   </point>
   <point name="MessageButtons">
      <text>mbOK</text>
      <hint>Message Buttons</hint>
   </point>
   <code language="Delphi" delimiter="|">
      <![CDATA[MessageDlg('|Message|', |MessageType|, [|MessageButtons|], 0);|end|]]>
   </code>
   </template>
</codetemplate>

General Language Templates[]

TODO[]

This template will create a TODO item in your source

TEMPLATE FILE NAME: todo.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate	xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
				version="1.0.0">
	<template name="todo" invoke="auto">
		<description>A live template to create a TODO item</description>
		<author>Bill Mullen</author>
		<point name="Owner">
			<text>Owner</text>
			<hint>Enter the person responsible for this item</hint>
		</point>
		<point name="Category">
			<text>General</text>
			<hint>Enter the category for this item</hint>
		</point>
		<point name="ActionItem">
			<text>ActionItem</text>
			<hint>Enter the action to be taken</hint>
		</point>
		<code language="Delphi" delimiter="|">
			<![CDATA[{TODO -o|Owner| -c|Category| : |ActionItem|}]]>
		</code>
	</template>
</codetemplate>


Database Live Templates[]

EOF[]

Here is a live template that automatically creates the following block of code (and allows you to change the dataset name) quickly. You simply type "eof" and hit <space> and the code block appears, positions you to change the name of "dataset", changes the name both places it's referenced, then places the cursor at the top of the new begin block.

 while not dataset.eof do
 begin
 dataset.Next;
 end;

TEMPLATE FILE NAME: not_eof.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate	xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
				version="1.0.0">
<template name="eof" invoke="auto">
<point name="dataset">
  <script language="Delphi">
  InvokeCodeCompletion;
  </script>
  <text>
    dataset
  </text>
  <hint>
    dataset to loop through
  </hint>
</point>
<description>
  Template to loop through a dataset while not eof
</description>
<author>
  Jeremy D. Mullin
</author>
<code language="Delphi" context="methodbody" delimiter="|"><![CDATA[while not |dataset|.eof do
begin
|*||end|
|*||dataset|.Next;
end;
]]>
</code>
</template>
</codetemplate>

Live Templates for Developers used to CodeRush[]

FreeAndNil[]

Typing F translates into FreeAndNil(Variable). With the help of the LiveTemplate ScriptEngine from Adam Markowitz (see CodeCentral ID 23910) the text of the first point defaults to the Clipboard content. This template also works without this ScriptEngine installed.

TEMPLATE FILE NAME: cr_live_template_freeandnil.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0">
  <template name="f" invoke="auto">
    <point name="variable">
      <text>variable</text>
      <hint>variable to be freed</hint>
    </point>
    <description>
      FreeAndNil
    </description>
    <author>
      Sebastian Modersohn
    </author>
    <script language="DelphiExample" onenter="false" onvalidate="true">
      |variable| := GetClipboardContents();
    </script>
    <code language="Delphi" context="methodbody" delimiter="|"><![CDATA[FreeAndNil(|variable|);]]>
    </code>
  </template>
</codetemplate>

i: Integer Declaration[]

Typing i: results in i: Integer. Useful for declaring i: Integer variable.

TEMPLATE FILE NAME: cr_live_template_integerdecl.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0">
  <template name="i:" invoke="auto">
    <description>
      AutoComplete i: Integer declaration
    </description>
    <author>
      Sebastian Modersohn
    </author>
    <code language="Delphi" context="methodbody" delimiter="|"><![CDATA[i: Integer;]]>
    </code>
  </template>
</codetemplate>

Alternatively, if you want to use it anywhere but have your variable declared in the correct spot:

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0">
  <template name="i:" invoke="auto">
    <description>
      AutoComplete i: Integer declaration
    </description>
    <author>
      Sebastian Modersohn / Thomas Mueller
    </author>
    <point name="ident" editable="false">
      <text>i</text>
    </point>
    <point name="type" editable="false">
      <text>Integer</text>
    </point>
    <script language="Delphi" onenter="false" onleave="true">
      DeclareVariable(|ident|, |type|);
      RemoveTemplate;
    </script>
    <code language="Delphi" context="methodbody" delimiter="|">
      <![CDATA[|ident||type|]]>
    </code>
  </template>
</codetemplate>

s: String Declaration[]

Typing s: results in s: String. Useful for declaring s: String variable.

TEMPLATE FILE NAME: cr_live_template_stringdecl.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0">
  <template name="s:" invoke="auto">
    <description>
      AutoComplete s: String declaration
    </description>
    <author>
      Sebastian Modersohn
    </author>
    <code language="Delphi" context="methodbody" delimiter="|"><![CDATA[s: String;]]>
    </code>
  </template>
</codetemplate>

convert typo ";=" to ":="[]

This will convert a common typo where you type ";=" but really meant ":=" to what you meant.

TEMPLATE FILE NAME: semicolon-equals-typo.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0">
  <template name=";=" invoke="auto">
    <description>
      convert typo ;= to :=
    </description>
    <author>
      twm
    </author>
    <code language="Delphi" delimiter="|">
      <![CDATA[:= |end|]]>
    </code>
  </template>
</codetemplate>

Property that refers to a field[]

Those two templates create a property declaration that refers to a field. Press Ctrl-Shift-C afterwards to have the IDE add the fields.

Readonly property[]

This will create a readonly property that refers to an object's field.

TEMPLATE FILE NAME: propfreadonly.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate	xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
				version="1.0.0">
	<template name="propfreadonly" invoke="none">
		<description>
			read only property for field
		</description>
		<author>
			twm
		</author>
		<point name="ident">
			<text>Name</text>
			<hint>the name for the property</hint>
		</point>
		<point name="type">
			<text>Integer</text>
			<hint>the type for the property</hint>
		</point>
		<script language="Delphi" onenter="false" onleave="true">
			InvokeClassCompletion;
		</script>
		<code language="Delphi" delimiter="|">
		<![CDATA[property |ident|: |type| read F|ident|;
|end|]]>
		</code>
	</template>
</codetemplate>

Read/write property[]

This will create a read / write property that refers to an object's field.

TEMPLATE FILE NAME: propfreadwrite.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate	xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
				version="1.0.0">
	<template name="propfreadwrite" invoke="none">
		<description>
			read write property for field
		</description>
		<author>
			twm
		</author>
		<point name="ident">
			<text>Name</text>
			<hint>the name for the property</hint>
		</point>
		<point name="type">
			<text>Integer</text>
			<hint>the type for the property</hint>
		</point>
		<script language="Delphi" onenter="false" onleave="true">
			InvokeClassCompletion;
		</script>
		<code language="Delphi" delimiter="|">
		<![CDATA[property |ident|: |type| read F|ident| write F|ident|;
|end|]]>
		</code>
	</template>
</codetemplate>

Getter, Setter or Field[]

This will create a read / write property that refers to either Get/Set methods or an object's field depending on what changes you make once invoked using propgs and either tab or space in the IDE.

TEMPLATE FILE NAME: PropertyGetSet.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate    xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0">
    <template name="propgs" invoke="auto">
        <description>Property with Getter and Setter.</description>
        <author>twm-tdh</author>
        <point name="Name">
            <text>Name</text>
            <hint>the Name for the property</hint>
        </point>
        <point name="Type">
            <text>Integer</text>
            <hint>the Type for the property</hint>
        </point>
        <point name="Getter">
            <text>Get</text>
            <hint>the property Getter</hint>
        </point>
        <point name="Setter">
            <text>Set</text>
            <hint>the property Setter</hint>
        </point>
        <code language="Delphi" delimiter="|">
        <![CDATA[property |Name|: |Type| read |Getter||Name| write |Setter||Name|;|end|]]>
        </code>
    </template>
</codetemplate>

Execute class method for a form[]

Generates a class method for a form that creates the form, shows it modally and returns true, if OK was pressed. Press Shift-Ctrl-C afterwards to add the method's declaration. Adding the script Tag with InvokeClassCompletion (see below) makes it unnecessary to press the Shift-Ctrl-C afterwards

TEMPLATE FILE NAME: FormExecute.xml

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate	xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
				version="1.0.0">
	<template name="FormExecute" invoke="manual">
		<description>
			creates an Execute class method for a form, press Shift-Ctrl afterwards
			to add the method declaration.
		</description>
		<author>
			twm
		</author>
		<point name="FormClass">
			<text>TForm</text>
			<hint>name of the form class</hint>
		</point>
		<point name="Value">
			<text>_Value</text>
			<hint>value edited with this form</hint>
		</point>
		<point name="Type">
			<text>string</text>
			<hint>Type of value</hint>
		</point>
		<point name="control">
			<text>Edit1</text>
			<hint>control that edits the value</hint>
		</point>
		<point name="property">
			<text>Text</text>
			<hint>property of the control for editing</hint>
		</point>
		<script language="Delphi" onenter="false" onleave="true">
			InvokeClassCompletion;
		</script>
		<code language="Delphi" delimiter="|"><![CDATA[
class function |FormClass|.Execute(_Owner: TComponent; var |Value|: |Type|): boolean;
var
  frm: |FormClass|;
begin
  frm := |FormClass|.Create(_Owner);
  try
	frm.|control|.|property| := |Value|;|end|
	Result := (frm.ShowModal = mrOK);
	if Result then begin
	  |Value| := frm.|control|.|property|;
	end;
  finally
	frm.Free;
  end;
end;
		]]>
		</code>
	</template>
</codetemplate>

Como assim?

Live Templates for Pseudo Templates[]

On https://osdn.net/projects/dzlib-tools/ you can find "pseudo templates". "Pseudo templates" are actually more like C++'s templates or C# and Java's generic types.

In the 1.0.1 release some Live Templates are included that make using these pseudo templates easier.

Improvements for existing templates[]

forin[]

The forin template always declares the iterator variable as TObject (QC 36085). Here is a forint template which has an entry point for the type too. Unfortunately the type stays in the code and must be removed manually (there is only RemoveTemplate as a script command available, but that would clear everything).

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate	xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
				version="1.0.0">
	<template name="forint" surround="true" invoke="manual">
		<script language="Delphi" onenter="false" onleave="false" onvalidate="true">
			ValidateForTemplate;
		</script>
		<point name="ident">
			<text>
			MyElem
			</text>
			<hint>
				collection element iterator variable
			</hint>
		</point>
		<point name="type">
			<text>
			MyElemType
			</text>
			<hint>
				type of iterator variable
			</hint>
		</point>
		<point name="collection">
			<text>
				MyList
			</text>
			<hint>
				collection to iterate
			</hint>
		</point>
		<description>
			for in loop
		</description>
		<author>
			Sebastian Modersohn
		</author>
		<script language="Delphi" onenter="false" onleave="true">
			DeclareVariable(|ident|, |type|);
		</script>
		<code language="Delphi" context="methodbody" delimiter="|"><![CDATA[for |ident|: |type| in |collection| do
begin
|selected||*||end|
end;
]]>
		</code>
	</template>
</codetemplate>

Troubleshooting Tips[]

  • The language attribute is case-sensitive. "delphi" doesn't work, but "Delphi" does.


More Information on Live Templates[]

See Live Templates Technical Info

See Editing the template_template

Simon Stuart had a Live Template Editor project called RADPlates but unfortunately it's no longer available.

a big collection of Live Templates

Advertisement