Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2009-11

Auto indentation

77 messages · 12 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mattias Gärtner

The IDE now has a smarter auto indentation algorithm when pressing return or when pasting code.

Features:

* Easy configuration: You don't need to setup long lists of options, because this indenter looks at the surrounding code and mimics the indentation. You can simply provide example code or adapt the standard example code. For example when pressing return after a 'try' the indenter will search for another 'try..finally' block and copy the indentation.
Environment / Options ... / Codetools / General / Indentation

* Context sensitive: When working on several projects with different indentation rules you don't need to switch the rule set. In fact you don't even need to setup rule sets. The indenter starts searching in the current unit. If this is a project unit it will search all other project units. If this is a package unit it will search all other package units. Finally it searches in your example file.

* If you don't like other people styles, and always want to your indentation you can turn the context sensitivity off. Then it will only search in your example.

* When pasting code the indenter will indent the whole block - every line by the same amount.

Mattias

Reply by email

Paul Ishenin
to Mattias Gärtner
Mattias G?rtner wrote
* If you don't like other people styles, and always want to your indentation you can turn the context sensitivity off. Then it will only search in your example.

choosed this option to test

* When pasting code the indenter will indent the whole block - every line by the same amount.

and pasted the next code to check how indentation works:

[code]
try
Button1Click(sender)
finally
end;
[/code]

as result I have the next code in the IDE:

[code]
procedure TForm1.Button1Click(Sender: TObject);
begin
try
  Button1Click(sender)
  finally
end;
end;
[/code]

Unexpected result :)

Best regards,
Paul Ishenin.

Reply by email

Paul Ishenin
to Paul Ishenin: choosed this option to test and pasted the next code to check how indentation works:…
Paul Ishenin wrote 8 lines
Mattias G?rtner wrote: > * If you don't like other people styles, and always want to your > indentation you can turn the context sensitivity off. Then it will > only search in your example. choosed this option to test > * When pasting code the indenter will indent the whole block - every > line by the same amount. and pasted the next code to check how indentation works:

More examples:

the code in the buffer is:
[code]
for i := 0 to 10 do
if i = j then begin
  j := i;
end;
[/code]
procedure TForm1.Button1Click(Sender: TObject);
begin
|
end;
pasting at the cursor (|) result:
[code]
procedure TForm1.Button1Click(Sender: TObject);
begin
for i := 0 to 10 do
  if i = j then begin
    j := i;
end;
end;
[/code]
procedure TForm1.Button1Click(Sender: TObject);
begin
  |
end;
pasting at the cursor (|) result:
[code]
procedure TForm1.Button1Click(Sender: TObject);
begin
  for i := 0 to 10 do
  if i = j then begin
    j := i;
end;
end;
[/code]

Best regards,
Paul Ishenin.

Reply by email

Mattias Gärtner
to Paul Ishenin: choosed this option to test and pasted the next code to check how indentation works:…

Zitat von Paul Ishenin :

Show quoted text 29 lines
Mattias G?rtner wrote: > * If you don't like other people styles, and always want to your > indentation you can turn the context sensitivity off. Then it will > only search in your example. choosed this option to test > * When pasting code the indenter will indent the whole block - > every line by the same amount. and pasted the next code to check how indentation works: [code] try Button1Click(sender) finally end; [/code] as result I have the next code in the IDE: [code] procedure TForm1.Button1Click(Sender: TObject); begin try Button1Click(sender) finally end; end; [/code] Unexpected result :)

Hmm.
Apparently synedit's line range is unreliable to find out what was inserted or what lines have changed.
I will ask Martin.

Mattias

Reply by email

Michael Van Canneyt
to Mattias Gärtner: Zitat von Michael Van Canneyt : Of course. Mattias
Mattias G?rtner wrote 14 lines
Zitat von Michael Van Canneyt : > > > On Tue, 3 Nov 2009, Mattias G?rtner wrote: > >> The IDE now has a smarter auto indentation algorithm when pressing >> return or when pasting code. >> >> Features: > > Can all this be switched off ? Of course.

Great :-)

