From 7aed4587e568bf9a4f2e562623d63d13dc87209b Mon Sep 17 00:00:00 2001 From: Leandro Martinez Date: Tue, 11 Feb 2025 15:31:55 -0300 Subject: [PATCH] support interpolation in sel"" macro. --- src/select.jl | 29 +++++++++++++++++++++++++---- test/runtests.jl | 5 +++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/select.jl b/src/select.jl index 504fbc8..9b3a7e8 100644 --- a/src/select.jl +++ b/src/select.jl @@ -435,18 +435,39 @@ Trivial selector that returns `true` for any structural element. allselector(el) = true # Acts as a function when used within typical julia filtering functions -# by converting a string selection into a query call +# by converting a string selection into a query call struct Select <: Function sel::String end - (s::Select)(at) = apply_query(parse_query(s.sel), at) +# +# Parse selection string allowing interpolation in sel macro: +# https://discourse.julialang.org/t/str-string-interpolation/125766/11?u=lmiq +# +_select(args...) = Select(string(args...)) "String selection syntax." -macro sel_str(str) - Select(str) +macro sel_str(s) + ex = Expr(:call, GlobalRef(BioStructures, :_select)) + i = firstindex(s) + buf = IOBuffer(maxsize=ncodeunits(s)) + while i <= ncodeunits(s) + c = @inbounds s[i] + i = nextind(s, i) + if c === '$' + position(buf) > 0 && push!(ex.args, String(take!(buf))) + val, i = Meta.parse(s, i; greedy=false) + Meta.isexpr(val, :incomplete) && error(val.args[1]) + val !== nothing && push!(ex.args, val) + else + print(buf, c) + end + end + position(buf) > 0 && push!(ex.args, String(take!(buf))) + return esc(ex) end + const operators = ( "=" => (x, y) -> isequal(x, y), "<" => (x, y) -> isless(x, y), diff --git a/test/runtests.jl b/test/runtests.jl index 6838387..86603b4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -928,6 +928,11 @@ end @test length(collectatoms(struc, sel"disordered")) == 68 @test length(collectatoms(struc, sel"sscode E")) == 2448 @test length(collectatoms(struc, sel"helix")) == 4047 + # check interpolation support + ss_type = "helix" + @test length(collectatoms(struc, sel"$ss_type")) == 4047 + sel_chains = ('A', 'B') + @test length(collectresidues(struc, sel"chain $(first(sel_chains)) or chain $(last(sel_chains))")) == 544 @test length(collectresidues(struc, sel"chain A or chain B")) == 544 @test length(collectresidues(struc, sel"standard")) == 1420