Difference between revisions of "Lazarus IDE Tools"

From Free Pascal wiki
Jump to navigationJump to search
 
(96 intermediate revisions by 21 users not shown)
Line 1: Line 1:
 
{{Lazarus IDE Tools}}
 
{{Lazarus IDE Tools}}
  
==Описание==
+
The '''[[Lazarus Faq|Lazarus]] IDE Tools''' is a library of [[Free Pascal]] source parsing and editing tools, called the "codetools".
The IDE uses a library of pascal source parsing and editing tools, called the "codetools". These tools provide features like find declaration, code completion, extraction, moving inserting and beautifying pascal sources. These functions saves you a lot of time and double work. They are customizable and every feature is available via short cuts (see Editor Options).
 
  
Because they work solely on sources and understand fpc, delphi and kylix code, they don't require compiled units nor an installed Borland compiler. You can edit Delphi and FPC code at the same time. You can even work with several Delphi and FPC versions at the same time. This makes porting Delphi code much more easier.
+
These tools provide features like ''Find Declaration'', ''Code Completion'', ''Extraction'', ''Moving Inserting'' and ''Beautifying Pascal'' sources. These functions can save a lot of time and duplicated work. They are customizable, and every feature is available via shortcuts (see Editor Options).
 +
 
 +
Because they work solely on Pascal sources and understand FPC, [[Delphi]] and [[Kylix]] code, they do not require compiled units or an installed Borland/Embarcadero compiler. Delphi and FPC code can be edited at the same time, with several Delphi and FPC versions. This makes porting Delphi code to FPC/Lazarus much easier.
  
 
==Summary Table of IDE shortcuts==
 
==Summary Table of IDE shortcuts==
 
