Difference between revisions of "Fully automatic indentation"
m (Text replace - "delphi>" to "syntaxhighlight>") |
m (Fixed syntax highlighting) |
||
(One intermediate revision by one other user not shown) | |||
Line 12: | Line 12: | ||
For example you have the code: | For example you have the code: | ||
− | < | + | <syntaxhighlight lang=pascal> |
procedure TMainForm.Button1Click(Sender: TObject); | procedure TMainForm.Button1Click(Sender: TObject); | ||
begin | begin | ||
| | | | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
You place the cursor at column 1 and paste the code | You place the cursor at column 1 and paste the code | ||
− | < | + | |
+ | <syntaxhighlight lang=pascal> | ||
if Visible then | if Visible then | ||
begin | begin | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
Note that the code on the clipboard is already indented by 4. | Note that the code on the clipboard is already indented by 4. | ||
Line 30: | Line 31: | ||
The indenter first scans the code, finds out, that the insertion position is in a ''begin..end'' block of a ''procedure''. With the standard options it searches the code in front for other ''procedure begin..end'' blocks. If it does not find the code it searches behind the code, then in all units of the project (or package) and finally in the example code of the options. For instance it finds: | The indenter first scans the code, finds out, that the insertion position is in a ''begin..end'' block of a ''procedure''. With the standard options it searches the code in front for other ''procedure begin..end'' blocks. If it does not find the code it searches behind the code, then in all units of the project (or package) and finally in the example code of the options. For instance it finds: | ||
− | < | + | <syntaxhighlight lang=pascal> |
procedure TMainForm.FormPaint(Sender: TObject); | procedure TMainForm.FormPaint(Sender: TObject); | ||
begin | begin | ||
with Canvas do FillRect(0,0,Width,Height); | with Canvas do FillRect(0,0,Width,Height); | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
The indentation of the first token ''with'' is 2. The indentation of the first token of clipboard code is 4, so the indenter unindents the code by 2, resulting in: | The indentation of the first token ''with'' is 2. The indentation of the first token of clipboard code is 4, so the indenter unindents the code by 2, resulting in: | ||
− | < | + | <syntaxhighlight lang=pascal> |
procedure TMainForm.Button1Click(Sender: TObject); | procedure TMainForm.Button1Click(Sender: TObject); | ||
begin | begin | ||
Line 46: | Line 47: | ||
end;| | end;| | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
The indenter always indents the whole block, not every line. For example pasting | The indenter always indents the whole block, not every line. For example pasting | ||
− | < | + | <syntaxhighlight lang=pascal> |
DoSomething(Param1, | DoSomething(Param1, | ||
Param2); | Param2); | ||
− | </ | + | </syntaxhighlight> |
will keep the indent both lines by the same amount, keeping the two ''Params'' aligned. | will keep the indent both lines by the same amount, keeping the two ''Params'' aligned. | ||
Line 59: | Line 60: | ||
The indenter scans what is inserted. For instance pasting | The indenter scans what is inserted. For instance pasting | ||
− | < | + | <syntaxhighlight lang=pascal> |
end; | end; | ||
− | </ | + | </syntaxhighlight> |
will end the the begin block, resulting in: | will end the the begin block, resulting in: | ||
− | < | + | <syntaxhighlight lang=pascal> |
procedure TMainForm.Button1Click(Sender: TObject); | procedure TMainForm.Button1Click(Sender: TObject); | ||
begin | begin | ||
end;| | end;| | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
=Examples= | =Examples= | ||
Line 76: | Line 77: | ||
Sometimes record and classes are aligned to the keywords instead of start of last line. | Sometimes record and classes are aligned to the keywords instead of start of last line. | ||
− | < | + | <syntaxhighlight lang=pascal> |
type TMyRecord = record | type TMyRecord = record | ||
i: integer; | i: integer; | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
At the moment the indenter supports only amount of spaces, not aligning to keywords or symbols. | At the moment the indenter supports only amount of spaces, not aligning to keywords or symbols. | ||
Line 86: | Line 87: | ||
==begin end== | ==begin end== | ||
− | < | + | <syntaxhighlight lang=pascal> |
procedure Do; | procedure Do; | ||
var | var | ||
Line 96: | Line 97: | ||
end; // unindent before end | end; // unindent before end | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
− | < | + | <syntaxhighlight lang=pascal> |
procedure Do; | procedure Do; | ||
begin | begin | ||
Line 105: | Line 106: | ||
end; // unindent before end | end; // unindent before end | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
− | < | + | <syntaxhighlight lang=pascal> |
procedure Do; | procedure Do; | ||
begin | begin | ||
Line 115: | Line 116: | ||
end; // no unindent before end | end; // no unindent before end | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
− | < | + | <syntaxhighlight lang=pascal> |
procedure Do; | procedure Do; | ||
begin | begin | ||
Line 125: | Line 126: | ||
end; // unindent before end | end; // unindent before end | ||
end; | end; | ||
− | </ | + | </syntaxhighlight> |
==repeat until== | ==repeat until== | ||
Line 131: | Line 132: | ||
I never saw code other than this: | I never saw code other than this: | ||
− | < | + | <syntaxhighlight lang=pascal> |
repeat | repeat | ||
Code; // indent after repeat | Code; // indent after repeat | ||
until ; // unindent before until | until ; // unindent before until | ||
− | </ | + | </syntaxhighlight> |
==try finally== | ==try finally== | ||
Line 141: | Line 142: | ||
I never saw code other than this: | I never saw code other than this: | ||
− | < | + | <syntaxhighlight lang=pascal> |
try | try | ||
Code; // indent after try | Code; // indent after try | ||
Line 147: | Line 148: | ||
on e do ; // indent after finally | on e do ; // indent after finally | ||
end; // unindent before finally-end | end; // unindent before finally-end | ||
− | </ | + | </syntaxhighlight> |
==case of end== | ==case of end== | ||
− | < | + | <syntaxhighlight lang=pascal> |
case expr of | case expr of | ||
1: ; // no indent after case-of | 1: ; // no indent after case-of | ||
Line 163: | Line 164: | ||
Code; // indent after case-else | Code; // indent after case-else | ||
end; // unindent after case-else statements | end; // unindent after case-else statements | ||
− | </ | + | </syntaxhighlight> |
− | < | + | <syntaxhighlight lang=pascal> |
case expr of | case expr of | ||
Line 175: | Line 176: | ||
else // no indent before case-else | else // no indent before case-else | ||
end; // no indent before case-end | end; // no indent before case-end | ||
− | </ | + | </syntaxhighlight> |
==if then else== | ==if then else== | ||
− | < | + | <syntaxhighlight lang=pascal> |
if expr then | if expr then | ||
Code | Code | ||
Line 186: | Line 187: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | < | + | <syntaxhighlight lang=pascal> |
if expr or | if expr or | ||
expr or | expr or | ||
Line 195: | Line 196: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | < | + | <syntaxhighlight lang=pascal> |
if expr | if expr | ||
or expr | or expr | ||
Line 204: | Line 205: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | < | + | <syntaxhighlight lang=pascal> |
if SrcEdit.SelectionAvailable | if SrcEdit.SelectionAvailable | ||
and SrcEdit.CaretInSelection(CaretPos) | and SrcEdit.CaretInSelection(CaretPos) |
Latest revision as of 06:11, 16 February 2020
Overview
Since 0.9.29 the lazarus source editor has a new algorithm for automatic indentation on pressing Enter or on pasting code from clipboard. This new algorithm works only for pascal and does not use static rules, but parses the sources to imitate the indentation. Most other editors use either a fixed set of rules or a set of options to configure the rules. This is semi automatic indentation. These options are either too simple or too complex. And the other editors only allow one set of rules, so editing sources with different policies is difficult.
Fully automatic indentation tries to guess the rules from the surrounding code. It does that by searching for similar code and copying the indent.
Because it works fully automatic there are only a few options. You can disable it, you can setup the search scope and you can provide an example code: Codetools Options: Indentation. You do not need to learn rules, just write pascal.
How it works
Indent on paste from clipboard
For example you have the code:
procedure TMainForm.Button1Click(Sender: TObject);
begin
|
end;
You place the cursor at column 1 and paste the code
if Visible then
begin
end;
Note that the code on the clipboard is already indented by 4.
The indenter first scans the code, finds out, that the insertion position is in a begin..end block of a procedure. With the standard options it searches the code in front for other procedure begin..end blocks. If it does not find the code it searches behind the code, then in all units of the project (or package) and finally in the example code of the options. For instance it finds:
procedure TMainForm.FormPaint(Sender: TObject);
begin
with Canvas do FillRect(0,0,Width,Height);
end;
The indentation of the first token with is 2. The indentation of the first token of clipboard code is 4, so the indenter unindents the code by 2, resulting in:
procedure TMainForm.Button1Click(Sender: TObject);
begin
if Visible then
begin
end;|
end;
The indenter always indents the whole block, not every line. For example pasting
DoSomething(Param1,
Param2);
will keep the indent both lines by the same amount, keeping the two Params aligned.
The indenter scans what is inserted. For instance pasting
end;
will end the the begin block, resulting in:
procedure TMainForm.Button1Click(Sender: TObject);
begin
end;|
end;
Examples
Sometimes record and classes are aligned to the keywords instead of start of last line.
type TMyRecord = record
i: integer;
end;
At the moment the indenter supports only amount of spaces, not aligning to keywords or symbols.
begin end
procedure Do;
var
i: integer; // indent after var
begin // no indent after procedure, no indent before procedure-begin, unindent after var section
if expr then
begin // no indent after then, no indent before then-begin
Code; // indent after begin
end; // unindent before end
end;
procedure Do;
begin
if expr then begin
Code; // indent after begin
end; // unindent before end
end;
procedure Do;
begin
if expr then
begin // indent after then and unindent after then-statement
Code; // no indent after begin
end; // no unindent before end
end;
procedure Do;
begin
if expr then
begin // indent after then and unindent after then-statement
Code; // indent after begin
end; // unindent before end
end;
repeat until
I never saw code other than this:
repeat
Code; // indent after repeat
until ; // unindent before until
try finally
I never saw code other than this:
try
Code; // indent after try
finally // unindent before finally
on e do ; // indent after finally
end; // unindent before finally-end
case of end
case expr of
1: ; // no indent after case-of
2:
Code; // indent after case-colon
3:
begin // indent after case-colon
Code; // indent after case-colon-begin
end; // unindent before case-colon-end, unindent after case-colon-end
else // no indent case-else
Code; // indent after case-else
end; // unindent after case-else statements
case expr of
1: ; // indent after case-of
2:
begin // no indent after case-colon
end;
else // no indent before case-else
end; // no indent before case-end
if then else
if expr then
Code
else
Code;
if expr or
expr or
expr then
Code
else
Code;
if expr
or expr
then
Code
else
Code;
if SrcEdit.SelectionAvailable
and SrcEdit.CaretInSelection(CaretPos)
then Expression := SrcEdit.GetText(True)
else Expression := Identifier;
if not DebugBoss.Evaluate(Expression, DebugEval)
or (DebugEval = '')
then DebugEval := '???';