|
1 | 1 | # CodeSearch
|
2 | 2 |
|
3 |
| -[](https://LilithHafner.github.io/CodeSearch.jl/stable/) |
| 3 | +<!-- [](https://LilithHafner.github.io/CodeSearch.jl/stable/) --> |
4 | 4 | [](https://LilithHafner.github.io/CodeSearch.jl/dev/)
|
5 | 5 | [](https://github.com/LilithHafner/CodeSearch.jl/actions/workflows/CI.yml?query=branch%3Amain)
|
6 | 6 | [](https://codecov.io/gh/LilithHafner/CodeSearch.jl)
|
7 | 7 | [](https://JuliaCI.github.io/NanosoldierReports/pkgeval_badges/C/CodeSearch.html)
|
8 | 8 | [](https://github.com/JuliaTesting/Aqua.jl)
|
| 9 | + |
| 10 | + |
| 11 | +CodeSearch.jl is a package for semantically searching Julia code. Unlike plain string search |
| 12 | +and regex search, CodeSearch performs search operations _after_ parsing. Thus the search |
| 13 | +patterns `j"a + b"` and `j"a+b"` are equivalent, and both match the code `a +b`. |
| 14 | + |
| 15 | +```julia |
| 16 | +julia> using CodeSearch |
| 17 | + |
| 18 | +julia> j"a + b" == j"a+b" |
| 19 | +true |
| 20 | + |
| 21 | +julia> findfirst(j"a+b", "sqrt(a +b)/(a+ b)") |
| 22 | +6:9 |
| 23 | +``` |
| 24 | + |
| 25 | +The other key feature in this package is wildcard matching. You can use the character `*` to |
| 26 | +match any expression. For example, the pattern `j"a + *"` matches both `a + b` and |
| 27 | +`a + (b + c)` . |
| 28 | + |
| 29 | +```julia |
| 30 | +julia> Expr.(eachmatch(j"a + *", "a + (a + b), a + sqrt(2)")) |
| 31 | +3-element Vector{Expr}: |
| 32 | + :(a + (a + b)) |
| 33 | + :(a + b) |
| 34 | + :(a + sqrt(2)) |
| 35 | +``` |
| 36 | + |
| 37 | +Here we can see that `j"a + *"` matches multiple places, even some that nest within |
| 38 | +eachother! |
| 39 | + |
| 40 | +Finally, it is possible to extract the "captured values" that match the wildcards. |
| 41 | + |
| 42 | +```julia |
| 43 | +julia> m = match(j"a + *", "a + (a + b), a + sqrt(2)") |
| 44 | +CodeSearch.Match((call-i a + (call-i a + b)), captures=[(call-i a + b)]) |
| 45 | + |
| 46 | +julia> m.captures |
| 47 | +1-element Vector{JuliaSyntax.SyntaxNode}: |
| 48 | + (call-i a + b) |
| 49 | + |
| 50 | +julia> Expr(only(m.captures)) |
| 51 | +:(a + b) |
| 52 | +``` |
| 53 | + |
| 54 | +## How to use this package |
| 55 | + |
| 56 | +1. Create `Pattern`s with the `@j_str` macro or the |
| 57 | + `CodeSearch.pattern` function. |
| 58 | +2. Search an `AbstractString` or a `JuliaSyntax.SyntaxNode` for whether and where that |
| 59 | + pattern occurs with generic functions like `occursin`, `findfirst`, `findlast`, or |
| 60 | + `findall` _OR_ extract the actual `Match`es with generic functions like `eachmatch` and |
| 61 | + `match`. |
| 62 | +3. If you extracted an actual match, access relevant information using the public |
| 63 | + `syntax_node` and `captures` fields, convert to a `SyntaxNode`, `Expr`, or |
| 64 | + `AbstractString` via constructors, index into the captures directly with `getindex`, or |
| 65 | + extract the indices in the original string that match the capture with |
| 66 | + `indices`. |
0 commit comments