Forum > SynEdit

SynBeautifier: Autoindent and tab settings

(1/2) > >>

Martin_fr:
From https://bugs.freepascal.org/view.php?id=38843

--- Quote from: martok ---
--- Quote from: martin_fr ---AutoIndent is done by TSynBeautifier and that has it's own settings.

The default class (none language specific beautifier) has
SynEdit.Beautifier.IndentType
--- End quote ---
Another setting? Hm. Could this be documented somewhere?
Default Beautifier properties set in Object Inspector are not saved to LFM so this has to be set in code, is that intentional?

On a more general note, that means that, so far:
- block indent of selections uses BlockIndent/BlockTabIndent
- smart indent from [Tab] at line start uses CreateTabsAndSpaces(TabWidth)
- autoindent uses the Beautifier
All of these have completely different rules and depending on which one you happen to hit, the resulting text looks completely different. Is it really supposed to be that messy?

--- End quote ---

The short bits....

1) AutoIndent can require handling of situations (conflict/see below) that BlockIndent never has to deal with. So it needs additional settings.

2) There are a lot of ways those feature can be set. Many of them came from user-requests (or from the original SynEdit). That leads to a lot of settings, unfortunately...

3) Grouping of settings / finding them all over the place => see "modularity" below.
  (Also note, that some of those settings will also be influenced by "trimming trailing spaces", which are on a module of their own.

So between all of that, it's not trivial to find one good way to have all the settings accessible.
(For the OI, a special property editor with a wizard style configurator might be an idea / but who would write that?)


Why the extra setting.

If you look at the options

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- sbitConvertToTabSpace, // convert to tabs, fill with spcaces if needed sbitConvertToTabOnly // convert to tabs, even if shorterYou will see that the Beautifier can not follow the "BlockIndent" settings, because they do not contain info how to resolve conflicts. So additional settings are needed.

Yet see the proposal on the mantis issue, about how to at least make it follow for none conflict cases.

Given that new setting, it would be nice, if this was not crammed into a single property.
But if that is to be changed, special care needs to be taken, so the old property can still be read (IIRC possible with "DefineProperty")


Why the "invisible" default Beautifier

Due to historical reasons SynEdit has a lot of add-ons pre-added. (I.e. SynEdit used to be a big block of "all or nothing" code.).
The overall goal is to make it more modular.

Many features have been extracted (and more should be), so they can be added as needed.

The problem is, they can not simply be removed from the drag-and-drop SynEdit, because any project having a SynEdit on a form would loose all the features.
So instead a new lean SynEdit that does not have them pre-added needs to be created.
However creating that now, also recreates the above problem, if it is used and more features become add-ons... (And I don't want to end with half a dozen different LeanSynEdit.)

Off topic, this is also why I try to publish as few properties as possible. Once in OI, and lfm files, it becomes hell to change them.
If they are in code only, they get deprecated with a note how to replace them.
Code is checked when you compile, users will get a note or error. LFM are not check, they crash and maybe only sometimes.


The beautifier is one of the things SynEdit should only have, if added by a user. (And then the user would configure it).
But the problem is as told, existing projects expect it (or it's behaviour) to be present.

So that behaviour needed to be kept. Therefore there is now a default Beautifier as a fallback.
IIRC its a global object shared by all edits (needs to be checked).

The default can not work in the OI  (It would take quite some dirty workarounds....)., and it shouldn't even be shown (Not sure why it does, or since when / I almost overlooked that part of your comment completely).
So the idea is to add your own, if you want to configure it.

Hope I did not miss anything else.

Martin_fr:
Just adding, the implementation of the default beautifier, suggests it was meant to be avail in OI, and maybe save to lfm... Need to dig deeper...

And it is not global, it is one per each SynEdit.

Martok:
Hi Martin,

first of all, thank you for the long explanation. I didn't even know what the goal architecture for the refactoring was, quite a few things make a lot more sense now.

Do you have plans to at some point cut compatibility and use the new modular system to assemble a SynEdit that doesn't have to deal with compatibility requirements? Not as a "LeanSynEdit", more like a proper rebuild of a "baseline" feature set on the new architecture.
That could be useful as a general text editor and have a "simpler" external interface that controls the individual plugin parts, even if it doesn't expose all of them.



--- Quote from: Martin_fr on May 04, 2021, 03:10:03 pm ---Why the extra setting.

If you look at the options

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- sbitConvertToTabSpace, // convert to tabs, fill with spcaces if needed sbitConvertToTabOnly // convert to tabs, even if shorterYou will see that the Beautifier can not follow the "BlockIndent" settings, because they do not contain info how to resolve conflicts. So additional settings are needed.

Yet see the proposal on the mantis issue, about how to at least make it follow for none conflict cases.
--- End quote ---
Right. The thing that bugs me is that the action "indent the following line up to character N" is fundamentally different from "indent the current line up to character N" (I can see why SmartIndent is different). In terms of the redesign, should that be a function of the TextBuffer "insert padding according to the current rules" that both features call to?


--- Quote from: Martin_fr on May 04, 2021, 03:10:03 pm ---Many features have been extracted (and more should be), so they can be added as needed.

The problem is, they can not simply be removed from the drag-and-drop SynEdit, because any project having a SynEdit on a form would loose all the features.
So instead a new lean SynEdit that does not have them pre-added needs to be created.
However creating that now, also recreates the above problem, if it is used and more features become add-ons... (And I don't want to end with half a dozen different LeanSynEdit.)
--- End quote ---
True, having to keep the same interface of the component means that someone will try to use them.

Although I wonder... both FPC and Lazarus have made pretty heavy breaking changes in the past, replacing a few properties with linked components seems managable?



--- Quote from: Martin_fr on May 04, 2021, 03:10:03 pm ---Off topic, this is also why I try to publish as few properties as possible. Once in OI, and lfm files, it becomes hell to change them.
If they are in code only, they get deprecated with a note how to replace them.
Code is checked when you compile, users will get a note or error. LFM are not check, they crash and maybe only sometimes.
--- End quote ---
Markups are one of these new properties, right? Took me a while to figure out how to make the SpecialChars a different color, since the comment on the flag that says the're grayed out is not true anymore.


--- Quote from: Martin_fr on May 04, 2021, 03:10:03 pm ---So that behaviour needed to be kept. Therefore there is now a default Beautifier as a fallback.
--- End quote ---

--- Quote from: Martin_fr on May 04, 2021, 07:45:03 pm ---Just adding, the implementation of the default beautifier, suggests it was meant to be avail in OI, and maybe save to lfm... Need to dig deeper...

And it is not global, it is one per each SynEdit.

--- End quote ---
The thing is, I for one hadn't even noticed that it is even possible to assign a different Beautifier. It presents very similar to properties like Font in the OI...
And since the field is published as TSynCustomBeautifier, setting IndentType only works with a typecast... come to think of it, maybe that is why it doesn't save correctly?

Martin_fr:

--- Quote from: Martok on May 08, 2021, 11:14:43 pm ---Do you have plans to at some point cut compatibility and use the new modular system to assemble a SynEdit that doesn't have to deal with compatibility requirements? Not as a "LeanSynEdit", more like a proper rebuild of a "baseline" feature set on the new architecture.
That could be useful as a general text editor and have a "simpler" external interface that controls the individual plugin parts, even if it doesn't expose all of them.

--- End quote ---

First of all, "plans" is currently something that can be reaching far into the future. With all the other stuff on my list....

The idea is to maybe create a TLaz[Syn]Edit, which would be the core only.
TSynEdit itself would stay as it is, and inherit from the new LazEdit. TSynEdit might then disappear from the component palette, to encourage using the new one.


--- Quote ---Right. The thing that bugs me is that the action "indent the following line up to character N" is fundamentally different from "indent the current line up to character N" (I can see why SmartIndent is different).
--- End quote ---

First of all, they are always different. The "beautify indent" is more like the "smart tab" (and smart tab, can be indent, but also be in the middle of the line).

- Normal Indent always goes to a "reachable location". Indent by "one tab" will never need to indent to a position that can't be reached by tabs.
- "Block indent" adds to existing indent, and needs not to worry if there are spaces (block un-indent might).

- "beauty indent" (like smart indent) does not go to a position given by tabs. It goes to an x given by the line(s) above. (the line above can contain spaces).
  "beauty indent" therefore might need spaces, even if normal indent will work with tabs only.

Normal indent => calculate X from the tabs
beauty indent => calculate tabs from X

So by their own nature they are different.


--- Quote --- In terms of the redesign, should that be a function of the TextBuffer "insert padding according to the current rules" that both features call to?
--- End quote ---
That would not solve the issue. There still remain cases that will need spaces, when normal indent is tab only.

It does not need to go to the TextBuffer, see my proposal of adding more enum to the option.

It is even more complex. If 2 SynEdits share a text buffer, the 2 SynEdit can have different config. So indent would (and should) act different depending which SynEdit you type in.
It's up to the user code to sync any options that should be the same.
For example, if the editor had a keycombo to toggle trimming spaces, then that could very well be per editor (and not per textbuffer). That way a user could temp disable it in one of the editors.


--- Quote ---Markups are one of these new properties, right?
--- End quote ---
Yes as well as the shared textbuffer, and the TextViews (some of them contain functionality that should not be in textviews, like the CharWidths stuff)

Markups are not published, because there are some pre-installed. And having some auto created elements in the list, makes streaming a hell.
Gutter has such hell-ish code....


--- Quote ---I for one hadn't even noticed that it is even possible to assign a different Beautifier.
--- End quote ---
That is a problem....

I can either hide the default in OI (by means of a special property editor).
But then you can't edit in OI...

Or I can make it stream to lfm. But then it should show in OI.

And in either case, there is no way to set it to "nil"


--- Quote ---come to think of it, maybe that is why it doesn't save correctly
--- End quote ---
Not checked 100%, but I believe it is because it is an inlined component. And SynEdit as owner does not return it, when asked by the streaming system.

Martin_fr:
Couldn't think of a good word for it before, now I got it: align.

Smart indent and beautifier are not so much indent functions. They are align functions.

Navigation

[0] Message Index

[#] Next page

Go to full version