I'm sorry to say, but in my experience many of these well-meant automatic features get it wrong more often than right... I still didn't figure out if it is me or the features that are at fault :(

Michael.

Reply by email

Henry Vermaak
to Michael Van Canneyt

2009/11/3 Michael Van Canneyt :

I'm sorry to say, but in my experience many of these well-meant automatic features get it wrong more often than right... I still didn't figure out if it is me or the features that are at fault :(

I also tend to disable these features, since I find it a bit disconcerting if something strange happens while I type, but it's probably just a matter of getting used to it.

Henry

Reply by email

Mattias Gärtner
to Paul Ishenin: More examples: the code in the buffer is: [code] for i := 0 to 10 do if i = j then begin…

Zitat von Paul Ishenin :

Show quoted text 18 lines
Paul Ishenin wrote: > Mattias G?rtner wrote: >> * If you don't like other people styles, and always want to your >> indentation you can turn the context sensitivity off. Then it will >> only search in your example. > choosed this option to test >> * When pasting code the indenter will indent the whole block - >> every line by the same amount. > and pasted the next code to check how indentation works: More examples: the code in the buffer is: [code] for i := 0 to 10 do if i = j then begin j := i; end; [/code]

Just a note:
The indenter indents the pasted block as whole, not every line. This has pros and cons. Maybe eventually an option can be added to indent instead every line. Indenting every line means bad and good indenting will be undone. IMO this is the inferior technique. With the current synedit line ranges only the line-indenting can be implemented.

Mattias

Reply by email

Paul Ishenin
to Mattias Gärtner
Mattias G?rtner wrote 15 lines
> the code in the buffer is: > [code] > for i := 0 to 10 do > if i = j then begin > j := i; > end; > [/code] Just a note: The indenter indents the pasted block as whole, not every line. This has pros and cons. Maybe eventually an option can be added to indent instead every line. Indenting every line means bad and good indenting will be undone. IMO this is the inferior technique. With the current synedit line ranges only the line-indenting can be implemented.

Ok, but in any way the final 'end' in the above example should be indented and also indentation should not be switched off because of the cursor position.

Best regards,
Paul Ishenin.

Reply by email

Mattias Gärtner
to Henry Vermaak: 2009/11/3 Michael Van Canneyt : I also tend to disable these features, since I find it a…

Zitat von Henry Vermaak :

Show quoted text 5 lines
2009/11/3 Michael Van Canneyt : > > I'm sorry to say, but in my experience many of these well-meant automatic > features get it wrong more often than right... I still didn't figure out > if it is me or the features that are at fault :(

I guess you mean the block completion (begin..end). I agree here. For beginners it can be a big help. But if it fails in 10% of the cases it is still annoying. Same in other IDE's for other languages too.

I also tend to disable these features, since I find it a bit disconcerting if something strange happens while I type, but it's probably just a matter of getting used to it.

I worked with auto indenting since a few days and it helps me already. Indent on paste is a big time saver - at least when synedit gives me correct values. I will try to find a solution.

Mattias

Reply by email

Mattias Gärtner
to Paul Ishenin: Ok, but in any way the final 'end' in the above example should be indented and also…

Zitat von Paul Ishenin :

Show quoted text 19 lines
Mattias G?rtner wrote: >> the code in the buffer is: >> [code] >> for i := 0 to 10 do >> if i = j then begin >> j := i; >> end; >> [/code] > > Just a note: > The indenter indents the pasted block as whole, not every line. > This has pros and cons. Maybe eventually an option can be added to > indent instead every line. Indenting every line means bad and good > indenting will be undone. IMO this is the inferior technique. > With the current synedit line ranges only the line-indenting can be > implemented. Ok, but in any way the final 'end' in the above example should be indented and also indentation should not be switched off because of the cursor position.

Synedit adds or subtracts a 1 to the FirstLinePos, LastLinePos depending on various things. For example pasting one whole line or two whole lines gives the same range. And when you replace a line then FirstLinePos includes the line above that was not changed. So the line range is unusable for what I need.

Mattias

Reply by email

Michael Van Canneyt
to Mattias Gärtner: Zitat von Henry Vermaak : I guess you mean the block completion (begin..end). I agree…
Mattias G?rtner wrote 9 lines
Zitat von Henry Vermaak : > 2009/11/3 Michael Van Canneyt : >> >> I'm sorry to say, but in my experience many of these well-meant automatic >> features get it wrong more often than right... I still didn't figure out >> if it is me or the features that are at fault :( I guess you mean the block completion (begin..end).

Exactly.

Show quoted text 11 lines
I agree here. For beginners it can be a big help. But if it fails in 10% of the cases it is still annoying. Same in other IDE's for other languages too. > I also tend to disable these features, since I find it a bit > disconcerting if something strange happens while I type, but it's > probably just a matter of getting used to it. I worked with auto indenting since a few days and it helps me already. Indent on paste is a big time saver - at least when synedit gives me correct values. I will try to find a solution.

Looking forward to a solution, because the indent on paste sounds good.

Michael.

Reply by email

Martin
to Mattias Gärtner: Zitat von Paul Ishenin : Synedit adds or subtracts a 1 to the FirstLinePos, LastLinePos…

Mattias,

have you looked at using
  StartLine := Min(Old:ogCaret.Y, LogCaret.Y);
  EndLine := Max(Old:ogCaret.Y, LogCaret.Y);

That would also have the advantage that an "end" would be unindented correctly. e.g typing

if a > 1 then begin
  b:= 1; // the indenter has added 2 spaces => correct
  end;|

now hit return at "|".
The line with the end in it does not change, so it is not in the range. But it is in the caret range. And it should be unindented

Martin

Mattias G?rtner wrote 27 lines
Zitat von Paul Ishenin : > Mattias G?rtner wrote: >>> the code in the buffer is: >>> [code] >>> for i := 0 to 10 do >>> if i = j then begin >>> j := i; >>> end; >>> [/code] >> >> Just a note: >> The indenter indents the pasted block as whole, not every line. >> This has pros and cons. Maybe eventually an option can be added to >> indent instead every line. Indenting every line means bad and good >> indenting will be undone. IMO this is the inferior technique. >> With the current synedit line ranges only the line-indenting can be >> implemented. > Ok, but in any way the final 'end' in the above example should be > indented and also indentation should not be switched off because of > the cursor position. Synedit adds or subtracts a 1 to the FirstLinePos, LastLinePos depending on various things. For example pasting one whole line or two whole lines gives the same range. And when you replace a line then FirstLinePos includes the line above that was not changed. So the line range is unusable for what I need.

Reply by email

Mattias Gärtner
to Martin

Zitat von Martin :

Show quoted text 5 lines
Mattias, have you looked at using StartLine := Min(Old:ogCaret.Y, LogCaret.Y); EndLine := Max(Old:ogCaret.Y, LogCaret.Y);

Sometimes synedit gives me too many lines, sometimes not enough. I need the real insert range.

Show quoted text 10 lines
That would also have the advantage that an "end" would be unindented correctly. e.g typing if a > 1 then begin b:= 1; // the indenter has added 2 spaces => correct end;| now hit return at "|". The line with the end in it does not change, so it is not in the range. But it is in the caret range. And it should be unindented

Correcting the leaving line is a todo and planned from the beginning. Another one is a better indenting for breaking long expressions/statements. But first I want to find a better solution for the indent on paste.

Mattias

Reply by email

Jürgen Hestermann
to Henry Vermaak: 2009/11/3 Michael Van Canneyt : I also tend to disable these features, since I find it a…
I also tend to disable these features, since I find it a bit disconcerting if something strange happens while I type,

me too

but it's probably just a matter of getting used to it.

If it helps speeding up typing and if it works rock solid and if the user is aware of the mechnism it can be of great help.

What I am missing with indentation is the good old turbo pascal way where TAB moved below the beginning of the next word in the line above. It was very easy to arrange code with this feature, especially if code was copied (partially) and changed afterwards so that it had to be rearranged manually.

Reply by email

Martin
to Mattias Gärtner: Zitat von Martin : Sometimes synedit gives me too many lines, sometimes not enough. I…
Mattias G?rtner wrote 10 lines
Zitat von Martin : > Mattias, > > have you looked at using > StartLine := Min(Old:ogCaret.Y, LogCaret.Y); > EndLine := Max(Old:ogCaret.Y, LogCaret.Y); Sometimes synedit gives me too many lines, sometimes not enough. I need the real insert range.

Even if you use the info from the caret?

Yes, I looked at the FirstLinePos, LastLinePos range => it is wrong sometimes. But the caret seems to be ok for all I have seen.

Also, as I wrote before: FirstLinePos, LastLinePos is not usable for you, because in syncro-mode it will report more lines than you need (and that is by design).

In syncro mode, you can press enter inside a cell, and the cell willbecome multi-line => indenting in this case must be limited to the cell which was active,
-FirstLinePos, LastLinePos will include the range for *all* cells => if you indent every line in that range, the syncro module, will keep copying every change you make accross all cells => total chaos.
- the caret will give you the correct range

Show quoted text 14 lines
> That would also have the advantage that an "end" would be unindented > correctly. e.g typing > > if a > 1 then begin > b:= 1; // the indenter has added 2 spaces => correct > end;| > > now hit return at "|". > The line with the end in it does not change, so it is not in the > range. But it is in the caret range. And it should be unindented Correcting the leaving line is a todo and planned from the beginning.

use the caret-info and it should already happen

Show quoted text 13 lines
Another one is a better indenting for breaking long expressions/statements. But first I want to find a better solution for the indent on paste. Mattias -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Martin
to Jürgen Hestermann: me too If it helps speeding up typing and if it works rock solid and if the user is aware…
J?rgen Hestermann wrote 7 lines
What I am missing with indentation is the good old turbo pascal way where TAB moved below the beginning of the next word in the line above. It was very easy to arrange code with this feature, especially if code was copied (partially) and changed afterwards so that it had to be rearranged manually.

Smart-tabs ? (editor options / general)

They work, but only if you are exactly at the beginning of the first word of the line

Example
  for a:=1 to b.count do
    |foo();

press tab, and you will be below "a", then "to", ...

Martin

Reply by email

Mattias Gaertner
to Martin: Even if you use the info from the caret? Yes, I looked at the FirstLinePos, LastLinePos…
Show quoted text 12 lines
Mattias G?rtner wrote: > Zitat von Martin : > >> Mattias, >> >> have you looked at using >> StartLine := Min(Old:ogCaret.Y, LogCaret.Y); >> EndLine := Max(Old:ogCaret.Y, LogCaret.Y); > > Sometimes synedit gives me too many lines, sometimes not enough. I > need the real insert range. Even if you use the info from the caret?

For example:

inserting one line:
OldCaret=(x=1,y=47) NewCaret=(x=1,y=48) FirstLinePos=47 LastLinePos=48

replacing one line with one line
OldCaret=(x=1,y=48) NewCaret=(x=1,y=48) FirstLinePos=46 LastLinePos=48

replacing one line with one line
OldCaret=(x=1,y=47) NewCaret=(x=1,y=48) FirstLinePos=46 LastLinePos=48

Show quoted text 6 lines
Yes, I looked at the FirstLinePos, LastLinePos range => it is wrong sometimes. But the caret seems to be ok for all I have seen. Also, as I wrote before: FirstLinePos, LastLinePos is not usable for you, because in syncro-mode it will report more lines than you need (and that is by design).

Yes.
How to find out if synedit is in syncro mode?

Show quoted text 7 lines
In syncro mode, you can press enter inside a cell, and the cell willbecome multi-line => indenting in this case must be limited to the cell which was active, -FirstLinePos, LastLinePos will include the range for *all* cells => if you indent every line in that range, the syncro module, will keep copying every change you make accross all cells => total chaos. - the caret will give you the correct range

How?

Mattias

Reply by email

Graeme Geldenhuys
to Mattias Gärtner: The IDE now has a smarter auto indentation algorithm when pressing return or when pasting…
Mattias G?rtner wrote
The IDE now has a smarter auto indentation algorithm when pressing return or when pasting code.

I'll try it tomorrow when I get a Lazarus update. Thanks for the note.

By the way, do you know if it is possible to implement the feature request #9650 in Lazarus IDE yet? At the time of the feature request, SynEdit did not have the capability to set variable length tabstops (tabstops based on varying pixel widths) per line. SynEdit could only set tab stops per complete file and were character based if I remember correctly - every line has the same tab stop points.

http://bugs.freepascal.org/view.php?id=9650

I remember trying out the Java demo editor using Elastic Tabstops and write some Object Pascal code with comments aligned on the right of code etc. Elastic TabStops worked very nicely. And when saved, tabs are removed and spaces inserted - so other developers using a different editor or not using Elastic Tabstops feature will not be hassled.

The following site explain benefits of Elastic Tabstops and bust some myths: http://tibleiz.net/code-browser/elastic-tabstops.html

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Martin
to Mattias Gaertner: On Tue, 03 Nov 2009 17:46:48 +0000 For example: inserting one line: OldCaret=(x=1,y=47)…
Mattias Gaertner wrote 21 lines
On Tue, 03 Nov 2009 17:46:48 +0000 Martin wrote: > Mattias G?rtner wrote: > >> Zitat von Martin >>> have you looked at using >>> StartLine := Min(Old:ogCaret.Y, LogCaret.Y); >>> EndLine := Max(Old:ogCaret.Y, LogCaret.Y); >>> >> Sometimes synedit gives me too many lines, sometimes not enough. I >> need the real insert range. >> > Even if you use the info from the caret? > For example: inserting one line: OldCaret=(x=1,y=47) NewCaret=(x=1,y=48) FirstLinePos=47 LastLinePos=48

You mean inserting a full line using paste? so you have a complet new line 47, and the old line 47 is now 48? But then the info from the caret is correct, with one addition

Text changed between 47/1 and 48/1 Since there is nothing before line 48/1 That means the line has not changed (ending on the next line with pos=1 means that the last modified think is the linefeed)

replacing one line with one line OldCaret=(x=1,y=48) NewCaret=(x=1,y=48) FirstLinePos=46 LastLinePos=48

Good point, if you had a selection before, then the caret is *not* sufficient

But in this situation, even if the line range was correct, this would bring back the problem of detecting how much of line 47 was changed. => it could be that only the last few chars where selected, in this case the insert (according to you) should not re-indent line 47 => or line 47 was fully selected, and should be re-indented

So this case is a good example, even the combination of correct line-range and both carets are not enough. You must additionally take in account the selection that was present before the edit took place. (and you must take in account if the selection is persistent, or will/will-not be overwritten)

Show quoted text 16 lines
replacing one line with one line OldCaret=(x=1,y=47) NewCaret=(x=1,y=48) FirstLinePos=46 LastLinePos=48 > Yes, I looked at the FirstLinePos, LastLinePos range => it is wrong > sometimes. But the caret seems to be ok for all I have seen. > > Also, as I wrote before: FirstLinePos, LastLinePos is not usable for > you, because in syncro-mode it will report more lines than you need > (and that is by design). > Yes. How to find out if synedit is in syncro mode?

Currently not available. The syncroEditModule is created in sourceditor line 2565 => So a reference could be kept. Same would have to be done for TemplateEdits
And then each time any similar module is added, check will need to be added.

There is no central point, Synedit doesn't know. It was one of the important design goals that the syncro module can extend synedit, without synedit having to know about it.
Which is why (even if fixed) the FirstLinePos, LastLinePos range will always include such kind of edits.

Similar, it will be with persistent blocks, the can be moved to a new location, which will edit both places (delete them at the old place / insert them at the new place). Changed lines will be including all of this.

Show quoted text 13 lines
> In syncro mode, you can press enter inside a cell, and the cell > willbecome multi-line => indenting in this case must be limited to > the cell which was active, > -FirstLinePos, LastLinePos will include the range for *all* cells => > if you indent every line in that range, the syncro module, will keep > copying every change you make accross all cells => total chaos. > - the caret will give you the correct range > How?

After the example with the overwriting of a selection. The correct answer is:
The caret and observing the selection (hooking synedit to know what it was before the edit action).

The end of story is, it seems there is no simple way to do this. If I have time I will fix the line-range. But as far as I am concerned it is of little value. Using this (even now) the auto indent will cause big trouble if used during synro or template mode (if someone does paste into a cell)

The combination of monitoring block and caret (and maybe even more) would solve it. (as already noted above => replacing a selected line OR replacing a partly selected line, including the linefeed)

However instead of filling he generic beautifier with more and more IDE specific code, I would suggest to have a subclass of the Beautifier residing in source-editor. Every synedit that is created in the IDE will be assigned the special IDEBeautifier. the ide beautifier can then sort out what happened.
It basically has to know how synedit will react, and calculate the required data.

Martin

Reply by email

Martin
to Graeme Geldenhuys: I'll try it tomorrow when I get a Lazarus update. Thanks for the note. By the way, do you…
Graeme Geldenhuys wrote 19 lines
By the way, do you know if it is possible to implement the feature request #9650 in Lazarus IDE yet? At the time of the feature request, SynEdit did not have the capability to set variable length tabstops (tabstops based on varying pixel widths) per line. SynEdit could only set tab stops per complete file and were character based if I remember correctly - every line has the same tab stop points. http://bugs.freepascal.org/view.php?id=9650 I remember trying out the Java demo editor using Elastic Tabstops and write some Object Pascal code with comments aligned on the right of code etc. Elastic TabStops worked very nicely. And when saved, tabs are removed and spaces inserted - so other developers using a different editor or not using Elastic Tabstops feature will not be hassled. The following site explain benefits of Elastic Tabstops and bust some myths: http://tibleiz.net/code-browser/elastic-tabstops.htm

Yes it is possible, and yes it should be very easy to do so. With one exception: Any form of auto Indent will not work with it yet

The calculation of tabs is done entirely (with the exception of auto indent) in the unit SynEditTextTabExpander

The unit can set the "width" (amount of spaces covered by) each tab individually.

If you subclass it, and then do the calculation inside (and add callbacks to tell synedit, that lines must be repainted), then it should work out of the box

Martin

Reply by email

Martin
to Martin: You mean inserting a full line using paste? so you have a complet new line 47, and the…

BTW: what line rang should be reported if a line was deleted?

Martin wrote 128 lines
Mattias Gaertner wrote: > On Tue, 03 Nov 2009 17:46:48 +0000 > Martin wrote: > >> Mattias G?rtner wrote: >> >>> Zitat von Martin >>>> have you looked at using >>>> StartLine := Min(Old:ogCaret.Y, LogCaret.Y); >>>> EndLine := Max(Old:ogCaret.Y, LogCaret.Y); >>>> >>> Sometimes synedit gives me too many lines, sometimes not enough. I >>> need the real insert range. >>> >> Even if you use the info from the caret? >> > > For example: > inserting one line: > OldCaret=(x=1,y=47) NewCaret=(x=1,y=48) FirstLinePos=47 LastLinePos=48 > You mean inserting a full line using paste? so you have a complet new line 47, and the old line 47 is now 48? But then the info from the caret is correct, with one addition Text changed between 47/1 and 48/1 Since there is nothing before line 48/1 That means the line has not changed (ending on the next line with pos=1 means that the last modified think is the linefeed) > replacing one line with one line > OldCaret=(x=1,y=48) NewCaret=(x=1,y=48) FirstLinePos=46 LastLinePos=48 > Good point, if you had a selection before, then the caret is *not* sufficient But in this situation, even if the line range was correct, this would bring back the problem of detecting how much of line 47 was changed. => it could be that only the last few chars where selected, in this case the insert (according to you) should not re-indent line 47 => or line 47 was fully selected, and should be re-indented So this case is a good example, even the combination of correct line-range and both carets are not enough. You must additionally take in account the selection that was present before the edit took place. (and you must take in account if the selection is persistent, or will/will-not be overwritten) > replacing one line with one line > OldCaret=(x=1,y=47) NewCaret=(x=1,y=48) FirstLinePos=46 LastLinePos=48 > > > >> Yes, I looked at the FirstLinePos, LastLinePos range => it is wrong >> sometimes. But the caret seems to be ok for all I have seen. >> >> Also, as I wrote before: FirstLinePos, LastLinePos is not usable for >> you, because in syncro-mode it will report more lines than you need >> (and that is by design). >> > > Yes. > How to find out if synedit is in syncro mode? > Currently not available. The syncroEditModule is created in sourceditor line 2565 => So a reference could be kept. Same would have to be done for TemplateEdits And then each time any similar module is added, check will need to be added. There is no central point, Synedit doesn't know. It was one of the important design goals that the syncro module can extend synedit, without synedit having to know about it. Which is why (even if fixed) the FirstLinePos, LastLinePos range will always include such kind of edits. Similar, it will be with persistent blocks, the can be moved to a new location, which will edit both places (delete them at the old place / insert them at the new place). Changed lines will be including all of this. > > >> In syncro mode, you can press enter inside a cell, and the cell >> willbecome multi-line => indenting in this case must be limited to >> the cell which was active, >> -FirstLinePos, LastLinePos will include the range for *all* cells => >> if you indent every line in that range, the syncro module, will keep >> copying every change you make accross all cells => total chaos. >> - the caret will give you the correct range >> > > How? > After the example with the overwriting of a selection. The correct answer is: The caret and observing the selection (hooking synedit to know what it was before the edit action). The end of story is, it seems there is no simple way to do this. If I have time I will fix the line-range. But as far as I am concerned it is of little value. Using this (even now) the auto indent will cause big trouble if used during synro or template mode (if someone does paste into a cell) The combination of monitoring block and caret (and maybe even more) would solve it. (as already noted above => replacing a selected line OR replacing a partly selected line, including the linefeed) However instead of filling he generic beautifier with more and more IDE specific code, I would suggest to have a subclass of the Beautifier residing in source-editor. Every synedit that is created in the IDE will be assigned the special IDEBeautifier. the ide beautifier can then sort out what happened. It basically has to know how synedit will react, and calculate the required data. Martin -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Graeme Geldenhuys
to Martin: Yes it is possible, and yes it should be very easy to do so. With one exception: Any form…
Martin wrote
Yes it is possible, and yes it should be very easy to do so. With one exception: Any form of auto Indent will not work with it yet

That is good to know. With Elastic Tabstops, "auto indent" is not really needed. A simple press of the Tab key will automatically indent the correct amount of pixels to align with the block (Cell) above it.

This page explains the "cells" or "code blocks" in a visual form to understand it better.
http://nickgravgaard.com/elastictabstops/

The calculation of tabs is done entirely (with the exception of auto indent) in the unit SynEditTextTabExpander

So where would I start with an elastic tabstops implementation. I remember years ago you (or somebody else) mentioned that the best approach might be some synedit plugin.

The unit can set the "width" (amount of spaces covered by) each tab individually.

Is "width" in characters or in pixels? Currently elastic tabstops work like a word processor where tabstop width is set in pixels.

Just to be clear of how Elastic Tabstops work, here follows a simple explanation.

eg: Using the elastic tabstops plugin for Gnome's gEdit editor, I can set some custom user defined parameters values.

gconftool-2 --type int --set
/apps/gedit-2/plugins/elastictabstops/minimumwidth 10 gconftool-2 --type int --set
/apps/gedit-2/plugins/elastictabstops/paddingwidth 16

This sets the miminum stabstop width to 10 pixels. And paddingwidth to 16 pixels. The later is used for tabs after text, not the first tab on a line. So if I was at the left edge of my editor window and I press the Tab key, I would jump 10 pixels right. That 10 pixel width is only constant for the first tabstop in a line. After that, pressing the Tab key, it will align to the tab cell/block above it.

eg: <t> = Tab key pressed and Char(09) is inserted

begin
<t>i := 0;<t>// line one comment
<t><t>// line 2 comment
end;

Using a minimumwidth and paddingwidth of above. With elastic tabstops the first tab will be 10 pixels from the left. The second tab on that same line with be 10 + 16 pixels (minimumwidth + paddingwidth) away from the text before the "// line one comment" is located.

On line 2, the first Tabstop is again 10 pixels. The second Tabstop will jump a large about so it lines up with the second tabstop of the previous line.

So even though the second line only has two physical Tab characters ($09), the comment will start wherever the previous lines second tabstop is set. This is the "elastic" part of elastic tabstops.

So the current SynEdit used in Lazarus should be able to support this? Sorry if I sound repetitive, but I don't want to start a possible complex implementation, just to find out later that SynEdit doesn't actually support what "elastic tabstops" required from a editor component. :-)

If you subclass it, and then do the calculation inside (and add callbacks to tell synedit, that lines must be repainted), then it should work out of the box

I'll take a closer look at the synedit code in a week or two, when time permits. But from what I remember in my last synedit adventure, the synedit code was quite complex and riddled with IFDEF statements.

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Martin
to Graeme Geldenhuys
Graeme Geldenhuys wrote 9 lines
On 03/11/2009, Martin wrote: > The unit can set the "width" (amount of spaces covered by) each tab > individually. > Is "width" in characters or in pixels? Currently elastic tabstops work like a word processor where tabstop width is set in pixels.

From what I read, setting it in pixel is not a pre-condition. You could same as good set it to "char pos" (like 1 pixel = 1 char-width)

The point it that you extend the behaviour of having "defined/fixed tabstops".
And for that it does not even matter if your "defined/fixed tabstop" happens every 4 chars, or at a list of given positions "4, 10, 16, 22, ..."

Elastic tabstop simply mean:
- if the is no line (in the paragraph (above or below)) with equal or more tabstops than the current line, then a normal tab stop is used (next from fixed list)
- if there is another such line, then all tabstop that share the same position will be vertiacal aligned

Or in even other words:
if in any line in a paragraph, the n-th tabstop is pushed behind it's fixed position (due to text in front not fitting otherwise) => then in every other line in the given paragraph the n-th tabstop is pushed to the same vertical location

So it can work basen on char positions. No pixel position needed.

Pixel position could be introduced, by extending
SynEditTextDoubleWidthChars. which defines the width of a char, based as a multiply of the base-char. The base char currently is the width of latin chars => but if you set it to one pixel .... It would have side efects, such as the x positon in the status bar getting too large...

Show quoted text 38 lines
Just to be clear of how Elastic Tabstops work, here follows a simple explanation. eg: Using the elastic tabstops plugin for Gnome's gEdit editor, I can set some custom user defined parameters values. gconftool-2 --type int --set /apps/gedit-2/plugins/elastictabstops/minimumwidth 10 gconftool-2 --type int --set /apps/gedit-2/plugins/elastictabstops/paddingwidth 16 This sets the miminum stabstop width to 10 pixels. And paddingwidth to 16 pixels. The later is used for tabs after text, not the first tab on a line. So if I was at the left edge of my editor window and I press the Tab key, I would jump 10 pixels right. That 10 pixel width is only constant for the first tabstop in a line. After that, pressing the Tab key, it will align to the tab cell/block above it. eg: <t> = Tab key pressed and Char(09) is inserted begin <t>i := 0;<t>// line one comment <t><t>// line 2 comment end; Using a minimumwidth and paddingwidth of above. With elastic tabstops the first tab will be 10 pixels from the left. The second tab on that same line with be 10 + 16 pixels (minimumwidth + paddingwidth) away from the text before the "// line one comment" is located. On line 2, the first Tabstop is again 10 pixels. The second Tabstop will jump a large about so it lines up with the second tabstop of the previous line. So even though the second line only has two physical Tab characters ($09), the comment will start wherever the previous lines second tabstop is set. This is the "elastic" part of elastic tabstops.

Any tab in the first line will have a width given as n-spaces => so any char following a tab, will be within synedits char grid The tabs in the 2nd line therefore can also be converted into n spaces.

If of course text is inserted in the first line, pushing the tab out, then the 2nd line must adapt too. => possible

The amount of spaces for any tab, can be specified in unit SynEditTextTabExpander
function TSynEditStringTabExpander.GetPhysicalCharWidths(const Line: String;

an array, that specifies for every BYTE in the lines text, how many cells it occupies on the screen
multybyte utf8 chars, have there width assigned to their first (or last) byte. and all other bytes set to 0

So all you need to implement is the algorithm that scans the paragraph and finds the widths

2nd thing you have to implement is, that if one line in the paragraph changes, you have to find all other lines n the same paragraph and trigger the notifications to synedit, so they get redrawn too -> if the get redrawnd a call for each line will be made asking for the width of the tabs.

Show quoted text 19 lines
So the current SynEdit used in Lazarus should be able to support this? Sorry if I sound repetitive, but I don't want to start a possible complex implementation, just to find out later that SynEdit doesn't actually support what "elastic tabstops" required from a editor component. :-) > If you subclass it, and then do the calculation inside (and add callbacks > to tell synedit, that lines must be repainted), then it should work out of > the box > I'll take a closer look at the synedit code in a week or two, when time permits. But from what I remember in my last synedit adventure, the synedit code was quite complex and riddled with IFDEF statements.

Reply by email

Martin
to Martin

Further thought about auto indent (for paste) and syncro/template mode.

The only reliable position is the final caret pos (based on that you can do indent on return)

- the line-range will be too big.
- the inital caret position will be unusable. because the if any cell was above the caret pos, then the text will have moved downwards, while the initial caretpos would still be on top

syncro and template edit are created in Sourceeditor around line 2565. They are owned and destroyed by synedit (however synedit only knows they are plugins, and has no idea what they do)

SourceEditor could keep a reference to the syncro and template module.

Both of them have an Active property. If it is true, you should not indent-on-paste

-------
The alternative is to have an "OnBeforePaste" event, and modify the text to be pasted, *before* synedit inserts it
(or keep the to-be-pasted text, and act backwards on the final caret pos)

Martin

Martin wrote 12 lines
Mattias G?rtner wrote: > > Hmm. > Apparently synedit's line range is unreliable to find out what was > inserted or what lines have changed. > I will ask Martin. > It should be better now. I tested for return and various paste events Martin

Reply by email

Hans-Peter Diettrich
to Graeme Geldenhuys: I'll try it tomorrow when I get a Lazarus update. Thanks for the note. By the way, do you…
The following site explain benefits of Elastic Tabstops and bust some myths: http://tibleiz.net/code-browser/elastic-tabstops.html

Source code formatting is a matter of taste. Regardless of the internal storage of horizontal formatting, the result does not please everybody.

I'd appreciate a version control system that separates formatting from content, and thus would track only changes in the content, regardless of whitespace and line breaks. Then everybody could apply his preferred formatting to some shared source code, edit it, and store back only the essential changes. Furthermore the *language* should allow for automatic formatting, and the OPL has certain deficiencies in this area.

If somebody wants to have formatted tables, he'll have to insert formatting *instructions*, so that the layout can be restored later - but where should such instructions be stored? We'll also need an editor that hides the formatting instructions while editing, with all the problems when text is moved (cut&paste) across formatted parts of the text.

DoDi

Reply by email

Graeme Geldenhuys
to Hans-Peter Diettrich

2009/11/4 Hans-Peter Diettrich :

Source code formatting is a matter of taste. Regardless of the internal storage of horizontal formatting, the result does not please everybody.

Yes I know that, but elastic tabstops is so far the best formatting option I could find. And I would definitely us it for my own projects
- if it existed in Lazarus.

Also, as I mentioned, the gEdit plugin that enables elastic tabstops has a option to automatically do conversions. So you can work with elastic tabstops enabled, but when saved, the file gets converted back to using spaces.

Also elastic tabstops touch on a point that most formatting arguments (tabs vs spaces) do not pick up on. Formatting MUST be done by the Editor in a visual only way - same as what editors visually do Code Folding, or drawing Procedure Divider lines. Code Folding markers or Procedure Divider lines are not something in your actual code content. This "eye candy" is applied over your code and *not* in the source code itself.

Same thing should apply to code formatting, which is what Elastic Tabstops does. You press the Tab key, which inserts the char $09 - nothing more! Now the editor does the formatting for you, but doesn't modify the source code contents to do it.

I'd appreciate a version control system that separates formatting from content, and thus would track only changes in the content, regardless of whitespace and line breaks.

Then switch to Git. It has had this option since the beginning of Git (a few years back).

essential changes. Furthermore the *language* should allow for automatic formatting, and the OPL has certain deficiencies in this area.

Rubbish, you just said formatting is a personal thing! Plus the compiler doesn't give a crap what formatting you use, as long as the code syntax is valid. This is exactly how it should work. Formatting is definitely NOT a language feature.

If somebody wants to have formatted tables, he'll have to insert formatting *instructions*, so that the layout can be restored later - but where should such instructions be stored?

This has been done for years in C programming. Have you not noticed the first line in many C source code files, it specifies the tab width in a commented line.

But that is also not ideal, because now you are forcing YOUR formatting onto other people that open that file. Again, Elastic tabstops solves the problem nicely, because you personally define the formatting of a Tab character ($09) in your editor - *without* needing to modify the source code to get formatting correctly.

If you are still confused as to what Elastic Tabstops do, then re-read my earlier post that explains it. Each line in that example only uses two Tab characters, but based on your customizations of elastic tabstop settings, the formatting will be different between users, but still align correctly for everybody. That applies even if you use a variable width font too! So you are no more limited to only coding with monospace type fonts.

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Martin: From what I read, setting it in pixel is not a pre-condition. You could same as good set…

2009/11/4 Martin :

From what I read, setting it in pixel is not a pre-condition. You could same as good set it to "char pos" (like 1 pixel = 1 char-width)

Thinking about it a bit more you are 100% correctly. Character width (count) could also be used in the Elastic Tabstop algorithm.

eg: Using the elastic tabstops customization variables:

* minimumwidth could be set to 3, meaning the with of 3 base characters (exact width is not too important anyway, as long as all left edge tabstops use the same width).

* paddingwidth colud be set to 2, meaning the width of 2 base characters.

Thanks for pointing this out.

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Mattias Gaertner
to Martin: Further thought about auto indent (for paste) and syncro/template mode. The only reliable…
Further thought about auto indent (for paste) and syncro/template mode.

I disabled auto indent during syncro/template editing.

The only reliable position is the final caret pos (based on that you can do indent on return)

I use that now for ecLineBreak.

Show quoted text 20 lines
- the line-range will be too big. - the inital caret position will be unusable. because the if any cell was above the caret pos, then the text will have moved downwards, while the initial caretpos would still be on top syncro and template edit are created in Sourceeditor around line 2565. They are owned and destroyed by synedit (however synedit only knows they are plugins, and has no idea what they do) SourceEditor could keep a reference to the syncro and template module. Both of them have an Active property. If it is true, you should not indent-on-paste ------- The alternative is to have an "OnBeforePaste" event, and modify the text to be pasted, *before* synedit inserts it (or keep the to-be-pasted text, and act backwards on the final caret pos)

I guess this is the better solution for ecPaste.
Can you add such an event?

Mattias

Reply by email

Martin
to Mattias Gaertner
Mattias Gaertner wrote 10 lines
On Wed, 04 Nov 2009 00:27:20 +0000 Martin wrote: > Further thought about auto indent (for paste) and syncro/template > mode. > I disabled auto indent during syncro/template editing.

you need the same for TSynPluginTemplateEdit (template edit, which includes it's own syncro mode)

    TSynPluginTemplateEdit.Create(FEditor);
    FSyncroEdit := TSynPluginSyncroEdit.Create(FEditor);
Show quoted text 28 lines
> - the line-range will be too big. > - the inital caret position will be unusable. because the if any cell > was above the caret pos, then the text will have moved downwards, > while the initial caretpos would still be on top > > > syncro and template edit are created in Sourceeditor around line > 2565. They are owned and destroyed by synedit (however synedit only > knows they are plugins, and has no idea what they do) > > SourceEditor could keep a reference to the syncro and template module. > > Both of them have an Active property. If it is true, you should not > indent-on-paste > > ------- > The alternative is to have an "OnBeforePaste" event, and modify the > text to be pasted, *before* synedit inserts it > (or keep the to-be-pasted text, and act backwards on the final caret > pos) > I guess this is the better solution for ecPaste. Can you add such an event?

Yes, the question is, if it is ok for codetools, since it would be called before the paste => that is you have to interpret the to-be-pasted text before it is part of the source

At the moment you can indent based on the complete source *after* the paste

The alternative is a combination:
- in the OnPaste event you store the text to be pasted (as well as the mode normal, column ....)
- in the OnIndent, you take the final caret pos and you know how far to go back (since the pasted text always ends at the final caret pos)

I'll update you, when I got it done.

Martin

Reply by email

Mattias Gaertner
to Martin
Show quoted text 16 lines
Mattias Gaertner wrote: > On Wed, 04 Nov 2009 00:27:20 +0000 > Martin wrote: > > >> Further thought about auto indent (for paste) and syncro/template >> mode. >> > > I disabled auto indent during syncro/template editing. > you need the same for TSynPluginTemplateEdit (template edit, which includes it's own syncro mode) TSynPluginTemplateEdit.Create(FEditor); FSyncroEdit := TSynPluginSyncroEdit.Create(FEditor);

Please check svn rev 22435.

Show quoted text 8 lines
[...] > I guess this is the better solution for ecPaste. > Can you add such an event? > > Yes, the question is, if it is ok for codetools, since it would be called before the paste => that is you have to interpret the to-be-pasted text before it is part of the source

np

Show quoted text 11 lines
At the moment you can indent based on the complete source *after* the paste The alternative is a combination: - in the OnPaste event you store the text to be pasted (as well as the mode normal, column ....) - in the OnIndent, you take the final caret pos and you know how far to go back (since the pasted text always ends at the final caret pos) I'll update you, when I got it done.

Thanks.

Mattias

Reply by email

Martin
to Mattias Gaertner

I just stumbled on the below

if SrcEdit.EditorComponent.SelectionModesmNormal then exit;

will not prevent the indent if an smColum mode block is inserted.

The mode of the data inserted has nothing to do with the mode of the current block.
And after the insert, there is no block, therefore it can not be checked.

the new event will explicitly report the mode.

The advantage of OnPaste is that it will also be called for quick-paste (middle mouse) which indenter currently is not.

Only thing that will not call anything, is drop-drag-edit (can be addressed later)

Martin

Show quoted text 10 lines
ecPaste: begin if not CodeToolsOpts.IndentOnPaste then exit; if SrcEdit.EditorComponent.SelectionModesmNormal then exit; if LogCaret.X>1 then inc(FirstLinePos); if LogCaret.Y=LastLinePos then dec(LastLinePos); if LastLinePos<FirstLinePos then exit; // not a whole line end

Reply by email

Hans-Peter Diettrich
to Graeme Geldenhuys: 2009/11/4 Hans-Peter Diettrich : Yes I know that, but elastic tabstops is so far the best…
Show quoted text 11 lines
> Source code formatting is a matter of taste. Regardless of the internal > storage of horizontal formatting, the result does not please everybody. Yes I know that, but elastic tabstops is so far the best formatting option I could find. And I would definitely us it for my own projects - if it existed in Lazarus. Also, as I mentioned, the gEdit plugin that enables elastic tabstops has a option to automatically do conversions. So you can work with elastic tabstops enabled, but when saved, the file gets converted back to using spaces.

What will happen when you commit your changes?
Will everybody have to work with your formatting, casted into spaces?

Show quoted text 7 lines
Also elastic tabstops touch on a point that most formatting arguments (tabs vs spaces) do not pick up on. Formatting MUST be done by the Editor in a visual only way - same as what editors visually do Code Folding, or drawing Procedure Divider lines. Code Folding markers or Procedure Divider lines are not something in your actual code content. This "eye candy" is applied over your code and *not* in the source code itself.

That's acceptable, even if I have no use for such eye candy.

Same thing should apply to code formatting, which is what Elastic Tabstops does. You press the Tab key, which inserts the char $09 - nothing more! Now the editor does the formatting for you, but doesn't modify the source code contents to do it.

I'd agree with different tabstop codes, so that the formatting can be undone or suppressed at any time.

Show quoted text 6 lines
> I'd appreciate a version control system that separates formatting from > content, and thus would track only changes in the content, regardless of > whitespace and line breaks. Then switch to Git. It has had this option since the beginning of Git (a few years back).

Maybe you didn't understand my point?

Show quoted text 7 lines
> essential changes. Furthermore the *language* should allow for automatic > formatting, and the OPL has certain deficiencies in this area. Rubbish, you just said formatting is a personal thing! Plus the compiler doesn't give a crap what formatting you use, as long as the code syntax is valid. This is exactly how it should work. Formatting is definitely NOT a language feature.

Automatic formatting has to know about the language, in order to know where to indent and outdent blocks, or how to build columns of other items.

Show quoted text 7 lines
> If somebody wants to have formatted tables, he'll have to insert formatting > *instructions*, so that the layout can be restored later - but where should > such instructions be stored? This has been done for years in C programming. Have you not noticed the first line in many C source code files, it specifies the tab width in a commented line.

I never saw that, but what's the use of such indicators?

Show quoted text 5 lines
But that is also not ideal, because now you are forcing YOUR formatting onto other people that open that file. Again, Elastic tabstops solves the problem nicely, because you personally define the formatting of a Tab character ($09) in your editor - *without* needing to modify the source code to get formatting correctly.

This only applies to tabs at the begin of a line, where formatting also can be done automatically.

If you are still confused as to what Elastic Tabstops do, then re-read my earlier post that explains it.

Sorry, it doesn't explain much. It shows how the output could look like, if everything works.

Each line in that example only uses two Tab characters, but based on your customizations of elastic tabstop settings, the formatting will be different between users, but still align correctly for everybody.

Where "correct" reflects the opinion of the inventor.

That applies even if you use a variable width font too! So you are no more limited to only coding with monospace type fonts.

That's right, from the technical view. Nonetheless the use of proportional fonts is limited in programming, in detail with tables and numbers. At least all (hex) digits should have the same width. With small characters, like 'i', it's hard to position the cursor for insertion or deletion. Moving the cursor through consecutive lines can become a nightmare :-(

DoDi

Reply by email

Martin
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 7 lines
Graeme Geldenhuys schrieb: > Also, as I mentioned, the gEdit plugin that enables elastic tabstops > has a option to automatically do conversions. So you can work with > elastic tabstops enabled, but when saved, the file gets converted back > to using spaces. What will happen when you commit your changes? Will everybody have to work with your formatting, casted into spaces?

If any commit converts tabs to spaces, then elastic tabs do not solve any problem any more or less than any other tab handling does.

In this case the stored text has only spaces. If you check it out again, and wish to edit it, you need an editor, that detects where those spaces should be tabs (magical guessing according to your taste) Such conversion (to spaces / from spaces) can be applied to any form of tabs that you have in your source code

NOTE: The conversion of tabs to spaces can be defined in 2 ways:
1) tabs a converted to an as many spaces as needed, so the look on the pc of the converter does not change
2) tabs and consecutive tabs (as well as consecutive spaces) are converted to a single space nly (except in strings or other white space sensitive areas)

The first solution does not solve anything, as the checked in text still expresses the format of the one writer who converted it. => Format is still part of the content, not applied to a content

The 2nd form will work (exceptions see further down) but requires are really good formater for any one wanting to work with this text

Show quoted text 7 lines
> Same thing should apply to code formatting, which is what Elastic > Tabstops does. You press the Tab key, which inserts the char $09 - > nothing more! Now the editor does the formatting for you, but doesn't > modify the source code contents to do it. I'd agree with different tabstop codes, so that the formatting can be undone or suppressed at any time.

Tab stops in the source (white space insensitive area / outside strings etc) are formating.
They are formatting, because they cause different layout, unless they can be ignored / handled same as spaces

After all Graeme would only need a single (or 2) tab char in the source, in order to align comments at the end of several lines I need maybe between 1 and 10 tab stops per line so my editor shows the comments aligned (using normal tabs)

If all editors are to handle them elastic, then they carry format into the content

>> content, and thus would track only changes in the content, >> regardless of >> whitespace and line breaks.

Line breaks are interesting.

Since some people write:
if a then begin
or:
if a then
begin

the line break itself embeds formatting into the content.

If you want to archive, what you describe (format free content) then all whitespaces (including tabs, newline) must be stored as simple space (except some basic interpreters, which have linebreak as part of the language)

Applying tabs and linebreaks is eye candy, that your editor should apply on top of the content.....

Linebreaks could be used for paragraph like grouping of statements, that represent a logical entity in your code, yet are not presented as a procedure of their own.

---------------------------
I may have shlightly disconnected from reality while writing the above....

Martin

Reply by email

Martin
to Martin: you need the same for TSynPluginTemplateEdit (template edit, which includes it's own…
Martin wrote 19 lines
Mattias Gaertner wrote: > I guess this is the better solution for ecPaste. > Can you add such an event? > Yes, the question is, if it is ok for codetools, since it would be called before the paste => that is you have to interpret the to-be-pasted text before it is part of the source At the moment you can indent based on the complete source *after* the paste The alternative is a combination: - in the OnPaste event you store the text to be pasted (as well as the mode normal, column ....) - in the OnIndent, you take the final caret pos and you know how far to go back (since the pasted text always ends at the final caret pos) I'll update you, when I got it done.

Added. There are now
SynEdit.OnPaste: TSynCopyPasteEvent
SynEdit.OnCutCopy: TSynCopyPasteEvent // you do not need

I still have to do the tests. It doesnt breek anything existing, but I havent checked if the events do 100% as advertised

The event is called immediately before the actual paste happens.

  TSynCopyPasteEvent = procedure(
Sender: TObject;     // the synedit
var AText: String;     // the text, which you can modify, before it will
be pasted
var AMode: TSynSelectionMode;   // smNormal, smColumn....
ALogStartPos: TPoint;   // The position at which it will be inserted ***
var AnAction: TSynCopyPasteAction   // see below
) of object;

TSynCopyPasteAction = (
scaContinue, // do the insert as normal
scaPlainText, // do the insert, but (except for
smColumn,smNormal,smLine) ignore all synedit specifics (such as fold info that came with the paste)
scaAbort // do not insert anything
);

*** ALogStartPos: TPoint;   // The position at which it will be inserted ***
Is the position where the new text will start.

However the event does not include any information, if a block selection exists.
A BlockSelection MAY be deleted before the paste
- if it is not persistent
- if eoOverwriteSelection is set

Reply by email

Graeme Geldenhuys
to Hans-Peter Diettrich: What will happen when you commit your changes? Will everybody have to work with your…
Hans-Peter Diettrich wrote
What will happen when you commit your changes? Will everybody have to work with your formatting, casted into spaces?

With mono fonts it will look at the surrounding text and add enough spaces to keep the aligned text in the same position. Please note that such conversions (tabs to spaces) are user selectable and is only a stop-gap (work-around) for people not using elastic tabstops.

To get the full benefit of elastic tabstops, you would switch your projects to using tabs instead of spaces. I would definitely switch my projects to using tabs instead of spaces. Elastic Tabstop formating would then correct the alignment of text for each developer in my team.

I'd agree with different tabstop codes, so that the formatting can be undone or suppressed at any time.

Code formatting has always been a screw-up, and no idea is a perfect one, that even applies to spaces. I simply think Elastic Tabstops is a point in the right direction and solves more formatting problems that it causes. Compare that to other methods...

As for examples of screwed-up formatting... Just look at Lazarus and FPC code.

We have hundreds of variations as follows:

---------------------

   procedure Myproc;

vs

   procedure Myproc ;

---------------------

   procedure Myproc;
   var
     i: string;
   begin
    ...
vs
   procedure Myproc;
   var
     i: string;
   begin
    ...
---------------------

Or the old favourite...

  if a=b then begin
    ...

vs

  if a = b then
  begin
    ...

---------------------

Automatic formatting has to know about the language, in order to know where to indent and outdent blocks, or how to build columns of other items.

No it as nothing to do with the language... as my Object Pascal examples above shows. Every developer seems to have there own idea of what code formatting looks correct. Even if they all program in the same language.

Show quoted text 10 lines
>> If somebody wants to have formatted tables, he'll have to insert >> formatting *instructions*, so that the layout can be restored >> later - but where should such instructions be stored? > This has been done for years in C programming. Have you not noticed > the first line in many C source code files, it specifies the tab > width in a commented line. I never saw that, but what's the use of such indicators?

The customization lines seen in a C source code using the vim editor... -------------------------
/* vim: set autoindent: */
/* vim: set tabstop=2: */
...
-------------------------

And Mozilla C source code...
--------------------------
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
...
---------------------------

And even some PHP source code
-------------------------------------
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
//
...
-------------------------------------

For millions more examples, use the Google Source Code Search tool. http://www.google.com/codesearch?hl=en

Did you know you can even find Lazarus source code on Google. :-) http://www.google.com/codesearch?hl=en&q=fpgui

This only applies to tabs at the begin of a line, where formatting also can be done automatically.

No, this applies to tabs anywhere in your code.

Show quoted text 5 lines
> If you are still confused as to what Elastic Tabstops do, then > re-read my earlier post that explains it. Sorry, it doesn't explain much. It shows how the output could look like, if everything works.

I can see you don't understand how elastic tabstops work. Neither did I at first. No problem, maybe the original website might explain it better, including the java applet editor which has elastic tabstops support. Also view the gEdit screencast.

http://nickgravgaard.com/elastictabstops/

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Martin: If any commit converts tabs to spaces, then elastic tabs do not solve any problem any…
Martin wrote
If any commit converts tabs to spaces, then elastic tabs do not solve any problem any more or less than any other tab handling does.

Correct. The true benefit of elastic tabstops is when you don't have to do such conversions. Simply switch your source code to only using tab characters for indentation and a Elastic Tabstop enabled editor will do the rest for you - no matter what the users tabwidth preference is set at.

The conversion from Tabs to Spaces when using a elastic tabstops enabled editor is simply as a stop-gap or for backward compatibility with users that don't have elastic tabstops enabled editors.

Personally, I would switch immediately to using tabs instead of spaces. In standard editors like Lazarus IDE, I prefer a default tab width of 3 characters, but I don't use tabs in my code simply because I work on various projects with other developers. A sad compromise - I know.

Maybe later when Jedi Code Formatter works correctly in Lazarus, all source code will look consistent. eg: You write your add-on / patch for Lazarus in your favourite coding style. The just before you generate a patch you press Ctrl+D and the code is formatting as per the Lazarus project standards, then generate the patch. But that wouldn't work in all cases either. :-(

Such conversion (to spaces / from spaces) can be applied to any form of tabs that you have in your source code

No true. Most editors have a single value for a tab to space conversion. eg: 1 Tab character = 4 spaces. Elastic tabstops conversion from tabs to spaces doesn't do that. It's a bit more intelligent. I looks at the surrounding code to see how things are aligned using tabs, then inserts variable amount of spaces so that alignment of the content stays the same after the conversion.

I'm not 100% sure how the conversion from Spaces to Tabs word. But if I had to use Elastic Tabstops, I would switch my projects to using tabs only - so no conversions or guesswork is required.

Plus, have you seen how much smaller source code files become if you user tabs instead of spaces. Also elastic tabstop enabled editors use even less tab characters than normal editors. The size difference is actually quite big (I was even surprised).

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Mattias Gaertner
to Graeme Geldenhuys: With mono fonts it will look at the surrounding text and add enough spaces to keep the…
Show quoted text 19 lines
Hans-Peter Diettrich wrote: [...] > I'd agree with different tabstop codes, so that the formatting can > be undone or suppressed at any time. Code formatting has always been a screw-up, and no idea is a perfect one, that even applies to spaces. I simply think Elastic Tabstops is a point in the right direction and solves more formatting problems that it causes. Compare that to other methods... As for examples of screwed-up formatting... Just look at Lazarus and FPC code. We have hundreds of variations as follows: --------------------- procedure Myproc; vs procedure Myproc ;

What has this to do with elastic tabstops?

Show quoted text 15 lines
--------------------- procedure Myproc; var i: string; begin ... vs procedure Myproc; var i: string; begin ...

Same here ...

Show quoted text 10 lines
--------------------- Or the old favourite... if a=b then begin ... vs if a = b then begin ...

... and here?

BTW,
Elastic tabstops define the position of tabstops, it does not add tabs. That's the job of auto indentation. Both are useful.

Show quoted text 7 lines
[...] I can see you don't understand how elastic tabstops work. Neither did problem, maybe the original website might explain it better, including the java applet editor which has elastic tabstops support. Also view the gEdit screencast. http://nickgravgaard.com/elastictabstops/

Mattias

Reply by email

Alexander Klenin
to Mattias Gaertner
On Thu, 05 Nov 2009 09:08:10 +0200 Graeme Geldenhuys wrote: > As for examples of screwed-up formatting... Just look at Lazarus and > FPC code.

While I agree that Lazarus and FPC code has bad formatting issues...

Mattias Gaertner wrote
What has this to do with elastic tabstops?

... I also think that elastic tabstops will not help with most formatting problems.
In fact, I think using them in Lazarus itself will hurt by introducing yet another
different way of formatting.

Alexander S. Klenin

Reply by email

Graeme Geldenhuys
to Mattias Gaertner: On Thu, 05 Nov 2009 09:08:10 +0200 What has this to do with elastic tabstops? Same here…
Mattias Gaertner wrote
BTW, Elastic tabstops define the position of tabstops, it does not add tabs. That's the job of auto indentation. Both are useful.

Exactly my point. :-)
The code formatting I showed in my previous message was simply to show that various code formatting style are already present is Lazarus and FPC source code. And all developers live with it. So if Elastic Tabstops implementation doesn't do a 100% job on conversion from Tabs to Spaces, it's definitely not the end of the world - because there already exists various code formating rules the Lazarus and FPC code.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Alexander Klenin: While I agree that Lazarus and FPC code has bad formatting issues... On Thu, Nov 5, 2009…
Alexander Klenin wrote
>> As for examples of screwed-up formatting... Just look at Lazarus >> and FPC code. While I agree that Lazarus and FPC code has bad formatting issues...

"screwed-up formatting" was probably a bit of a harsh statement. I meant to say that various code formatting rules already exist in Lazarus and FPC code. Everything seems to go - not to much fuss is made about it.

... I also think that elastic tabstops will not help with most formatting problems. In fact, I think using them in Lazarus itself will hurt by introducing yet another different way of formatting.

That might only apply to Lazarus code, but I don't only use Lazarus IDE to write Lazarus or FPC code. I mostly work on other personal projects, where elastic tabstops (ET from now onwards) and Tab (instead of spaces) would be much prefered by me.

If you want to see how ET will affect Lazarus code, then use gEdit with the ET plugin. Convert a unit from Spaces to Tabs, make a few changes and then let it convert the Tabs back to Spaces when you save. If anything, I think it makes some code a bit neater.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Mattias Gaertner
to Graeme Geldenhuys: Exactly my point. :-) The code formatting I showed in my previous message was simply to…
Show quoted text 7 lines
Mattias Gaertner wrote: > > BTW, > Elastic tabstops define the position of tabstops, it does not add > tabs. That's the job of auto indentation. Both are useful. Exactly my point. :-)

Then please use another subject.

Show quoted text 6 lines
The code formatting I showed in my previous message was simply to show that various code formatting style are already present is Lazarus and FPC source code. And all developers live with it. So if Elastic Tabstops implementation doesn't do a 100% job on conversion from Tabs to Spaces, it's definitely not the end of the world - because there already exists various code formating rules the Lazarus and FPC code.

You don't need to go that far. Even in lazarus exists several different packages and formatting styles. And that is good. Monoculture is bad. But mixing several styles in one unit is confusing.

Mattias

Reply by email

Hans-Peter Diettrich
to Martin: If any commit converts tabs to spaces, then elastic tabs do not solve any problem any…
Show quoted text 8 lines
>> Also, as I mentioned, the gEdit plugin that enables elastic tabstops >> has a option to automatically do conversions. So you can work with >> elastic tabstops enabled, but when saved, the file gets converted back >> to using spaces. > What will happen when you commit your changes? > Will everybody have to work with your formatting, casted into spaces? If any commit converts tabs to spaces, then elastic tabs do not solve any problem any more or less than any other tab handling does.

This is a problem with almost any version control system. When changed whitespace is not considered as a change, then a changed formatting is not transferred into the repository. This makes the formatting non-persistent and doesn't help anybody.
Else every change in formatting is transferred, so that the repository is updated after a user has reformatted the text, and committed some change. This would result in excessive bloat of the repository history, whenever a user commits an change with reformatted text.

That's why I consider any kind of artificial formatting as quite useless, as soon as a VCS comes into the play :-(

If ever, we should have a tool that creates a canonical form of all files, before changes are committed. This tool should be part of the editor, so that the user specified formatting can be applied to every loaded file, and is removed when a file is saved.

Show quoted text 10 lines
Line breaks are interesting. Since some people write: if a then begin or: if a then begin the line break itself embeds formatting into the content.

And that's kind of formatting that I don't like. My formatter would append dangling begins to the end of the preceding part of the statement. This is where the language syntax comes into play:

Pascal:
if a then BEGIN
...
END else BEGIN
...
END
(the requirement for BEGIN-END pairs depends on single/multiple statements in every branch, or on the opinion of the coder)

Modula:
if a then
...
else
...
end;
(no need for optional or required begin-end pairs, the syntax is unambiguous)

Applying tabs and linebreaks is eye candy, that your editor should apply on top of the content.....

and remove it again when a file is saved!

Linebreaks could be used for paragraph like grouping of statements, that represent a logical entity in your code, yet are not presented as a procedure of their own.

That's what I do frequently :-)
I prefer to use outdented comments as section headings, so that these sections can/could be folded automatically. This convention stands in contrast to Elastic Tabs or any other reformatting, that would change the indentation level of such headings. Eventually section headings could be flagged by /// or any acceptable special characters appended to the begin of the comment.

DoDi

Reply by email

Hans-Peter Diettrich
to Graeme Geldenhuys: With mono fonts it will look at the surrounding text and add enough spaces to keep the…
I can see you don't understand how elastic tabstops work.

I only can imagine how they *may* work, but I'm missing a strong definition of the behaviour, that could be discussed and used to provide counter-examples.

While I agree that tab characters should be preferred, instead of sequences of spaces, an agreement about the handling of tabs is required as soon as tabstops shall have a variable distance.

The use of Unicode might cure many formatting problems, when more characters than only spaces and tabs can be used to indicate desired formatting (dedicated characters for paragraphs or columns, non-breaking spaces, soft hyphens, joiners...).

DoDi

Reply by email

Hans-Peter Diettrich
to Graeme Geldenhuys: Correct. The true benefit of elastic tabstops is when you don't have to do such…
Show quoted text 11 lines
Personally, I would switch immediately to using tabs instead of spaces. In standard editors like Lazarus IDE, I prefer a default tab width of 3 characters, but I don't use tabs in my code simply because I work on various projects with other developers. A sad compromise - I know. Maybe later when Jedi Code Formatter works correctly in Lazarus, all source code will look consistent. eg: You write your add-on / patch for Lazarus in your favourite coding style. The just before you generate a patch you press Ctrl+D and the code is formatting as per the Lazarus project standards, then generate the patch. But that wouldn't work in all cases either. :-(

It could work when the Lazarus editor applies the user-defined formatting after a file is loaded (imported), and applies the exchange formatting before a file is stored (exported). All we need is a strong definition of the exchange format, and the ability to install predefined or user-supplied pairs of import/export reformatters.

I'm not 100% sure how the conversion from Spaces to Tabs word.

That's my one and only objection against the use of Elastic Tabstops, so far. The *exact* behaviour should be known, not only the *intended* results. IMO the exact behaviour *must* take the language syntax into account, so that string literals and comments can be handled properly. Remember that the C and Pascal syntax is different for these items!

Show quoted text 8 lines
But if I had to use Elastic Tabstops, I would switch my projects to using tabs only - so no conversions or guesswork is required. Plus, have you seen how much smaller source code files become if you user tabs instead of spaces. Also elastic tabstop enabled editors use even less tab characters than normal editors. The size difference is actually quite big (I was even surprised).

Runtime formatting can require much time and space. And it may fail just when editing such formatted text, garbling whole passages of the text :-(

We may need both raw and vanilla edit modes, so that changes to the formatting can be done in raw mode, with no automatism getting into the way. We also could use different editor panes for both views (on demand), with formatting aids being available for easy adjustments (see the fpdoc editor, HTML editors...).

DoDi

Reply by email

Martin
to Graeme Geldenhuys: Correct. The true benefit of elastic tabstops is when you don't have to do such…
Graeme Geldenhuys wrote 11 lines
Martin wrote: > If any commit converts tabs to spaces, then elastic tabs do not solve > any problem any more or less than any other tab handling does. > Correct. The true benefit of elastic tabstops is when you don't have to do such conversions. Simply switch your source code to only using tab characters for indentation and a Elastic Tabstop enabled editor will do the rest for you - no matter what the users tabwidth preference is set at.

True again, but again elastic tabs do not have a benefit over normal tabs here.

If I save all my indent with tabs in the old way, then I have "procedure", most outer "begin" = 0 Tabs; indent of code on procedure level = 1 tab; indent of first nested begin = 2 Tabs ......
- I can save/store this without conversion (keeping tabs) => anyone can view it never how width their tabs are. They get their preferred indent, but all will align
- Save/Store it as spaces => will work too

Elastic tabs come only as a benefit if you want to use tabs, that are not leading whitespaces, but embedded into the middle of your line (e.g. indent comments to align them at end of line).
But in this case the benefit is not just about storing (beneficial storing is just a side-effect or consequence). In this Case the benefit is, that even while being open within the same editor, if I modify the length of text before a tab in one of the lines, all other lines will follow. (Storing and opening in an other editor, is nothing but modifying the length of text in one line...)

Elastic tabs is only one scenario for this. Same as good you could have:
- leading tabs (before any none-white-space) = every 2 or 4 spaces
- embedded tabs at fixed location (first embedded tab at column 80 for comments)

It is not as flexible (but that's a matter of taste and requirement) => but it does survive storing / other editor too

The conversion from Tabs to Spaces when using a elastic tabstops enabled editor is simply as a stop-gap or for backward compatibility with users that don't have elastic tabstops enabled editors.

If all users are too have elastic tabs, then I could also require that all users have tabs at a width of 4. Same thing, same requirement for all. No benefit in elastic tabs. All users must have the same.

Elastic tabs is nothing else but a specific way to define the width of tabs as "according to formula xyz" instead of a number. But the definition must be followed by all users

Show quoted text 11 lines
> Such conversion (to spaces / from spaces) can be applied to any form of > tabs that you have in your source code > No true. Most editors have a single value for a tab to space conversion. eg: 1 Tab character = 4 spaces. Elastic tabstops conversion from tabs to spaces doesn't do that. It's a bit more intelligent. I looks at the surrounding code to see how things are aligned using tabs, then inserts variable amount of spaces so that alignment of the content stays the same after the conversion.

See above. elastic tabs have a fixed definition too. If a user has a fixed tab width of 4, and you load this later with elastic tabs => it will look screwed. and vice versa.

I am not to deny that elastic tabs have there use, and are good in various situations. But they do not solve interchangeability. One could even say they make interchangeability worse, because now there is one more way.
Previoulsy it was: 1,2,3,4,5,6,7,8 ...
Now it is: elastic, 1,2,3,4,5,6,7,8 ...

If you say, now should be only elastic, I say it can be solved the same way, by saying mow should be only 4. Both is picking on definition at random, but everyone needs to follow the picked definition

Martin

Reply by email

Martin
to Hans-Peter Diettrich: This is a problem with almost any version control system. When changed whitespace is not…
Hans-Peter Diettrich wrote 12 lines
Martin schrieb: > Linebreaks could be used for paragraph like grouping of statements, > that represent a logical entity in your code, yet are not presented > as a procedure of their own. That's what I do frequently :-) I prefer to use outdented comments as section headings, so that these sections can/could be folded automatically. This convention stands in contrast to Elastic Tabs or any other reformatting, that would change the indentation level of such headings. Eventually section headings could be flagged by /// or any acceptable special characters appended to the begin of the comment.

For section heading {%region} {%endregion} is usefull => since it allows folding

Reply by email

Jürgen Hestermann
to Hans-Peter Diettrich: This is a problem with almost any version control system. When changed whitespace is not…
Show quoted text 9 lines
And that's kind of formatting that I don't like. My formatter would append dangling begins to the end of the preceding part of the statement. This is where the language syntax comes into play: Pascal: if a then BEGIN ... END else BEGIN ... END

And that's something *I* don't like. You never know which END belongs to wheach BEGIN. I always column align all ENDs to their corresponding BEGINs. That makes it much easier to check if some of these keywords are missing:

if a then

    begin
    xxxxx
    .....
    yyyyy
    zzzzz
    end;

To me BEGIN and END clamp a logical block (that is indented by 3 characters) so they need to be aligned with all commands of the same level. Each next block of IF, WHILE, REPEAT etc. is indented again by 3 characters. By following this strict rule the code is much more readable to me.

Reply by email

Mattias Gaertner
to Jürgen Hestermann
Show quoted text 28 lines
> And that's kind of formatting that I don't like. My formatter would > append dangling begins to the end of the preceding part of the > statement. This is where the language syntax comes into play: > Pascal: > if a then BEGIN > ... > END else BEGIN > ... > END And that's something *I* don't like. You never know which END belongs to wheach BEGIN. I always column align all ENDs to their corresponding BEGINs. That makes it much easier to check if some of these keywords are missing: if a then begin xxxxx ..... yyyyy zzzzz end; To me BEGIN and END clamp a logical block (that is indented by 3 characters) so they need to be aligned with all commands of the same level. Each next block of IF, WHILE, REPEAT etc. is indented again by 3 characters. By following this strict rule the code is much more readable to me.

I disagree, but the new auto indenter supports this too. And as already said: you don't even need to set an option. It works automatically.
With the new synedit OnPaste event I will try to fix the indent on paste.

Mattias

Reply by email

waldo kitty
to Jürgen Hestermann: And that's something *I* don't like. You never know which END belongs to wheach BEGIN. I…
J?rgen Hestermann wrote 14 lines
> And that's kind of formatting that I don't like. My formatter would > append dangling begins to the end of the preceding part of the > statement. This is where the language syntax comes into play: > Pascal: > if a then BEGIN > ... > END else BEGIN > ... > END And that's something *I* don't like. You never know which END belongs to wheach BEGIN. I always column align all ENDs to their corresponding BEGINs. That makes it much easier to check if some of these keywords are missing:

exactly... you've stated it better than i was going to...

Show quoted text 13 lines
if a then begin xxxxx ..... yyyyy zzzzz end; To me BEGIN and END clamp a logical block (that is indented by 3 characters) so they need to be aligned with all commands of the same level. Each next block of IF, WHILE, REPEAT etc. is indented again by 3 characters. By following this strict rule the code is much more readable to me.

this is the way i was taught way back with Turbo Pascal 2 and 3... except that we were taught 2 spaces indenting for each sub-block... heck, i don't think i've ever touched the TAB key while coding anything except for some perl stuff a while back... for me, the TAB is to move from field to field in a spread sheet or database... that's the way i was taught and have worked for 30+ years...

Reply by email

Hans-Peter Diettrich
to Jürgen Hestermann: And that's something *I* don't like. You never know which END belongs to wheach BEGIN. I…
Show quoted text 13 lines
> And that's kind of formatting that I don't like. My formatter would > append dangling begins to the end of the preceding part of the > statement. This is where the language syntax comes into play: > Pascal: > if a then BEGIN > ... > END else BEGIN > ... > END And that's something *I* don't like. You never know which END belongs to wheach BEGIN. I always column align all ENDs to their corresponding BEGINs.

You missed the second part of my argumentation. I'm thinking in the superior Modula syntax, that does not require begin-end pairs around statement sequences.

DoDi

Reply by email

Hans-Peter Diettrich
to Mattias Gaertner: On Thu, 05 Nov 2009 17:46:25 +0100 I disagree, but the new auto indenter supports this…
With the new synedit OnPaste event I will try to fix the indent on paste.

IMO you should rethink the handling of insertion/deletion. A single Replace(start, delta, text) method can handle every case, with positive deltas meaning insertion and negative deltas meaning deletion or substitution of text. This single method knows about the range of the affected text, as required for the handling of all related attributes (line count, cursor position, syntax highlighting, blocks, folding, formatting, bookmarks...). All related objects should implement the same method for dealing with updates.

DoDi

Reply by email

Hans-Peter Diettrich
to waldo kitty: exactly... you've stated it better than i was going to... this is the way i was taught…
for me, the TAB is to move from field to field in a spread sheet or database... that's the way i was taught and have worked for 30+ years...

You should distinguish between updating text and navigation. Tab *characters* are inserted into the text, while the tab *key* is used to navigate in special document GUIs, with distinct fields. The text in an editor is not organized into fields, so that the tab key here can be used as it was before other GUIs have been invented.

DoDi

Reply by email

Martin
to Hans-Peter Diettrich: Such verbose formatting is unusable, for several reasons: - it is bound to an special…
Hans-Peter Diettrich wrote 11 lines
Martin schrieb: > For section heading {%region} {%endregion} is usefull => since it > allows folding Such verbose formatting is unusable, for several reasons: - it is bound to an special editor - it is imposed on every user - it must be maintained manually - it is pure overhead

So what did you mean, what are your ideas of folding?

There are many possibilities, but most of them will be supported by very few editors, if few ideas I had, but not all worth doing:

- language specific folds (begin/end or open/close tags in xml) => existing for pascal

- temporary folds: not bound to any content. They exist as long as the editor is open, (and would be a poor substitute for having 2 windows of the same content)
They would work, by selecting any amount of lines, and fold them

- folding any paragraph, (defined by at least one empty line in-between

- folding by level of indent

- folding by special comments (as you indicated "///") but that again is very editor specific. it is just a shorter notion of region. It could be configurable by specifing the pattern / and it has the advance of an automatic end at the next section / and they could be leveled ("///", "////", "/////", ...)

The "///" are what you mentioned in your post. But (with the exception maybe of overhead) it has the same properties as region:
- it is bound to an special editor
(or a set of a few special editors)
- it is imposed on every user
(if it is not treated as editor specific directive it is a comment; so is {%region ...} )
- it must be maintained manually
(except for the end of each block is found automatically, sometimes an advantage, sometimes a disadvantage)

Reply by email

Martin
to Hans-Peter Diettrich: IMO you should rethink the handling of insertion/deletion. A single Replace(start, delta,…
Hans-Peter Diettrich wrote 14 lines
Mattias Gaertner schrieb: > With the new synedit OnPaste event I will try to fix the indent on > paste. IMO you should rethink the handling of insertion/deletion. A single Replace(start, delta, text) method can handle every case, with positive deltas meaning insertion and negative deltas meaning deletion or substitution of text. This single method knows about the range of the affected text, as required for the handling of all related attributes (line count, cursor position, syntax highlighting, blocks, folding, formatting, bookmarks...). All related objects should implement the same method for dealing with updates.

Maybe you can elaborate in which context you the above statement should be interpreted?

We are talking here about specifically selected (and selected only) events for which SynEdit is providing an interface for *external* components.
This is the same as a buttons OnClick, or OnFoo event that allows code not known to the component to react to events occurring inside the component.

Inside the IDE OnPaste is going to be used by codetools, but in user apps the programmer is free to use (and of course abuse) this on his/her terms.
Codetools does not need to know every edit/modification of the text. In fact there are many edits/modifications that this part of codetool should not react to.

Clipboard interaction (for an editor component) is a generic event that mat be of interest, in the same way as OnClick is on a button.

-----
Internally SynEdit has a small set of methods through which *all* modifications to text are done.
Agreed one would have been enough. But it is the same distinction has having 2 methods [cut and copy] or one [CutCopy(DeleteSelection:Boolean)].

They do however not move the caret. This would have meant to add special params. After all not every text modification moves the caret. They do provide hooks, that are used by other editor feature to react to the changes.

I am aware that you (IIRC) prefer a micro-controller scenario. But for various features it is IMHO better to use generic hooks. Example: No micro controller is/should be needed to update bookmarks (Except for the controlling element in the bookmark manager). The bookmark manager hooks into synedit, observes any text change, and adjusts all bookmarks.

This is actually a pre-condition for having the same content in multiply editor windows. Each SynEdit (using the same shared TextBuffer) can hook into the textbuffer and adjust to any change that happens.

A single Replace(start, delta, text) method

Can not deal (unless given a specialized argument) with the differentiation between smNormal and smColum. smColumn is very specific to Block-Selection and therefore translated there. the basic text modification only knows contineus/flowing text that can be edited/replaced.

This again makes it a difference to an OnPaste event, which exposes the speciality of smColumn. something that does not exist in other edit actions.

Martin

Reply by email

Hans-Peter Diettrich
to Martin: So what did you mean, what are your ideas of folding? There are many possibilities, but…
Show quoted text 10 lines
>> For section heading {%region} {%endregion} is usefull => since it >> allows folding > > Such verbose formatting is unusable, for several reasons: > - it is bound to an special editor > - it is imposed on every user > - it must be maintained manually > - it is pure overhead > So what did you mean, what are your ideas of folding?

First level folding is based on the language, that suggests syntactical constructs that can be folded.

Second level are logically sequential parts of the text, maybe sequences of statements, methods, declarations etc. Only these areas deserve special marks in the text, and the marks can be bound to very short or otherwise intuitive indicators. Like

  //--- begin of lengthy section ---

or

  //- purpose of the following lines of code

Such comments can also be used for documentation or navigation purposes.

There are many possibilities, but most of them will be supported by very few editors, if do not mean that every section really should be foldable by an editor.

It often is easier to ignore passages of currently uninteresting code, than to really collapse or expand blocks in the display. With the above indicators an editor could fill an treeview, and allow navigation to the section marks from that tree (as an extension or in addition to an code or structure explorer).

A few ideas I had, but not all worth doing:

I have no special ideas about folding, I found it too much work to collapse or expand blocks, and to hide again automatically expanded blocks after navigating e.g. to a declaration.

Show quoted text 5 lines
- folding by special comments (as you indicated "///") but that again is very editor specific. it is just a shorter notion of region. It could be configurable by specifing the pattern / and it has the advance of an automatic end at the next section / and they could be leveled ("///", "////", "/////", ...)

Something like this seems a natural way to give source code a logical and hierarchical structure. As mentioned above, an file index could be created from such markers, allowing for navigation. Inside that tree folding would make sense even to me, because that folding must not be reflected in the displayed source code.

Show quoted text 10 lines
The "///" are what you mentioned in your post. But (with the exception maybe of overhead) it has the same properties as region: - it is bound to an special editor (or a set of a few special editors) - it is imposed on every user (if it is not treated as editor specific directive it is a comment; so is {%region ...} ) - it must be maintained manually (except for the end of each block is found automatically, sometimes an advantage, sometimes a disadvantage)

Maybe I have written too much structured documentation, so that working with similarly structured source code seems natural to me. I also start the implementation of a procedure by inserting comments, indicating the required steps. Then I fill in the code in between these comments. And in the implementation part, I mark sections for logically related procedures, and move auto-created method bodies into these sections, regardless of their naming.

I also do not ask for folding or mapping support in an general purpose editor but - as every better word processor, HTML or other dedicated editor does - my preferred source code editor should support kind of such "structured" handling of the text.

DoDi

Reply by email

Jürgen Hestermann
to Hans-Peter Diettrich: You missed the second part of my argumentation. I'm thinking in the superior Modula…
Show quoted text 6 lines
> And that's something *I* don't like. You never know which END belongs > to wheach BEGIN. I always column align all ENDs to their corresponding > BEGINs. You missed the second part of my argumentation. I'm thinking in the superior Modula syntax, that does not require begin-end pairs around statement sequences.

I am not sure why you mention the Modula syntax. I thought we are talking about Pascal here. And Pascal requires the begin-end pairs (unless it is a single statement). And there is a logic behind it. I always see directly which block is related to the IF (WHILE, REPEAT, ...) statement:

-----------------
if a then
    begin
    xxxxxx;
    yyyyyy;
    ....
    zzzzzz;
    end;
aaaaa;
bbbbb;
ccccc;
-----------------
-----------------
if a then
    xxxxxx;
aaaaa;
bbbbb;
ccccc;
-----------------

And if the statement or block is very short I can put the whole on one line:

-----------------
if a then begin xxxxxx yyyyyy .... zzzzzz end;
aaaaa;
bbbbb;
ccccc;
-----------------
-----------------
if a then xxxxxx;
aaaaa;
bbbbb;
ccccc;
-----------------

I *never* put deeper level commands/blocks on the same column (including BEGIN/END) and I *always* align the BEGIN/ENDs. The BEGIN/ENDs delimit the block and are part of it so IMO they should be treated the same as all other commands of the block and be aligned with them.

Reply by email

Aleksa Todorovic
to Jürgen Hestermann
J?rgen Hestermann wrote
I *never* put deeper level commands/blocks on the same column

Yes, that's one of the worst things one can do.

(including BEGIN/END) and I *always* align the BEGIN/ENDs.

Absolutely necessary, otherwise you get nice spaghetti :-)

The BEGIN/ENDs delimit the block and are part of it so IMO they should be treated the same as all other commands of the block and be aligned with them.

On the other hand, I think of BEGIN/END as other commands are INSIDE begin/end block, so I align begin/end with previous if/while/for/procedure/function, and indent commands inside the block.

As of one-lines like:

if (a > b) then a := b;

I NEVER use them. They could take up less space, but it is very easy to overlook them when you read lot of code. Moreover, having inner command on the new line adds up to the consistency of your code.

Reply by email

Hans-Peter Diettrich
to Martin: Maybe you can elaborate in which context you the above statement should be interpreted?…
Show quoted text 18 lines
>> With the new synedit OnPaste event I will try to fix the indent on >> paste. > > IMO you should rethink the handling of insertion/deletion. A single > Replace(start, delta, text) method can handle every case, with > positive deltas meaning insertion and negative deltas meaning deletion > or substitution of text. This single method knows about the range of > the affected text, as required for the handling of all related > attributes (line count, cursor position, syntax highlighting, blocks, > folding, formatting, bookmarks...). All related objects should > implement the same method for dealing with updates. > Maybe you can elaborate in which context you the above statement should be interpreted? We are talking here about specifically selected (and selected only) events for which SynEdit is providing an interface for *external* components.

And that interface IMO already is too bloated. What does any plug-in have to know about changes, other than the range affected?

This is the same as a buttons OnClick, or OnFoo event that allows code not known to the component to react to events occurring inside the component.

In contrast to other components, changes to an text have only one single effect - parts of the text are changed. It's unimportant what caused that change (keyboard, clipboard, file load...).

Show quoted text 6 lines
Inside the IDE OnPaste is going to be used by codetools, but in user apps the programmer is free to use (and of course abuse) this on his/her terms. Codetools does not need to know every edit/modification of the text. In fact there are many edits/modifications that this part of codetool should not react to.

It's up to every single tool to determine the impact of every modification.

Clipboard interaction (for an editor component) is a generic event that mat be of interest, in the same way as OnClick is on a button.

I see no need for special handling.

Internally SynEdit has a small set of methods through which *all* modifications to text are done.

Good.

Agreed one would have been enough. But it is the same distinction has having 2 methods [cut and copy] or one [CutCopy(DeleteSelection:Boolean)].

That's a very different situation. Only Cut affects the text, no tool needs to know about a Copy.

They do however not move the caret. This would have meant to add special params.

The affected range is sufficient for the caret positioning management.

After all not every text modification moves the caret.

Right, when the caret is outside the modified range :-)

They do provide hooks, that are used by other editor feature to react to the changes.

IMO a single hook would be sufficient. What does it make a difference, whether some text is deleted by DelChar, DelBlock, Cut or any other editing procedure?

Show quoted text 6 lines
I am aware that you (IIRC) prefer a micro-controller scenario. But for various features it is IMHO better to use generic hooks. Example: No micro controller is/should be needed to update bookmarks (Except for the controlling element in the bookmark manager). The bookmark manager hooks into synedit, observes any text change, and adjusts all bookmarks.

That's my opinion as well - and it works with a single kind of notification.

This is actually a pre-condition for having the same content in multiply editor windows. Each SynEdit (using the same shared TextBuffer) can hook into the textbuffer and adjust to any change that happens.

ACK.

Show quoted text 10 lines
> A single Replace(start, delta, text) method Can not deal (unless given a specialized argument) with the differentiation between smNormal and smColum. smColumn is very specific to Block-Selection and therefore translated there. the basic text modification only knows contineus/flowing text that can be edited/replaced. This again makes it a difference to an OnPaste event, which exposes the speciality of smColumn. something that does not exist in other edit actions.

Different how far? When a range of text is changed, it doesn't matter when some parts of it happen to stay unchanged. The *entire* range must be parsed again, tabs and bookmarks may need adjustment etc.

DoDi

Reply by email

Hans-Peter Diettrich
to Jürgen Hestermann: I am not sure why you mention the Modula syntax. I thought we are talking about Pascal…
Show quoted text 33 lines
>> And that's something *I* don't like. You never know which END belongs >> to wheach BEGIN. I always column align all ENDs to their >> corresponding BEGINs. > You missed the second part of my argumentation. I'm thinking in the > superior Modula syntax, that does not require begin-end pairs around > statement sequences. I am not sure why you mention the Modula syntax. I thought we are talking about Pascal here. And Pascal requires the begin-end pairs (unless it is a single statement). And there is a logic behind it. I always see directly which block is related to the IF (WHILE, REPEAT, ...) statement: ----------------- if a then begin xxxxxx; yyyyyy; .... zzzzzz; end; aaaaa; bbbbb; ccccc; ----------------- ----------------- if a then xxxxxx; aaaaa; bbbbb; ccccc; -----------------

The indentation allows to identify the block ranges, without any optical special search for BEGIN and END keywords - only the *formatter* must deal with the concrete syntax.

Show quoted text 5 lines
And if the statement or block is very short I can put the whole on one line: ----------------- if a then begin xxxxxx yyyyyy .... zzzzzz end;

That's questionable practice. It's impossible to set an breakpoint into the body of the conditional statement.

I *never* put deeper level commands/blocks on the same column (including BEGIN/END) and I *always* align the BEGIN/ENDs.

I align the *lines*, *containing* BEGIN/ENDs ;-)

The BEGIN/ENDs delimit the block and are part of it so IMO they should be treated the same as all other commands of the block and be aligned with them.

There exist substancially different opinions about the alignment of BEGIN/ENDs - should they align with their parent statement or be indented, and should their content be aligned or indented. As long as the extra-line blockers <g> cannot agree about the one and only acceptable solution, I feel free to ignore that debate and move the block delimiters to the next best place, saving one or more lines in my code with every single block.

DoDi

Reply by email

Graeme Geldenhuys
to Hans-Peter Diettrich: Such verbose formatting is unusable, for several reasons: - it is bound to an special…
Hans-Peter Diettrich wrote 6 lines
Martin schrieb: > For section heading {%region} {%endregion} is usefull => since it allows > folding Such verbose formatting is unusable, for several reasons:

I disagree... If the editor doesn't support it, it is simply two extra comments that will be ignore.

Also for Form Designers like the one in fpGUI Toolkit, where it writes the form layout and design INSIDE the .pas file, the custom folding is very handy, because it hides the code parts that are normally not maintained by users.

The option of folding on {%region} tags is also user selectable, so if you don't like folding, simple don't enable it.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Jürgen Hestermann: And that's something *I* don't like. You never know which END belongs to wheach BEGIN. I…
J?rgen Hestermann wrote
To me BEGIN and END clamp a logical block (that is indented by 3 characters) so they need to be aligned with all commands of the same

And this is exactly where standard Tabs or Elastic Tabstops will help. Tab width are user definable, where Spaces for indentation is not.

Out of interest: I also prefer a 3 character indentation.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Mattias Gärtner
to Graeme Geldenhuys

Zitat von Graeme Geldenhuys :

Show quoted text 6 lines
J?rgen Hestermann wrote: > > To me BEGIN and END clamp a logical block (that is indented by 3 > characters) so they need to be aligned with all commands of the same And this is exactly where standard Tabs or Elastic Tabstops will help.

Huh?

Tab width are user definable, where Spaces for indentation is not. Out of interest: I also prefer a 3 character indentation.

Mattias

Reply by email

Graeme Geldenhuys
to Mattias Gärtner
Mattias G?rtner wrote 5 lines
>> To me BEGIN and END clamp a logical block (that is indented by 3 >> characters) so they need to be aligned with all commands of the same > And this is exactly where standard Tabs or Elastic Tabstops will help. Huh?

What I meant is that is Tab characters where used for indentation instead of Spaces, then the developers preferred indentation will be more likely correct that when Spaces are used.

For example:
Using default Delphi coding style where two spaces are used for indentation. Now everybody sees indentation as two spaces.

If Tabs where used instead, then when I viewed that source code, the indentation would be closer to what I prefer. In my case that would be TabWidth = 3 for indentation. Other users might have there TabWidth = 4 or 8 set, and it will look correct for them as well.

So when Tabs are used, each developer can set there preferred tab width. But using standard tabs, this solution is still not ideal, as my other post titled "Elastic Tabstops: benefits or not" shows. Elastic Tabstops still solves this problem in a better why than standard tabs or spaces, because single tab characters are used more often that multiple tab characters.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Mattias Gärtner
to Graeme Geldenhuys

Zitat von Graeme Geldenhuys :

Show quoted text 14 lines
Mattias G?rtner wrote: >>> To me BEGIN and END clamp a logical block (that is indented by 3 >>> characters) so they need to be aligned with all commands of the same >> And this is exactly where standard Tabs or Elastic Tabstops will help. > > Huh? [...] So when Tabs are used, each developer can set there preferred tab width. But using standard tabs, this solution is still not ideal, as my other post titled "Elastic Tabstops: benefits or not" shows. Elastic Tabstops still solves this problem in a better why than standard tabs or spaces, because single tab characters are used more often that multiple tab characters.

This thread is about 'Auto indentation' - how much space to add *in front of* the first token of each line. Elastic tabstops is about the space *after* the first token. Elastic tabstops is an interesting topic, especially for you, but it is a different topic.

Mattias

Reply by email

Hans-Peter Diettrich
to Graeme Geldenhuys: I disagree... If the editor doesn't support it, it is simply two extra comments that will…
Show quoted text 6 lines
>> For section heading {%region} {%endregion} is usefull => since it allows >> folding > Such verbose formatting is unusable, for several reasons: I disagree... If the editor doesn't support it, it is simply two extra comments that will be ignore.

The eye of the reader doesn't easily ignore such comments :-(

Also for Form Designers like the one in fpGUI Toolkit, where it writes the form layout and design INSIDE the .pas file, the custom folding is very handy, because it hides the code parts that are normally not maintained by users.

This again requires an editor that implements folding, and that hides the marked sections by default. I don't trust such defaults :-(

Also I'd put auto-generated parts into include files, a much simpler and safer separation from the user viewpoint.

DoDi

Reply by email

Jürgen Hestermann
to Aleksa Todorovic: On Fri, Nov 6, 2009 at 07:18, J?rgen Hestermann Yes, that's one of the worst things one…
On the other hand, I think of BEGIN/END as other commands are INSIDE begin/end block, so I align begin/end with previous if/while/for/procedure/function, and indent commands inside the block.

Yes, lots of people think so. But beside the logic (to me the BEGIN/ENDs are part of the block) it is confusing if for some IF/WHILE/REPEAT statements the next line is aligned and for others (without BEGIN/END, just one command) it is not. Also, the IF/WHILE/REPEAT statements stand out much better if the next line is always indented.

As of one-lines like: if (a > b) then a := b; I NEVER use them. They could take up less space, but it is very easy to overlook them when you read lot of code.

Yes, that's true. I only use this in situations where the command is of low importance (i.e., if it does a side thing that is not very related to the major task) and when otherwise the code would be teared too much apart.

Reply by email

Jürgen Hestermann
to Hans-Peter Diettrich: The indentation allows to identify the block ranges, without any optical special search…
Show quoted text 5 lines
> And if the statement or block is very short I can put the whole on one > line: > if a then begin xxxxxx yyyyyy .... zzzzzz end; That's questionable practice. It's impossible to set an breakpoint into the body of the conditional statement.

Yes. I only do this, when the IF statement does a side thing and when it is unlikely that I have to debug it. But your are right, I sometimes have to change this for debugging but I always change it back afterwards.

Reply by email

Hans-Peter Diettrich
to Hans-Peter Diettrich: The eye of the reader doesn't easily ignore such comments :-( This again requires an…
Show quoted text 8 lines
Graeme Geldenhuys schrieb: >>> For section heading {%region} {%endregion} is usefull => since it >>> allows folding >> Such verbose formatting is unusable, for several reasons: > > I disagree... If the editor doesn't support it, it is simply two extra > comments that will be ignore.

I forgot to mention:

Section breaks can be implemented using tabs as well, with VT instead of HT.

There exist more control codes that can be used for various formatting/folding purposes. A closer look at the ASCII table reveals: VT: vertical tab, usable for sections
SI, SO: shift in/out, could be used for folding or regions GS, RS, US: group/record/unit separators, usable for table formatting

DoDi

Reply by email

Graeme Geldenhuys
to Hans-Peter Diettrich: The eye of the reader doesn't easily ignore such comments :-( This again requires an…

2009/11/6 Hans-Peter Diettrich :

This again requires an editor that implements folding, and that hides the marked sections by default. I don't trust such defaults :-(

Most editors have code folding these days. And in this case I am talking about Lazarus specifically, as that is the only code editor I use to write software in.

Also, the 'region' code folding tag allows for comments and if the region needs to be folder by default or not. My Form Designer adds a comment which is what the user seen in the first 'region' tag, saying that the code folder is maintained by the forms designer. No need for guessing what is folded in this case.

Also I'd put auto-generated parts into include files, a much simpler and safer separation from the user viewpoint.

Although include files are very handy and I use them in occasions for other code, I prefer less files lying around - hence the reason the UI code is directly inside the .pas file (unlike Delphi, Lazarus or MSEide).

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

waldo kitty
to Hans-Peter Diettrich: <OT> I just read about another Italian aberreation: ravioli code. It seems to mean…
Hans-Peter Diettrich wrote 12 lines
Aleksa Todorovic schrieb: > Absolutely necessary, otherwise you get nice spaghetti :-) <OT> I just read about another Italian aberreation: ravioli code. It seems to mean separating everything into so many pieces (classes, procedures...), that one can't see the wood for trees any more. </OT>

Now That's Funny!!! ::LOL::

Reply by email