allow RMarkdown style chunk option passing:

e.g.:
- `julia, k1 = v1`
- `{julia, k1 = v1}`
- `julia k1 = v1`
pull/353/head
Shuhei Kadowaki 2020-05-25 00:49:12 +09:00
parent dd0c51b6e5
commit b0db8b991c
4 changed files with 38 additions and 27 deletions

View File

@ -5,7 +5,7 @@ function parse_markdown(document_body; is_pandoc = false)
r"^<<(?<options>.*?)>>=\s*$",
r"^@\s*$"
else
r"^[`~]{3}(?:\{?)julia(?:;?)\s*(?<options>.*?)(\}|\s*)$",
r"^[`~]{3}(\{?)julia\s*([;,]?)\s*(?<options>.*?)(\}|\s*)$",
r"^[`~]{3}\s*$"
end
return header, parse_markdown_body(document_body, code_start, code_end, offset)
@ -55,22 +55,17 @@ function parse_markdown_body(document_body, code_start, code_end, offset)
content = ""
start_line = offset
options = Dict()
options = OptionDict()
option_string = ""
chunks = WeaveChunk[]
for (line_no, line) in enumerate(lines)
m = match(code_start, line)
if !isnothing(m) && state === :doc
state = :code
option_string = isnothing(m[:options]) ? "" : strip(m[:options])
options = Dict{Symbol,Any}()
if !isempty(option_string)
expr = Meta.parse(option_string)
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
Base.Meta.isexpr(expr, :toplevel) &&
map(pushopt, fill(options, length(expr.args)), expr.args)
end
option_string = isnothing(m[:options]) ? "" : strip(m[:options])
options = parse_options(option_string)
haskey(options, :label) && (options[:name] = options[:label])
haskey(options, :name) || (options[:name] = nothing)

View File

@ -64,12 +64,6 @@ function parse_doc(document, informat)
error("unsupported input format given: $informat")
end
function pushopt(options::Dict, expr::Expr)
if Base.Meta.isexpr(expr, :(=))
options[expr.args[1]] = expr.args[2]
end
end
# inline
# ------
@ -100,6 +94,34 @@ end
parse_inline(str) = Inline[InlineText(str, 1)]
# options
# -------
const OptionDict = Dict{Symbol,Any}
function parse_options(str)::OptionDict
str = string('(', str, ')')
ex = Meta.parse(str)
nt = if Meta.isexpr(ex, (
:block, # "(k1 = v1; k2 = v2, ...)"
:tuple, # "(k1 = v1, k2 = v2, ...)"
))
eval(Expr(:tuple, filter(is_valid_kv, ex.args)...))
elseif is_valid_kv(ex) # "(k = v)"
eval(Expr(:tuple, ex))
else
NamedTuple{}()
end
return dict(nt)
end
is_valid_kv(x) = Meta.isexpr(x, :(=))
dict(nt) = Dict((k => v for (k,v) in zip(keys(nt), values(nt))))
nt(dict) = NamedTuple{(Symbol.(keys(dict))...,)}((collect(values(dict))...,))
# each input format
# -----------------
include("markdown.jl")
include("script.jl")
include("notebook.jl")

View File

@ -12,14 +12,14 @@ function parse_script(document_body)
code_no = 0
start_line = 1
options = Dict{Symbol,Any}()
options = OptionDict()
option_string = ""
chunks = WeaveChunk[]
chunks = WeaveChunk[]
for (line_no, line) in enumerate(lines)
if (m = match(doc_line, line)) !== nothing && (m = match(opt_line, line)) === nothing
line = replace(line, doc_start => "", count = 1)
startswith(line, ' ') && (line = line[2:end])
startswith(line, ' ') && (line = replace(line, ' ' => "", count = 1))
if state === :code && !isempty(strip(content))
push!(chunks, CodeChunk(string('\n', strip(content)), code_no += 1, start_line, option_string, options))
content = ""
@ -39,13 +39,7 @@ function parse_script(document_body)
end
option_string = replace(line, opt_start => "", count = 1)
options = Dict{Symbol,Any}()
if !isempty(option_string)
expr = Meta.parse(option_string)
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
Base.Meta.isexpr(expr, :toplevel) &&
map(pushopt, fill(options, length(expr.args)), expr.args)
end
options = parse_options(option_string)
haskey(options, :label) && (options[:name] = options[:label])
haskey(options, :name) || (options[:name] = nothing)

View File

@ -47,7 +47,7 @@ function CodeChunk(content, number, start_line, optionstring, options)
options,
"",
"",
AbstractStringString[],
AbstractString[],
ChunkOutput[]
)
end