Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to enforce using tabs instead of spaces?

StyleCop offers to check for consistent use of spaces, but sadly lacks the opposite idea: Force source code to use tabs. Is there some way to add this functionality? It does not have to be StyleCop, other tools are welcome as well.

like image 242
mafu Avatar asked Feb 17 '10 13:02

mafu


People also ask

Why do people use spaces instead of tabs?

Tabs Debate. Pro-spaces programmers argue that using the space bar makes the layout more flexible. However, pro-tabs users rebut saying tabs makes code more readable and aesthetically pleasing.

Should I use tabs or spaces to indent?

Conclusion. So, at the end of the day, tabs versus spaces is truly a matter of preference, however the tab is still the character specifically designed for indentation, and using one tab character per indentation level instead of 2 or 4 spaces will use less disk space / memory / compiler resources and the like.

Do tabs take up less storage than spaces?

In general, tabs take fewer key presses and use less computer storage, but are more imprecise. Spaces, on the other hand, offer more clarity for coders, but practice takes up more space.

Should HTML use tabs or spaces?

As nobody mentioned it, the Google HTML/CSS Style Guide and the W3School HTML(5) Style Guide recommend 2 spaces. This article also brings an analysis of the effect of tabs vs spaces in the resulting file size. Show activity on this post. Do not use tabs; use two spaces.


3 Answers

I'm a tabs-not-spaces person, too, though there are plenty of reasons to use either one and there are other places to get into why you think one is better than the other. :)

I actually wanted the same thing - a rule to check for tab indents - so I wrote it based on the SpacingRules source from StyleCop. It seems to work reasonably well, though I've only used it on a few projects so far. It could probably be optimized or whatever... but it works.

using System;
using System.Text.RegularExpressions;
using Microsoft.StyleCop;
using Microsoft.StyleCop.CSharp;

namespace CustomRules.StyleCop.CSharp
{
  [SourceAnalyzer(typeof(CsParser))]
  public class SpacingRules : SourceAnalyzer
  {
    public SpacingRules()
    {
    }

    public override void AnalyzeDocument(CodeDocument document)
    {
      Param.RequireNotNull(document, "document");

      CsDocument csdocument = (CsDocument)document;
      if (csdocument.RootElement != null && !csdocument.RootElement.Generated)
      {
        this.CheckSpacing(csdocument.Tokens);
      }
    }

    private void CheckSpacing(MasterList<CsToken> tokens)
    {
      Param.AssertNotNull(tokens, "tokens");

      foreach (var token in tokens)
      {
        if (this.Cancel)
        {
          break;
        }

        if (token.Generated)
        {
          continue;
        }

        switch (token.CsTokenType)
        {
          case CsTokenType.WhiteSpace:
            this.CheckWhitespace(token as Whitespace);
            break;

          case CsTokenType.XmlHeader:
            XmlHeader header = (XmlHeader)token;
            foreach (var xmlChild in header.ChildTokens)
            {
              this.CheckTabsInComment(xmlChild);
            }
            break;

          case CsTokenType.SingleLineComment:
          case CsTokenType.MultiLineComment:
            this.CheckTabsInComment(token);
            break;
        }

        switch (token.CsTokenClass)
        {
          case CsTokenClass.ConstructorConstraint:
            this.CheckSpacing(((ConstructorConstraint)token).ChildTokens);
            break;

          case CsTokenClass.GenericType:
            this.CheckGenericSpacing((GenericType)token);
            this.CheckSpacing(((TypeToken)token).ChildTokens);
            break;

          case CsTokenClass.Type:
            this.CheckSpacing(((TypeToken)token).ChildTokens);
            break;
        }
      }
    }

    private void CheckGenericSpacing(GenericType generic)
    {
      Param.AssertNotNull(generic, "generic");
      if (generic.ChildTokens.Count == 0)
      {
        return;
      }

      foreach (var token in generic.ChildTokens)
      {
        if (this.Cancel)
        {
          break;
        }

        if (token.CsTokenClass == CsTokenClass.GenericType)
        {
          this.CheckGenericSpacing(token as GenericType);
        }

        if (!token.Generated && token.CsTokenType == CsTokenType.WhiteSpace)
        {
          this.CheckWhitespace(token as Whitespace);
        }
      }
    }

    private void CheckWhitespace(Whitespace whitespace)
    {
      Param.AssertNotNull(whitespace, "whitespace");

      if (whitespace.Location.StartPoint.IndexOnLine == 0 && Regex.IsMatch(whitespace.Text, "^ +"))
      {
        this.AddViolation(whitespace.FindParentElement(), whitespace.LineNumber, "TabsMustBeUsed");
      }
    }

    private void CheckTabsInComment(CsToken comment)
    {
      Param.AssertNotNull(comment, "comment");

      var lines = comment.Text.Split('\n');
      for (int i = 0; i < lines.Length; i++)
      {
        if (Regex.IsMatch(lines[i], "^ +"))
        {
          this.AddViolation(comment.FindParentElement(), comment.LineNumber + i, "TabsMustBeUsed");
        }
      }
    }
  }
}

Note that you also have to have the embedded XML file "SpacingRules.xml" in the assembly alongside this thing. (Read the StyleCop SDK doc for more on that.)

<?xml version="1.0" encoding="utf-8" ?>
<SourceAnalyzer Name="Custom Spacing Rules">
  <Description>
    Rules which verify the spacing placed between keywords and symbols in the code.
  </Description>
  <Rules>
    <Rule Name="TabsMustBeUsed" CheckId="MY1027">
      <Context>Spaces are not allowed. Use tabs instead.</Context>
      <Description>Verifies that the code does not contain spaces.</Description>
    </Rule>
  </Rules>
</SourceAnalyzer>
like image 122
Travis Illig Avatar answered Sep 26 '22 12:09

Travis Illig


You can use StyleCop+ plugin to enforce usage of tabs.

After downloading StyleCopPlus.dll place it in Custom Rules folder inside the main StyleCop folder C:\Program Files (x86)\StyleCop 4.7\Custom Rules or directly in the main folder.

Now, when opening a Settings.StyleCop with StyleCopSettingsEditor you will be able to set rule SP2001: CheckAllowedIndentationCharacters.

This rule can be found under the StyleCop+ tab, under the More Custom Rules subtab, under the Formatting heading:

Rule Options

like image 8
Răzvan Flavius Panda Avatar answered Sep 25 '22 12:09

Răzvan Flavius Panda


One thing you could do, assuming you are using Visual Studio as your IDE, and that your team-mates buy-in to this idea, would be to set VS to use tabs instead of spaces, export and share the settings file.

The setting can be found under Tools > Options > Text Editor > All Languages (or the language you wish to use) > Tabs and then on the right hand side you can pick to 'Insert Spaces' or 'Keep Tabs'.

To export the settings from your visual studio: Tools > Import and Export Settings > Export selected environment settings > select the 'Options'

Just a thought - but to be honest the real problem seems to be the buy-in from your team-mates. They can always revert back to their settings otherwise. Alternatively, upon check-in, as Sam suggested, you can do some automated re-formatting.

HTH

like image 3
FOR Avatar answered Sep 27 '22 12:09

FOR