Skip to content

fs0414/rfmt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

234 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

rfmt

A Ruby code formatter written in Rust

Gem Version License: MIT

Installation β€’ Usage β€’ Features β€’ Editor Integration β€’ Documentation β€’ Contributing


What is rfmt?

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

Features

Performance

Built with Rust for improved execution speed. See Performance Benchmarks section for details.

Consistent Style

Enforces code style rules:

  • Automatic indentation
  • Spacing and alignment normalization
  • Quote style standardization
  • Method definition formatting

Performance

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.

Installation

Requirements

  • Ruby 3.0 or higher
  • Rust 1.70 or higher (for building from source)

From RubyGems

gem install rfmt

In Your Gemfile

gem 'rfmt'

Then run:

bundle install

From Source

git clone https://github.com/fs0414/rfmt.git
cd rfmt
bundle install
bundle exec rake compile

Usage

Initialize Configuration

First, create a configuration file with default settings:

rfmt init

This 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 --force

Command Line

Format a single file:

rfmt lib/user.rb

Format multiple files:

rfmt lib/**/*.rb

Format all files in your project:

rfmt .

Check if files need formatting (CI/CD):

rfmt check .

Show diff without modifying files:

rfmt lib/user.rb --diff

Quiet mode (minimal output):

rfmt --quiet lib/**/*.rb

Enable verbose output for debugging:

rfmt --verbose lib/user.rb

Common Options

Option Description
--check Check formatting without writing files
--diff Show diff of changes
--quiet Minimal output
--verbose Detailed output with timing

Output Modes

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 formatted

Verbose 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.6

Parallel Processing

rfmt 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/

Cache Management

rfmt uses caching to improve performance on large codebases:

# Clear cache if needed
rfmt cache clear

# View cache statistics  
rfmt cache stats

Ruby API

Input (unformatted code):

require 'rfmt'

source = <<~RUBY
  class User
  def initialize(name)
  @name=name
  end
  end
RUBY

formatted = Rfmt.format(source)
puts formatted

Output (formatted code):

class User
  def initialize(name)
    @name=name
  end
end

Configuration

Configuration File Discovery

rfmt automatically searches for configuration files in this order:

  1. Current directory (.rfmt.yml, .rfmt.yaml, rfmt.yml, or rfmt.yaml)
  2. Parent directories (up to root)
  3. User home directory (.rfmt.yml, .rfmt.yaml, rfmt.yml, or rfmt.yaml)
  4. Default settings (if no file found)

Ruby API for Configuration

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, ...}, ...}

Examples

Before Formatting

class User<ApplicationRecord
has_many :posts
validates :email,presence: true
def full_name
"#{first_name} #{last_name}"
end
end

After Formatting

class User < ApplicationRecord
  has_many :posts
  validates :email, presence: true

  def full_name
    "#{first_name} #{last_name}"
  end
end

Editor Integration

Neovim

Format 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,
})

Coming Soon

  • VS Code - Extension in development
  • RubyMine - Plugin in development
  • Zed - Extension in development

Development

Setup

After cloning the repository:

bundle install
bundle exec lefthook install

Git Hooks

This 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

Running Tests

# Ruby tests
bundle exec rspec

# Rust tests
cargo test --manifest-path ext/rfmt/Cargo.toml

# All tests
bundle exec rake dev:test_all

Documentation

Documentation is available in the docs directory:

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Comparison with Other Tools

rfmt vs RuboCop

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.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the rfmt project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Support

Acknowledgments

  • Built with Prism - Modern Ruby parser
  • Powered by Rust - Performance and safety
  • FFI via Magnus - Ruby-Rust bridge

Created by Fujitani Sora

About

A fast Ruby code formatter build in Rust

Topics

Resources

License

MIT, MIT licenses found

Licenses found

MIT
LICENSE
MIT
LICENSE.txt

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •