Skip to content

Commit

Permalink
Separate indicator processing (#3)
Browse files Browse the repository at this point in the history
Allows for processing to be done at parse time instead of runtime when
interpolation is present.
  • Loading branch information
omus authored Sep 2, 2020
1 parent 6071847 commit 29e85b4
Showing 1 changed file with 55 additions and 49 deletions.
104 changes: 55 additions & 49 deletions src/MultilineStrings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,53 +43,7 @@ Revise a multiline string according to the provided style and chomp encoded in t
- "lk" / "|+": literal and keep
"""
function multiline(str::AbstractString, indicators::AbstractString)
indicators_len = length(indicators)
indicators_len > 2 && throw(ArgumentError("Too many indicators provided"))

# Note: Using '\0` to indicate undefined
yaml_chomp = false
style_char, chomp_char = if indicators_len == 2
indicators
elseif indicators_len == 1
ind = indicators[1]
if ind in ('f', 'l')
ind, '\0'
elseif ind in ('>', '|')
yaml_chomp = true
ind, '\0'
else
'\0', ind
end
else
'\0', '\0'
end

if style_char != '\0' && chomp_char != '\0' && isletter(style_char) isletter(chomp_char)
throw(ArgumentError("Can't mix YAML style block indicators with letter indicators"))
end

style = if style_char == 'f' || style_char == '>'
:folded
elseif style_char == 'l' || style_char == '|'
:literal
elseif style_char == '\0'
DEFAULT_STYLE
else
throw(ArgumentError("Unknown style indicator: $(repr(style_char))"))
end

chomp = if chomp_char == 'c' || yaml_chomp
:clip
elseif chomp_char == 's' || chomp_char == '-'
:strip
elseif chomp_char == 'k' || chomp_char == '+'
:keep
elseif chomp_char == '\0'
DEFAULT_CHOMP
else
throw(ArgumentError("Unknown chomping indicator: $(repr(chomp_char))"))
end

style, chomp = _process_indicators(indicators)
return multiline(str, style, chomp)
end

Expand Down Expand Up @@ -148,16 +102,17 @@ julia> m\"\"\"
```
"""
macro m_str(str::AbstractString, indicators::AbstractString="")
style, chomp = _process_indicators(indicators)
parsed = interpolate(str)

# When no string interpolation needs to take place we can just process the multiline
# string during parse time. If string interpolation needs to take place we'll evaluate
# the multiline string at runtime so that we can process after interpolation has taken
# place.
result = if parsed isa String
multiline(unescape_string(parsed), indicators)
multiline(unescape_string(parsed), style, chomp)
else
Expr(:call, :(MultilineStrings.multiline), parsed, indicators)
Expr(:call, :(MultilineStrings.multiline), parsed, QuoteNode(style), QuoteNode(chomp))
end

return esc(result)
Expand Down Expand Up @@ -193,4 +148,55 @@ function interpolate(str::AbstractString)
return Expr(:string, components...)
end

function _process_indicators(indicators::AbstractString)
indicators_len = length(indicators)
indicators_len > 2 && throw(ArgumentError("Too many indicators provided"))

# Note: Using '\0` to indicate undefined
yaml_chomp = false
style_char, chomp_char = if indicators_len == 2
indicators
elseif indicators_len == 1
ind = indicators[1]
if ind in ('f', 'l')
ind, '\0'
elseif ind in ('>', '|')
yaml_chomp = true
ind, '\0'
else
'\0', ind
end
else
'\0', '\0'
end

if style_char != '\0' && chomp_char != '\0' && isletter(style_char) isletter(chomp_char)
throw(ArgumentError("Can't mix YAML style block indicators with letter indicators"))
end

style = if style_char == 'f' || style_char == '>'
:folded
elseif style_char == 'l' || style_char == '|'
:literal
elseif style_char == '\0'
DEFAULT_STYLE
else
throw(ArgumentError("Unknown style indicator: $(repr(style_char))"))
end

chomp = if chomp_char == 'c' || yaml_chomp
:clip
elseif chomp_char == 's' || chomp_char == '-'
:strip
elseif chomp_char == 'k' || chomp_char == '+'
:keep
elseif chomp_char == '\0'
DEFAULT_CHOMP
else
throw(ArgumentError("Unknown chomping indicator: $(repr(chomp_char))"))
end

return style, chomp
end

end

2 comments on commit 29e85b4

@omus
Copy link
Collaborator Author

@omus omus commented on 29e85b4 Sep 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/20709

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.1.0 -m "<description of version>" 29e85b42db49ce47ff38afd367429c122a837938
git push origin v0.1.0

Please sign in to comment.