refactor /reader/

pull/351/head
Shuhei Kadowaki 2020-05-24 21:21:15 +09:00
parent 819079c0f6
commit 976d822f58
5 changed files with 72 additions and 109 deletions

View File

@ -49,29 +49,24 @@ end
function parse_markdown_body(document_body, code_start, code_end, offset) function parse_markdown_body(document_body, code_start, code_end, offset)
lines = split(document_body, '\n') lines = split(document_body, '\n')
state = "doc" state = :doc
doc_no = 0
docno = 1 code_no = 0
codeno = 1
content = "" content = ""
start_line = offset start_line = offset
options = Dict() options = Dict()
optionString = "" option_string = ""
chunks = WeaveChunk[] chunks = WeaveChunk[]
for (lineno, line) in enumerate(lines) for (line_no, line) in enumerate(lines)
m = match(code_start, line) m = match(code_start, line)
if !isnothing(m) && state == "doc" if !isnothing(m) && state === :doc
state = "code" state = :code
if m.captures[1] == nothing option_string = isnothing(m[:options]) ? "" : strip(m[:options])
optionString = ""
else
optionString = strip(m.captures[1])
end
options = Dict{Symbol,Any}() options = Dict{Symbol,Any}()
if length(optionString) > 0 if !isempty(option_string)
expr = Meta.parse(optionString) expr = Meta.parse(option_string)
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2]) Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
Base.Meta.isexpr(expr, :toplevel) && Base.Meta.isexpr(expr, :toplevel) &&
map(pushopt, fill(options, length(expr.args)), expr.args) map(pushopt, fill(options, length(expr.args)), expr.args)
@ -79,42 +74,27 @@ function parse_markdown_body(document_body, code_start, code_end, offset)
haskey(options, :label) && (options[:name] = options[:label]) haskey(options, :label) && (options[:name] = options[:label])
haskey(options, :name) || (options[:name] = nothing) haskey(options, :name) || (options[:name] = nothing)
if !isempty(strip(content)) isempty(strip(content)) || push!(chunks, DocChunk(content, doc_no += 1, start_line))
chunk = DocChunk(content, docno, start_line)
docno += 1
push!(chunks, chunk)
end
start_line = line_no + offset
content = "" content = ""
start_line = lineno + offset
continue continue
end end
if occursin(code_end, line) && state == "code" if occursin(code_end, line) && state === :code
chunk = CodeChunk(content, codeno, start_line, optionString, options) push!(chunks, CodeChunk(content, code_no += 1, start_line, option_string, options))
codeno += 1 start_line = line_no + offset
start_line = lineno + offset
content = "" content = ""
state = "doc" state = :doc
push!(chunks, chunk)
continue continue
end end
if lineno == 1 content *= isone(line_no) ? line : string('\n', line)
content *= line
else
content *= "\n" * line
end
end end
# Remember the last chunk # Remember the last chunk
if strip(content) != "" isempty(strip(content)) || push!(chunks, DocChunk(content, doc_no += 1, start_line))
chunk = DocChunk(content, docno, start_line)
# chunk = Dict{Symbol,Any}(:type => "doc", :content => content,
# :number => docno, :start_line => start_line)
push!(chunks, chunk)
end
return chunks return chunks
end end

View File

@ -1,22 +1,21 @@
using JSON
function parse_notebook(document_body) function parse_notebook(document_body)
nb = JSON.parse(document_body) nb = JSON.parse(document_body)
chunks = WeaveChunk[] code_no = 0
doc_no = 0
# TODO: handle some of options ?
options = Dict{Symbol,Any}() options = Dict{Symbol,Any}()
opt_string = "" opt_string = ""
docno = 1
codeno = 1
for cell in nb["cells"] chunks = map(nb["cells"]) do cell
srctext = "\n" * join(cell["source"], "") text = string('\n', join(cell["source"]), '\n')
return if cell["cell_type"] == "code"
if cell["cell_type"] == "code" CodeChunk(text, code_no += 1, 0, opt_string, options)
chunk = CodeChunk(rstrip(srctext), codeno, 0, opt_string, options)
push!(chunks, chunk)
codeno += 1
else else
chunk = DocChunk(srctext * "\n", docno, 0; notebook = true) DocChunk(text, doc_no += 1, 0; notebook = true)
push!(chunks, chunk)
docno += 1
end end
end end

View File

@ -1,4 +1,4 @@
using JSON, YAML using YAML
function WeaveDoc(source, informat = nothing) function WeaveDoc(source, informat = nothing)

View File

