Monday, August 8, 2022

Porting a project from spaces to tabs

I'm currently working on a JavaScript codebase that has some old crusty code, and I'm modernizing it in various ways, like upgrading to ES6 syntax and linting with ESLint. I also like to add in Prettier to every codebase, as an automated step, so that my code is always consistently formatted, and so that future pull requests from other developers can easily follow the same conventions.

But I had a dilemma: half my code was written with 2 space indents, the other half was written with 4 space indents, and I needed to tell Prettier what to use. What's a girl to do?? Well, I considered averaging it for nice 3-space indents everywhere (I kid, I kid), but I instead made a radical decision: just use tabs! I'd heard that Prettier is considering making tabs the default anyway, and after reading the many comments on their PR thread, I became convinced that tabs are better than spaces, at least for an autoformatted project.

Since my projects and editors have used spaces forever, there were a few things I needed to do in order to smoothly move over to tabs. Here's the steps I took:

  • Reformat files to use tabs. To change all my current files to tabs, I used Prettier. First I configured it by specifying "useTabs" in my .prettierrc.json:

    {
    	"useTabs": true
    }
    

    Then I ran the prettier command on all my JS/JSON files:

    prettier \"**/*.{js,json}\" --ignore-path ./.eslintignore --write
          
  • Ignore the reformat commit in git blame. I really hate when reformatting commits make it harder to use git blame to track logical changes, so I was thrilled to discover that there's a way for Git/Github to ignore particular revisions while blaming. I followed this blog post, adding a .git-blame-ignore-revs with my most recent commit:

    # Reformat js/json with Prettier, spaces to tabs
    a08f09aa7c4e9381ae2036754bd9311e78c3b40f
    

    Then I ran a command to tell my local git to ignore the revision:
    git config blame.ignoreRevsFile .git-blame-ignore-revs

    Once I pushed the commit with that file, I saw that Github does indeed ignore changes from that commit when I use the blame feature. So cool! Screenshot from Github blame UI

  • Make Github render tabs using 4 spaces.For whatever reason, Github defaults to 8 spaces for tabs, and that is too dang much. To make Github render the tabs in my projects with just 4 spaces, I added an .editorconfig file to my project:

    root = true
    
    [*]
    indent_style = tab
    indent_size = 4
    

    Github also allows users to customize tabs across all project repositories, and that user setting takes precedence over the per-project .editorconfig setting. That's likely for accessibility reasons, since some folks might require a large number of spaces for better readability. To change my account preference, I opened up Settings > Appearance and selected my desired number of spaces:

    Screenshot of Github settings

    So, if I visit my project in an incognito window, Github will render the tabs with 4 spaces, but if I visit the project from my logged in browser, Github will render the tab with 2 spaces.

  • Make VS Code insert tabs when I tab. VS Code tries to adjust its indentation style with autodetection based on the current file, but I wanted to make sure it always inserted a tab in new files in my project, too. It defaults to inserting spaces when it isn't sure, so I needed to explicitly override that setting. I could have changed the setting across all projects, but most of my other projects use spaces, so I instead figured out how to change it in just this project for now.

    To change it, I opened up Settings > Workspace, searched for "insert spaces", and un-checked the "Editor: Insert spaces" setting. That created a .vscode/settings.json file with an "editor.insertSpaces" property:

    {
    	"editor.insertSpaces": false
    }
    

    Another option for VS Code is to use a VS Code plugin that understands .editorconfig files. If you go that route, you don't need to finagle with the VS Code settings yourself.

No comments: