A Ruby code formatter written in Rust
Installation β’ Usage β’ Features β’ Editor Integration β’ Documentation β’ Contributing
RubyGems reference DeepWiki rfmt
rfmt is a Ruby code formatter that enforces consistent style across your codebase. Key characteristics:
- Opinionated: Minimal configuration with consistent output
- Idempotent: Running multiple times produces identical results
- Comment preservation: Maintains existing comment placement
- Rust implementation: Core formatter implemented in Rust
Built with Rust for improved execution speed. See Performance Benchmarks section for details.
Enforces code style rules:
- Automatic indentation
- Spacing and alignment normalization
- Quote style standardization
- Method definition formatting
rfmt delivers consistent, fast formatting across projects of any size:
| Project Size | Files | Execution Time | Throughput |
|---|---|---|---|
| Small | 9 files | ~105ms | 85 files/sec |
| Medium | 35 files | ~110ms | 315 files/sec |
| Large | 151 files | ~100ms | 1,560 files/sec |
Key Performance Characteristics:
- Constant Time: Execution time stays around 100ms regardless of project size
- Parallel Processing: Automatic scaling with available CPU cores
- High Throughput: Up to 1,500+ files per second on large projects
- Low Overhead: Minimal startup time and memory usage
Test Environment:
- CPU: Apple Silicon (arm64)
- Ruby: 3.4.8
- Average of 5 runs per test
Built with Rust for optimal performance and memory efficiency.
For detailed performance comparisons and benchmarks, see Performance Benchmarks.
- Ruby 3.0 or higher
- Rust 1.70 or higher (for building from source)
gem install rfmtgem 'rfmt'Then run:
bundle installgit clone https://github.com/fs0414/rfmt.git
cd rfmt
bundle install
bundle exec rake compileFirst, create a configuration file with default settings:
rfmt initThis creates a .rfmt.yml file with default settings:
version: "1.0"
formatting:
line_length: 100 # Maximum line length (40-500)
indent_width: 2 # Spaces/tabs per indent (1-8)
indent_style: "spaces" # "spaces" or "tabs"
quote_style: "double" # "double", "single", or "consistent"
include:
- "**/*.rb"
- "**/*.rake"
- "**/Rakefile"
- "**/Gemfile"
exclude:
- "vendor/**/*"
- "tmp/**/*"
- "node_modules/**/*"
- "db/schema.rb"Options:
# Specify custom path
rfmt init --path config/.rfmt.yml
# Overwrite existing configuration
rfmt init --forceFormat a single file:
rfmt lib/user.rbFormat multiple files:
rfmt lib/**/*.rbFormat all files in your project:
rfmt .Check if files need formatting (CI/CD):
rfmt check .Show diff without modifying files:
rfmt lib/user.rb --diffQuiet mode (minimal output):
rfmt --quiet lib/**/*.rbEnable verbose output for debugging:
rfmt --verbose lib/user.rb| Option | Description |
|---|---|
--check |
Check formatting without writing files |
--diff |
Show diff of changes |
--quiet |
Minimal output |
--verbose |
Detailed output with timing |
Normal mode (default):
$ rfmt app/
Processing 25 file(s)...
β Formatted app/controllers/users_controller.rb
β Formatted app/models/user.rb
β Processed 25 files
(3 formatted, 22 unchanged)Quiet mode (--quiet or -q):
$ rfmt --quiet app/
β 3 files formattedVerbose mode (--verbose or -v):
$ rfmt --verbose app/
Processing 25 file(s)...
Using sequential processing for 25 files
β Formatted app/controllers/users_controller.rb
β app/models/application_record.rb already formatted
...
β Processed 25 files
(3 formatted, 22 unchanged)
Details:
Total files: 25
Total time: 0.45s
Files/sec: 55.6rfmt automatically chooses the optimal processing mode:
- < 20 files: Sequential processing (fastest for small batches)
- 20-49 files: Automatic based on average file size
- β₯ 50 files: Parallel processing (utilizes multiple cores)
You can override this behavior:
# Force parallel processing
rfmt --parallel app/
# Force sequential processing
rfmt --no-parallel app/rfmt uses caching to improve performance on large codebases:
# Clear cache if needed
rfmt cache clear
# View cache statistics
rfmt cache statsInput (unformatted code):
require 'rfmt'
source = <<~RUBY
class User
def initialize(name)
@name=name
end
end
RUBY
formatted = Rfmt.format(source)
puts formattedOutput (formatted code):
class User
def initialize(name)
@name=name
end
endrfmt automatically searches for configuration files in this order:
- Current directory (
.rfmt.yml,.rfmt.yaml,rfmt.yml, orrfmt.yaml) - Parent directories (up to root)
- User home directory (
.rfmt.yml,.rfmt.yaml,rfmt.yml, orrfmt.yaml) - Default settings (if no file found)
require 'rfmt'
# Generate configuration file
Rfmt::Config.init('.rfmt.yml', force: false)
# Find configuration file
config_path = Rfmt::Config.find
# => "/Users/username/project/.rfmt.yml"
# Check if configuration exists
Rfmt::Config.exists?
# => true
# Load configuration
config = Rfmt::Config.load
# => {"version"=>"1.0", "formatting"=>{"line_length"=>100, ...}, ...}class User<ApplicationRecord
has_many :posts
validates :email,presence: true
def full_name
"#{first_name} #{last_name}"
end
endclass User < ApplicationRecord
has_many :posts
validates :email, presence: true
def full_name
"#{first_name} #{last_name}"
end
endFormat Ruby files on save using autocmd:
-- ~/.config/nvim/init.lua
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = { "*.rb", "*.rake", "Gemfile", "Rakefile" },
callback = function()
local filepath = vim.fn.expand("%:p")
local result = vim.fn.system({ "rfmt", filepath })
if vim.v.shell_error == 0 then
vim.cmd("edit!")
end
end,
})- VS Code - Extension in development
- RubyMine - Plugin in development
- Zed - Extension in development
After cloning the repository:
bundle install
bundle exec lefthook installThis project uses lefthook for automated validation before push:
Pre-push checks:
- RuboCop (Ruby linting)
- cargo fmt --check (Rust formatting)
- cargo clippy (Rust linting)
Skip hooks temporarily:
# Skip all hooks for this push
LEFTHOOK=0 git push
# Skip specific hook
LEFTHOOK_EXCLUDE=rubocop git push# Ruby tests
bundle exec rspec
# Rust tests
cargo test --manifest-path ext/rfmt/Cargo.toml
# All tests
bundle exec rake dev:test_allDocumentation is available in the docs directory:
- User Guide - Comprehensive usage guide
- Error Reference - Error codes and troubleshooting
- Contributing Guide - How to contribute
We welcome contributions! Please see our Contributing Guide for details.
| Feature | rfmt | RuboCop |
|---|---|---|
| Primary Purpose | Code formatting | Linting + formatting |
| Configuration | Minimal | Extensive |
| Code Quality Checks | No | Yes |
| Bug Detection | No | Yes |
Note: rfmt focuses on code formatting, while RuboCop provides additional code quality analysis. They can be used together.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the rfmt project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
- π Documentation
- π Issues
- π§ Email: fujitanisora0414@gmail.com
- Built with Prism - Modern Ruby parser
- Powered by Rust - Performance and safety
- FFI via Magnus - Ruby-Rust bridge
Created by Fujitani Sora