Try the Whitespace Cleaner

Whitespace as Syntax: Python Indentation, YAML Structure, Prettier, and .editorconfig

Python uses indentation as syntax; YAML prohibits tabs entirely; Make requires tabs. Here's whitespace as code structure, the tabs vs spaces debate resolved by autoformatters like Prettier and Black, .editorconfig for cross-editor consistency, and the CRLF vs LF line ending problem in mixed-platform teams.

By sadiqbd Β· June 11, 2026

Whitespace as Syntax: Python Indentation, YAML Structure, Prettier, and .editorconfig

Whitespace is not neutral in code β€” Python and YAML use it as syntax, and getting it wrong crashes your program

Most programming languages treat whitespace as insignificant: extra spaces and newlines are ignored. Python and YAML are different. In Python, indentation determines block structure. In YAML, indentation determines data hierarchy. A misplaced space in a YAML configuration file silently changes the structure; in Python, it raises a SyntaxError or worse, changes the program's logic without raising an error.

Understanding whitespace as syntax β€” and the tools that enforce consistent whitespace in codebases β€” is foundational to writing maintainable code in modern development environments.


Python: indentation as syntax

Python uses indentation to define code blocks. There are no {} braces or begin/end keywords β€” the indentation level is the syntax.

# Correct: 4-space indentation (PEP 8 standard)
def process_data(data):
    if data:
        for item in data:
            result = transform(item)
            print(result)
    else:
        print("No data")

# IndentationError: mixed indentation
def process_data(data):
    if data:           # 4 spaces
          for item in data:  # 10 spaces β€” IndentationError

The tabs vs spaces problem in Python:

Python 2 allowed mixing tabs and spaces (treating each tab as equivalent to an unspecified number of spaces). This produced code that looked correct in one editor but broke in another with different tab display settings.

Python 3 made this an error: mixing tabs and spaces for indentation raises TabError: inconsistent use of tabs and spaces in indentation.

PEP 8: Python's style guide specifies 4 spaces per indentation level. This is the universal Python convention β€” virtually all Python tooling enforces it.


YAML: whitespace determines structure

YAML is used for configuration files (GitHub Actions, Kubernetes, Docker Compose, Ansible, GitLab CI, many others). Whitespace errors in YAML can silently change the meaning or raise parse errors.

# Correct: items under "steps" are part of the jobs/build block
jobs:
  build:
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Build
        run: npm run build

# WRONG: misindented "run" β€” now it's a mapping key at the wrong level
jobs:
  build:
    steps:
      - name: Build
      run: npm run build  # This is now wrong YAML structure

YAML indentation rules:

  • Must use spaces, not tabs (YAML explicitly prohibits tabs for indentation)
  • The number of spaces is flexible but must be consistent within a structure
  • Two spaces per level is conventional in most YAML files

Common YAML whitespace errors:

  • Tab characters instead of spaces (yaml: found character '\t' that cannot start any token)
  • Inconsistent indentation depth within a block
  • Items at the wrong level (creating unintended nesting)
  • Trailing whitespace on lines with multi-line string syntax (some parsers are sensitive)

The tabs vs spaces debate: history and practical resolution

The historical debate: some programmers prefer tabs (tab width is configurable per editor preference), others prefer spaces (consistent display regardless of editor settings). In Python, the debate was resolved by PEP 8 (spaces) and enforced by Python 3. In most other languages, the debate became practically resolved by autoformatters.

The autoformatter resolution:

Modern codebases use autoformatters that enforce a consistent style automatically on save or commit:

Prettier (JavaScript/TypeScript/CSS/HTML/YAML/JSON):

# Format all files in the project
npx prettier --write .

# Check formatting without changing files
npx prettier --check .

Prettier is "opinionated" β€” it has minimal configuration options by design. The goal is to eliminate the formatting discussion entirely: run Prettier, and the output is the canonical format.

Black (Python):

# Format Python files
black .

# Check without changing
black --check .

Black is Python's equivalent to Prettier: opinionated, deterministic, and designed to end stylistic debate. It uses 88 characters per line (not the PEP 8 standard 79) as a deliberate choice that better fits modern screens.

gofmt (Go): Go has an official formatter built into the toolchain. gofmt is run automatically by the Go tooling and enforces the language's official style. There is no tabs vs spaces debate in Go β€” gofmt uses tabs, and that's that.