{|
 
{|
 
|-
 
|-
| [[Lazarus_IDE_Tools#Find Declaration|Declaration Jumping]] || Ctrl+Click or Alt+Up (jump to declaration of type or variable)
+
| [[Lazarus_IDE_Tools#Find Declaration|Declaration Jumping]] || {{keypress|Ctrl}}+Click or {{keypress|Alt}}+{{keypress|Up}} (jump to declaration of type or variable)
 +
|-
 +
| [[Lazarus_IDE_Tools#Method Jumping|Method Jumping]] || {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|Up}} (toggle between definition and body)
 +
|-
 +
| [[Lazarus_IDE_Tools#Code Templates|Code Templates]] || {{keypress|Ctrl}}+{{keypress|J}}
 
|-
 
|-
| [[Lazarus_IDE_Tools#Method Jumping|Method Jumping]] || Ctrl+Shift+Up (toggle between definition and body)
+
| [[Lazarus_IDE_Tools#Syncro Edit|Syncro Edit]] || {{keypress|Ctrl}}+{{keypress|J}} (while text is selected)
 
|-
 
|-
| [[Lazarus_IDE_Tools#Code Templates|Code Templates]] || Ctrl+J
+
| [[Lazarus_IDE_Tools#Code Completion|Code Completion]] (Class Completion) || {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|C}},  {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|X}} for creating class fields instead of local variables
 
|-
 
|-
| [[Lazarus_IDE_Tools#Code Completion|Code Completion]] (Class Completion) || Ctrl+Shift+C
+
| [[Lazarus_IDE_Tools#Identifier Completion|Identifier Completion]] || {{keypress|Ctrl}}+{{keypress|space}}
 
|-
 
|-
| [[Lazarus_IDE_Tools#Identifier Completion|Identifier Completion]] || Ctrl+Space
+
| [[Lazarus_IDE_Tools#Word Completion|Word Completion]] || {{keypress|Ctrl}}+{{keypress|W}}
 
|-
 
|-
| [[Lazarus_IDE_Tools#Word Completion|Word Completion]] || Ctrl+W
+
| [[Lazarus_IDE_Tools#Parameter Hints|Parameter Hints]] || {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|space}}
 
|-
 
|-
| [[Lazarus_IDE_Tools#Parameter Hints|Parameter Hints]] || Ctrl+Shift+Space
+
| [[Lazarus_IDE_Tools#Incremental Search|Incremental Search]] || {{keypress|Ctrl}}+{{keypress|E}}
 
|-
 
|-
| [[Lazarus_IDE_Tools#Incremental Search|Incremental Search]] || Ctrl+E
+
| [[Lazarus_IDE_Tools#Rename Identifier|Rename Identifier]] || {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|E}}
 
|}
 
|}
  
 
==Method Jumping==
 
==Method Jumping==
To jump between a procedure body (begin..end) and the procedure definition (procedure Name;) use Ctrl+Shift+Up.
+
To jump between a procedure body (begin..end) and the procedure definition (procedure Name;) use {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|Up}}.
  
 
For example:
 
For example:
interface
+
 
 +
<syntaxhighlight lang="pascal">
 +
interface
 
   
 
   
procedure DoSomething; // procedure definition
+
procedure DoSomething; // procedure definition
 
    
 
    
implementation
+
implementation
 
    
 
    
procedure DoSomething; // procedure body  
+
procedure DoSomething; // procedure body  
begin
+
begin
end;
+
end;
If the cursor is on the procedure body and you press Ctrl+Shift+Up, the cursor will jump to the definition. Pressing Ctrl+Shift+Up again will jump to the body, after 'begin'.
+
</syntaxhighlight>
 +
 
 +
If the cursor is on the procedure body and {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|Up}} is pressed, the cursor will jump to the definition. Pressing {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|Up}} again will jump to the body, after 'begin'.
  
 
This works between methods (procedures in classes) as well.
 
This works between methods (procedures in classes) as well.
Line 47: Line 56:
  
 
For example a procedure with different parameter types:
 
For example a procedure with different parameter types:
interface
+
 
 +
<syntaxhighlight lang="pascal">
 +
interface
 
   
 
   
procedure DoSomething(p: char); // procedure definition
+
procedure DoSomething(p: char); // procedure definition
 
   
 
   
implementation
+
implementation
 
    
 
    
procedure DoSomething(p: string); // procedure body
+
procedure DoSomething(p: string); // procedure body
begin
+
begin
end;
+
end;
 +
</syntaxhighlight>
 +
 
 
Jumping from the definition to the body will position the cursor at the 'string' keyword. This can be used for renaming methods and/or changing the parameters.  
 
Jumping from the definition to the body will position the cursor at the 'string' keyword. This can be used for renaming methods and/or changing the parameters.  
  
For example:<br>
+
For example:
 +
 
 
You renamed 'DoSomething' to 'MakeIt':  
 
You renamed 'DoSomething' to 'MakeIt':  
interface
+
 
 +
<syntaxhighlight lang="pascal">
 +
interface
 
   
 
   
procedure MakeIt; // procedure definition
+
procedure MakeIt; // procedure definition
 
   
 
   
implementation
+
implementation
 
   
 
   
procedure DoSomething; // procedure body
+
procedure DoSomething; // procedure body
begin
+
begin
end;
+
end;
 +
</syntaxhighlight>
 +
 
 
Then you jump from MakeIt to the body. The IDE searches for a fitting body, does not find one, and hence searches for a candidate. Since you renamed only one procedure there is exactly one body without definition (DoSomething) and so it will jump to DoSomething and position the cursor right on 'DoSomething'. Then you can simply rename it there too. This works for parameters as well.
 
Then you jump from MakeIt to the body. The IDE searches for a fitting body, does not find one, and hence searches for a candidate. Since you renamed only one procedure there is exactly one body without definition (DoSomething) and so it will jump to DoSomething and position the cursor right on 'DoSomething'. Then you can simply rename it there too. This works for parameters as well.
  
 
==Include Files==
 
==Include Files==
Include files are files inserted into sources with the {$I filename} or {$INCLUDE filename} compiler directive. Lazarus and FPC uses a lot of these things to reduce redundancy and avoid unreadable {$IFDEF} constructs to support different platforms.
+
 
 +
Include files are files inserted into sources with the {$I filename} or {$INCLUDE filename} compiler directive. Lazarus and FPC often uses include files to reduce redundancy and avoid unreadable {$IFDEF} constructs, needed to support different platforms.
  
 
Contrary to Delphi, the Lazarus IDE has full support for include files. You can for example jump from the method in the .pas file to the method body in the include file. All codetools like code completion consider include files as special bounds.
 
Contrary to Delphi, the Lazarus IDE has full support for include files. You can for example jump from the method in the .pas file to the method body in the include file. All codetools like code completion consider include files as special bounds.
 
   
 
   
For instance: When code completion adds a new method body behind another method body, it keeps them both in the same file. This way you can put whole class implementations in include files, like the LCL does for nearly all controls.
+
For instance: When code completion adds a new method body behind another method body, it keeps them both in the same file. This way you can put whole class implementations in include files, as the LCL does for nearly all controls.
  
But there is a newbie trap:
+
But there is a trap for newbies: If you open an include file for the first time and try method jumping or find declaration you will get an error. The IDE does not yet know to which unit the include file belongs. You must open the unit first.
If you open an include file for the first time and try method jumping or find declaration you will get an error. The IDE does not know to which unit the include file belongs. You must open the unit first.
 
  
As soon as the IDE parses the unit, it will parse the include directives there and the IDE will remember this relationship. It saves this information on exit and on project save to ~/.lazarus/includelinks.xml. The next time you open this include file and jump or do a find declaration, the IDE will internally open the unit and the jump will work.
+
As soon as the IDE parses the unit, it will parse the include directives there and the IDE will remember this relationship. It saves this information on exit and on project save to ~/.lazarus/includelinks.xml. The next time you open this include file and jump or do a find declaration, the IDE will internally open the unit and the jump will work. You can also hint the IDE by putting
You can also hint the IDE by putting  
+
<syntaxhighlight lang="pascal" inline>{%mainunit yourunit.pas}</syntaxhighlight> at the top of yourinclude.inc.
{%mainunit yourunit.pas}  
 
on the top of yourinclude.inc.
 
  
This mechanism has of course limits. Some include files are included twice or more. For example: lcl/include/winapih.inc.
+
This mechanism has limits. Some include files are included twice or more. For example: lcl/include/winapih.inc.
  
Jumping from the procedure/method definitions in this include file to the bodies depends on your last actions. If you worked on lcl/lclintf.pp the IDE will jump to winapi.inc. If you worked on lcl/interfacebase.pp, then it will jump to lcl/include/interfacebase.inc (or one of the other include files). If you are working on both, then you can get confused. ;)
+
How you will jump from the procedure/method definitions in this include file to their bodies will depend on your last action. If you worked on lcl/lclintf.pp the IDE will jump to winapi.inc. If you worked on lcl/interfacebase.pp, then it will jump to lcl/include/interfacebase.inc (or one of the other include files). If you are working on both, then you can get confused. ;)
  
 
==Code Templates==
 
==Code Templates==
 
Code Templates converts an identifier into a text or code fragment.
 
Code Templates converts an identifier into a text or code fragment.
  
Code Templates default short cut is Ctrl+J. You can type an identifier, press Ctrl+J and the identifier is replaced by the text defined for the identifier. Code Templates can be defined in Environment -> Editor Options -> CodeTools.
+
Code Templates default short cut is {{keypress|Ctrl}}+{{keypress|J}}. You can type an identifier, press {{keypress|Ctrl}}+{{keypress|J}} and the identifier is replaced by the text defined for the identifier. Code Templates can be defined in Tools -> Options -> CodeTools.
  
 
Example:
 
Example:
Write the identifier 'classf', leave the cursor right behind the 'f' and press Ctrl+J. The 'classf' will be replaced by
+
Write the identifier 'classf', leave the cursor right behind the 'f' and press {{keypress|Ctrl}}+{{keypress|J}}. The 'classf' will be replaced by
T = class(T)
+
 
private
+
<syntaxhighlight lang="pascal">
 +
T = class(T)
 +
private
 
   
 
   
public
+
public
  constructor Create;
+
  constructor Create;
  destructor Destroy; override;
+
  destructor Destroy; override;
end;
+
end;
 +
</syntaxhighlight>
 +
 
 
and the cursor is behind the 'T'.
 
and the cursor is behind the 'T'.
You can get the list of templates by positioning the cursor on space (not on an identifier) and pressing Ctrl+J. The list of code templates will pop up. Use the cursor keys or type some chars to choose one. Return creates the selected template and Escape closes the pop up.
 
  
The biggest time savers are templates 'b'+Ctrl+J for begin..end.
+
You can get the list of templates by positioning the cursor on space (not on an identifier) and pressing {{keypress|Ctrl}}+{{keypress|J}}. The list of code templates will pop up. Use the cursor keys or type some chars to choose one. Return creates the selected template and Escape closes the pop up.
 +
 
 +
The biggest time savers are templates 'b'+{{keypress|Ctrl}}+{{keypress|J}} for begin..end.
  
 
==Parameter Hints==
 
==Parameter Hints==
Line 113: Line 134:
 
Parameter Hints shows a hint box with the parameter declarations for the current parameter list.
 
Parameter Hints shows a hint box with the parameter declarations for the current parameter list.
  
For example
+
For example: <syntaxhighlight lang="pascal" inline>  Canvas.FillRect(|);</syntaxhighlight>
 +
 
 +
Place the cursor in the brackets and press {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|space}}. A hint box will show up showing the parameters of FillRect.
 +
 
 +
[[Image:Parameterhints1.png]]
  
  Canvas.FillRect(|);
+
Since 0.9.31 there is a button to the right of each declaration to insert the missing parameters.This will copy the parameter names from the chosen declaration to the cursor position.
  
Place the cursor in the brackets and press Ctrl+Shift+Space. A hint box will show up showing the parameters of FillRect.
+
[[Image:Parameterhints2.png]]
 +
 
 +
Hint: Use the [[#Variable Declaration Completion|Variable Declaration Completion]] to declare the variables.
 +
 
 +
{{Note|The short cut's name is "Show code context".}}
  
 
==Incremental Search==
 
==Incremental Search==
  
Incremental Search changes the statusbar of the source editor. Type some characters and the editor will search and highlight immediately all occurrences in the text.
+
Incremental Search changes the statusbar of the source editor. Type some characters and the editor will search and highlight immediately all occurrences in the text. Shortcut is {{keypress|Ctrl}}+{{keypress|e}}.
*For example pressing 'e' will search and highlight all occurrences of 'e'.
+
*For example pressing {{keypress|e}} will search and highlight all occurrences of 'e'.
*Then pressing 't' will search and highlight all occurrences of 'et' and so forth.
+
*Then pressing {{keypress|t}} will search and highlight all occurrences of 'et' and so forth.
*You can jump to the next with F3 (or ctrl-e while in search) and the previous with Shift+F3.
+
*You can jump to the next with {{keypress|F3}} (or {{keypress|Ctrl}}+{{keypress|e}} while in search) and the previous with {{keypress|Shift}}+{{keypress|F3}}.
 
*Backspace deletes the last character
 
*Backspace deletes the last character
 
*return stops the search without adding a new line in the editor.
 
*return stops the search without adding a new line in the editor.
*You can resume the last search by pressing ctrl-e a 2nd time, immediately after you started incr-search with ctrl-e. that is while the search term is still empty.
+
*You can resume the last search by pressing {{keypress|Ctrl}}+{{keypress|e}} a second time, immediately after you started incr-search with {{keypress|Ctrl}}+{{keypress|e}}. that is while the search term is still empty.
*Paste Ctrl-V will append the text from the clipboard to the current search text (since lazarus 0.9.27 r19824).
+
*Paste {{keypress|Ctrl}}+{{keypress|V}} will append the text from the clipboard to the current search text (since lazarus 0.9.27 r19824).
  
 
===Hint: Quick searching an identifier with incremental search===
 
===Hint: Quick searching an identifier with incremental search===
  
 
*Place text cursor on identifier (do not select anything)
 
*Place text cursor on identifier (do not select anything)
*Press Ctrl+C. The source editor will select the identifier and copy it to the clipboard
+
*Press {{keypress|Ctrl}}+{{keypress|C}}. The source editor will select the identifier and copy it to the clipboard
*Press Ctrl+E to start incremental search
+
*Press {{keypress|Ctrl}}+{{keypress|E}} to start incremental search
*Press Ctrl+V to search for the identifier (since 0.9.27)
+
*Press {{keypress|Ctrl}}+{{keypress|V}} to search for the identifier (since 0.9.27)
*Use F3 and Shift+F3 to quickly jump to next/previous.
+
*Use {{keypress|F3}} and {{keypress|Shift}}+{{keypress|F3}} to quickly jump to next/previous.
 
*Use any key (for example cursor left or right) to end the search
 
*Use any key (for example cursor left or right) to end the search
 +
 +
==Syncro Edit==
 +
Syncro Edit allows you to edit all occurrences of a word at the same time (synchronized). You simple edit the word in one place, and as you type, all other occurrences of the word are updated too.
 +
 +
Syncro Edit works on all words in a selected area:
 +
* Select a block of text
 +
* press {{keypress|Ctrl}}+{{keypress|J}} or click the icon in the gutter. (This only works, if there are any words that occur more than once in the selection.
 +
** From Lazarus 4.0 on the following are available:
 +
** {{keypress|Ctrl}}+{{keypress|J}}  Words are grouped independent of the upper/lower casing.
 +
** {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|J}}  Words are only grouped if they have the same upper/lower casing.
 +
** {{keypress|Ctrl}}+{{keypress|Alt}}+{{keypress|J}}  Words are only grouped if they have the same context. Identifiers are different from the same word in a comment, or the same word as keyword or string.
 +
** {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|Alt}}+{{keypress|J}}  Words are only grouped if they have the same context and same upper/lower casing.
 +
* use the {{keypress|tab}} key to select the word you want to edit (if several different words occurred more than once)
 +
* Edit the word
 +
* Press {{keypress|Esc}} to finish
 +
 +
See an animated example [[New_IDE_features_since#Syncron-Edit|here]]
 +
 +
{{Note| {{keypress|Ctrl}}+{{keypress|J}} is also used for template edit. It switches its meaning if you select some text. }}
  
 
==Find next / previous word occurrence==
 
==Find next / previous word occurrence==
Line 149: Line 197:
  
 
==Code Completion==
 
==Code Completion==
Code Completion can be found in the IDE menu Edit -> Complete Code and has as standard short cut Ctrl+Shift+C.
+
Code Completion can be found in the IDE menu Edit -> Complete Code and has as standard short cut {{keypress|Ctrl|Shift|C}}.
  
 
For Delphians:
 
For Delphians:
Delphi calls "code completion" the function showing the list of identifiers at the current source position (Ctrl+Space). Under Lazarus this is called "Identifier completion".
+
Delphi calls "code completion" the function showing the list of identifiers at the current source position ({{keypress|Ctrl|Space}}). Under Lazarus this is called "Identifier completion".
  
 
Code Completion combines several powerful functions. Examples:
 
Code Completion combines several powerful functions. Examples:
* Class Completion: completes properties, adds/updates method bodies, add private variables and private access methods
+
* [[#Class Completion|Class Completion]]: completes properties, adds/updates method bodies, add private variables and private access methods
* Forward Procedure Completion: adds procedure bodies
+
* [[#Forward Procedure Completion|Forward Procedure Completion]]: adds procedure bodies
* Event Assignment Completion: completes event assignments and adds method definition and body
+
* [[#Event Assignment Completion|Event Assignment Completion]]: completes event assignments and adds method definition and body
* Variable Declaration Completion: adds local variable definitions  
+
* [[#Variable Declaration Completion|Variable Declaration Completion]]: adds local variable definitions  
* Procedure Call Completion: adds a new procedure
+
* [[#Procedure Call Completion|Procedure Call Completion]]: adds a new procedure
* Reversed procedure completion: adds procedure declarations for procedure/function bodies
+
* [[#Reversed Procedure Completion|Reversed procedure completion]]: adds procedure declarations for procedure/function bodies
* Reversed class completion: adds method declarations for method bodies
+
* [[#Reversed Class Completion|Reversed Class Completion]]: adds method declarations for method bodies
  
 
Which function is used, depends on the cursor position in the editor and will be explained below.  
 
Which function is used, depends on the cursor position in the editor and will be explained below.  
  
Code Completion can be found in the IDE menu Edit -> Complete Code and has as standard short cut Ctrl+Shift+C.
+
Code Completion can be found in the IDE menu Edit -> Complete Code and has as standard short cut {{keypress|Ctrl|Shift|C}}.
  
 
===Class Completion===
 
===Class Completion===
Line 173: Line 221:
 
For example: Create a class (see Code Templates to save you some type work):  
 
For example: Create a class (see Code Templates to save you some type work):  
  
TExample = class(TObject)
+
<syntaxhighlight lang="pascal">
public
+
TExample = class(TObject)
  constructor Create;
+
public
  destructor Destroy; override;
+
  constructor Create;
end;
+
  destructor Destroy; override;
Position the cursor somewhere in the class and press Ctrl+Shift+C. This will create the method missing bodies and move the cursor to the first created method body, so you can just start writing the class code:  
+
end;</syntaxhighlight>
 +
 
 +
Position the cursor somewhere in the class and press {{keypress|Ctrl|Shift|C}}. This will create the method missing bodies and move the cursor to the first created method body, so you can just start writing the class code:  
  
{ TExample }
+
<syntaxhighlight lang="pascal">
 +
{ TExample }
 
   
 
   
constructor TExample.Create;
+
constructor TExample.Create;
begin
+
begin
  |
+
  |
end;
+
end;
 
   
 
   
destructor TExample.Destroy;
+
destructor TExample.Destroy;
begin
+
begin
  inherited Destroy;
+
  inherited Destroy;
end;
+
end;
Note: The '|' is the cursor and is not added.  
+
</syntaxhighlight>
 +
 
 +
{{Note|The '&#124;' is the cursor and is not added.}}
  
Hint: You can jump between a method and its body with Ctrl+Shift+Up.  
+
{{Tip|You can jump between a method and its body with {{keypress|Ctrl|Shift|Up}}. }}
  
 
You can see, that the IDE added the 'inherited Destroy' call too. This is done, if there is an 'override' keyword in the class definition.  
 
You can see, that the IDE added the 'inherited Destroy' call too. This is done, if there is an 'override' keyword in the class definition.  
Line 199: Line 252:
 
Now add a method DoSomething:  
 
Now add a method DoSomething:  
  
TExample = class(TObject)
+
<syntaxhighlight lang="pascal">
public
+
TExample = class(TObject)
  constructor Create;
+
public
  procedure DoSomething(i: integer);
+
  constructor Create;
  destructor Destroy; override;
+
  procedure DoSomething(i: integer);
end;
+
  destructor Destroy; override;
Then press Ctrl+Shift+C and the IDE will add
+
end;
 +
</syntaxhighlight>
  
procedure TExample.DoSomething(i: integer);
+
Then press {{keypress|Ctrl|Shift|C}} and the IDE will add
begin
+
 
  |
+
<syntaxhighlight lang="pascal">
end;
+
procedure TExample.DoSomething(i: integer);
You can see, that the new method body is inserted between Create and Destroy, exactly as in the class definition. This way the bodies keep the same logical ordering as you define. You can define the insertion policy in Environment > Codetools Options -> Code Creation.  
+
begin
 +
  |
 +
end;
 +
</syntaxhighlight>
 +
 
 +
You can see, that the new method body is inserted between Create and Destroy, exactly as in the class definition. This way the bodies keep the same logical ordering as you define. You can define the insertion policy in Tools > Options -> Codetools -> Code Creation.  
 +
 
 +
'''Complete Properties'''
  
'''Complete Properties'''<br>
 
 
Add a property AnInteger:
 
Add a property AnInteger:
TExample = class(TObject)
+
 
public
+
<syntaxhighlight lang="pascal">
  constructor Create;
+
TExample = class(TObject)
  procedure DoSomething(i: integer);
+
public
  destructor Destroy; override;
+
  constructor Create;
  property AnInteger: Integer;
+
  procedure DoSomething(i: integer);
end;
+
  destructor Destroy; override;
Press Ctrl+Shift+C and you will get:
+
  property AnInteger: Integer;
procedure TExample.SetAnInteger(const AValue: integer);
+
end;
begin
+
</syntaxhighlight>
  |if FAnInteger=AValue then exit;
+
 
  FAnInteger:=AValue;
+
Press {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|C}} and you will get:
end;
+
 
 +
<syntaxhighlight lang="pascal">
 +
procedure TExample.SetAnInteger(const AValue: integer);
 +
begin
 +
  |if FAnInteger=AValue then exit;
 +
  FAnInteger:=AValue;
 +
end;</syntaxhighlight>
 +
 
 
The code completion has added a Write access modifier and added some common code.
 
The code completion has added a Write access modifier and added some common code.
Jump to the class with Ctrl+Shift+Up to see the new class:
+
Jump to the class with {{keypress|Ctrl|Shift|Up}} to see the new class:
TExample = class(TObject)
+
 
private
+
<syntaxhighlight lang="pascal">
  FAnInteger: integer;
+
TExample = class(TObject)
  procedure SetAnInteger(const AValue: integer);
+
private
public
+
  FAnInteger: integer;
  constructor Create;
+
  procedure SetAnInteger(const AValue: integer);
  procedure DoSomething(i: integer);
+
public
  destructor Destroy; override;
+
  constructor Create;
  property AnInteger: integer read FAnInteger write SetAnInteger;
+
  procedure DoSomething(i: integer);
end;
+
  destructor Destroy; override;
 +
  property AnInteger: integer read FAnInteger write SetAnInteger;
 +
end;
 +
</syntaxhighlight>
 +
 
 
The property was extended by a Read and Write access modifier. The class got the new section 'private' with a Variable 'FAnInteger' and the method 'SetAnInteger'.
 
The property was extended by a Read and Write access modifier. The class got the new section 'private' with a Variable 'FAnInteger' and the method 'SetAnInteger'.
It is a common Delphi style rule to prepend private variables with an 'F' and the write method with a 'Set'. If you don't like that, you can change this in Environment > Codetools Options -> Code Creation.
+
It is a common Delphi style rule to prepend private variables with an 'F' and the write method with a 'Set'. If you don't like that, you can change this in Tools -> Options > Codetools -> Code Creation.
  
 
Creating a read only property:
 
Creating a read only property:
property PropName: PropType read;
+
 
 +
<syntaxhighlight lang="pascal">
 +
property PropName: PropType read;
 +
</syntaxhighlight>
 +
 
 
Will be expanded to
 
Will be expanded to
property PropName: PropType read FPropName;
+
 
 +
<syntaxhighlight lang="pascal">
 +
property PropName: PropType read FPropName;
 +
</syntaxhighlight>
 +
 
 
Creating a write only property:
 
Creating a write only property:
  property PropName: PropType write;
+
 
 +
<syntaxhighlight lang="pascal">
 +
property PropName: PropType write;
 +
</syntaxhighlight>
 +
 
 
Will be expanded to
 
Will be expanded to
property PropName: PropType write SetPropName;
+
 
 +
<syntaxhighlight lang="pascal">
 +
property PropName: PropType write SetPropName;
 +
</syntaxhighlight>
 +
 
 
Creating a read only property with a Read method:
 
Creating a read only property with a Read method:
property PropName: PropType read GetPropName;
+
 
 +
<syntaxhighlight lang="pascal">
 +
property PropName: PropType read GetPropName;
 +
</syntaxhighlight>
 +
 
 
Will be kept and a GetPropName function will be added:
 
Will be kept and a GetPropName function will be added:
function GetpropName: PropType;
+
 
 +
<syntaxhighlight lang="pascal">
 +
function GetpropName: PropType;
 +
</syntaxhighlight>
 +
 
 
Creating a property with a stored modifier:
 
Creating a property with a stored modifier:
property PropName: PropType stored;
+
 
 +
<syntaxhighlight lang="pascal">
 +
property PropName: PropType stored;
 +
</syntaxhighlight>
 +
 
 
Will be expanded to
 
Will be expanded to
property PropName: PropType read FPropName write SetPropName stored PropNameIsStored;
+
 
 +
<syntaxhighlight lang="pascal">
 +
property PropName: PropType read FPropName write SetPropName stored PropNameIsStored;
 +
</syntaxhighlight>
 +
 
 
Because stored is used for streaming read and write modifiers are automatically added as well.
 
Because stored is used for streaming read and write modifiers are automatically added as well.
  
 
Hint:
 
Hint:
 
Identifier completion also recognizes incomplete properties and will suggest the default names. For example:
 
Identifier completion also recognizes incomplete properties and will suggest the default names. For example:
property PropName: PropType read |;
+
 
Place the cursor one space behind the 'read' keyword and press Ctrl+Space for the identifier completion. It will present you the variable 'FPropName' and the procedure 'SetPropName'.
+
<syntaxhighlight lang="pascal">
 +
property PropName: PropType read |;
 +
</syntaxhighlight>
 +
 
 +
Place the cursor one space behind the 'read' keyword and press {{keypress|Ctrl}}+{{keypress|Space}} for the identifier completion. It will present you the variable 'FPropName' and the procedure 'SetPropName'.
  
 
===Forward Procedure Completion===
 
===Forward Procedure Completion===
 +
 
"Forward Procedure Completion" is part of the Code Completion and adds missing procedure bodies. It is invoked, when the cursor is on a forward defined procedure.
 
"Forward Procedure Completion" is part of the Code Completion and adds missing procedure bodies. It is invoked, when the cursor is on a forward defined procedure.
  
 
For example:
 
For example:
 
Add a new procedure to the interface section:
 
Add a new procedure to the interface section:
procedure DoSomething;
+
 
Place the cursor on it and press Ctrl+Shift+C for code completion. It will create in the implementation section:
+
<syntaxhighlight lang="pascal">
procedure DoSomething;
+
procedure DoSomething;
begin
+
</syntaxhighlight>
  |
+
 
end;
+
Place the cursor on it and press {{keypress|Ctrl|Shift|C}} for code completion. It will create in the implementation section:
Hint: You can jump between a procedure definition and its body with Ctrl+Shift+Up.
+
 
 +
<syntaxhighlight lang="pascal">
 +
procedure DoSomething;
 +
begin
 +
  |
 +
end;
 +
</syntaxhighlight>
 +
 
 +
Hint: You can jump between a procedure definition and its body with {{keypress|Ctrl|Shift|Up}}.
  
 
The new procedure body will be added in front of the class methods. If there are already some procedures in the interface the IDE tries to keep the ordering. For example:
 
The new procedure body will be added in front of the class methods. If there are already some procedures in the interface the IDE tries to keep the ordering. For example:
  procedure Proc1;
+
 
  procedure Proc2; // new proc
+
<syntaxhighlight lang="pascal">
  procedure Proc3;
+
procedure Proc1;
If the bodies of Proc1 and Proc3 already exists, then the Proc2 body will be inserted between the bodies of Proc1 and Proc3. This behaviour can be setup in Environment > Codetools Options -> Code Creation.
+
procedure Proc2; // new proc
 +
procedure Proc3;
 +
</syntaxhighlight>
 +
 
 +
If the bodies of Proc1 and Proc3 already exists, then the Proc2 body will be inserted between the bodies of Proc1 and Proc3. This behaviour can be setup in Tools ->  Options -> Codetools -> Code Creation.
  
 
Multiple procedures:
 
Multiple procedures:
procedure Proc1_Old; // body exists
+
 
procedure Proc2_New; // body does not exists
+
<syntaxhighlight lang="pascal">
procedure Proc3_New; //  "
+
procedure Proc1_Old; // body exists
procedure Proc4_New; //  "
+
procedure Proc2_New; // body does not exist
procedure Proc5_Old; // body exists
+
procedure Proc3_New; //  "
 +
procedure Proc4_New; //  "
 +
procedure Proc5_Old; // body exists
 +
</syntaxhighlight>
 +
 
 
Code Completion will add all 3 procedure bodies (Proc2_New, Proc3_New, Proc4_New).
 
Code Completion will add all 3 procedure bodies (Proc2_New, Proc3_New, Proc4_New).
  
Why calling it "Forward Procedure Completion"?
+
Why is it called "Forward Procedure Completion"?
  
 
Because it does not only work for procedures defined in the interface, but for procedures with the "forward" modifier as well. And because the codetools treats procedures in the interface as having an implicit 'forward' modifier.
 
Because it does not only work for procedures defined in the interface, but for procedures with the "forward" modifier as well. And because the codetools treats procedures in the interface as having an implicit 'forward' modifier.
  
 
===Event Assignment Completion===
 
===Event Assignment Completion===
 +
 
"Event Assignment Completion" is part of the Code Completion and completes a single Event:=| statement. It is invoked, when the cursor is behind an assignment to an event.
 
"Event Assignment Completion" is part of the Code Completion and completes a single Event:=| statement. It is invoked, when the cursor is behind an assignment to an event.
  
 
For example:
 
For example:
 
In a method, say the FormCreate event, add a line 'OnPaint:=':
 
In a method, say the FormCreate event, add a line 'OnPaint:=':
procedure TForm1.Form1Create(Sender: TObject);
+
 
begin
+
<syntaxhighlight lang="pascal">
  OnPaint:=|
+
procedure TForm1.Form1Create(Sender: TObject);
end;
+
begin
 +
  OnPaint:=|
 +
end;
 +
</syntaxhighlight>
 +
 
 
The '|' is the cursor and should not be typed.
 
The '|' is the cursor and should not be typed.
Then press Ctrl+Shift+C for code completion. The statement will be completed to
+
Then press {{keypress|Ctrl}}+{{keypress|Shift}}+{{keypress|C}} for code completion. The statement will be completed to
OnPaint:=@Form1Paint;
+
 
 +
<syntaxhighlight lang="pascal">
 +
OnPaint:=@Form1Paint;
 +
</syntaxhighlight>
 +
 
 
A new method Form1Paint will be added to the TForm1 class. Then class completion is started and you get:
 
A new method Form1Paint will be added to the TForm1 class. Then class completion is started and you get:
procedure TForm1.Form1Paint(Sender: TObject);
+
 
begin
+
<syntaxhighlight lang="pascal">
  |
+
procedure TForm1.Form1Paint(Sender: TObject);
end;
+
begin
 +
  |
 +
end;
 +
</syntaxhighlight>
 +
 
 
This works just like adding methods in the object inspector.
 
This works just like adding methods in the object inspector.
  
Note:<br>
+
{{Note|You must place the cursor just after the ':&#61;' assignment operator. If you place the cursor on the identifier (e.g. OnPaint) code completion will invoke "Local Variable Completion", which fails, because OnPaint is already defined.}}
You must place the cursor behind the ':=' assignment operator. If you place the cursor on the identifier (e.g. OnPaint) code completion will invoke "Local Variable Completion", which fails, because OnPaint is already defined.
 
  
Hint:<br>
+
Hints:
You can define the new method name by yourself. For example:
+
 
   OnPaint:=@ThePaintMethod;
+
*You can choose the default visibility of the new method in Tools / Options / Codetools / Class Completion / Default section of methods (since 1.8)
 +
*You can define the new method name by yourself. For example: <syntaxhighlight lang="pascal" inline>OnPaint:=@ThePaintMethod;</syntaxhighlight>.
 +
 
 +
Since 0.9.31 Lazarus completes procedure parameters. For example
 +
 
 +
<syntaxhighlight lang="pascal">
 +
procedure TForm1.FormCreate(Sender: TObject);
 +
var
 +
   List: TList;
 +
begin
 +
  List:=TList.Create;
 +
  List.Sort(@MySortFunction|);
 +
end;
 +
</syntaxhighlight>
 +
 
 +
Place the cursor on 'MySortFunction' and press {{keypress|Ctrl|Shift|C}} for code completion. You get a new procedure:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
function MySortFunction(Item1, Item2: Pointer): Integer;
 +
begin
 +
  |
 +
end;
 +
 
 +
procedure TForm1.FormCreate(Sender: TObject);
 +
var
 +
  List: TList;
 +
begin
 +
  List:=TList.Create;
 +
  List.Sort(@MySortFunction);
 +
end;
 +
</syntaxhighlight>
  
 
===Variable Declaration Completion===
 
===Variable Declaration Completion===
 +
 
"Variable Declaration Completion" is part of the Code Completion and adds a local variable definition for a Identifier:=Term; statement. It is invoked, when the cursor is on the identifier of an assignment or a parameter.
 
"Variable Declaration Completion" is part of the Code Completion and adds a local variable definition for a Identifier:=Term; statement. It is invoked, when the cursor is on the identifier of an assignment or a parameter.
  
 
For example:
 
For example:
<delphi>
+
 
 +
<syntaxhighlight lang="pascal">
 
procedure TForm1.Form1Create(Sender: TObject);
 
procedure TForm1.Form1Create(Sender: TObject);
 
begin
 
begin
 
   i:=3;
 
   i:=3;
 
end;
 
end;
</delphi>
+
</syntaxhighlight>
Place the cursor on the 'i' or just behind it. Then press Ctrl+Shift+C for code completion and you will get:
+
 
<delphi>
+
Place the cursor on the 'i' or just behind it. Then press {{keypress|Ctrl|Shift|C}} for code completion and you will get:
 +
 
 +
<syntaxhighlight lang="pascal">
 
procedure TForm1.Form1Create(Sender: TObject);
 
procedure TForm1.Form1Create(Sender: TObject);
 
var
 
var
Line 341: Line 511:
 
   i:=3;
 
   i:=3;
 
end;
 
end;
</delphi>
+
</syntaxhighlight>
 +
 
 
The codetools first checks, if the identifier 'i' is already defined and if not it will add the declaration 'var i: integer;'. The type of the identifier is guessed from the term right to the assignment ':=' operator. Numbers like the 3 defaults to Integer.
 
The codetools first checks, if the identifier 'i' is already defined and if not it will add the declaration 'var i: integer;'. The type of the identifier is guessed from the term right to the assignment ':=' operator. Numbers like the 3 defaults to Integer.
  
 
Another example:
 
Another example:
<delphi>
+
 
 +
<syntaxhighlight lang="pascal">
 
type
 
type
 
   TWhere = (Behind, Middle, InFront);
 
   TWhere = (Behind, Middle, InFront);
Line 355: Line 527:
 
     for Where:=Low(a) to High(a) do writeln(a[Where]);
 
     for Where:=Low(a) to High(a) do writeln(a[Where]);
 
   end;
 
   end;
</delphi>
+
</syntaxhighlight>
Place the cursor on 'Where' and press Ctrl+Shift+C for code completion. You get:
+
 
<delphi>
+
Place the cursor on 'Where' and press {{keypress|Ctrl|Shift|C}} for code completion. You get:
 +
 
 +
<syntaxhighlight lang="pascal">
 
   procedure TForm1.Form1Create(Sender: TObject);
 
   procedure TForm1.Form1Create(Sender: TObject);
 
   var
 
   var
Line 365: Line 539:
 
     for Where:=Low(a) to High(a) do writeln(a[Where]);
 
     for Where:=Low(a) to High(a) do writeln(a[Where]);
 
   end;
 
   end;
</delphi>
+
</syntaxhighlight>
  
 
Since 0.9.11 Lazarus also completes parameters. For example
 
Since 0.9.11 Lazarus also completes parameters. For example
<delphi>
+
 
 +
<syntaxhighlight lang="pascal">
 
   procedure TForm1.FormPaint(Sender: TObject);
 
   procedure TForm1.FormPaint(Sender: TObject);
 
   begin
 
   begin
Line 375: Line 550:
 
     end;
 
     end;
 
   end;
 
   end;
</delphi>
+
</syntaxhighlight>
Place the cursor on 'x1' and press Ctrl+Shift+C for code completion. You get:
+
 
<delphi>
+
Place the cursor on 'x1' and press {{keypress|Ctrl|Shift|C}} for code completion. You get:
 +
 
 +
<syntaxhighlight lang="pascal">
 
   procedure TForm1.FormPaint(Sender: TObject);
 
   procedure TForm1.FormPaint(Sender: TObject);
 
   var
 
   var
Line 386: Line 563:
 
     end;
 
     end;
 
   end;
 
   end;
</delphi>
+
</syntaxhighlight>
 +
 
 +
Since 0.9.31 Lazarus completes pointer parameters. For example
 +
 
 +
<syntaxhighlight lang="pascal">
 +
  procedure TForm1.FormCreate(Sender: TObject);
 +
  begin
 +
    CreateIconIndirect(@IconInfo);
 +
  end;</syntaxhighlight>
 +
 
 +
Place the cursor on 'IconInfo' and press {{keypress|Ctrl|Shift|C}} for code completion. You get:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
  procedure TForm1.FormCreate(Sender: TObject);
 +
  var
 +
    IconInfo: TIconInfo;
 +
  begin
 +
    CreateIconIndirect(@IconInfo);
 +
  end;
 +
</syntaxhighlight>
 +
 
 +
In all above examples you can use {{keypress|Ctrl|Shift|X}} to show a Code Creation dialog where you can set more options.
  
 
===Procedure Call Completion===
 
===Procedure Call Completion===
 +
 
Code completion can create a new procedure from a call statement itself.
 
Code completion can create a new procedure from a call statement itself.
  
 
Assume you just wrote the statement "DoSomething(Width);"
 
Assume you just wrote the statement "DoSomething(Width);"
<delphi>
+
 
 +
<syntaxhighlight lang="pascal">
 
procedure SomeProcedure;
 
procedure SomeProcedure;
 
var
 
var
Line 400: Line 600:
 
   DoSomething(Width);
 
   DoSomething(Width);
 
end;
 
end;
</delphi>
+
</syntaxhighlight>
  
Position the cursor over the identifier "DoSomething" and press Ctrl+Shift+C to get:
+
Position the cursor over the identifier "DoSomething" and press {{keypress|Ctrl|Shift|C}} to get:
  
<delphi>
+
<syntaxhighlight lang="pascal">
 
procedure DoSomething(aWidth: LongInt);
 
procedure DoSomething(aWidth: LongInt);
 
begin
 
begin
Line 417: Line 617:
 
   DoSomething(Width);
 
   DoSomething(Width);
 
end;
 
end;
</delphi>
+
</syntaxhighlight>
  
 
It does not yet create functions nor methods.
 
It does not yet create functions nor methods.
Line 427: Line 627:
  
 
For example:
 
For example:
 +
 +
<syntaxhighlight lang="pascal">
 
   procedure TForm1.DoSomething(Sender: TObject);
 
   procedure TForm1.DoSomething(Sender: TObject);
 
   begin
 
   begin
 
   end;
 
   end;
 +
</syntaxhighlight>
  
The method DoSomething is not yet declared in TForm1. Press Ctrl+Shift+C and the IDE will add "procedure DoSomething(Sender: TObject);" to the private methods of TForm1.
+
The method DoSomething is not yet declared in TForm1. Press {{keypress|Ctrl|Shift|C}} and the IDE will add "procedure DoSomething(Sender: TObject);" to the private methods of TForm1.
  
 
For Delphians:
 
For Delphians:
Line 437: Line 640:
  
 
===Comments and Code Completion===
 
===Comments and Code Completion===
 +
 
Code completion tries to keep comments where they belong.  
 
Code completion tries to keep comments where they belong.  
 
For example:
 
For example:
 +
 +
<syntaxhighlight lang="pascal">
 
   FList: TList; // list of TComponent
 
   FList: TList; // list of TComponent
 
   FInt: integer;
 
   FInt: integer;
 +
</syntaxhighlight>
 +
 
When inserting a new variable between FList and FInt, the comment is kept in the FList line. Same is true for
 
When inserting a new variable between FList and FInt, the comment is kept in the FList line. Same is true for
 +
 +
<syntaxhighlight lang="pascal">
 
   FList: TList; { list of TComponent
 
   FList: TList; { list of TComponent
 
     This is a comment over several lines, starting
 
     This is a comment over several lines, starting
Line 448: Line 658:
 
     relationship. Code is inserted behind the comment. }
 
     relationship. Code is inserted behind the comment. }
 
   FInt: integer;
 
   FInt: integer;
 +
</syntaxhighlight>
 +
 
If the comment starts in the next line, then it will be treated as if it belongs to the code below. For example:
 
If the comment starts in the next line, then it will be treated as if it belongs to the code below. For example:
  FList: TList; // list of TComponent
+
 
 +
<syntaxhighlight lang="pascal">  FList: TList; // list of TComponent
 
     { This comment belongs to the statement below.  
 
     { This comment belongs to the statement below.  
 
       New code is inserted above this comment and  
 
       New code is inserted above this comment and  
 
       behind the comment of the FList line. }
 
       behind the comment of the FList line. }
 
   FInt: integer;
 
   FInt: integer;
 +
</syntaxhighlight>
  
 
===Method update===
 
===Method update===
 +
 
Normally class completion will add all missing method bodies. (Since 0.9.27) But if exactly one method differ between class and bodies then the method body is updated. For example: You have a method ''DoSomething''.
 
Normally class completion will add all missing method bodies. (Since 0.9.27) But if exactly one method differ between class and bodies then the method body is updated. For example: You have a method ''DoSomething''.
<Delphi>
+
 
 +
<syntaxhighlight lang="pascal">
 
   public
 
   public
 
     procedure DoSomething;
 
     procedure DoSomething;
Line 465: Line 681:
 
begin
 
begin
 
end;
 
end;
</Delphi>
+
</syntaxhighlight>
  
 
Now add a parameter:
 
Now add a parameter:
  
<Delphi>
+
<syntaxhighlight lang="pascal">
 
   public
 
   public
 
     procedure DoSomething(i: integer);
 
     procedure DoSomething(i: integer);
 
   end;
 
   end;
</Delphi>
+
</syntaxhighlight>
  
and invoke Code Completion (Ctrl+Shift+C). The method body will be updated and the new parameter will be copied:
+
and invoke Code Completion ({{keypress|Ctrl|Shift|C}}). The method body will be updated and the new parameter will be copied:
  
<Delphi>
+
<syntaxhighlight lang="pascal">
 
procedure TForm.DoSomething(i: integer);
 
procedure TForm.DoSomething(i: integer);
 
begin
 
begin
 
end;
 
end;
</Delphi>
+
</syntaxhighlight>
  
 
==Refactoring==
 
==Refactoring==
Line 489: Line 705:
 
;Abstract: : "Invert Assignments" takes some selected pascal statements and inverts all assignments from this code. This tool is usefull for transforming a "save" code to a "load" one and inverse operation.
 
;Abstract: : "Invert Assignments" takes some selected pascal statements and inverts all assignments from this code. This tool is usefull for transforming a "save" code to a "load" one and inverse operation.
  
Example:<br>
+
Example:
procedure DoSomething;
+
 
begin
+
<syntaxhighlight lang="pascal">
  AValueStudio:= BValueStudio;
+
procedure DoSomething;
  AValueAppartment :=BValueAppartment;
+
begin
  AValueHouse:=BValueHouse;
+
  AValueStudio:= BValueStudio;
end;
+
  AValueAppartment :=BValueAppartment;
 +
  AValueHouse:=BValueHouse;
 +
end;
 +
</syntaxhighlight>
 +
 
 
Select the lines with assignments (between begin and end) and do Invert Assignments. All assignments will be inverted and identation will be add automatically. For example:
 
Select the lines with assignments (between begin and end) and do Invert Assignments. All assignments will be inverted and identation will be add automatically. For example:
  
 
Result:
 
Result:
procedure DoSomething;
+
 
begin
+
<syntaxhighlight lang="pascal">
  BValueStudio    := AValueStudio;
+
procedure DoSomething;
  BValueAppartment := AValueAppartment;
+
begin
  BValueHouse      := AValueHouse;
+
  BValueStudio    := AValueStudio;
end;
+
  BValueAppartment := AValueAppartment;
 +
  BValueHouse      := AValueHouse;
 +
end;
 +
</syntaxhighlight>
 +
 
 
===Enclose Selection===
 
===Enclose Selection===
 +
 
Select some text and invoke it. A dialog will popup where you can select if the selection should be enclosed into '''try..finally''' or many other common blocks.
 
Select some text and invoke it. A dialog will popup where you can select if the selection should be enclosed into '''try..finally''' or many other common blocks.
  
 
===Rename Identifier===
 
===Rename Identifier===
 +
 
Place the cursor on an identifier and invoke it. A dialog will appear, where you can setup the search scope and the new name.  
 
Place the cursor on an identifier and invoke it. A dialog will appear, where you can setup the search scope and the new name.  
 
* It will rename all occurences and only those that actually use this declaration. That means it does not rename declarations with the same name.  
 
* It will rename all occurences and only those that actually use this declaration. That means it does not rename declarations with the same name.  
Line 515: Line 741:
  
 
===Find Identifier References===
 
===Find Identifier References===
 +
 
Place the cursor on an identifier and invoke it. A dialog will appear, where you can setup the search scope. The IDE will then search for all occurences and only those that actually use this declaration. That means it does not show other declarations with the same name.
 
Place the cursor on an identifier and invoke it. A dialog will appear, where you can setup the search scope. The IDE will then search for all occurences and only those that actually use this declaration. That means it does not show other declarations with the same name.
  
 
===Show abstract methods===
 
===Show abstract methods===
 +
 
This feature lists and auto completes virtual, abstracts methods that need to be implemented.
 
This feature lists and auto completes virtual, abstracts methods that need to be implemented.
 
Place the cursor on a class declaration and invoke it. If there are missing abstract methods a dialog will appear listing them. Select the methods to implement and the IDE creates the method stubs.
 
Place the cursor on a class declaration and invoke it. If there are missing abstract methods a dialog will appear listing them. Select the methods to implement and the IDE creates the method stubs.
 +
Since Lazarus 1.3 it adds missing ''class interface'' methods too.
  
 
===Extract Procedure===
 
===Extract Procedure===
  
See [[IDE_Window:_Extract_Procedure|Extract Procedure]]
+
See [[IDE Window: Extract Procedure|Extract Procedure]].
  
 
==Find Declaration==
 
==Find Declaration==
Position the cursor on an identifier and do 'Find Declaration'. Then it will search the declaration of this identifier, open the file and jump to it.
+
 
 +
Position the cursor on an identifier and do 'Find Declaration'. Then it will search the declaration of this identifier, open the file and jump to it. If the cursor is already at a declaration it will jump to the previous declaration with the same name. This allows to find redefinitions and overrides.
  
 
Every find declaration sets a Jump Point. That means you jump with find declaration to the declaration and easily jump back with Search -> Jump back.
 
Every find declaration sets a Jump Point. That means you jump with find declaration to the declaration and easily jump back with Search -> Jump back.
  
There are some differences to Delphi:
+
There are some differences to Delphi: the codetools work on sources following the normal pascal rules, instead of using the compiler output. The compiler returns the final type. The codetools see the sources and all steps in between. For example:
The codetools work on sources following the normal pascal rules, instead of using the compiler output. The compiler returns the final type. The codetools see the sources and all steps in between. For example:
 
  
The ''Visible'' property is first defined in TControl (controls.pp), then redefined in TCustomForm and finally redefined in TForm.
+
The ''Visible'' property is first defined in ''TControl'' (controls.pp), then redefined in TCustomForm and finally redefined in TForm.
 
Invoking find declaration on Visible will you first bring to Visible in TForm. Then you can invoke Find Declaration again to jump to Visible in TCustomForm and again to jump to Visible in TControl.
 
Invoking find declaration on Visible will you first bring to Visible in TForm. Then you can invoke Find Declaration again to jump to Visible in TCustomForm and again to jump to Visible in TControl.
  
Same is true for types like TColor.
+
Same is true for types like ''TColor''. For the compiler it is simply a 'longint'. But in the sources it is defined as
For the compiler it is simply a 'longint'. But in the sources it is defined as
+
 
TGraphicsColor = -$7FFFFFFF-1..$7FFFFFFF;
+
<syntaxhighlight lang="pascal">
TColor = TGraphicsColor;
+
TGraphicsColor = -$7FFFFFFF-1..$7FFFFFFF;
 +
TColor = TGraphicsColor;
 +
</syntaxhighlight>
 +
 
 +
And the same for '''forward defined classes''': for instance in ''TControl'', there is a private variable
 +
 
 +
<syntaxhighlight lang="pascal">
 +
FHostDockSite: TWinControl;
 +
</syntaxhighlight>
  
And the same for '''forward defined classes''':
 
For instance in TControl, there is a private variable
 
FHostDockSite: TWinControl;
 
 
Find declaration on TWinControl jumps to the forward definition
 
Find declaration on TWinControl jumps to the forward definition
TWinControl = class;
+
 
 +
<syntaxhighlight lang="pascal">
 +
TWinControl = class;
 +
</syntaxhighlight>
 +
 
 
And invoking it again jumps to the real implementation
 
And invoking it again jumps to the real implementation
TWinControl = class(TControl)
+
 
 +
<syntaxhighlight lang="pascal">
 +
TWinControl = class(TControl)
 +
</syntaxhighlight>
 +
 
 
This way you can track down every identifier and find every overload.
 
This way you can track down every identifier and find every overload.
  
'''Hints:''' You can jump back with Ctrl+H.
+
===Hints===
 +
 
 +
* ump back with {{keypress|Ctrl|H}}.
 +
* view/navigate all visited locations via Menu: View -> "jump history"
 +
* With a 5 button Mouse the 2 extra buttons to go forward/backward between the visited points
 +
:using [[IDE_Window:_EditorMouseOptionsAdvanced#Change_History_Jumps_for_3_button_Mouse_.28follow_back_the_.22Source_Link.22_trail.29|advanced mouse options]] the buttons can be remapped.
  
 
==Identifier Completion==
 
==Identifier Completion==
"Identifier Completion" is invoked by Ctrl+Space. It shows all identifiers in scope. For example:
 
  
  procedure TForm1.FormCreate(Sender: TObject);
+
"Identifier Completion" is invoked by {{keypress|Ctrl|space}}. It shows all identifiers in scope. For example:
  begin
+
 
    |
+
<syntaxhighlight lang="pascal">
  end;
+
procedure TForm1.FormCreate(Sender: TObject);
 +
begin
 +
  |
 +
end;
 +
</syntaxhighlight>
  
Place the cursor between ''begin'' and ''end'' and press Ctrl+Space. The IDE/CodeTools will now parse all reachable code and present you a list of all found identifiers. The CodeTools cache the results, so invoking it a second time will be much faster.
+
Place the cursor between ''begin'' and ''end'' and press {{keypress|Ctrl|space}}. The IDE/CodeTools will now parse all reachable code and present you a list of all found identifiers. The CodeTools cache the results, so invoking it a second time will be much faster.
  
'''Note for Delphians:''' Delphi calls it ''Code completion''.
+
{{Note| for Delphians: Delphi calls it ''Code completion''.}}
  
 
Some identifiers like 'Write', 'ReadLn', 'Low', 'SetLength', 'Self', 'Result', 'Copy' are built into the compiler and are not defined anywhere in source. The identifier completion has a lot of these things built in as well. If you find one missing, just create a feature request in the bug tracker.
 
Some identifiers like 'Write', 'ReadLn', 'Low', 'SetLength', 'Self', 'Result', 'Copy' are built into the compiler and are not defined anywhere in source. The identifier completion has a lot of these things built in as well. If you find one missing, just create a feature request in the bug tracker.
  
''Identifier completion'' does not complete all '''keywords'''. So you can not use it to complete 'repe' to 'repeat'. For these things use Ctrl+W [[#Word Completion|Word Completion]] or Ctrl+J [[#Code Templates|Code Templates]]. Since 0.9.27 ''identifier completion'' completes some keywords.
+
''Identifier completion'' does not complete all '''keywords'''. So you can not use it to complete 'repe' to 'repeat'. For these things use {{keypress|Ctrl|W}} [[#Word Completion|Word Completion]] or {{keypress|Ctrl|J}} [[#Code Templates|Code Templates]]. Since 0.9.27 ''identifier completion'' completes some keywords.
  
 
Identifier completion shows even those identifiers, that are not compatible.
 
Identifier completion shows even those identifiers, that are not compatible.
  
===Prefix===
+
===Matching only the first part of a word===
You can start identifier completion in a word. Then the letters to the left will be taken as prefix. For example:
 
  
  procedure TForm1.FormCreate(Sender: TObject);
+
You can invoke identifier completion only on the first few characters in a word. Position the cursor within a word. ''Only characters to the left of the cursor'' will be used to look up identifiers. For example:
  begin
+
 
    Ca|ption
+
<syntaxhighlight lang="pascal">
  end;
+
procedure TForm1.FormCreate(Sender: TObject);
 +
begin
 +
  Ca|ption
 +
end;
 +
</syntaxhighlight>
  
The box will show you only the identifiers beginning with 'Ca'.
+
The box will show you only identifiers beginning with 'Ca' ( | indicates the cursor position).
  
 
===Keys===
 
===Keys===
Line 595: Line 848:
 
When cursor is in a class definition and you identifier complete a method defined in an ancestor class the parameters and the override keyword will be added automatically. For example:
 
When cursor is in a class definition and you identifier complete a method defined in an ancestor class the parameters and the override keyword will be added automatically. For example:
  
<Delphi>
+
<syntaxhighlight lang="pascal">
 
TMainForm = class(TForm)
 
TMainForm = class(TForm)
 
protected
 
protected
 
   mous|
 
   mous|
 
end;
 
end;
</DELPHI>
+
</syntaxhighlight>
  
 
Completing '''MouseDown''' gives:
 
Completing '''MouseDown''' gives:
  
<Delphi>
+
<syntaxhighlight lang="pascal">
 
TMainForm = class(TForm)
 
TMainForm = class(TForm)
 
protected
 
protected
Line 610: Line 863:
 
         Y: Integer); override;
 
         Y: Integer); override;
 
end;
 
end;
</DELPHI>
+
</syntaxhighlight>
  
 
===Properties===
 
===Properties===
  
<Delphi>
+
<syntaxhighlight lang="pascal">
 
property MyInt: integer read |;
 
property MyInt: integer read |;
</DELPHI>
+
</syntaxhighlight>
  
 
Identifier completion will show '''FMyInt''' and '''GetMyInt'''.
 
Identifier completion will show '''FMyInt''' and '''GetMyInt'''.
  
<Delphi>
+
<syntaxhighlight lang="pascal">
 
property MyInt: integer write |;
 
property MyInt: integer write |;
</DELPHI>
+
</syntaxhighlight>
  
 
Identifier completion will show '''FMyInt''' and '''SetMyInt'''.
 
Identifier completion will show '''FMyInt''' and '''SetMyInt'''.
Line 628: Line 881:
 
===Uses section / Unit names===
 
===Uses section / Unit names===
  
In uses sections the identifier completion will show the filenames of all units in the search path. These will show all lowercase (e.g. '''avl_tree'''), because most units have lowercase filenames. On completion it will insert the nice case of the unit (e.g. '''AVL_Tree''').
+
In uses sections the identifier completion will show the filenames of all units in the search path. These will show all lowercase (e.g. ''avl_tree''), because most units have lowercase filenames. On completion it will insert the case of the unit (e.g. ''AVL_Tree'').
  
 
===Statements===
 
===Statements===
  
<DELPHI>
+
<syntaxhighlight lang="pascal">
 
procedure TMainForm.Button1Click(Sender: TObject);
 
procedure TMainForm.Button1Click(Sender: TObject);
 
begin
 
begin
 
   ModalRe|;
 
   ModalRe|;
 
end;
 
end;
</DELPHI>
+
</syntaxhighlight>
  
 
becomes:
 
becomes:
  
<DELPHI>
+
<syntaxhighlight lang="pascal">
 
procedure TMainForm.Button1Click(Sender: TObject);
 
procedure TMainForm.Button1Click(Sender: TObject);
 
begin
 
begin
 
   ModalResult:=|;
 
   ModalResult:=|;
 
end;
 
end;
</DELPHI>
+
</syntaxhighlight>
 +
 
 +
===Icons in completion window===
 +
 
 +
In Lazarus 1.9+, option exists to show icons instead of "types", for lines in the completion window.
 +
Picture shows these icons:
 +
 
 +
[[Image:ide_completion_icons.png]]
  
 
==Word Completion==
 
==Word Completion==
"Word Completion" is invoked by Ctrl+W. It shows all words of all currently open editors and can therefore be used in non pascal sources, in comments and for keywords.
+
 
 +
''Word Completion'' is invoked by {{keypress|Ctrl|W}}. It shows all words of all currently open editors and can therefore be used in non pascal sources, in comments and for keywords.
  
 
Otherwise it works the same as identifier completion.
 
Otherwise it works the same as identifier completion.
 +
 +
==Unit / Identifier Dictionary (Cody)==
 +
 +
This dialog lets you search for identifiers in other units. The units do not yet have to be used by your code.
 +
 +
This feature is part of the package "Cody". To activate the feature install the package.
  
 
==Goto Include Directive==
 
==Goto Include Directive==
 +
 
"Goto Include Directive" in the search menu of the IDE jumps to {$I filename} statement where the current include file is used.
 
"Goto Include Directive" in the search menu of the IDE jumps to {$I filename} statement where the current include file is used.
  
 
==Publish Project==
 
==Publish Project==
 +
 
Creates a copy of the whole project. If you want to send someone just the sources and compiler settings of your code, this function is your friend.
 
Creates a copy of the whole project. If you want to send someone just the sources and compiler settings of your code, this function is your friend.
  
A normal project directory contains a lot of information. Most of it is not needed to be published:
+
A normal project directory contains a lot of information. Most of it is not needed to be published: the .lpi file can contain session information (like caret position and bookmarks of closed units) and the project directory contains a lot of .ppu, .o files and the executable. To create a lpi file with only the base information and only the sources, along with all sub directories use "Publish Project".
The .lpi file contains session information (like caret position and bookmarks of closed units) and the project directory contains a lot of .ppu, .o files and the executable.
+
 
To create a lpi file with only the base information and only the sources, along with all sub directories use "Publish Project".
+
{{Note| Since version 0.9.13 there is a new ''Project Option'' that allows you to store session information in a separate file from the normal .lpi file.  This new file ends with the .lps extension and only contains session information, which will leave your .lpi file much cleaner.}}
 +
 
 +
In the dialog you can setup a filter to include and exclude certain files; with the command after you can compress the output into one archive.
 +
 
 +
==Hints from comments==
 +
 
 +
At several places the IDE shows hints for an identifier. For example when moving the mouse over an identifier in the source editor and waiting a few seconds. When the IDE shows a hint for an identifier it searches the declaration and all its ancestors and looks for comments and fpdoc files. There are many coding styles and many commenting styles. In order to support many of the common comment styles the IDE uses the following heuristics:
 +
 
 +
===Comments shown in the hint===
 +
 
 +
Comments in front of a declaration, without empty line and not starting with the ''<'' sign:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
var
 +
  {Comment}
 +
  Identifier: integer;
 +
</syntaxhighlight>
 +
 
 +
Comments with the ''<'' sign belong to the prior identifier.
 +
 
 +
Comments behind an identifier on the same line:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
var
 +
  identifier, // Comment
 +
  other,
 +
</syntaxhighlight>
 +
 
 +
Comments behind the definition on the same line:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
var
 +
  identifier:
 +
    char; // Comment
 +
</syntaxhighlight>
 +
 
 +
An example for '''<''' sign:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
const
 +
  a = 1;
 +
  //< comment for a
 +
  b = 2;
 +
  // comment for c
 +
  c = 3;
 +
</syntaxhighlight>
 +
 
 +
All three comment types are supported:
 +
<syntaxhighlight lang="pascal">
 +
  {Comment}(*Comment*)//Comment
 +
  c = 1;
 +
</syntaxhighlight>
  
'''Note''': Since version 0.9.13 there is a new ''Project Option'' that allows you to store session information in a seperate file from the normal .lpi file.  This new file ends with the .lps extension and only contains session information, which will leave you .lpi file much cleaner.
+
===Comments not shown in the hint===
  
In the dialog you can setup the exclude and include filter, and with the command after you can compress the output into one archive.
+
Comments starting with '''$''' or '''%''' are ignored. For example ''//% Hiddden'', ''//$ Hidden'', ''(*$ Hidden*)''.
 +
 
 +
Comments in front separated with an empty line are treated as not specific to the following identifier. For example the following class header comment is not shown in the hint:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
type
 +
  { TMyClass }
 +
 
 +
  TMyClass = class
 +
</syntaxhighlight>
 +
 
 +
The class header comments are created on class completion. You can turn this off in the ''Options / Codetools / Class completion / Header comment for class''. If you want to show the header comment in the hint, just remove the empty line.
 +
 
 +
The following comment will be shown for GL_TRUE, but not for GL_FALSE:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
  // Boolean
 +
  GL_TRUE                          = 1;
 +
  GL_FALSE                          = 0;
 +
</syntaxhighlight>
 +
 
 +
==Quick Fixes==
 +
 
 +
Quick Fixes are menu items for specific compiler messages. They help you to quickly fix the problem. Select a message in the ''Messages'' window and right click, or right click in the source editor on the icon to the left.
 +
*Unit not found: remove from uses section
 +
*Unit not found: find unit in loaded packages and allow to auto add package dependency
 +
*Constructing a class "$1" with abstract method "$2": show dialog to override all abstract methods
 +
*Local variable "$1" not used: remove definition
 +
*Circular unit reference between $1 and $2: show Unit Dependencies dialog with full path between the two units
 +
*Identifier not found: search via Code Browser
 +
*Identifier not found: search via Cody Dictionary (needs package [[Cody]])
 +
*Identifier not found: add local variable
 +
*Recompiling $1, checksum changed for $2: show a dialog with search paths and other information
 +
*IDE warning: other sources path of package %s contains directory...: open package
 +
*any hint, note, warning: add IDE directive {%H-}
 +
*any hint, note, warning: add compiler directive {$warn id off} (since 1.7)
 +
*any hint, note, warning: add compiler option -vm<messageid>
 +
*Local variable "i" does not seem to be initialized: insert assignment (since 1.5)
 +
*Inherited method is hidden: add modifier override, overload, or reintroduce (since 1.9)
 +
 
 +
==Outline==
 +
 
 +
This option is located in the IDE Options dialog, Editor - Display - Markup and Matches - Outline (global).
 +
 
 +
It makes highlighting of Pascal keywords together with their begin-end brackets. This allows to see nesting of big blocks.
 +
For example, for such procedure body:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
  with ADockObject do
 +
  begin
 +
    if DropAlign = alNone then
 +
    begin
 +
      if DropOnControl <> nil then
 +
        DropAlign := DropOnControl.GetDockEdge(DropOnControl.ScreenToClient(DragPos))
 +
      else
 +
        DropAlign := Control.GetDockEdge(DragTargetPos);
 +
    end;
 +
    PositionDockRect(Control, DropOnControl, DropAlign, FDockRect);
 +
  end;
 +
</syntaxhighlight>
 +
 
 +
it highlights:
  
==Original contributors==
+
* outer with-do-begin-end in orange
This page has been converted from the epikwiki [http://lazarus-ccr.sourceforge.net/index.php?wiki=LazarusIdeTools version].
+
* next if-then-begin-end in green
* Created page and initial template - 4/6/2004 [[User:Tom Lisjac| VlxAdmin]]
+
* inner if-then-else in cyan
* Initial content posted - 4/10/2004 MattiasG
 
* Small wiki and formatting fixes - 4/11/2004 [[User:Tom Lisjac| VlxAdmin]]
 
* Added a summary table for IdeTools shortcuts - 12 July 2004 [[User:Kirkpatc]]
 
  
----
+
[[Image:ide_outline.png]]
[[Lazarus Database Tutorial]]
 

Latest revision as of 22:20, 13 March 2024

Deutsch (de) English (en) español (es) suomi (fi) français (fr) 日本語 (ja) 한국어 (ko) Nederlands (nl) português (pt) русский (ru) slovenčina (sk) 中文(中国大陆)‎ (zh_CN)

The Lazarus IDE Tools is a library of Free Pascal source parsing and editing tools, called the "codetools".

These tools provide features like Find Declaration, Code Completion, Extraction, Moving Inserting and Beautifying Pascal sources. These functions can save a lot of time and duplicated work. They are customizable, and every feature is available via shortcuts (see Editor Options).

Because they work solely on Pascal sources and understand FPC, Delphi and Kylix code, they do not require compiled units or an installed Borland/Embarcadero compiler. Delphi and FPC code can be edited at the same time, with several Delphi and FPC versions. This makes porting Delphi code to FPC/Lazarus much easier.

Summary Table of IDE shortcuts

Declaration Jumping Ctrl+Click or Alt+ (jump to declaration of type or variable)
Method Jumping Ctrl+ Shift+ (toggle between definition and body)
Code Templates Ctrl+J
Syncro Edit Ctrl+J (while text is selected)
Code Completion (Class Completion) Ctrl+ Shift+C, Ctrl+ Shift+X for creating class fields instead of local variables
Identifier Completion Ctrl+space
Word Completion Ctrl+W
Parameter Hints Ctrl+ Shift+space
Incremental Search Ctrl+E
Rename Identifier Ctrl+ Shift+E

Method Jumping

To jump between a procedure body (begin..end) and the procedure definition (procedure Name;) use Ctrl+ Shift+.

For example:

interface
 
procedure DoSomething; // procedure definition
  
implementation
  
procedure DoSomething; // procedure body 
begin
end;

If the cursor is on the procedure body and Ctrl+ Shift+ is pressed, the cursor will jump to the definition. Pressing Ctrl+ Shift+ again will jump to the body, after 'begin'.

This works between methods (procedures in classes) as well.

Hints: 'Method Jumping' jumps to the same procedure with the same name and parameter list. If there is no exact procedure, it jumps to the best candidate and positions the cursor on the first difference. (For Delphians: Delphi can not do this).

For example a procedure with different parameter types:

interface
 
procedure DoSomething(p: char); // procedure definition
 
implementation
   
procedure DoSomething(p: string); // procedure body
begin
end;

Jumping from the definition to the body will position the cursor at the 'string' keyword. This can be used for renaming methods and/or changing the parameters.

For example:

You renamed 'DoSomething' to 'MakeIt':

interface
 
procedure MakeIt; // procedure definition
 
implementation
 
procedure DoSomething; // procedure body
begin
end;

Then you jump from MakeIt to the body. The IDE searches for a fitting body, does not find one, and hence searches for a candidate. Since you renamed only one procedure there is exactly one body without definition (DoSomething) and so it will jump to DoSomething and position the cursor right on 'DoSomething'. Then you can simply rename it there too. This works for parameters as well.

Include Files

Include files are files inserted into sources with the {$I filename} or {$INCLUDE filename} compiler directive. Lazarus and FPC often uses include files to reduce redundancy and avoid unreadable {$IFDEF} constructs, needed to support different platforms.

Contrary to Delphi, the Lazarus IDE has full support for include files. You can for example jump from the method in the .pas file to the method body in the include file. All codetools like code completion consider include files as special bounds.

For instance: When code completion adds a new method body behind another method body, it keeps them both in the same file. This way you can put whole class implementations in include files, as the LCL does for nearly all controls.

But there is a trap for newbies: If you open an include file for the first time and try method jumping or find declaration you will get an error. The IDE does not yet know to which unit the include file belongs. You must open the unit first.

As soon as the IDE parses the unit, it will parse the include directives there and the IDE will remember this relationship. It saves this information on exit and on project save to ~/.lazarus/includelinks.xml. The next time you open this include file and jump or do a find declaration, the IDE will internally open the unit and the jump will work. You can also hint the IDE by putting {%mainunit yourunit.pas} at the top of yourinclude.inc.

This mechanism has limits. Some include files are included twice or more. For example: lcl/include/winapih.inc.

How you will jump from the procedure/method definitions in this include file to their bodies will depend on your last action. If you worked on lcl/lclintf.pp the IDE will jump to winapi.inc. If you worked on lcl/interfacebase.pp, then it will jump to lcl/include/interfacebase.inc (or one of the other include files). If you are working on both, then you can get confused. ;)

Code Templates

Code Templates converts an identifier into a text or code fragment.

Code Templates default short cut is Ctrl+J. You can type an identifier, press Ctrl+J and the identifier is replaced by the text defined for the identifier. Code Templates can be defined in Tools -> Options -> CodeTools.

Example: Write the identifier 'classf', leave the cursor right behind the 'f' and press Ctrl+J. The 'classf' will be replaced by

T = class(T)
private
 
public
  constructor Create;
  destructor Destroy; override;
end;

and the cursor is behind the 'T'.

You can get the list of templates by positioning the cursor on space (not on an identifier) and pressing Ctrl+J. The list of code templates will pop up. Use the cursor keys or type some chars to choose one. Return creates the selected template and Escape closes the pop up.

The biggest time savers are templates 'b'+Ctrl+J for begin..end.

Parameter Hints

Parameter Hints shows a hint box with the parameter declarations for the current parameter list.

For example: Canvas.FillRect(|);

Place the cursor in the brackets and press Ctrl+ Shift+space. A hint box will show up showing the parameters of FillRect.

Parameterhints1.png

Since 0.9.31 there is a button to the right of each declaration to insert the missing parameters.This will copy the parameter names from the chosen declaration to the cursor position.

Parameterhints2.png

Hint: Use the Variable Declaration Completion to declare the variables.

Light bulb  Note: The short cut's name is "Show code context".

Incremental Search

Incremental Search changes the statusbar of the source editor. Type some characters and the editor will search and highlight immediately all occurrences in the text. Shortcut is Ctrl+e.

  • For example pressing e will search and highlight all occurrences of 'e'.
  • Then pressing t will search and highlight all occurrences of 'et' and so forth.
  • You can jump to the next with F3 (or Ctrl+e while in search) and the previous with Shift+F3.
  • Backspace deletes the last character
  • return stops the search without adding a new line in the editor.
  • You can resume the last search by pressing Ctrl+e a second time, immediately after you started incr-search with Ctrl+e. that is while the search term is still empty.
  • Paste Ctrl+V will append the text from the clipboard to the current search text (since lazarus 0.9.27 r19824).

Hint: Quick searching an identifier with incremental search

  • Place text cursor on identifier (do not select anything)
  • Press Ctrl+C. The source editor will select the identifier and copy it to the clipboard
  • Press Ctrl+E to start incremental search
  • Press Ctrl+V to search for the identifier (since 0.9.27)
  • Use F3 and Shift+F3 to quickly jump to next/previous.
  • Use any key (for example cursor left or right) to end the search

Syncro Edit

Syncro Edit allows you to edit all occurrences of a word at the same time (synchronized). You simple edit the word in one place, and as you type, all other occurrences of the word are updated too.

Syncro Edit works on all words in a selected area:

  • Select a block of text
  • press Ctrl+J or click the icon in the gutter. (This only works, if there are any words that occur more than once in the selection.
    • From Lazarus 4.0 on the following are available:
    • Ctrl+J Words are grouped independent of the upper/lower casing.
    • Ctrl+ Shift+J Words are only grouped if they have the same upper/lower casing.
    • Ctrl+Alt+J Words are only grouped if they have the same context. Identifiers are different from the same word in a comment, or the same word as keyword or string.
    • Ctrl+ Shift+Alt+J Words are only grouped if they have the same context and same upper/lower casing.
  • use the Tab key to select the word you want to edit (if several different words occurred more than once)
  • Edit the word
  • Press Esc to finish

See an animated example here

Light bulb  Note: Ctrl+J is also used for template edit. It switches its meaning if you select some text.

Find next / previous word occurrence

The two functions can be found in the popup menu of the source editor

  • Source editor / popup menu / Find / Find next word occurrence
  • Source editor / popup menu / Find / Find previous word occurrence

And you can assign them shortcuts in the editor options.

Code Completion

Code Completion can be found in the IDE menu Edit -> Complete Code and has as standard short cut Ctrl+ Shift+C.

For Delphians: Delphi calls "code completion" the function showing the list of identifiers at the current source position (Ctrl+Space). Under Lazarus this is called "Identifier completion".

Code Completion combines several powerful functions. Examples:

Which function is used, depends on the cursor position in the editor and will be explained below.

Code Completion can be found in the IDE menu Edit -> Complete Code and has as standard short cut Ctrl+ Shift+C.

Class Completion

The most powerful code completion feature is "Class Completion". You write a class, add the methods and properties and Code Completion will add the method bodies, the property access methods/variables and the private variables.

For example: Create a class (see Code Templates to save you some type work):

TExample = class(TObject)
public
  constructor Create;
  destructor Destroy; override;
end;

Position the cursor somewhere in the class and press Ctrl+ Shift+C. This will create the method missing bodies and move the cursor to the first created method body, so you can just start writing the class code:

{ TExample }
 
constructor TExample.Create;
begin
  |
end;
 
destructor TExample.Destroy;
begin
  inherited Destroy;
end;
Light bulb  Note: The '|' is the cursor and is not added.
Note-icon.png

Tip: You can jump between a method and its body with Ctrl+ Shift+.

You can see, that the IDE added the 'inherited Destroy' call too. This is done, if there is an 'override' keyword in the class definition.

Now add a method DoSomething:

TExample = class(TObject)
public
  constructor Create;
  procedure DoSomething(i: integer);
  destructor Destroy; override;
end;

Then press Ctrl+ Shift+C and the IDE will add

procedure TExample.DoSomething(i: integer);
begin
  |
end;

You can see, that the new method body is inserted between Create and Destroy, exactly as in the class definition. This way the bodies keep the same logical ordering as you define. You can define the insertion policy in Tools > Options -> Codetools -> Code Creation.

Complete Properties

Add a property AnInteger:

TExample = class(TObject)
public
  constructor Create;
  procedure DoSomething(i: integer);
  destructor Destroy; override;
  property AnInteger: Integer;
end;

Press Ctrl+ Shift+C and you will get:

procedure TExample.SetAnInteger(const AValue: integer);
begin
  |if FAnInteger=AValue then exit;
  FAnInteger:=AValue;
end;

The code completion has added a Write access modifier and added some common code. Jump to the class with Ctrl+ Shift+ to see the new class:

TExample = class(TObject)
private
  FAnInteger: integer;
  procedure SetAnInteger(const AValue: integer);
public
  constructor Create;
  procedure DoSomething(i: integer);
  destructor Destroy; override;
  property AnInteger: integer read FAnInteger write SetAnInteger;
end;

The property was extended by a Read and Write access modifier. The class got the new section 'private' with a Variable 'FAnInteger' and the method 'SetAnInteger'. It is a common Delphi style rule to prepend private variables with an 'F' and the write method with a 'Set'. If you don't like that, you can change this in Tools -> Options > Codetools -> Code Creation.

Creating a read only property:

property PropName: PropType read;

Will be expanded to

property PropName: PropType read FPropName;

Creating a write only property:

property PropName: PropType write;

Will be expanded to

property PropName: PropType write SetPropName;

Creating a read only property with a Read method:

property PropName: PropType read GetPropName;

Will be kept and a GetPropName function will be added:

function GetpropName: PropType;

Creating a property with a stored modifier:

property PropName: PropType stored;

Will be expanded to

property PropName: PropType read FPropName write SetPropName stored PropNameIsStored;

Because stored is used for streaming read and write modifiers are automatically added as well.

Hint: Identifier completion also recognizes incomplete properties and will suggest the default names. For example:

property PropName: PropType read |;

Place the cursor one space behind the 'read' keyword and press Ctrl+Space for the identifier completion. It will present you the variable 'FPropName' and the procedure 'SetPropName'.

Forward Procedure Completion

"Forward Procedure Completion" is part of the Code Completion and adds missing procedure bodies. It is invoked, when the cursor is on a forward defined procedure.

For example: Add a new procedure to the interface section:

procedure DoSomething;

Place the cursor on it and press Ctrl+ Shift+C for code completion. It will create in the implementation section:

procedure DoSomething;
begin
  |
end;

Hint: You can jump between a procedure definition and its body with Ctrl+ Shift+.

The new procedure body will be added in front of the class methods. If there are already some procedures in the interface the IDE tries to keep the ordering. For example:

procedure Proc1;
procedure Proc2; // new proc
procedure Proc3;

If the bodies of Proc1 and Proc3 already exists, then the Proc2 body will be inserted between the bodies of Proc1 and Proc3. This behaviour can be setup in Tools -> Options -> Codetools -> Code Creation.

Multiple procedures:

procedure Proc1_Old; // body exists
procedure Proc2_New; // body does not exist
procedure Proc3_New; //  "
procedure Proc4_New; //  "
procedure Proc5_Old; // body exists

Code Completion will add all 3 procedure bodies (Proc2_New, Proc3_New, Proc4_New).

Why is it called "Forward Procedure Completion"?

Because it does not only work for procedures defined in the interface, but for procedures with the "forward" modifier as well. And because the codetools treats procedures in the interface as having an implicit 'forward' modifier.

Event Assignment Completion

"Event Assignment Completion" is part of the Code Completion and completes a single Event:=| statement. It is invoked, when the cursor is behind an assignment to an event.

For example: In a method, say the FormCreate event, add a line 'OnPaint:=':

procedure TForm1.Form1Create(Sender: TObject);
begin
  OnPaint:=|
end;

The '|' is the cursor and should not be typed. Then press Ctrl+ Shift+C for code completion. The statement will be completed to

OnPaint:=@Form1Paint;

A new method Form1Paint will be added to the TForm1 class. Then class completion is started and you get:

procedure TForm1.Form1Paint(Sender: TObject);
begin
  |
end;

This works just like adding methods in the object inspector.

Light bulb  Note: You must place the cursor just after the ':=' assignment operator. If you place the cursor on the identifier (e.g. OnPaint) code completion will invoke "Local Variable Completion", which fails, because OnPaint is already defined.

Hints:

  • You can choose the default visibility of the new method in Tools / Options / Codetools / Class Completion / Default section of methods (since 1.8)
  • You can define the new method name by yourself. For example: OnPaint:=@ThePaintMethod;.

Since 0.9.31 Lazarus completes procedure parameters. For example

procedure TForm1.FormCreate(Sender: TObject);
var
  List: TList;
begin
  List:=TList.Create;
  List.Sort(@MySortFunction|);
end;

Place the cursor on 'MySortFunction' and press Ctrl+ Shift+C for code completion. You get a new procedure:

function MySortFunction(Item1, Item2: Pointer): Integer;
begin
  |
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  List: TList;
begin
  List:=TList.Create;
  List.Sort(@MySortFunction);
end;

Variable Declaration Completion

"Variable Declaration Completion" is part of the Code Completion and adds a local variable definition for a Identifier:=Term; statement. It is invoked, when the cursor is on the identifier of an assignment or a parameter.

For example:

procedure TForm1.Form1Create(Sender: TObject);
begin
  i:=3;
end;

Place the cursor on the 'i' or just behind it. Then press Ctrl+ Shift+C for code completion and you will get:

procedure TForm1.Form1Create(Sender: TObject);
var
  i: Integer;
begin
  i:=3;
end;

The codetools first checks, if the identifier 'i' is already defined and if not it will add the declaration 'var i: integer;'. The type of the identifier is guessed from the term right to the assignment ':=' operator. Numbers like the 3 defaults to Integer.

Another example:

type
  TWhere = (Behind, Middle, InFront);
 
  procedure TForm1.Form1Create(Sender: TObject);
  var
    a: array[TWhere] of char;
  begin
    for Where:=Low(a) to High(a) do writeln(a[Where]);
  end;

Place the cursor on 'Where' and press Ctrl+ Shift+C for code completion. You get:

  procedure TForm1.Form1Create(Sender: TObject);
  var
    a: array[TWhere] of char;
    Where: TWhere;
  begin
    for Where:=Low(a) to High(a) do writeln(a[Where]);
  end;

Since 0.9.11 Lazarus also completes parameters. For example

  procedure TForm1.FormPaint(Sender: TObject);
  begin
    with Canvas do begin
      Line(x1,y1,x2,y2);
    end;
  end;

Place the cursor on 'x1' and press Ctrl+ Shift+C for code completion. You get:

  procedure TForm1.FormPaint(Sender: TObject);
  var
    x1: integer;
  begin
    with Canvas do begin
      Line(x1,y1,x2,y2);
    end;
  end;

Since 0.9.31 Lazarus completes pointer parameters. For example

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    CreateIconIndirect(@IconInfo);
  end;

Place the cursor on 'IconInfo' and press Ctrl+ Shift+C for code completion. You get:

  procedure TForm1.FormCreate(Sender: TObject);
  var
    IconInfo: TIconInfo;
  begin
    CreateIconIndirect(@IconInfo);
  end;

In all above examples you can use Ctrl+ Shift+X to show a Code Creation dialog where you can set more options.

Procedure Call Completion

Code completion can create a new procedure from a call statement itself.

Assume you just wrote the statement "DoSomething(Width);"

procedure SomeProcedure;
var
  Width: integer;
begin
  Width:=3;
  DoSomething(Width);
end;

Position the cursor over the identifier "DoSomething" and press Ctrl+ Shift+C to get:

procedure DoSomething(aWidth: LongInt);
begin

end;

procedure SomeProcedure;
var
  Width: integer;
begin
  Width:=3;
  DoSomething(Width);
end;

It does not yet create functions nor methods.

Reversed Class Completion

"Reversed Class Completion" is part of the Code Completion and adds a private method declaration for the current method body. It is invoked, when the cursor is in a method body, not yet defined in the class. This feature is available since Lazarus 0.9.21.

For example:

  procedure TForm1.DoSomething(Sender: TObject);
  begin
  end;

The method DoSomething is not yet declared in TForm1. Press Ctrl+ Shift+C and the IDE will add "procedure DoSomething(Sender: TObject);" to the private methods of TForm1.

For Delphians: Class completion works under Lazarus always in one way: From class interface to implementation or backwards/reversed from class implementation to interface. Delphi always invokes both directions. The Delphi way has the disadvantage, that if a typo will easily create a new method stub without noticing.

Comments and Code Completion

Code completion tries to keep comments where they belong. For example:

  FList: TList; // list of TComponent
  FInt: integer;

When inserting a new variable between FList and FInt, the comment is kept in the FList line. Same is true for

  FList: TList; { list of TComponent
    This is a comment over several lines, starting
    in the FList line, so codetools assumes it belongs 
    to the FLIst line and will not break this 
    relationship. Code is inserted behind the comment. }
  FInt: integer;

If the comment starts in the next line, then it will be treated as if it belongs to the code below. For example:

  FList: TList; // list of TComponent
    { This comment belongs to the statement below. 
      New code is inserted above this comment and 
      behind the comment of the FList line. }
  FInt: integer;

Method update

Normally class completion will add all missing method bodies. (Since 0.9.27) But if exactly one method differ between class and bodies then the method body is updated. For example: You have a method DoSomething.

  public
    procedure DoSomething;
  end;

procedure TForm.DoSomething;
begin
end;

Now add a parameter:

  public
    procedure DoSomething(i: integer);
  end;

and invoke Code Completion (Ctrl+ Shift+C). The method body will be updated and the new parameter will be copied:

procedure TForm.DoSomething(i: integer);
begin
end;

Refactoring

Invert Assignments

Abstract
: "Invert Assignments" takes some selected pascal statements and inverts all assignments from this code. This tool is usefull for transforming a "save" code to a "load" one and inverse operation.

Example:

procedure DoSomething;
begin
  AValueStudio:= BValueStudio;
  AValueAppartment :=BValueAppartment;
  AValueHouse:=BValueHouse;
end;

Select the lines with assignments (between begin and end) and do Invert Assignments. All assignments will be inverted and identation will be add automatically. For example:

Result:

procedure DoSomething;
begin
  BValueStudio     := AValueStudio;
  BValueAppartment := AValueAppartment;
  BValueHouse      := AValueHouse;
end;

Enclose Selection

Select some text and invoke it. A dialog will popup where you can select if the selection should be enclosed into try..finally or many other common blocks.

Rename Identifier

Place the cursor on an identifier and invoke it. A dialog will appear, where you can setup the search scope and the new name.

  • It will rename all occurences and only those that actually use this declaration. That means it does not rename declarations with the same name.
  • And it will first check for name conflicts.
  • Limits: It only works on pascal sources, does not yet rename files nor adapt lfm/lrs files nor lazdoc files.

Find Identifier References

Place the cursor on an identifier and invoke it. A dialog will appear, where you can setup the search scope. The IDE will then search for all occurences and only those that actually use this declaration. That means it does not show other declarations with the same name.

Show abstract methods

This feature lists and auto completes virtual, abstracts methods that need to be implemented. Place the cursor on a class declaration and invoke it. If there are missing abstract methods a dialog will appear listing them. Select the methods to implement and the IDE creates the method stubs. Since Lazarus 1.3 it adds missing class interface methods too.

Extract Procedure

See Extract Procedure.

Find Declaration

Position the cursor on an identifier and do 'Find Declaration'. Then it will search the declaration of this identifier, open the file and jump to it. If the cursor is already at a declaration it will jump to the previous declaration with the same name. This allows to find redefinitions and overrides.

Every find declaration sets a Jump Point. That means you jump with find declaration to the declaration and easily jump back with Search -> Jump back.

There are some differences to Delphi: the codetools work on sources following the normal pascal rules, instead of using the compiler output. The compiler returns the final type. The codetools see the sources and all steps in between. For example:

The Visible property is first defined in TControl (controls.pp), then redefined in TCustomForm and finally redefined in TForm. Invoking find declaration on Visible will you first bring to Visible in TForm. Then you can invoke Find Declaration again to jump to Visible in TCustomForm and again to jump to Visible in TControl.

Same is true for types like TColor. For the compiler it is simply a 'longint'. But in the sources it is defined as

TGraphicsColor = -$7FFFFFFF-1..$7FFFFFFF;
TColor = TGraphicsColor;

And the same for forward defined classes: for instance in TControl, there is a private variable

FHostDockSite: TWinControl;

Find declaration on TWinControl jumps to the forward definition

TWinControl = class;

And invoking it again jumps to the real implementation

TWinControl = class(TControl)

This way you can track down every identifier and find every overload.

Hints

  • ump back with Ctrl+H.
  • view/navigate all visited locations via Menu: View -> "jump history"
  • With a 5 button Mouse the 2 extra buttons to go forward/backward between the visited points
using advanced mouse options the buttons can be remapped.

Identifier Completion

"Identifier Completion" is invoked by Ctrl+space. It shows all identifiers in scope. For example:

procedure TForm1.FormCreate(Sender: TObject);
begin
  |
end;

Place the cursor between begin and end and press Ctrl+space. The IDE/CodeTools will now parse all reachable code and present you a list of all found identifiers. The CodeTools cache the results, so invoking it a second time will be much faster.

Light bulb  Note: for Delphians: Delphi calls it Code completion.

Some identifiers like 'Write', 'ReadLn', 'Low', 'SetLength', 'Self', 'Result', 'Copy' are built into the compiler and are not defined anywhere in source. The identifier completion has a lot of these things built in as well. If you find one missing, just create a feature request in the bug tracker.

Identifier completion does not complete all keywords. So you can not use it to complete 'repe' to 'repeat'. For these things use Ctrl+W Word Completion or Ctrl+J Code Templates. Since 0.9.27 identifier completion completes some keywords.

Identifier completion shows even those identifiers, that are not compatible.

Matching only the first part of a word

You can invoke identifier completion only on the first few characters in a word. Position the cursor within a word. Only characters to the left of the cursor will be used to look up identifiers. For example:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Ca|ption
end;

The box will show you only identifiers beginning with 'Ca' ( | indicates the cursor position).

Keys

  • Letter or number: add the character to the source editor and the current prefix. This will update the list.
  • Backspace: remove the last character from source editor and prefix. Updates the list.
  • Return: replace the whole word at cursor with the selected identifier and close the popup window.
  • Shift+Return: as Return, but replaces only the prefix (left part) of the word at the cursor.
  • Up/Down: move selection
  • Escape: close popup without change
  • Tab: completes the prefix to next choice. For example: The current prefix is 'But' and the identifier completion only shows 'Button1' and 'Button1Click'. Then pressing Tab will complete the prefix to 'Button1'.
  • Else: as Return and add the character to the source editor

Methods

When cursor is in a class definition and you identifier complete a method defined in an ancestor class the parameters and the override keyword will be added automatically. For example:

TMainForm = class(TForm)
protected
  mous|
end;

Completing MouseDown gives:

TMainForm = class(TForm)
protected
  procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X,
         Y: Integer); override;
end;

Properties

property MyInt: integer read |;

Identifier completion will show FMyInt and GetMyInt.

property MyInt: integer write |;

Identifier completion will show FMyInt and SetMyInt.

Uses section / Unit names

In uses sections the identifier completion will show the filenames of all units in the search path. These will show all lowercase (e.g. avl_tree), because most units have lowercase filenames. On completion it will insert the case of the unit (e.g. AVL_Tree).

Statements

procedure TMainForm.Button1Click(Sender: TObject);
begin
  ModalRe|;
end;

becomes:

procedure TMainForm.Button1Click(Sender: TObject);
begin
  ModalResult:=|;
end;

Icons in completion window

In Lazarus 1.9+, option exists to show icons instead of "types", for lines in the completion window. Picture shows these icons:

ide completion icons.png

Word Completion

Word Completion is invoked by Ctrl+W. It shows all words of all currently open editors and can therefore be used in non pascal sources, in comments and for keywords.

Otherwise it works the same as identifier completion.

Unit / Identifier Dictionary (Cody)

This dialog lets you search for identifiers in other units. The units do not yet have to be used by your code.

This feature is part of the package "Cody". To activate the feature install the package.

Goto Include Directive

"Goto Include Directive" in the search menu of the IDE jumps to {$I filename} statement where the current include file is used.

Publish Project

Creates a copy of the whole project. If you want to send someone just the sources and compiler settings of your code, this function is your friend.

A normal project directory contains a lot of information. Most of it is not needed to be published: the .lpi file can contain session information (like caret position and bookmarks of closed units) and the project directory contains a lot of .ppu, .o files and the executable. To create a lpi file with only the base information and only the sources, along with all sub directories use "Publish Project".

Light bulb  Note: Since version 0.9.13 there is a new Project Option that allows you to store session information in a separate file from the normal .lpi file. This new file ends with the .lps extension and only contains session information, which will leave your .lpi file much cleaner.

In the dialog you can setup a filter to include and exclude certain files; with the command after you can compress the output into one archive.

Hints from comments

At several places the IDE shows hints for an identifier. For example when moving the mouse over an identifier in the source editor and waiting a few seconds. When the IDE shows a hint for an identifier it searches the declaration and all its ancestors and looks for comments and fpdoc files. There are many coding styles and many commenting styles. In order to support many of the common comment styles the IDE uses the following heuristics:

Comments shown in the hint

Comments in front of a declaration, without empty line and not starting with the < sign:

var
  {Comment}
  Identifier: integer;

Comments with the < sign belong to the prior identifier.

Comments behind an identifier on the same line:

var 
  identifier, // Comment
  other,

Comments behind the definition on the same line:

var
  identifier: 
    char; // Comment

An example for < sign:

const
  a = 1;
  //< comment for a
  b = 2;
  // comment for c
  c = 3;

All three comment types are supported:

  {Comment}(*Comment*)//Comment
  c = 1;

Comments not shown in the hint

Comments starting with $ or % are ignored. For example //% Hiddden, //$ Hidden, (*$ Hidden*).

Comments in front separated with an empty line are treated as not specific to the following identifier. For example the following class header comment is not shown in the hint:

type
  { TMyClass }
  
  TMyClass = class

The class header comments are created on class completion. You can turn this off in the Options / Codetools / Class completion / Header comment for class. If you want to show the header comment in the hint, just remove the empty line.

The following comment will be shown for GL_TRUE, but not for GL_FALSE:

  // Boolean
  GL_TRUE                           = 1;
  GL_FALSE                          = 0;

Quick Fixes

Quick Fixes are menu items for specific compiler messages. They help you to quickly fix the problem. Select a message in the Messages window and right click, or right click in the source editor on the icon to the left.

  • Unit not found: remove from uses section
  • Unit not found: find unit in loaded packages and allow to auto add package dependency
  • Constructing a class "$1" with abstract method "$2": show dialog to override all abstract methods
  • Local variable "$1" not used: remove definition
  • Circular unit reference between $1 and $2: show Unit Dependencies dialog with full path between the two units
  • Identifier not found: search via Code Browser
  • Identifier not found: search via Cody Dictionary (needs package Cody)
  • Identifier not found: add local variable
  • Recompiling $1, checksum changed for $2: show a dialog with search paths and other information
  • IDE warning: other sources path of package %s contains directory...: open package
  • any hint, note, warning: add IDE directive {%H-}
  • any hint, note, warning: add compiler directive {$warn id off} (since 1.7)
  • any hint, note, warning: add compiler option -vm<messageid>
  • Local variable "i" does not seem to be initialized: insert assignment (since 1.5)
  • Inherited method is hidden: add modifier override, overload, or reintroduce (since 1.9)

Outline

This option is located in the IDE Options dialog, Editor - Display - Markup and Matches - Outline (global).

It makes highlighting of Pascal keywords together with their begin-end brackets. This allows to see nesting of big blocks. For example, for such procedure body:

  with ADockObject do
  begin
    if DropAlign = alNone then
    begin
      if DropOnControl <> nil then
        DropAlign := DropOnControl.GetDockEdge(DropOnControl.ScreenToClient(DragPos))
      else
        DropAlign := Control.GetDockEdge(DragTargetPos);
    end;
    PositionDockRect(Control, DropOnControl, DropAlign, FDockRect);
  end;

it highlights:

  • outer with-do-begin-end in orange
  • next if-then-begin-end in green
  • inner if-then-else in cyan

ide outline.png