comby
A code rewrite tool for structural search and replace that supports ~every language.
Top Related Projects
Tools for code analysis, visualizations, or style-preserving source transformation.
Lightweight static analysis for many languages. Find bug variants with patterns that look like source code.
An incremental parsing system for programming tools
Quick Overview
Comby is a tool for searching and rewriting code. It uses a unique pattern matching language that works across many programming languages and file formats. Comby aims to make structural code changes easier and more reliable than traditional regex-based approaches.
Pros
- Language-agnostic: Works with many programming languages and file formats
- Powerful pattern matching: Supports structural matching beyond simple regex
- Easy to use: Simple syntax for common operations
- Extensible: Can be integrated into other tools and workflows
Cons
- Learning curve: Requires learning a new pattern matching syntax
- Limited to structural changes: Not suitable for complex semantic transformations
- Performance: May be slower than language-specific tools for large codebases
- Documentation: Could benefit from more extensive examples and use cases
Code Examples
- Basic match and rewrite:
comby 'printf(":[1]");' 'console.log(":[1]");' .js
This command replaces all printf
calls with console.log
in JavaScript files.
- Using hole variables:
comby 'function :[name](:[args]) { :[body] }' 'const :[name] = (:[args]) => { :[body] }' .js
This transforms traditional function declarations into arrow functions.
- Using where clauses:
comby 'if (:[condition]) { :[then_branch] } else { :[else_branch] }' ':[condition] ? :[then_branch] : :[else_branch]' .js -match-only 'where :[then_branch] != "..."'
This converts if-else statements to ternary operators, but only when the then branch is not a block.
Getting Started
To get started with Comby:
-
Install Comby:
bash <(curl -sL get.comby.dev)
-
Run a basic match and rewrite:
comby 'foo(:[1])' 'bar(:[1])' .py
-
For more advanced usage, refer to the official documentation at https://comby.dev/docs/
Competitor Comparisons
Tools for code analysis, visualizations, or style-preserving source transformation.
Pros of pfff
- More comprehensive static analysis toolset with support for multiple languages
- Includes advanced features like type inference and dataflow analysis
- Offers visualization tools for code structure and dependencies
Cons of pfff
- Less actively maintained (last commit in 2019)
- Steeper learning curve due to its complexity
- Limited documentation and community support
Code Comparison
pfff (OCaml):
let parse_program file =
let ast = Parse_php.parse_program file in
let ast = Ast_php_simple_build.program ast in
ast
Comby (Pattern matching):
:[prefix]function :[name](...) {
:[body]
}
Key Differences
- pfff is a more comprehensive static analysis tool, while Comby focuses on pattern matching and rewriting
- pfff is written in OCaml, whereas Comby uses its own pattern matching language
- Comby is more actively maintained and has better documentation
- pfff offers deeper analysis capabilities, but Comby is easier to use for quick code transformations
Use Cases
- Use pfff for in-depth static analysis and visualization of large codebases
- Choose Comby for quick, language-agnostic code refactoring and pattern matching tasks
Lightweight static analysis for many languages. Find bug variants with patterns that look like source code.
Pros of Semgrep
- More extensive language support, covering 30+ languages
- Advanced features like taint analysis and dataflow tracking
- Large rule database with community-contributed rules
Cons of Semgrep
- Steeper learning curve for creating custom rules
- Slower performance on large codebases compared to Comby
- More complex setup and configuration process
Code Comparison
Semgrep rule example:
rules:
- id: detect-eval
pattern: eval($X)
message: "Dangerous use of eval()"
languages: [python]
severity: WARNING
Comby pattern example:
eval(:[arg])
Both tools aim to improve code quality and security through pattern matching, but they differ in approach and complexity. Semgrep offers more advanced features and broader language support, making it suitable for complex analysis tasks. Comby, on the other hand, provides a simpler, faster solution for basic pattern matching across multiple languages.
Semgrep's rule-based approach allows for more nuanced and context-aware checks, while Comby's lightweight design enables quick and easy pattern matching without the need for language-specific parsing.
Choose Semgrep for comprehensive, language-aware analysis in large projects, and Comby for rapid, language-agnostic pattern matching and transformation tasks in smaller codebases or specific use cases.
An incremental parsing system for programming tools
Pros of Tree-sitter
- More robust parsing with full syntax trees
- Supports incremental parsing for better performance
- Wider language support out-of-the-box
Cons of Tree-sitter
- Steeper learning curve for creating and modifying grammars
- Requires more setup and integration effort
- Less flexible for quick, pattern-based searches
Code Comparison
Tree-sitter grammar example:
module {
rules {
source_file: $ => repeat($._definition),
_definition: $ => choice(
$.function_definition,
$.variable_declaration
),
function_definition: $ => seq(
'func',
$.identifier,
$.parameter_list,
$.block
)
}
}
Comby pattern example:
func :[name](...) {
:[body]
}
Tree-sitter provides a more comprehensive parsing solution, generating full syntax trees for supported languages. It offers better performance for large codebases and incremental parsing capabilities. However, it requires more setup and has a steeper learning curve for creating custom grammars.
Comby, on the other hand, focuses on simpler pattern-based matching and rewriting. It's more flexible for quick searches and transformations but may not handle complex language constructs as accurately as Tree-sitter.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
comby
See the usage documentation.
A short example below shows how comby simplifies matching and rewriting compared to regex approaches like sed
.
Comby supports interactive review mode (click here to see it in action).
Install (pre-built binaries)
Mac OS X
brew install comby
Ubuntu Linux
-
bash <(curl -sL get-comby.netlify.app)
-
Other Linux distributions: The PCRE library is dynamically linked in the Ubuntu binary. For other distributions like Arch Linux, a fixup is needed:
sudo ln -s /usr/lib/libpcre.so /usr/lib/libpcre.so.3
. On Fedora, usesudo ln -s /usr/lib64/libpcre.so /usr/lib64/libpcre.so.3
. Alternatively, consider building from source.
Windows
- Install the Windows Subsystem for Linux and install Ubuntu. Then run
bash <(curl -sL get.comby.dev)
Docker
docker pull comby/comby
click to expand an example invocation for the docker image
Running with docker on stdin
:
docker run -a stdin -a stdout -a stderr -i comby/comby '(:[emoji] hi)' 'bye :[emoji]' lisp -stdin <<< '(ð hi)'
Or try it live.
Isn't a regex approach like sed good enough?
Sometimes, yes. But often, small changes and refactorings are complicated by nested expressions, comments, or strings. Consider the following C-like snippet. Say the challenge is to rewrite the two if
conditions to the value 1
. Can you write a regular expression that matches the contents of the two if condition expressions, and only those two? Feel free to share your pattern with @rvtond on Twitter.
if (fgets(line, 128, file_pointer) == Null) // 1) if (...) returns 0
return 0;
...
if (scanf("%d) %d", &x, &y) == 2) // 2) if (scanf("%d) %d", &x, &y) == 2) returns 0
return 0;
To match these with comby, all you need to write is if (:[condition])
, and specify one flag that this language is C-like. The replacement is if (1)
. See the live example.
Build from source
-
Install opam. TL;DR do
sh <(curl -sL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)
-
Run this if you don't have OCaml installed (it bootstraps the OCaml compiler):
opam init
opam switch create 4.11.0 4.11.0
-
Run
eval $(opam env)
-
Install OS dependencies:
-
Linux:
sudo apt-get install autoconf libpcre3-dev pkg-config zlib1g-dev m4 libgmp-dev libev4 libsqlite3-dev
-
Mac:
brew install pkg-config gmp pcre libev
-
-
Then install the library dependencies:
git clone https://github.com/comby-tools/comby
cd comby
opam install . --deps-only
- Build and test
make
make test
- Install
comby
on yourPATH
by running
make install
Top Related Projects
Tools for code analysis, visualizations, or style-preserving source transformation.
Lightweight static analysis for many languages. Find bug variants with patterns that look like source code.
An incremental parsing system for programming tools
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot