π EditorConfig Deep Learning Guide
A comprehensive guide to mastering EditorConfig for consistent code styling across teams and editors.
π Table of Contentsβ
- What is EditorConfig?
- Learning Roadmap
- Core Concepts
- Properties Reference
- Pattern Matching
- Real-World Examples
- Best Practices
- Advanced Techniques
- Troubleshooting
- Resources
π― What is EditorConfig?β
EditorConfig is a configuration file format that helps maintain consistent coding styles across:
- Different editors (VS Code, IntelliJ, Vim, Sublime, etc.)
- Different developers on the same project
- Different operating systems (Windows, macOS, Linux)
Key Benefitsβ
β
Universal: Works across 40+ editors
β
Simple: Human-readable INI format
β
Automatic: No manual editor configuration needed
β
Version-controlled: Configuration lives in your repository
β
Hierarchical: Can override settings at directory levels
π§© Core Conceptsβ
1. File Structureβ
# Comment: Top-level EditorConfig file
root = true
# Universal settings (applies to all files)
[*]
property = value
# Language-specific settings
[*.py]
property = value
# Multiple extensions
[*.{js,jsx,ts,tsx}]
property = value
2. How It Worksβ
Project Root
βββ .editorconfig β Root config
βββ src/
β βββ .editorconfig β Overrides root for src/
β βββ components/
β βββ Button.tsx β Uses both configs (merged)
βββ tests/
βββ test.py β Uses only root config
Resolution Order:
- Editor reads file being edited
- Searches up directory tree for
.editorconfigfiles - Stops when it finds
root = true - Merges all configs (closer files override distant ones)
3. Property Precedenceβ
root = true
[*]
indent_size = 4 # Priority: Low
[*.js]
indent_size = 2 # Priority: Medium (overrides [*])
[lib/**.js]
indent_size = 4 # Priority: High (most specific)
Rule: More specific patterns override general ones.
π Properties Referenceβ
Standard Propertiesβ
indent_styleβ
Controls indentation character type.
indent_style = space # Use spaces (recommended for most languages)
indent_style = tab # Use tabs (required for Makefiles, common in Go)
When to use tabs:
- Go (language standard)
- Makefiles (required)
- Some C/C++ projects
indent_sizeβ
Number of columns for each indentation level.
indent_size = 2 # JavaScript, Ruby, YAML
indent_size = 4 # Python, Java, C#
indent_size = 8 # Linux kernel style
Language Standards:
| Language | Standard | Rationale |
|---|---|---|
| Python | 4 | PEP 8 |
| JavaScript | 2 | Airbnb, Google, Standard JS |
| Java | 4 | Oracle Code Conventions |
| Ruby | 2 | Ruby Style Guide |
| Go | Tab | gofmt default |
tab_widthβ
Display width of tab character (only applies when indent_style = tab).
[*.go]
indent_style = tab
tab_width = 4 # Tabs displayed as 4 spaces wide
end_of_lineβ
Line ending character(s).
end_of_line = lf # Unix/Mac (recommended) - \n
end_of_line = crlf # Windows - \r\n
end_of_line = cr # Old Mac (rare) - \r
Best Practice: Use lf everywhere. Git can handle conversion with .gitattributes.
charsetβ
File character encoding.
charset = utf-8 # Unicode (recommended for all projects)
charset = utf-8-bom # UTF-8 with BOM (avoid unless needed for Windows)
charset = latin1 # ISO-8859-1 (legacy)
charset = utf-16be # UTF-16 Big Endian
charset = utf-16le # UTF-16 Little Endian
Best Practice: Always use utf-8 for new projects.
trim_trailing_whitespaceβ
Remove whitespace at end of lines.
trim_trailing_whitespace = true # Remove (recommended)
trim_trailing_whitespace = false # Keep (needed for Markdown)
Exception: Markdown uses trailing spaces for line breaks.
[*.md]
trim_trailing_whitespace = false
insert_final_newlineβ
Ensure file ends with newline.
insert_final_newline = true # Add newline (POSIX standard)
insert_final_newline = false # Don't add
Why it matters: POSIX defines a text file as ending with newline. Many tools expect this.
max_line_lengthβ
Maximum line length (not enforced by all editors).
max_line_length = 80 # Traditional standard
max_line_length = 100 # Modern compromise
max_line_length = 120 # Widescreen-friendly
max_line_length = off # No limit
Language Standards:
- Python (PEP 8): 79 characters (code), 72 (docstrings)
- JavaScript: 80-100 (varies by style guide)
- Go: No strict limit (gofmt wraps intelligently)
π¨ Pattern Matchingβ
Glob Patternsβ
EditorConfig uses glob patterns to match files.
Basic Patternsβ
# Exact filename
[Makefile]
# Extension
[*.js]
# Multiple extensions
[*.{js,jsx,ts,tsx}]
# Any file
[*]
Wildcard Charactersβ
| Pattern | Matches | Example |
|---|---|---|
* | Any string (except /) | *.js β app.js, index.js |
** | Any string (including /) | lib/**.js β lib/a.js, lib/b/c.js |
? | Any single character | ?.txt β a.txt, b.txt |
[abc] | Any character in brackets | [ABC].txt β A.txt, B.txt |
[!abc] | Any character NOT in brackets | [!0-9].txt β a.txt (not 1.txt) |
{s1,s2} | Any of the strings | {a,b}.txt β a.txt, b.txt |
Advanced Examplesβ
# All JavaScript files in src/ recursively
[src/**.{js,jsx}]
# Test files only
[*{test,spec}.{js,ts}]
# Configuration files in root only
[{package.json,tsconfig.json}]
# Exclude node_modules (doesn't work - see limitations)
[!node_modules/**] # β NOT SUPPORTED
# Files starting with dot
[.*]
indent_size = 2
Pattern Precedenceβ
More specific patterns override general ones:
[*]
indent_size = 4 # Default
[*.js]
indent_size = 2 # More specific: all .js files
[src/**.js]
indent_size = 8 # Most specific: .js files in src/
[src/legacy/old.js]
indent_size = 4 # Exact match: single file
Result:
src/legacy/old.jsβ 4src/utils/helper.jsβ 8test/test.jsβ 2README.mdβ 4
π Real-World Examplesβ
Example 1: Full-Stack JavaScript Projectβ
root = true
# Defaults for all files
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# JavaScript/TypeScript
[*.{js,jsx,ts,tsx,mjs,cjs}]
indent_style = space
indent_size = 2
max_line_length = 100
# JSON
[*.json]
indent_style = space
indent_size = 2
# YAML (strict 2-space requirement)
[*.{yml,yaml}]
indent_style = space
indent_size = 2
# Markdown (preserve trailing spaces for line breaks)
[*.md]
trim_trailing_whitespace = false
max_line_length = 80
# Package manager files
[{package.json,package-lock.json,yarn.lock,pnpm-lock.yaml}]
indent_style = space
indent_size = 2
Example 2: Python Data Science Projectβ
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# Python (PEP 8)
[*.py]
indent_style = space
indent_size = 4
max_line_length = 79
# Jupyter Notebooks metadata
[*.ipynb]
indent_style = space
indent_size = 1
# Requirements files
[requirements*.txt]
indent_style = space
indent_size = 4
# Configuration
[*.{toml,ini,cfg}]
indent_style = space
indent_size = 4
# Scripts
[*.sh]
indent_style = space
indent_size = 2
# Markdown
[*.md]
trim_trailing_whitespace = false
max_line_length = 88 # Black formatter compatible
Example 3: Go Projectβ
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# Go (gofmt standard)
[*.go]
indent_style = tab
indent_size = 4
# Go modules
[go.{mod,sum}]
indent_style = tab
# YAML (Kubernetes configs, etc.)
[*.{yml,yaml}]
indent_style = space
indent_size = 2
# Makefiles (must use tabs)
[Makefile]
indent_style = tab
# Shell scripts
[*.sh]
indent_style = space
indent_size = 2
Example 4: Monorepo with Multiple Languagesβ
root = true
# Global defaults
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
# Python overrides
[*.py]
indent_size = 4
# Go overrides
[*.go]
indent_style = tab
indent_size = 4
# Java overrides
[*.java]
indent_size = 4
# Makefiles (must use tabs)
[{Makefile,*.mk}]
indent_style = tab
# Configuration files
[*.{toml,ini}]
indent_size = 4
# Markdown
[*.md]
trim_trailing_whitespace = false
max_line_length = 120
β Best Practicesβ
1. Always Set root = trueβ
# β
Good
root = true
[*]
# ...
# β Bad - might inherit from parent directories
[*]
# ...
2. Order Patterns from General to Specificβ
# β
Good - easier to read and maintain
[*]
indent_size = 4
[*.js]
indent_size = 2
[test/**.js]
indent_size = 4
# β Bad - harder to understand precedence
[test/**.js]
indent_size = 4
[*]
indent_size = 4
[*.js]
indent_size = 2
3. Group Related File Typesβ
# β
Good - organized by category
# Frontend
[*.{js,jsx,ts,tsx}]
indent_size = 2
# Styles
[*.{css,scss,sass,less}]
indent_size = 2
# Backend
[*.{py,java,go}]
indent_size = 4
4. Document Non-Obvious Settingsβ
# Markdown: preserve trailing spaces for line breaks
[*.md]
trim_trailing_whitespace = false
# Python: PEP 8 compliance
[*.py]
indent_size = 4
max_line_length = 79
5. Use .gitattributes for Line Endingsβ
Don't rely solely on EditorConfig for line endings. Use both:
# .editorconfig
[*]
end_of_line = lf
# .gitattributes
* text=auto eol=lf
*.bat text eol=crlf
6. Keep It Simpleβ
# β
Good - minimal, clear
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
[*.py]
indent_size = 4
# β Bad - over-configured
root = true
[*]
charset = utf-8
end_of_line = lf
# ... 50 more properties for every conceivable file type
7. Test Your Configurationβ
# Install EditorConfig CLI
npm install -g editorconfig
# Check what properties apply to a file
editorconfig src/index.js
# Output example:
# indent_style=space
# indent_size=2
# end_of_line=lf
π Advanced Techniquesβ
1. Per-Directory Configurationβ
project/
βββ .editorconfig # Root config
βββ frontend/
β βββ .editorconfig # Frontend overrides (2-space)
β βββ src/
βββ backend/
βββ .editorconfig # Backend overrides (4-space)
βββ src/
Root .editorconfig:
root = true
[*]
charset = utf-8
end_of_line = lf
frontend/.editorconfig:
# Don't set root = true (inherit from parent)
[*.{js,jsx,ts,tsx}]
indent_size = 2
backend/.editorconfig:
# Don't set root = true
[*.py]
indent_size = 4
2. Unset Propertiesβ
[*]
indent_size = 4
[*.md]
indent_size = unset # Remove inherited indent_size
3. Integration with Lintersβ
EditorConfig works alongside linters. Configure both:
.editorconfig:
[*.js]
indent_size = 2
max_line_length = 100
.eslintrc.json:
{
"rules": {
"indent": ["error", 2],
"max-len": ["error", { "code": 100 }]
}
}
Some linters can read EditorConfig:
- ESLint:
eslint-plugin-editorconfig - Prettier: Reads EditorConfig automatically
4. Editor-Specific Extensionsβ
Some editors support non-standard properties:
# VS Code specific
[*.js]
# Standard properties
indent_size = 2
# VS Code extensions (require plugins)
quote_type = single # Not standard
Warning: Non-standard properties won't work in other editors.
5. Workspace vs Global EditorConfigβ
You can have both:
- Project config:
.editorconfigin repository (version-controlled) - Global config:
~/.editorconfig(personal defaults)
Project config always overrides global config.
π§ Troubleshootingβ
Problem: EditorConfig Not Workingβ
Checklist:
- β
Is
.editorconfigin project root? - β
Does it have
root = true? - β Is your editor supported? (Check here)
- β Is the plugin installed/enabled?
- β Are glob patterns correct?
- β Did you reload/reopen the file?
Problem: Settings Not Applied to Existing Filesβ
EditorConfig only applies when:
- File is opened
- File is edited
- Editor is restarted
Solution: Reload file or restart editor.
Problem: Conflicting Settingsβ
[*]
indent_size = 4
[*.js]
indent_size = 2
indent_size = 8 # β Conflict - last one wins
Solution: Remove duplicate properties.
Problem: Pattern Not Matchingβ
# β Won't work - EditorConfig doesn't support negation
[!test/*.js]
# β
Instead, be more specific with positive patterns
[src/**.js]
Problem: Tab Width vs Indent Sizeβ
# If using spaces
[*.js]
indent_style = space
indent_size = 2 # Correct
# If using tabs
[*.go]
indent_style = tab
tab_width = 4 # How tabs are displayed
indent_size = 4 # Should match tab_width (for tools)
Debugging Commandsβ
# Check EditorConfig CLI
editorconfig --version
# Test file matching
editorconfig /path/to/file.js
# Verify syntax (Python)
python -c "import configparser; configparser.ConfigParser().read('.editorconfig')"
π Resourcesβ
Official Documentationβ
- Official Site: https://editorconfig.org/
- Specification: https://spec.editorconfig.org/
- GitHub: https://github.com/editorconfig
Editor Pluginsβ
| Editor | Plugin | Installation |
|---|---|---|
| VS Code | Built-in | No plugin needed |
| IntelliJ IDEA | Built-in | No plugin needed |
| Sublime Text | EditorConfig | Package Control |
| Vim/Neovim | editorconfig-vim | Plugin manager |
| Emacs | editorconfig-emacs | MELPA |
| Atom | editorconfig | apm install |
Study Real-World Configsβ
Learn from popular projects:
# Clone and study
git clone https://github.com/nodejs/node.git
cat node/.editorconfig
git clone https://github.com/django/django.git
cat django/.editorconfig
git clone https://github.com/microsoft/vscode.git
cat vscode/.editorconfig
Projects to study:
Interactive Learningβ
- EditorConfig Playground: https://editorconfig-playground.netlify.app/
- Test patterns and see results immediately
CLI Toolsβ
# Install EditorConfig CLI (Node.js)
npm install -g editorconfig
# Or (Python)
pip install editorconfig
# Usage
editorconfig file.js
editorconfig --version
Style Guidesβ
Reference popular style guides:
- JavaScript: Airbnb, Google, Standard
- Python: PEP 8
- Ruby: Ruby Style Guide
- Go: Effective Go
- Java: Google Java Style
Communityβ
- Stack Overflow: editorconfig tag
- Reddit: r/programming discussions
- GitHub Issues: Report bugs or request features
π Learning Exercisesβ
Exercise 1: Basic Setupβ
Create an .editorconfig for a mixed project with:
- JavaScript (2 spaces)
- Python (4 spaces)
- YAML (2 spaces)
- Markdown (no trailing space trimming)
Exercise 2: Pattern Matchingβ
Write patterns to match:
- All test files (ending in
.test.jsor.spec.js) - All config files in root only
- All JavaScript files except in
node_modules
Exercise 3: Multi-Directoryβ
Set up a monorepo with:
- Root config with common settings
- Frontend folder with 2-space indents
- Backend folder with 4-space indents
Exercise 4: Migrationβ
Migrate an existing project from:
- Prettier config β EditorConfig
- ESLint config β EditorConfig
- Maintain compatibility with both
Exercise 5: Team Adoptionβ
Create a guide for your team on:
- How to install EditorConfig
- How to verify it's working
- How to resolve conflicts
π Mastery Checklistβ
- Created
.editorconfigfor at least 3 different project types - Understand all standard properties and when to use them
- Can write complex glob patterns
- Set up EditorConfig in all your editors
- Contributed to or fixed an EditorConfig issue
- Helped a team member set up EditorConfig
- Integrated EditorConfig with linters/formatters
- Wrote documentation for your organization's standards
- Can debug EditorConfig issues quickly
- Taught others about EditorConfig
π Quick Reference Cardβ
# Minimal template for any project
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
# Language overrides
[*.py]
indent_size = 4
[*.go]
indent_style = tab
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
Happy coding with consistent style! π
Last updated: 2025-11-30