Browse Source

update parser to have quarto-only functionality

pull/200/head
J S 2 years ago
parent
commit
9d6431cbe8
  1. 25
      src/Literate.jl
  2. 73
      test/runtests.jl

25
src/Literate.jl

@ -46,7 +46,7 @@ CodeChunk() = CodeChunk(String[], false) @@ -46,7 +46,7 @@ CodeChunk() = CodeChunk(String[], false)
ismdline(line) = (occursin(r"^\h*#$", line) || occursin(r"^\h*# .*$", line)) && !occursin(r"^\h*##", line)
function parse(content; allow_continued = true)
function parse(flavor::AbstractFlavor, content; allow_continued = true)
lines = collect(eachline(IOBuffer(content)))
chunks = Chunk[]
@ -76,9 +76,14 @@ function parse(content; allow_continued = true) @@ -76,9 +76,14 @@ function parse(content; allow_continued = true)
if !(chunks[end] isa CodeChunk)
push!(chunks, CodeChunk())
end
# remove "## " and "##\n", strip the leading "#" from "## xyz" and "##| xyz"
# Note: accepts only standard space character (not no-break space U+00A0)
line = replace(replace(line, r"^(\h*)#(#(:? |\|).*)$" => s"\1\2"), r"^(\h*#)#$" => s"\1")
# remove "## " and "##\n" (strips leading "#" for code comments)
if flavor isa QuartoFlavor
# for Quarto, strip leading "#" from code cell commands, eg, "##| echo: true" -> "#| echo: true"
line = replace(replace(line, r"^(\h*)#(#(:? |\|).*)$" => s"\1\2"), r"^(\h*#)#$" => s"\1")
else
# all other flavors
line = replace(replace(line, r"^(\h*)#(# .*)$" => s"\1\2"), r"^(\h*#)#$" => s"\1")
end
push!(chunks[end].lines, line)
end
end
@ -285,12 +290,12 @@ function edit_commit(inputfile, user_config) @@ -285,12 +290,12 @@ function edit_commit(inputfile, user_config)
end
# Default to DefaultFlavor() setting
pick_codefence(flavor::AbstractFlavor,execute::Bool,name::AbstractString)=pick_codefence(DefaultFlavor(),execute,name)
pick_codefence(flavor::DefaultFlavor,execute::Bool,name::AbstractString)=("````julia" => "````")
pick_codefence(flavor::DocumenterFlavor,execute::Bool,name::AbstractString)=(execute ?
pick_codefence(DefaultFlavor(),execute,name) : ("````@example $(name)" => "````")
pick_codefence(flavor::AbstractFlavor, execute::Bool, name::AbstractString)=pick_codefence(DefaultFlavor(), execute,name)
pick_codefence(flavor::DefaultFlavor, execute::Bool, name::AbstractString)=("````julia" => "````")
pick_codefence(flavor::DocumenterFlavor,execute::Bool, name::AbstractString)=(execute ?
pick_codefence(DefaultFlavor(), execute,name) : ("````@example $(name)" => "````")
)
pick_codefence(flavor::QuartoFlavor,execute::Bool,name::AbstractString)=(execute ?
pick_codefence(flavor::QuartoFlavor, execute::Bool, name::AbstractString)=(execute ?
error("QuartoFlavor does not support argument execute=true!") : ("```{julia}" => "```")
)
@ -490,7 +495,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) @@ -490,7 +495,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
content = replace_default(content, type; config=config)
# parse the content into chunks
chunks = parse(content; allow_continued = type !== :nb)
chunks = parse(config["flavor"], content; allow_continued = type !== :nb)
return chunks, config
end

73
test/runtests.jl

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import Literate, JSON
import Literate: Chunk, MDChunk, CodeChunk
import Literate: pick_codefence
import Literate: pick_codefence, DefaultFlavor, QuartoFlavor
using Test
# compare content of two parsed chunk vectors
@ -109,6 +109,8 @@ end @@ -109,6 +109,8 @@ end
## Line 77
##
## Line 79
# Line 80: Quarto Specific
##| Line 81
"""
expected_chunks = Chunk[
MDChunk(["" => "Line 1"]),
@ -146,10 +148,55 @@ end @@ -146,10 +148,55 @@ end
CodeChunk(["Line 64", " # Line 65", " Line 66", "Line 67"], false),
CodeChunk(["# Line 73", "#", "# Line 75"], false),
CodeChunk([" # Line 77", " #", " # Line 79"], false),
]
parsed_chunks = Literate.parse(content)
MDChunk(["" => "Line 80: Quarto Specific"]),
CodeChunk(["##| Line 81"], false)
]
parsed_chunks = Literate.parse(DefaultFlavor(), content)
compare_chunks(parsed_chunks, expected_chunks)
# QuartoFlavor parsing semantics
expected_chunks_quarto = Chunk[
MDChunk(["" => "Line 1"]),
CodeChunk(["Line 2"], false),
MDChunk(["" => "Line 3", "" => "","" => "Line 5"]),
CodeChunk(["Line 6", "","Line 8"], false),
MDChunk(["" => "Line 9"]),
MDChunk(["" => "Line 11"]),
CodeChunk(["Line 12"], false),
CodeChunk(["Line 14"], false),
MDChunk(["" => "Line 15"]),
MDChunk(["" => "Line 17"]),
CodeChunk(["Line 18"], false),
CodeChunk(["Line 20"], false),
MDChunk(["" => "Line 21"]),
CodeChunk(["Line 22", " Line 23", "Line 24"], false),
CodeChunk(["Line 26", " Line 27"], true),
CodeChunk(["Line 29"], false),
CodeChunk(["Line 31", " Line 32"], true),
MDChunk(["" => "Line 33"]),
CodeChunk(["Line 34"], false),
CodeChunk(["Line 36"], true),
CodeChunk([" Line 38"], true),
CodeChunk(["Line 40"], false),
CodeChunk(["Line 42", " Line 43"], true),
MDChunk(["" => "Line 44"]),
CodeChunk([" Line 45"], true),
MDChunk(["" => "Line 46"]),
CodeChunk(["Line 47"], false),
MDChunk(["" => "Line 48"]),
CodeChunk(["#Line 49", "Line 50"], false),
MDChunk(["" => "Line 53"]),
CodeChunk(["# Line 57", "Line 58", "# Line 59", "##Line 60"], false),
MDChunk([" " => "Line 62", " " => "# Line 63"]),
CodeChunk(["Line 64", " # Line 65", " Line 66", "Line 67"], false),
CodeChunk(["# Line 73", "#", "# Line 75"], false),
CodeChunk([" # Line 77", " #", " # Line 79"], false),
MDChunk(["" => "Line 80: Quarto Specific"]),
CodeChunk(["#| Line 81"], false) # parses correctly as code cell command
]
parsed_chunks = Literate.parse(QuartoFlavor(), content)
compare_chunks(parsed_chunks, expected_chunks_quarto)
# test leading/trailing whitespace removal
io = IOBuffer()
iows = IOBuffer()
@ -166,7 +213,7 @@ end @@ -166,7 +213,7 @@ end
foreach(x -> println(iows), 1:rand(2:5))
end
compare_chunks(Literate.parse(String(take!(io))), Literate.parse(String(take!(iows))))
compare_chunks(Literate.parse(DefaultFlavor(), String(take!(io))), Literate.parse(DefaultFlavor(), String(take!(iows))))
end # testset parser
@ -202,7 +249,6 @@ content = """ @@ -202,7 +249,6 @@ content = """
Source code only #src
## # Comment
## another comment
##| echo: false Quarto parameters
#-
for i in 1:10
print(i)
@ -324,7 +370,6 @@ const GITLAB_ENV = Dict( @@ -324,7 +370,6 @@ const GITLAB_ENV = Dict(
x + 3
# # Comment
# another comment
#| echo: false Quarto parameters
for i in 1:10
print(i)
@ -556,7 +601,6 @@ end end @@ -556,7 +601,6 @@ end end
x * 3
# # Comment
# another comment
#| echo: false Quarto parameters
````
````@example inputfile; continued = true
@ -1022,8 +1066,7 @@ end end @@ -1022,8 +1066,7 @@ end end
"x * 3\\n",
"x * 3\\n",
"# # Comment\\n",
"# another comment\\n",
"#| echo: false Quarto parameters"
"# another comment"
],
""",
@ -1419,16 +1462,16 @@ end end @@ -1419,16 +1462,16 @@ end end
@test occursin("Link to binder: www.example3.com/file.jl", script)
# Test pick_codefence function
default_codefence=pick_codefence(Literate.DefaultFlavor(),true,"testname")
default_codefence=pick_codefence(Literate.DefaultFlavor(), true, "testname")
@test default_codefence == ("````julia" => "````")
@test default_codefence == pick_codefence(Literate.FranklinFlavor(),true,"testname")
@test default_codefence == pick_codefence(Literate.DocumenterFlavor(),true,"testname")
@test default_codefence == pick_codefence(Literate.FranklinFlavor(), true, "testname")
@test default_codefence == pick_codefence(Literate.DocumenterFlavor(), true, "testname")
documenter_codefence = ("````@example testname" => "````")
@test documenter_codefence == pick_codefence(Literate.DocumenterFlavor(),false,"testname")
@test documenter_codefence == pick_codefence(Literate.DocumenterFlavor(), false, "testname")
let expected_exception=ErrorException("QuartoFlavor does not support argument execute=true!")
@test_throws expected_exception pick_codefence(Literate.QuartoFlavor(),true,"testname")
@test_throws expected_exception pick_codefence(Literate.QuartoFlavor(), true, "testname")
end
@test ("```{julia}" => "```") == pick_codefence(Literate.QuartoFlavor(),false,"testname")
@test ("```{julia}" => "```") == pick_codefence(Literate.QuartoFlavor(), false, "testname")
# Misc default configs
create(; type, kw...) = Literate.create_configuration(inputfile; user_config=Dict(), user_kwargs=kw, type=type)

Loading…
Cancel
Save