mirror of https://github.com/mpastell/Weave.jl
dynamic YAML option specification
parent
95c3dac962
commit
492d1f330b
|
@ -18,7 +18,7 @@ function format(doc::WeaveDoc)
|
|||
docformat.formatdict[:cwd] = doc.cwd # pass wd to figure formatters
|
||||
docformat.formatdict[:theme] = doc.highlight_theme
|
||||
|
||||
strip_header!(doc)
|
||||
restore_header!(doc)
|
||||
|
||||
for chunk in copy(doc.chunks)
|
||||
result = format_chunk(chunk, formatdict, docformat)
|
||||
|
@ -111,27 +111,20 @@ function render_doc(formatted, doc, format::JMarkdown2tex)
|
|||
)
|
||||
end
|
||||
|
||||
strip_header!(doc::WeaveDoc) = strip_header!(doc.chunks[1], doc.doctype)
|
||||
function strip_header!(docchunk::DocChunk, doctype)
|
||||
doctype == "pandoc" && return
|
||||
content = docchunk.content[1].content
|
||||
if (m = match(HEADER_REGEX, content)) !== nothing
|
||||
# TODO: is there other format where we want to keep headers ?
|
||||
docchunk.content[1].content = if doctype != "github"
|
||||
lstrip(replace(content, HEADER_REGEX => ""))
|
||||
else
|
||||
# only strips Weave headers
|
||||
header = YAML.load(m[:header])
|
||||
delete!(header, WEAVE_OPTION_NAME)
|
||||
if isempty(header)
|
||||
lstrip(replace(content, HEADER_REGEX => ""))
|
||||
else
|
||||
lstrip(replace(content, HEADER_REGEX => "---\n$(YAML.write(header))---"))
|
||||
end
|
||||
end
|
||||
end
|
||||
function restore_header!(doc)
|
||||
doctype = doc.doctype
|
||||
|
||||
# TODO: is there any other format where we want to restore headers ?
|
||||
doctype ≠ "github" && return
|
||||
|
||||
# only strips Weave headers
|
||||
delete!(doc.header, WEAVE_OPTION_NAME)
|
||||
isempty(doc.header) && return
|
||||
|
||||
# restore remained headers as `DocChunk`
|
||||
header_text = "---\n$(YAML.write(doc.header))---"
|
||||
pushfirst!(doc.chunks, DocChunk(header_text, 0, 0))
|
||||
end
|
||||
strip_header!(codechunk::CodeChunk, doctype) = return
|
||||
|
||||
function format_chunk(chunk::DocChunk, formatdict, docformat)
|
||||
return join([format_inline(c) for c in chunk.content], "")
|
||||
|
|
|
@ -2,18 +2,13 @@ using JSON, YAML
|
|||
|
||||
|
||||
function WeaveDoc(source, format::Union{Nothing,AbstractString} = nothing)
|
||||
document = replace(read(source, String), "\r\n" => "\n") # normalize line ending
|
||||
isnothing(format) && (format = detect_informat(source))
|
||||
chunks = parse_doc(document, format)
|
||||
return WeaveDoc(source, chunks)
|
||||
end
|
||||
|
||||
function WeaveDoc(source, chunks::Vector{WeaveChunk})
|
||||
path, fname = splitdir(abspath(source))
|
||||
basename = splitext(fname)[1]
|
||||
|
||||
header = parse_header(first(chunks))
|
||||
# get chunk defaults from header and update
|
||||
isnothing(format) && (format = detect_informat(source))
|
||||
header, chunks = parse_doc(read(source, String), format)
|
||||
|
||||
# update default chunk options from header
|
||||
chunk_defaults = deepcopy(get_chunk_defaults())
|
||||
if haskey(header, WEAVE_OPTION_NAME)
|
||||
for key in keys(chunk_defaults)
|
||||
|
@ -55,18 +50,17 @@ function detect_informat(source::AbstractString)
|
|||
return "noweb"
|
||||
end
|
||||
|
||||
function parse_doc(document, format)::Vector{WeaveChunk}
|
||||
return if format == "markdown"
|
||||
parse_markdown(document)
|
||||
elseif format == "noweb"
|
||||
parse_markdown(document, true)
|
||||
elseif format == "script"
|
||||
parse_script(document)
|
||||
elseif format == "notebook"
|
||||
parse_notebook(document)
|
||||
else
|
||||
function parse_doc(document, format)
|
||||
document = replace(document, "\r\n" => "\n") # normalize line ending
|
||||
|
||||
header_text, document = separete_header_text(document)
|
||||
|
||||
return parse_header(header_text),
|
||||
format == "markdown" ? parse_markdown(document) :
|
||||
format == "noweb" ? parse_markdown(document, true) :
|
||||
format == "script" ? parse_script(document) :
|
||||
format == "notebook" ? parse_notebook(document) :
|
||||
error("unsupported format given: $(format)")
|
||||
end
|
||||
end
|
||||
|
||||
function pushopt(options::Dict, expr::Expr)
|
||||
|
@ -84,12 +78,13 @@ function DocChunk(text::AbstractString, number, start_line; notebook = false)
|
|||
return DocChunk(content, number, start_line)
|
||||
end
|
||||
|
||||
const INLINE_REGEX = r"`j\s+(.*?)`|^!\s(.*)$"m
|
||||
const INLINE_REGEX = r"`j\s+(.*?)`"
|
||||
const INLINE_REGEXES = r"`j\s+(.*?)`|^!\s(.*)$"m
|
||||
|
||||
function parse_inlines(text)::Vector{Inline}
|
||||
occursin(INLINE_REGEX, text) || return parse_inline(text)
|
||||
occursin(INLINE_REGEXES, text) || return parse_inline(text)
|
||||
|
||||
inline_chunks = eachmatch(INLINE_REGEX, text)
|
||||
inline_chunks = eachmatch(INLINE_REGEXES, text)
|
||||
s = 1
|
||||
e = 1
|
||||
res = Inline[]
|
||||
|
@ -118,20 +113,28 @@ parse_inline(text) = Inline[InlineText(text, 1, length(text), 1)]
|
|||
# headers
|
||||
# -------
|
||||
|
||||
parse_header(chunk::CodeChunk) = Dict()
|
||||
|
||||
const HEADER_REGEX = r"^---$(?<header>((?!---).)+)^---$"ms
|
||||
|
||||
function parse_header(chunk::DocChunk)
|
||||
m = match(HEADER_REGEX, chunk.content[1].content)
|
||||
if m !== nothing
|
||||
header = YAML.load(string(m[:header]))
|
||||
else
|
||||
header = Dict()
|
||||
end
|
||||
return header
|
||||
# TODO: non-Weave headers should keep live in a doc
|
||||
# separates header section from `text`
|
||||
function separete_header_text(text)
|
||||
m = match(HEADER_REGEX, text)
|
||||
isnothing(m) && return "", text
|
||||
return m[:header], replace(text, HEADER_REGEX => "")
|
||||
end
|
||||
|
||||
# HACK:
|
||||
# YAML.jl can't parse text including ``` characters, so first replace all the inline code
|
||||
# with these temporary code start/end string
|
||||
const HEADER_INLINE_START = "<weave_header_inline_start>"
|
||||
const HEADER_INLINE_END = "<weave_header_inline_end>"
|
||||
|
||||
function parse_header(header_text)
|
||||
isempty(header_text) && return Dict()
|
||||
pat = INLINE_REGEX => SubstitutionString("$(HEADER_INLINE_START)\\1$(HEADER_INLINE_END)")
|
||||
header_text = replace(header_text, pat)
|
||||
return YAML.load(header_text)
|
||||
end
|
||||
|
||||
include("markdown.jl")
|
||||
include("script.jl")
|
||||
|
|
40
src/run.jl
40
src/run.jl
|
@ -100,6 +100,8 @@ function run_doc(
|
|||
executed = [executed; result_chunks]
|
||||
end
|
||||
|
||||
replace_header_inline!(doc, report, mod) # evaluate and replace inline code in header
|
||||
|
||||
doc.header_script = report.header_script
|
||||
doc.chunks = executed
|
||||
|
||||
|
@ -237,17 +239,11 @@ function capture_output(expr, SandBox::Module, term, disp, lastline, throw_error
|
|||
reader = @async read(rw, String)
|
||||
try
|
||||
obj = Core.eval(SandBox, expr)
|
||||
if (term || disp) && (typeof(expr) != Expr || expr.head != :toplevel)
|
||||
isnothing(obj) || display(obj)
|
||||
# This shows images and lone variables, result can
|
||||
# Handle last line sepately
|
||||
elseif lastline && !isnothing(obj)
|
||||
(typeof(expr) != Expr || expr.head != :toplevel) && display(obj)
|
||||
end
|
||||
catch E
|
||||
throw_errors && throw(E)
|
||||
display(E)
|
||||
@warn("ERROR: $(typeof(E)) occurred, including output in Weaved document")
|
||||
!isnothing(obj) && ((term || disp) || lastline) && display(obj)
|
||||
catch err
|
||||
throw_errors && throw(err)
|
||||
display(err)
|
||||
@warn "ERROR: $(typeof(err)) occurred, including output in Weaved document"
|
||||
finally
|
||||
redirect_stdout(oldSTDOUT)
|
||||
close(wr)
|
||||
|
@ -486,3 +482,25 @@ function collect_results(chunk::CodeChunk, fmt::CollectResult)
|
|||
end
|
||||
return [chunk]
|
||||
end
|
||||
|
||||
const HEADER_INLINE = Regex("$(HEADER_INLINE_START)(?<code>.+)$(HEADER_INLINE_END)")
|
||||
|
||||
replace_header_inline!(doc, report, mod) = _replace_header_inline!(doc, doc.header, report, mod)
|
||||
|
||||
function _replace_header_inline!(doc, header, report, mod)
|
||||
replace!(header) do (k,v)
|
||||
return k => v isa Dict ?
|
||||
_replace_header_inline!(doc, v, report, mod) :
|
||||
replace(v, HEADER_INLINE => s -> begin
|
||||
m = match(HEADER_INLINE, s)
|
||||
run_inline_code(m[:code], doc, report, mod)
|
||||
end)
|
||||
end
|
||||
return header
|
||||
end
|
||||
|
||||
function run_inline_code(s, doc, report, mod)
|
||||
inline = InlineCode(s, 1, 1, 1, :inline)
|
||||
inline = run_inline(inline, doc, report, mod)
|
||||
return strip(inline.output, '"')
|
||||
end
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
|
||||
|
||||
|
||||
<div class="Random plot">
|
||||
|
||||
<p>Some inline output</p>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
|
||||
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Random plot}
|
||||
|
||||
|
|
|
@ -51,33 +51,6 @@ doc.template = "templates/mini.tpl"
|
|||
rendered = Weave.render_doc("Hello", doc)
|
||||
@test rendered == "\nHello\n"
|
||||
|
||||
# Test header parsing and stripping
|
||||
header = """
|
||||
---
|
||||
title : Test block
|
||||
author : Matti Pastell
|
||||
---
|
||||
|
||||
# Actual header
|
||||
|
||||
and some text
|
||||
|
||||
"""
|
||||
|
||||
dchunk = Weave.DocChunk(header, 1, 1)
|
||||
h = Weave.parse_header(dchunk)
|
||||
h_ref = Dict("author" => "Matti Pastell", "title" => "Test block")
|
||||
@test h_ref == h
|
||||
|
||||
Weave.strip_header!(dchunk, "md2html")
|
||||
h_ref = """
|
||||
# Actual header
|
||||
|
||||
and some text
|
||||
|
||||
"""
|
||||
@test dchunk.content[1].content == h_ref
|
||||
|
||||
# Test wrapping
|
||||
|
||||
cows = repeat("🐄", 100)
|
||||
|
|
|
@ -12,7 +12,7 @@ Some markdown with inline stuff and `j code`
|
|||
|
||||
"""
|
||||
|
||||
ms = collect(eachmatch(Weave.INLINE_REGEX, doc))
|
||||
ms = collect(eachmatch(Weave.INLINE_REGEXES, doc))
|
||||
@test ms[1][2] == "println(\"Something\")"
|
||||
@test ms[2][1] == "code"
|
||||
@test ms[3][1] == "show(\"is\")"
|
||||
|
|
|
@ -6,7 +6,11 @@ using Weave: run_doc
|
|||
# TODO: add test for `include_weave`
|
||||
|
||||
# constructs `WeaveDoc` from `String`
|
||||
mock_doc(str, chunk_parser = Weave.parse_markdown) = Weave.WeaveDoc("dummy", chunk_parser(str))
|
||||
function mock_doc(str, format = "markdown")
|
||||
f = tempname()
|
||||
write(f, str)
|
||||
return Weave.WeaveDoc(f, format)
|
||||
end
|
||||
|
||||
|
||||
@testset "Weave" begin
|
||||
|
|
Loading…
Reference in New Issue