Elastic tabstops - a better way to indent and align code

New demo of elastic tabstops solves previous version's blank line issue

Judging from the feedback I've received so far, many people liked the concept but complained that the demo implementation meant they had to insert blank lines where they wouldn't normally. Well, I've been working on this for a few days and have come up with a variation on the previous system. Whereas the original system split the text into blocks (whenever it found a blank line), lined up all of the tabs in each block and then stretched each tabstop to fit the widest piece of text in each column, the new version takes advantage of the nested nature of code. As before, it works by creating an array from the text using tabs as the delimiter, but this time it finds a column block by looping through each column individually until it finds a missing tab and then it resizes that column block to fit the widest piece of text it contains. The result is a system that doesn't need all the blank lines that the first version did and makes better use of horizontal space. It also minimises the amount of text that moves on other lines when text is modified.

Please try the new version and give me your feedback. If you'd like to compare it with the old version you can try that here...

grid lines

Posted on Monday, 2006-07-10 at 13:53 UTC

24 comments


Monday 2006-07-10 23:33 UTC
James
I didn't try the first demo, but this second demo really looks good.

Monday 2006-07-10 23:53 UTC
Dave
This looks great. Will check this out at some point today.

Tuesday 2006-07-11 00:39 UTC
Ukuk
Now that IS great (=

Tuesday 2006-07-11 08:15 UTC
Peter Arrenbrecht <peter DOT arrenbrecht AT gmail DOT guess>
Interesting idea. How do you propose to align trailing comments across lines which are separated by other lines and blank lines? I sometimes have such comments far to the right. I cannot seem to properly align them with the second demo.

Tuesday 2006-07-11 09:08 UTC
Nick
Peter Arrenbrecht: If you copy and paste an example as a comment hopefully I'll be able to show you...

Tuesday 2006-07-11 17:23 UTC
Scott Noyes <ssnoyes AT hotmail DOT com>
I think Peter (and I!) are looking for this: if (someCondition) { doSomeStuff; // Align this with the below comment } if (someOtherCondition) { doSomethingElse; // Line this up with the above comment } I'm also curious about this issue: if (someCondition) { // This comment just squirrels everything. <- much! whitespace! here! }

Wednesday 2006-07-12 01:03 UTC
Dave
--- Scott Noyes --- I'm also curious about this issue: if (someCondition) { // This comment just squirrels everything. <- much! whitespace! here! } --- Scott Noyes --- I noticed this problem as well. Without using knowledge of the language being edited (block delimiters, etc) perhaps it could be fixed by taking note of which lines contain leading tabs and treating them slightly diferently.

Wednesday 2006-07-12 01:37 UTC
Eugene Kaganovich
I think Dave's problem can be solved by putting 2 tabs in front of the comment. Scott's is harder :) Another problem I see is that I think it'd be pretty hard (although not impossible) to upconvert the comment alignment from older code that uses spaces: int x = 123;//x int y = 0; //y You'd have to parse this quite a bit to realize that //x and //y should be aligned and therefore there is a tabstop before //x

Wednesday 2006-07-12 09:41 UTC
Nick
Dave: > I noticed this problem as well. At the moment it seems this system favours a coding style where squiggly brackets are on their own line: if (someCondition) // This comment no longer squirrels everything { <- tab back to minimum size! } > Without using knowledge of the language being edited (block delimiters, etc) perhaps it could be fixed by taking note of which lines contain leading tabs and treating them slightly diferently. I've had that idea at the back of my mind for weeks but I'm a little reluctant to implement it. The problem is that I don't want the system to be too complicated or users may think it's unpredictable. Also, the following code won't align properly if I make sure leading tabs have a fixed size: int someDemoCode( int fred, int wilma)

Wednesday 2006-07-12 09:48 UTC
Nick
Eugene Kaganovich: If there's no space before the "//x" comment it hasn't been aligned properly anyway, so I don't think I need to worry about that particular case...

Wednesday 2006-07-12 09:57 UTC
Nick
Scott Noyes: That's not possible in the latest demo, but stay tuned as I have an idea that may fix it...

Wednesday 2006-07-12 16:44 UTC
Scott Noyes
>> I don't want the system to be too complicated or users may think it's unpredictable. Yes, absolutely imperative. If we fail in that regard, the idea will die right on this page. For the question, it seems we're looking for a special last tab on the line that lines up with all the other special last tabs (but not the non-special last tabs). Maybe two tabs with no tabs following?

Wednesday 2006-07-12 17:59 UTC
Eugene Kaganovich
Nick: I'm not sure what you mean by "it hasn't been aligned properly anyway" (it does align, it just doesn't have any spaces, and we are talking exactly about alignment rules). I do agree that it's probably ok to ignore the case when there's no space. But there is still a problem with what to do for upconversion if there was a single space, esp. if you don't want to have language-specific features such as recognition for //. for example: // one two three .... // don't align "three"! As an aside, it would probably improve readability if the comments section here used monospaced fonts ;)

Wednesday 2006-07-12 23:55 UTC
Nick
Scott Noyes: What's more important, this lining up: int someDemoCode( int fred, int wilma) or solving the issues raised in your first post? I think they're mutually incompatible... :( My next implementation will solve the issues raised in your first post but mean that coders have to use int someDemoCode( int fred, int wilma)

Thursday 2006-07-13 00:09 UTC
Nick
Eugene Kaganovich: > I'm not sure what you mean by "it hasn't been aligned properly anyway" (it does align, it just doesn't have any spaces, and we are talking exactly about alignment rules). I just meant that the user had not used tabs or spaces to align it... > But there is still a problem with what to do for upconversion if there was a single space There may be a problem with single spaces, but we can always look to see if a piece of text starts on a multiple of 4 (or whatever the user says their coding standard uses) > As an aside, it would probably improve readability if the comments section here used monospaced fonts ;) :) That was deliberate - I wanted to remind people of the current problems with aligning proportional fonts. If people are copying and pasting code from this page into the example implementation monospaced fonts wouldn't help anyway.

Thursday 2006-07-13 15:02 UTC
Scott Noyes <ssnoyes AT hotmail DOT com>
I prefer int someDemoCode( int fred, int wilma) over int someDemoCode( int fred, int wilma) anyway. The double tab thing might fix that, but I don't know at what cost: int someDemoCode( align A, align A) align B var someOtherFunc() align B bitOfCode; alignB

Thursday 2006-07-13 22:19 UTC
Nick
Scott Noyes: I'm worried that your "special tab" idea may confuse people too much. I'm working on a new implementation of the demo, and hope to have it finished soon, so watch this space...

Tuesday 2006-08-08 17:50 UTC
micca
Love them. But the can't solve all usage patterns above. And I think they should not even try do that. Just let them align on row following eachother. For the case: if (someCondition) { // This comment just squirrels everything. <- much! whitespace! here! } The solution is to NOT use tab before the comment, or not using a comment on that row at all. It comes with a price. If one still wants to solve it the ony way i see is to have 2 tab types. e-tabs and tabs (normal tabs). But then You thinking what about N-column spaning tabs.. 0-tab (normal tab), 1-tab (e-tab), 2-tab, 3-tab, etc.. But that breaks the viewing compability.

Tuesday 2006-08-08 18:00 UTC
micca
Ahh.. perhaps. = normal tab = elastic-tab will work.

Tuesday 2006-08-08 18:02 UTC
micca
Sorry for that LG and GT got comsumed. (space)(tab) = normal tab (!space)(tab) = elastic-tab will work.

Tuesday 2006-10-31 12:59 UTC
Yakov Lerner <iler DOT ml AT gmail DOT com>
Nickl, I don't see specification (meaning, clear technical description of (1) what appears in the text file in the places where we see "elastic indent" and (2) how editor is supposed to comute the visual size of elastic indent"). Once you write up (and publish on your site) the clear technical specification, it can be implemented in editor(s). Missing the specification, the demo is not much useful; demo does not answer the questions (1) and (2) and what I see on your site is not specification.

Wednesday 2007-01-03 21:03 UTC
anonymous
The basic problem is to change column widths, like in int someDemo(\tab int* x, \tab int* y) { \tab int i,j; \tab etc. } The \tabs in the function header should define different column widths than the the \tabs in the function definition. An idea would be to use *different line endings* to encode this. F.i., a carriage return resets column widths whereas a form feed does not. So the newline after the culry brace "{" would be a carriage return, the others would be form feeds. On (older?) version of M*soft Word for Macintosh, there indeed existed two different newlines. The non-standard one was entered as "Shift + Return" as opposed to "Return" and was used to preserve block formatting.

Tuesday 2009-02-03 22:50 UTC
slacy
So, has anyone coded up an emacs elisp version of this? Does anyone actually use GEdit on a regular basis?

Friday 2014-11-21 08:56 UTC
Mark Y <markyag AT gmail DOT com>
The old version is better for tables with lots of blank entries. Like LR(1) parse tables, which is what I have to do for my compilers HW, so I'm glad the old version is still on your site.

Comments are closed.