Add ~i, ~b and ~l sigils
This commit is contained in:
parent
d056d33b21
commit
3cba749945
3 changed files with 152 additions and 9 deletions
|
@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
|
|||
### Added
|
||||
|
||||
- a `RDF.Graph` builder DSL available under the `RDF.Graph.build/2` function
|
||||
- new `RDF.Sigils` `~i`, `~b` and `~l` as variants of the `~I`, `~B` and `~L`
|
||||
sigils, which support string interpolation
|
||||
- `RDF.Graph.new/2` and `RDF.Graph.add/2` support the addition of `RDF.Dataset`s
|
||||
- `RDF.Description.empty?/1`, `RDF.Graph.empty?/1`, `RDF.Dataset.empty?/1` and
|
||||
`RDF.Data.empty?/1` which are significantly faster than `Enum.empty?/1`
|
||||
|
|
|
@ -6,7 +6,9 @@ defmodule RDF.Sigils do
|
|||
@doc ~S"""
|
||||
Handles the sigil `~I` for IRIs.
|
||||
|
||||
Note: The given IRI string is precompiled into an `RDF.IRI` struct.
|
||||
It returns an `RDF.IRI` from the given string without interpolations and
|
||||
without escape characters, except for the escaping of the closing sigil
|
||||
character itself.
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -19,9 +21,36 @@ defmodule RDF.Sigils do
|
|||
Macro.escape(RDF.iri!(iri))
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
Handles the sigil `~i` for IRIs.
|
||||
|
||||
It returns an `RDF.IRI` from the given string as if it was a double quoted
|
||||
string, unescaping characters and replacing interpolations.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> import RDF.Sigils
|
||||
iex> ~i<http://example.com/#{String.downcase("Foo")}>
|
||||
RDF.iri("http://example.com/foo")
|
||||
|
||||
"""
|
||||
defmacro sigil_i({:<<>>, _, [iri]}, []) when is_binary(iri) do
|
||||
Macro.escape(RDF.iri!(iri))
|
||||
end
|
||||
|
||||
defmacro sigil_i({:<<>>, line, pieces}, []) do
|
||||
quote do
|
||||
RDF.iri!(unquote({:<<>>, line, unescape_tokens(pieces)}))
|
||||
end
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
Handles the sigil `~B` for blank nodes.
|
||||
|
||||
It returns an `RDF.BlankNode` from the given string without interpolations
|
||||
and without escape characters, except for the escaping of the closing sigil
|
||||
character itself.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> import RDF.Sigils
|
||||
|
@ -33,9 +62,34 @@ defmodule RDF.Sigils do
|
|||
Macro.escape(RDF.BlankNode.new(bnode))
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
Handles the sigil `~b` for blank nodes.
|
||||
|
||||
It returns an `RDF.BlankNode` from the given string as if it was a double quoted
|
||||
string, unescaping characters and replacing interpolations.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> import RDF.Sigils
|
||||
iex> ~b<foo#{String.downcase("Bar")}>
|
||||
RDF.bnode("foobar")
|
||||
|
||||
"""
|
||||
defmacro sigil_b({:<<>>, _, [bnode]}, []) when is_binary(bnode) do
|
||||
Macro.escape(RDF.BlankNode.new(bnode))
|
||||
end
|
||||
|
||||
defmacro sigil_b({:<<>>, line, pieces}, []) do
|
||||
quote do
|
||||
RDF.BlankNode.new(unquote({:<<>>, line, unescape_tokens(pieces)}))
|
||||
end
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
Handles the sigil `~L` for plain Literals.
|
||||
|
||||
It returns an `RDF.Literal` from the given string without interpolations and without escape characters, except for the escaping of the closing sigil character itself.
|
||||
|
||||
The sigil modifier can be used to specify a language tag.
|
||||
|
||||
Note: Languages with subtags are not supported.
|
||||
|
@ -58,4 +112,49 @@ defmodule RDF.Sigils do
|
|||
defmacro sigil_L({:<<>>, _, [value]}, language) when is_binary(value) do
|
||||
Macro.escape(RDF.LangString.new(value, language: to_string(language)))
|
||||
end
|
||||
|
||||
@doc ~S"""
|
||||
Handles the sigil `~l` for blank nodes.
|
||||
|
||||
It returns an `RDF.Literal` from the given string as if it was a double quoted
|
||||
string, unescaping characters and replacing interpolations.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> import RDF.Sigils
|
||||
iex> ~l"foo #{String.downcase("Bar")}"
|
||||
RDF.literal("foo bar")
|
||||
iex> ~l"foo #{String.downcase("Bar")}"en
|
||||
RDF.literal("foo bar", language: "en")
|
||||
|
||||
"""
|
||||
defmacro sigil_l(value, language)
|
||||
|
||||
defmacro sigil_l({:<<>>, _, [value]}, []) when is_binary(value) do
|
||||
Macro.escape(RDF.XSD.String.new(value))
|
||||
end
|
||||
|
||||
defmacro sigil_l({:<<>>, _, [value]}, language) when is_binary(value) do
|
||||
Macro.escape(RDF.LangString.new(value, language: to_string(language)))
|
||||
end
|
||||
|
||||
defmacro sigil_l({:<<>>, line, pieces}, []) do
|
||||
quote do
|
||||
RDF.XSD.String.new(unquote({:<<>>, line, unescape_tokens(pieces)}))
|
||||
end
|
||||
end
|
||||
|
||||
defmacro sigil_l({:<<>>, line, pieces}, language) do
|
||||
quote do
|
||||
RDF.LangString.new(unquote({:<<>>, line, unescape_tokens(pieces)}),
|
||||
language: to_string(unquote(language))
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
defp unescape_tokens(tokens) do
|
||||
for token <- tokens do
|
||||
if is_binary(token), do: Macro.unescape_string(token), else: token
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,25 +5,67 @@ defmodule RDF.SigilsTest do
|
|||
|
||||
doctest RDF.Sigils
|
||||
|
||||
describe "IRI sigil without interpolation" do
|
||||
test "creating an IRI" do
|
||||
describe "~I sigil" do
|
||||
test "creates an IRI" do
|
||||
assert ~I<http://example.com> == RDF.iri("http://example.com")
|
||||
end
|
||||
|
||||
test "escaping" do
|
||||
assert ~I<http://example.com/f\no> == RDF.iri("http://example.com/f\\no")
|
||||
end
|
||||
end
|
||||
|
||||
describe "Blank node sigil without interpolation" do
|
||||
test "creating a blank node" do
|
||||
describe "~i sigil" do
|
||||
test "without interpolation" do
|
||||
assert ~i<http://example.com> == RDF.iri("http://example.com")
|
||||
end
|
||||
|
||||
test "with interpolation" do
|
||||
assert ~i<http://example.com/#{1 + 2}> == RDF.iri("http://example.com/3")
|
||||
assert ~i<http://example.com/#{:foo}> == RDF.iri("http://example.com/foo")
|
||||
assert ~i<http://example.com/#{"foo"}> == RDF.iri("http://example.com/foo")
|
||||
end
|
||||
|
||||
test "escaping" do
|
||||
assert ~i<http://example.com/f\no> == RDF.iri("http://example.com/f\\no")
|
||||
end
|
||||
end
|
||||
|
||||
describe "~B sigil" do
|
||||
test "creates a blank node" do
|
||||
assert ~B<foo> == RDF.bnode("foo")
|
||||
end
|
||||
end
|
||||
|
||||
describe "Literal sigil without interpolation" do
|
||||
test "creating a plain Literal" do
|
||||
describe "~b sigil" do
|
||||
test "without interpolation" do
|
||||
assert ~b<foo> == RDF.bnode("foo")
|
||||
end
|
||||
|
||||
test "with interpolation" do
|
||||
assert ~b<foo#{1 + 2}> == RDF.bnode("foo3")
|
||||
end
|
||||
end
|
||||
|
||||
describe "~L sigil" do
|
||||
test "creates a plain Literal" do
|
||||
assert ~L"foo" == RDF.literal("foo")
|
||||
end
|
||||
|
||||
test "creating a language-tagged Literal" do
|
||||
test "creates a language-tagged Literal" do
|
||||
assert ~L"foo"en == RDF.literal("foo", language: "en")
|
||||
end
|
||||
end
|
||||
|
||||
describe "~l sigil" do
|
||||
test "without interpolation" do
|
||||
assert ~l"foo" == RDF.literal("foo")
|
||||
assert ~l"foo"en == RDF.literal("foo", language: "en")
|
||||
end
|
||||
|
||||
test "with interpolation" do
|
||||
assert ~l"foo#{1 + 2}" == RDF.literal("foo3")
|
||||
assert ~l"foo#{1 + 2}"en == RDF.literal("foo3", language: "en")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue