Releases: alexpovel/srgn
srgn: v0.13.1
srgn: v0.13.0
0.13.0 (2024-08-18)
Highlights
srgn
is a tool for precise search and manipulation of text, with special support for source code in a number of languages (Rust, Python, Go and more). The main highlight in this release is a new search mode. Think of it like (rip)grep, which this is modeled after, with an additional understanding of source code syntax (and an option for manipulating, not just displaying findings). Search mode is entered when no manipulation is requested and a programming language is specified. For example, searching the pydantic repo:
$ srgn --python class --python doc-strings 'github\.com'
pydantic/networks.py
381: [`email-validator`](https://github.com/JoshData/python-email-validator) package:
426: [`email-validator`](https://github.com/JoshData/python-email-validator) package:
pydantic/config.py
732: See [#6737](https://github.com/pydantic/pydantic/pull/6737) for details.
744: serialization. See [#7209](https://github.com/pydantic/pydantic/issues/7209) for more details.
<SNIP>
The regex github\.com
was sought and found only within docstrings within class
bodies (aka, intersection works left-to-right), in all Python source code files of the working directory, recursively. Docstrings outside of class
bodies were not considered. Relevant files are found by consulting file extensions and shebang lines, a heuristic that can optionally be overwritten by a custom glob.
Variables
As another example, with the support for variables also landing as part of this release, one could rewrite GitHub issue links in only docstrings and comments (and not, for example, in "literal strings"
of source code) with an invocation of
$ srgn --join-language-scopes --python comments --python doc-strings ' (https://github\.com/(\w+)/(\w+)/issues/(\d+)/?) ' ' [issue $2/$3/$4]($1) '
pydantic/fields.py
pydantic/_internal/_model_construction.py
pydantic/_internal/_generics.py
pydantic/mypy.py
pydantic/v1/typing.py
pydantic/v1/validators.py
pydantic/v1/mypy.py
tests/test_edge_cases.py
turning them into into Markdown-formatted links (srgn
prints names of processed files to stdout), e.g.
- See https://github.com/pydantic/pydantic/issues/6763 for context.
+ See [issue pydantic/pydantic/6763](https://github.com/pydantic/pydantic/issues/6763) for context.
The variables ($1
, ...) in the replacement string are populated from regex capture groups. The --join-language-scopes
flag configures comments
and doc-strings
to be jointly considered (and not just "doc-strings
inside comments
" as before, which would probably come up empty).
Focus
srgn
builds on top of the excellent tree-sitter family of parsers. Its main focus is on search with just that little bit of extra precision regular expressions cannot offer on their own (in the context of language grammars). For large-scale, demanding refactoring efforts, consider one of the various similar tools: srgn
is focused on simplicity, with very obvious mechanisms and good discoverability. For example, it will give you a list of available options if an invalid one is specified:
$ srgn --rust class
error: invalid value 'class' for '--rust <RUST>'
[possible values: comments, doc-comments, uses, strings, attribute, struct, priv-struct, pub-struct, pub-crate-struct, pub-self-struct, pub-super-struct, enum, priv-enum, pub-enum, pub-crate-enum, pub-self-enum, pub-super-enum, enum-variant, fn, impl-fn, priv-fn, pub-fn, pub-crate-fn, pub-self-fn, pub-super-fn, const-fn, async-fn, unsafe-fn, extern-fn, test-fn, trait, impl, impl-type, impl-trait, mod, mod-tests, type-def, identifier, type-identifier, closure]
For more information, try '--help'.
In other words: there is no query language to learn. If you know regex and the basics of your language of choice, you are golden. Shell completions then make writing srgn
invocations quick and easy.
Performance
Lastly, srgn
is designed for performance: all processing happens in fast, native code (either C via tree-sitter or Rust). For example, running in the enormous kubernetes repo, the following completes in just 1 second (on M3 Pro, warm cache), finding about 9000 results of struct tags containing omitempty
markers:
srgn --go struct-tags 'omitempty'
⚠ BREAKING CHANGES
grep
-like, recursive search mode- Update
tree-sitter
& bindings - Adjust
IGNORE
pattern - Variables for replacement action
Ranges
Features
grep
-like, recursive search mode (d55b28f)Ranges
(bd8b0bc)- c#: Scope
class
definitions (f65137d) - c#: Scope
enum
definitions (31dc2cb) - c#: Scope
interface
definitions (338b5f4) - c#: Scope
struct
definitions (5b53286) - c#: Scope attribute names (c3fe051)
- c#: Scope constructor definitions (d8b5e7a)
- c#: Scope destructor definitions (6f9677b)
- c#: Scope field definitions (3f2d919)
- c#: Scope identifier names (0267196)
- c#: Scope method definitions (5b530a1)
- c#: Scope property definitions (769ffef)
- c#: Scope variable declarations (09879ea)
- cli:
-j
aka--join-language-scopes
flag (2c1b9e8) - go: Ignore file paths containing
vendor
(0be56d0) - go: Scope (any) type definitions (bf2e90c)
- go: Scope
const
assignments/specifications (61232b9) - go: Scope
defer
blocks (76a91b8) - go: Scope
func init()
definitions (106c4a6) - go: Scope
func
definitions (all, free, methods) (707e95a) - go: Scope
go
blocks (c38c5c3) - go: Scope
goto
statements (4133575) - go: Scope
select
blocks (ddbf9d9) - go: Scope
struct
andinterface
type definitions (392330f) - go: Scope
switch
blocks (61f5e08) - go: Scope
type
aliases (a1d707a) - go: Scope
var
assignments/specifications (367191d) - go: Scope labeled statements (308e28f)
- go: Scope type aka generic parameters (891aa11)
- HCL (HashiCorp Configuration Language) (814a592)
- hcl: Scope
data
blocks (dc38287) - hcl: Scope
locals
blocks (c22c475) - hcl: Scope
module
blocks (84965ed) - hcl: Scope
output
blocks (9627961) - hcl: Scope
provider
blocks (a77e603) - hcl: Scope
resource
blocks ([963d9a4](https://github.com/alexpovel/srgn/commit...
srgn: v0.12.0
srgn: v0.11.0
srgn: v0.10.2
srgn: v0.10.1
v0.10.0
v0.9.0
v0.8.0
v0.7.0
0.7.0 (2023-11-06)
⚠ BREAKING CHANGES
- Remove
Debug
implementation ofdyn Scoper
- Remove
Replacement::new
, force going through unescaping viaTryFrom<String>
- Make
Replacement
a newtype - Panic upon creation of inconsistent view