srgn: A Code Surgeon That Understands Your Syntax — Not Just Your Strings
文章目录
- Syntax-Aware Scoping: Unlike plain regex, you can restrict searches to specific syntactic elements (e.g., all class bodies in a Python file) using tree-sitter grammars. The regex is then applied only within those scopes, dramatically reducing false positives. In-Place Manipulation: Beyond search, srgn supports zero or more actions — replacements, case transformations (--upper, --lower, --camel, --snake), and more — all composable on the command line. Language Extensibility: Support for C, C++, Go, Java, JavaScript, Python, Rust, and more is built in via tree-sitter. The community is actively contributing new language parsers and --[lang]-query arguments (see discussions below).
-
- Contributor @bheylin submitted a PR that lets users pass custom tree-sitter .scm query files directly to srgn, rather than writing inline queries on the command line. The discussion involved reviewing the PhantomData approach for type safety and eventually simplifying it away for cleaner code: "The PhantomData approach existed to be extra strict. I expected those types to be shuffled about a lot, where confusing them would be bad. But turns out that doesn't really happen, with construction only occurring in a single place. Getting rid of the weirdly cyclic CodeQuery constructs is a breath of fresh air and appreciated." — @bheylin, PR #144
- The community debated renaming the core Language type to CompiledQuery, since it better reflects what the struct actually does — it's not a language enum but a compiled tree-sitter query scoped to a specific language. Maintainer @alexpovel guided the refactoring and merged it after fixing Clippy lints: "I reduced the amount of code in the impl_lang_scopes macro and fixed the tests. All clippies are fixed and the tests pass locally." — @bheylin, closing the rename PR after community review
- Building on PR #144, this issue proposes adding a dedicated --[lang]-query-file CLI argument for convenience. The discussion also surfaced a Rust toolchain version inconsistency in CI (some runners on 1.81, some on 1.82), which was noted as a flaky, pre-existing issue unrelated to the PR itself: "If you rebase onto main, there's some goodies waiting: ./scripts/update-readme.py will update the srgn --help section automatically — good quality of life improvement!" — @alexpovel, outlining upcoming contributor experience improvements
- srgn fills a genuine gap between blunt regex tools and heavyweight IDE refactoring. Its syntax-aware scoping means you can safely rename a method across an entire codebase without accidentally touching a comment that mentions the old name. The Rust implementation ensures it's fast, memory-efficient, and ships as a single static binary. With active community contributions for new language support and an approachable codebase, it's a project well worth exploring — or contributing to. If you regularly work across multiple languages and need more power than sed but less ceremony than a full IDE refactor, srgn might be exactly the tool you've been looking for. 🔗 Project: github.com/alexpovel/srgn — by @alexpovel
srgn (short for "surgeon") is a Rust-based, grep-like command-line tool that goes far beyond plain-text matching. While grep, sed, and regex are powerful in isolation, srgn combines them with tree-sitter syntax awareness to let you search and transform code with surgical precision — operating only within the syntactic elements you specify, like class bodies, function signatures, or string literals.
Think of it as the lovechild of tr, sed, ripgrep, and tree-sitter — a tool that knows what your code is, not just that it contains a string. It was recently featured on the Real Python Podcast, and its active GitHub community is pushing out new language parsers and ergonomic improvements every week.
- Syntax-Aware Scoping: Unlike plain regex, you can restrict searches to specific syntactic elements (e.g., all
class bodies in a Python file) using tree-sitter grammars. The regex is then applied only within those scopes, dramatically reducing false positives.
- In-Place Manipulation: Beyond search,
srgn supports zero or more actions — replacements, case transformations (--upper, --lower, --camel, --snake), and more — all composable on the command line.
- Language Extensibility: Support for C, C++, Go, Java, JavaScript, Python, Rust, and more is built in via tree-sitter. The community is actively contributing new language parsers and
--[lang]-query arguments (see discussions below).
class bodies in a Python file) using tree-sitter grammars. The regex is then applied only within those scopes, dramatically reducing false positives.srgn supports zero or more actions — replacements, case transformations (--upper, --lower, --camel, --snake), and more — all composable on the command line.--[lang]-query arguments (see discussions below).Contributor @bheylin submitted a PR that lets users pass custom tree-sitter .scm query files directly to srgn, rather than writing inline queries on the command line. The discussion involved reviewing the PhantomData approach for type safety and eventually simplifying it away for cleaner code:
"The
PhantomDataapproach existed to be extra strict. I expected those types to be shuffled about a lot, where confusing them would be bad. But turns out that doesn't really happen, with construction only occurring in a single place. Getting rid of the weirdly cyclicCodeQueryconstructs is a breath of fresh air and appreciated."— @bheylin, PR #144
The community debated renaming the core Language type to CompiledQuery, since it better reflects what the struct actually does — it's not a language enum but a compiled tree-sitter query scoped to a specific language. Maintainer @alexpovel guided the refactoring and merged it after fixing Clippy lints:
"I reduced the amount of code in the
impl_lang_scopesmacro and fixed the tests. All clippies are fixed and the tests pass locally."— @bheylin, closing the rename PR after community review
Building on PR #144, this issue proposes adding a dedicated --[lang]-query-file CLI argument for convenience. The discussion also surfaced a Rust toolchain version inconsistency in CI (some runners on 1.81, some on 1.82), which was noted as a flaky, pre-existing issue unrelated to the PR itself:
"If you rebase onto
main, there's some goodies waiting:./scripts/update-readme.pywill update thesrgn --helpsection automatically — good quality of life improvement!"— @alexpovel, outlining upcoming contributor experience improvements
srgn fills a genuine gap between blunt regex tools and heavyweight IDE refactoring. Its syntax-aware scoping means you can safely rename a method across an entire codebase without accidentally touching a comment that mentions the old name. The Rust implementation ensures it's fast, memory-efficient, and ships as a single static binary. With active community contributions for new language support and an approachable codebase, it's a project well worth exploring — or contributing to.
If you regularly work across multiple languages and need more power than sed but less ceremony than a full IDE refactor, srgn might be exactly the tool you've been looking for.
🔗 Project: github.com/alexpovel/srgn — by @alexpovel