SublimeText / ElasticTabstops

Tab characters automatically adjust to keep adjacent lines aligned.
https://github.com/SublimeText/ElasticTabstops
67 stars 6 forks source link

Option to Use Tabs only instead of Tabs+Spaces #6

Closed Ajedi32 closed 11 years ago

Ajedi32 commented 11 years ago

Currently, this plugin uses spaces to offset the tab characters so that they line up neatly into columns. While I can see how this makes sense from an implementation standpoint, as a user I think I'd prefer either tabs or spaces: not a mix of both.

Personally, when I'm trying to line up several bits of text into a column I use multiple tabs to accomplish that, not multiple spaces and then a single tab.

adzenith commented 11 years ago

Doing it that way creates an ambiguous situation that can't be resolved without guesswork.

adzenith commented 11 years ago

See e.g. https://github.com/SublimeText/ElasticTabstops/issues/3

Ajedi32 commented 11 years ago

Yeah, I realize this is somewhat similar to that issue. Personally, I wouldn't mind a bit of guesswork though if that's what it took to get the job done.

adzenith commented 11 years ago

Do you have any good ideas for how the guesswork would happen? If you do, I'd be interested to hear them. It's especially tricky because if you change the buffer there's no way to tell what change you made--this makes reindenting all of the adjacent lines difficult at best.

Ajedi32 commented 11 years ago

Hmm... okay let's use the example from Nick Gravgaard's website:

So this is what the code would look like if I reproduced it with normal tabstops (assuming a tab ~= 4 characters):

#include <stdio.h>

int someDemoCode(\t int fred,
\t  \t  \t  \t  \t  int wilma)
{
\t  x();\t  \t  \t  \t  \t  \t  \t      /* try making\t     */
\t  print("hello again!\n");\t  \t      /* this comment\t   */
\t  makeThisFunctionNameShorter();\t    /* a bit longer\t   */
\t  for (i = start; i < end; ++i)
\t  {
\t  \t  if (isPrime(i))
\t  \t  {
\t  \t  \t  ++numPrimes;
\t  \t  }
\t  }
\t  return numPrimes;
}

Now let's add a few m's to the name of that someDemoCode function. This is what would normally happen if we weren't using this plugin:

#include <stdio.h>

int someDemoCodemmmm(\t int fred,
\t  \t  \t  \t  \t  int wilma)
{

Notice that the text is out of alignment.

When we're using this plugin though that doesn't happen. The plugin notices that we're adding characters to that line, and looks at the characters after where we're inserting the text to see if there are any tab characters. It finds one, right before int. If inserting an m character has bumped the tabstop for that tab character forward, the plugin looks at the lines above and below to see if there are any other tab characters that had a tabstop at that same position. If there are, it adds another tab character to those lines:

#include <stdio.h>

int someDemoCodemmmm(\t int fred,
\t  \t  \t  \t  \t  \t  int wilma)
{

A similar process is followed when you later remove those m characters from the function name.

Do you see any problems with that sort of guesswork?

adzenith commented 11 years ago

I see two problems, unfortunately. The first one has a really annoying workaround; the second one I don't know how to resolve:

  1. There's no way to tell what changes were made to the buffer, without keeping track of the entire buffer yourself and diffing every time you get an on_modified callback. If you added the m's without doing that, then there's no way to tell which tabs should align with which.
  2. If you and I use different tab widths, our cells wouldn't necessarily line up. E.g.:
\t  x();\t  \t  \t  \t  \t  \t  \t      /* try making\t     */
\t  print("hello again!\n");\t  \t      /* this comment\t   */

vs:

\t      x();\t      \t      \t      \t      \t      \t      \t      /* try making\t     */
\t      print("hello again!\n");\t  \t      /* this comment\t   */

In the second case it looks like the comments should be in two different spots.

Ajedi32 commented 11 years ago
  1. So Sublime text doesn't tell you where text was added/removed? It only notifies you that something in the buffer changed? That's weird... How does this plugin work currently? Does it search through and update the whole buffer every time I make an edit? It seems to me like Sublime Text needs a better API in this area.

    Could you perhaps infer additional information about the edit based on what keys the user pressed and the current position of the cursor?

  2. Yeah, but doesn't that problem occur anyway when you use tabs to indent code? If I'm using tabs to indent my code anyway, this isn't a problem that I would expect this plugin to solve.

    Also, I think Sublime text has a button that updates the tab size automatically based on the contents of the buffer: "View -> Indentation -> Guess Settings from Buffer" I'm not sure how well it works, but perhaps you could use it solve this problem.

adzenith commented 11 years ago
  1. Yes... :( We search much of the buffer, using heuristics such as: where were your insertions points before the change? after the change? And then if we see two adjacent lines whose tabs are unaligned, we fix them. We can also stop searching at e.g. blank lines, which makes it go faster. We've been asking for a better API since ages.
  2. The tab-width problem occurs anyway, but in the current implementation of this plugin it remains unambiguous what should line up with what. If we used tabs instead of spaces, then if you re-opened the file with a different tab width, it would seem like the two comment lines weren't even supposed to be aligned.
Ajedi32 commented 11 years ago
  1. Yeah, but here's my point: If I open a file with Sublime Text and the tabs are all messed up, my initial reaction is going to be to either fix the tabs or change the tab width settings until everything looks fine again. (Whether or not ElasticTabstops is installed.) I wouldn't expect the ElasticTabstops plugin to fix the problem for me, and I wouldn't expect the plugin to function normally until the problem is resolved. So as long as the plugin can read the value from Sublime Text's tab width setting for the current file and use that as the tab width, everything should work just fine.

    So yes, the plugin wouldn't have any way of knowing that the two comment lines were supposed to be aligned, but the user is going to notice and correct the problem anyway, whether or not ElasticTabstops is installed. Once the user does correct the problem, everything should work normally again. Am I missing something?

adzenith commented 11 years ago

Yeah, that would solve problem number 2. And then if you solve problem number 1 by keeping track of the entire buffer to see exactly what changed, you could totally have something workable.

Ajedi32 commented 11 years ago

Hmm, maybe. That sounds like it would be really slow though, and probably a pain to implement. Do you have a post on UserEcho asking for a better API for tracking buffer changes? I'd certainly give it my vote.

adzenith commented 11 years ago

I'm sure I do. I'm not sure if anyone looks at UserEcho anymore, though.

Ajedi32 commented 11 years ago

Hmm, well there's still a pinned post on the Sublime Text forums saying that you should submit your feature requests to UserEcho. http://www.sublimetext.com/forum/viewtopic.php?f=4&t=1572 It's a really old post but I'm assuming it's still valid since it's still pinned.