@ -1,59 +1,47 @@
function parse_script(document_body) function parse_script(document_body)
lines = split(document_body, "\n") lines = split(document_body, '\n')
doc_line = r"(^#'.*)|(^#%%.*)|(^# %%.*)" doc_line = r"(^#'.*)|(^#%%.*)|(^# %%.*)"
doc_start = r"(^#')|(^#%%)|(^# %%)" doc_start = r"(^#')|(^#%%)|(^# %%)"
opt_line = r"(^#\+.*$)|(^#%%\+.*$)|(^# %%\+.*$)" opt_line = r"(^#\+.*$)|(^#%%\+.*$)|(^# %%\+.*$)"
opt_start = r"(^#\+)|(^#%%\+)|(^# %%\+)" opt_start = r"(^#\+)|(^#%%\+)|(^# %%\+)"
read = ""
docno = 1
codeno = 1
content = "" content = ""
state = :code
doc_no = 0
code_no = 0
start_line = 1 start_line = 1
options = Dict{Symbol,Any}() options = Dict{Symbol,Any}()
optionString = "" option_string = ""
chunks = WeaveChunk[] chunks = WeaveChunk[]
state = "code"
for lineno = 1:length(lines) for (line_no, line) in enumerate(lines)
line = lines[lineno] if (m = match(doc_line, line)) !== nothing && (m = match(opt_line, line)) === nothing
if (m = match(doc_line, line)) != nothing && (m = match(opt_line, line)) == nothing
line = replace(line, doc_start => "", count = 1) line = replace(line, doc_start => "", count = 1)
if startswith(line, " ") startswith(line, ' ') && (line = line[2:end])
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 = ""
start_line = line_no
end end
if state == "code" && strip(read) != "" state = :doc
chunk = elseif (m = match(opt_line, line)) !== nothing
CodeChunk("\n" * strip(read), codeno, start_line, optionString, options) start_line = line_no
push!(chunks, chunk) if state === :code && !isempty(strip(content))
codeno += 1 push!(chunks, CodeChunk(string('\n', strip(content)), code_no += 1, start_line, option_string, options))
read = "" content = ""
start_line = lineno
end end
state = "doc" if state === :doc && !isempty(strip(content))
elseif (m = match(opt_line, line)) != nothing iszero(doc_no) || (content = string('\n', content)) # Add whitespace to doc chunk. Needed for markdown output
start_line = lineno push!(chunks, DocChunk(content, doc_no += 1, start_line))
if state == "code" && strip(read) != "" content = ""
chunk =
CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
push!(chunks, chunk)
read = ""
codeno += 1
end
if state == "doc" && strip(read) != ""
(docno > 1) && (read = "\n" * read) # Add whitespace to doc chunk. Needed for markdown output
chunk = DocChunk(read, docno, start_line)
push!(chunks, chunk)
read = ""
docno += 1
end end
optionString = replace(line, opt_start => "", count = 1) option_string = replace(line, opt_start => "", count = 1)
# Get options
options = Dict{Symbol,Any}() options = Dict{Symbol,Any}()
if length(optionString) > 0 if !isempty(option_string)
expr = Meta.parse(optionString) expr = Meta.parse(option_string)
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2]) Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
Base.Meta.isexpr(expr, :toplevel) && Base.Meta.isexpr(expr, :toplevel) &&
map(pushopt, fill(options, length(expr.args)), expr.args) map(pushopt, fill(options, length(expr.args)), expr.args)
@ -61,29 +49,25 @@ function parse_script(document_body)
haskey(options, :label) && (options[:name] = options[:label]) haskey(options, :label) && (options[:name] = options[:label])
haskey(options, :name) || (options[:name] = nothing) haskey(options, :name) || (options[:name] = nothing)
state = "code" state = :code
continue continue
elseif state == "doc" # && strip(line) != "" && strip(read) != "" elseif state === :doc # && strip(line) != "" && strip(content) != ""
state = "code" state = :code
(docno > 1) && (read = "\n" * read) # Add whitespace to doc chunk. Needed for markdown output iszero(doc_no) || (content = string('\n', content)) # Add whitespace to doc chunk. Needed for markdown output
chunk = DocChunk(read, docno, start_line) push!(chunks, DocChunk(content, doc_no += 1, start_line))
push!(chunks, chunk) content = ""
options = Dict{Symbol,Any}() options = Dict{Symbol,Any}()
start_line = lineno start_line = line_no
read = ""
docno += 1
end end
read *= line * "\n" content *= string(line, '\n')
end end
# Handle the last chunk # Handle the last chunk
if state == "code" chunk = state === :code ?
chunk = CodeChunk("\n" * strip(read), codeno, start_line, optionString, options) CodeChunk(string('\n', strip(content)), code_no, start_line, option_string, options) :
push!(chunks, chunk) DocChunk(content, doc_no, start_line)
else push!(chunks, chunk)
chunk = DocChunk(read, docno, start_line)
push!(chunks, chunk)
end
return Dict(), chunks return Dict(), chunks
end end

View File

@ -37,7 +37,7 @@ mutable struct CodeChunk <: WeaveChunk
result::Vector{ChunkOutput} result::Vector{ChunkOutput}
function CodeChunk(content, number, start_line, optionstring, options) function CodeChunk(content, number, start_line, optionstring, options)
new( new(
rstrip(content) * "\n", string(rstrip(content), '\n'), # normalize end of chunk
number, number,
0, 0,
start_line, start_line,