rustfmt (Rust): The official Rust formatter enforces 4-space indentation and a consistent style across all Rust projects.


.editorconfig: consistent whitespace across editors

.editorconfig is a file format and standard that tells editors how to handle whitespace settings β€” tab width, indent style, end-of-line character, and charset β€” regardless of which editor team members use.

# .editorconfig placed in project root
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.py]
indent_size = 4

[*.go]
indent_style = tab
indent_size = 4

[Makefile]
indent_style = tab  # Make requires tabs

What this achieves:

  • All team members' editors use the same indentation settings for each file type
  • Trailing whitespace is removed on save (prevents noise in diffs)
  • Files end with a newline (POSIX convention; prevents diff tool warnings)
  • Line endings are consistent (LF on Unix/Mac, CRLF on Windows β€” specify LF for cross-platform projects)

.editorconfig support: natively supported in VS Code (via built-in support), JetBrains IDEs (IntelliJ, PyCharm, WebStorm), Neovim, Emacs, and most modern editors.


Line endings: the CRLF vs LF problem

Windows uses \r\n (CRLF, carriage return + line feed) as the line ending. Unix/Linux/macOS use \n (LF). This is a whitespace issue that causes constant friction in mixed-platform teams.

The git configuration:

# Windows: convert to CRLF on checkout, convert to LF on commit
git config --global core.autocrlf true

# Unix/Mac: no conversion on checkout, convert to LF on commit (ensures LF in repo)
git config --global core.autocrlf input

# Set explicit per-file rules in .gitattributes

.gitattributes file:

# Default: treat text files, normalise to LF in repo
* text=auto

# Explicitly LF
*.sh text eol=lf
*.py text eol=lf

# Windows batch files
*.bat text eol=crlf
*.cmd text eol=crlf

# Binary files (don't touch line endings)
*.png binary
*.jpg binary

The symptom of CRLF problems in code: shell scripts committed with CRLF endings fail on Linux with cryptic errors (/bin/sh^M: bad interpreter). The ^M is the carriage return character at the end of the shebang line.


Trailing whitespace in diffs

Trailing whitespace (spaces after the last visible character on a line) is a common source of noise in code diffs. Two commits that make no logical change can produce diff lines if one adds and another removes trailing spaces.

Git configuration to highlight trailing whitespace:

git config --global core.whitespace trailing-space,space-before-tab
git diff --check  # Shows whitespace errors before committing

Pre-commit hook to remove trailing whitespace:

# .git/hooks/pre-commit
git diff --cached --name-only | while read file; do
    if [ -f "$file" ]; then
        sed -i 's/[[:space:]]*$//' "$file"
    fi
done

How to use the Whitespace Cleaner on sadiqbd.com

  1. Paste any text
  2. Select cleaning operations:
    • Remove leading/trailing whitespace per line
    • Collapse multiple spaces to single space
    • Remove blank lines / normalise blank lines
    • Convert tabs to spaces (or vice versa)
  3. Apply and copy β€” cleaned text ready for use

Common use cases: cleaning pasted text from Word or PDFs (which often contain extra spaces and tabs), normalising data exports before database import, cleaning API response text for processing.


Frequently Asked Questions

Why do Make files require tabs for indentation? Make (the build tool) was written in 1976 when the author chose tab characters as the separator between target and command lines. This design decision was baked into Make's syntax and has been preserved in all subsequent versions for backward compatibility. It's one of the most famous specific whitespace-as-syntax decisions in computing history.

What is a non-breaking space and how is it different from a regular space? A non-breaking space (U+00A0) looks identical to a regular space (U+0020) but prevents line breaking at that point. Common in HTML ( ), in typeset text (before units: "100 kg"), and in some copy-pasted text from web pages. Non-breaking spaces in code can cause subtle parsing bugs because they look like spaces but behave differently.

Is the Whitespace Cleaner free? Yes β€” completely free, no sign-up required.


Whitespace is syntax in Python and YAML, significant in Makefiles, and a consistency concern in every collaborative codebase. Autoformatters and .editorconfig have largely resolved the debate for existing code β€” but understanding why whitespace matters in each context prevents the class of "but it looked fine in my editor" problems.

Try the Whitespace Cleaner free at sadiqbd.com β€” remove trailing whitespace, normalise indentation, collapse multiple spaces, and clean any text in seconds.

Try the related tool:
Open Whitespace Cleaner

More Whitespace Cleaner articles