317 lines
12 KiB
Julia
317 lines
12 KiB
Julia
const supported_packages = [:DataFrames, :NamedArrays, :Plots, :HypothesisTests, :CSVFiles]
|
|
|
|
# Generic fallback
|
|
orgshow(io::IO, Any, i; kwargs...) = show(io, i)
|
|
orgshow(io::IO, ::MIME"text/org", i; kwargs...) = show(io, i)
|
|
# Overload types
|
|
orgshow(io::IO, ::MIME"text/org", t::Tuple; kwargs...) = print(io, join(t, ','))
|
|
orgshow(io::IO, ::MIME"text/org", ::Nothing; kwargs...) = print(io, "")
|
|
orgshow(io::IO, ::MIME"text/org", a::Array{T,1}; kwargs...) where T <: Any = print(io, join(a, '\n'))
|
|
|
|
# You can override this with a better one that uses some available module
|
|
function orgshow(io::IO, ::MIME"text/html", i::Array{T,2}; kwargs...) where T <: Any
|
|
width = get(Dict(kwargs), :width, "100")
|
|
print(io, """<table style="width:$width%">""")
|
|
content = eachrow(i) |> x -> string("<tr>",
|
|
join([string("<th>", join(l, "</th><th>"))
|
|
for l in x], "</tr><tr>"))
|
|
print(io, content, "</table>")
|
|
end
|
|
|
|
function orgshow(io::IO, ::MIME"text/org", i::Array{T,2}; kwargs...) where T <: Any
|
|
out = eachrow(i) |> x -> join([join(l, ',') for l in x], '\n')
|
|
print(io, out)
|
|
end
|
|
|
|
function orgshow(io::IO, ::MIME"text/csv", i::Array{T,2}; kwargs...) where T <: Any
|
|
orgshow(io, MIME("text/org"), i; kwargs...)
|
|
end
|
|
|
|
function orgstring(e::Tuple{Exception,Any})
|
|
string("ERROR,", e[1], "\n",
|
|
"Stacktrace:\n",
|
|
join(e[2], '\n'))
|
|
end
|
|
|
|
# The comma is needed to allow export as table
|
|
function orgshow(io::IO, ::MIME"text/org", e::Tuple{Exception,Any};
|
|
kwargs...)
|
|
print(io, orgstring(e))
|
|
end
|
|
|
|
function orgshow(io::IO, ::MIME"text/org", t::NamedTuple)
|
|
print(io, join(string.(keys(t)), ','))
|
|
println(io)
|
|
print(io, join(t, ','))
|
|
end
|
|
|
|
function orgshow(io::IO, ::MIME"text/org",
|
|
ta::Vector{<:NamedTuple})
|
|
"This assume keys are the same. A better NamedTuple export is provided by
|
|
the DataFrames (DataFrame(ta))"
|
|
length(ta) <= 0 && return ""
|
|
println(io, join(keys(first(ta)), ','))
|
|
for t in ta
|
|
print(io, join(string.(values(t)), ','))
|
|
println(io)
|
|
end
|
|
end
|
|
|
|
OrgAPApvalue(p) = p < 0.001 ? "< .001" : string("= ", round(p, sigdigits = 2))
|
|
|
|
function define_HypothesisTests()
|
|
Main.@eval function orgshow(io::IO,
|
|
m::MIME"text/org",
|
|
test::PowerDivergenceTest; kwargs...)
|
|
println(io, join(["test", "df", "N", "stat", "p-value"], ','))
|
|
print(io, join(["X^2", test.df, test.n, test.stat, pvalue(test)], ','))
|
|
end
|
|
Main.@eval function orgshow(io::IO,
|
|
m::MIME"text/html",
|
|
test::PowerDivergenceTest; kwargs...)
|
|
print(io, string("X^2",
|
|
" (", test.df, ", N = ", test.n,
|
|
") = ",
|
|
round(test.stat; digits = 2),
|
|
", p ", OrgAPApvalue(pvalue(test))))
|
|
end
|
|
end
|
|
|
|
function define_Plots()
|
|
# Fallback: we will try to plot any image/png or image/svg
|
|
Main.@eval function orgshow(io::IO,
|
|
m::MIME"image/png",
|
|
any; kwargs...)
|
|
show(io, MIME("image/png"), plot(any; kwargs...))
|
|
end
|
|
Main.@eval function orgshow(io::IO,
|
|
m::MIME"image/svg+xml",
|
|
any; kwargs...)
|
|
show(io, MIME("image/svg+xml"), plot(any; kwargs...))
|
|
end
|
|
Main.@eval function orgshow(io::IO,
|
|
m::MIME"image/png",
|
|
p::Plots.Plot; kwargs...)
|
|
show(io, MIME("image/png"), plot(p; kwargs...))
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"image/png", e::Tuple{Exception,Any};
|
|
kwargs...)
|
|
let p = plot(showaxis = false, grid = false, bg = :yellow)
|
|
annotate!([0.5], [0.5], (orgstring(e), :red))
|
|
orgshow(io, MIME("image/png"), p; kwargs...)
|
|
end
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"image/svg+xml", e::Exception; kwargs...)
|
|
let p = plot(showaxis = false, grid = false, bg = :yellow)
|
|
annotate!([0.5], [0.5], (string("ERROR: ", e), :red))
|
|
orgshow(io, MIME("image/svg+xml"), p; kwargs...)
|
|
end
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/html", p::Plots.Plot; kwargs...)
|
|
p = plot(p; kwargs...)
|
|
p.attr[:html_output_format] = "png"
|
|
# Plots._show(io::IO, MIME("text/html"), p::Plots.Plot; kwargs...)
|
|
Plots._show(io, MIME("text/html"), p)
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"image/svg+xml", p::Plots.Plot; kwargs...)
|
|
show(io, MIME("image/svg+xml"), plot(p; kwargs...))
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"application/pdf", p::Plots.Plot; kwargs...)
|
|
# ps, eps, tex or pdf. I think extra packages are required for all but pdf
|
|
show(io, MIME("application/pdf"), plot(p; kwargs...))
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"application/postscript", p::Plots.Plot; kwargs...)
|
|
show(io, MIME("application/postscript"), plot(p; kwargs...))
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"image/eps", p::Plots.Plot;
|
|
kwargs...)
|
|
show(io, MIME("image/eps"), plot(p; kwargs...))
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"application/x-tex", p::Plots.Plot;
|
|
kwargs...)
|
|
show(io, MIME("application/x-tex"), plot(p; kwargs...))
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/org", p::Plots.Plot; kwargs...)
|
|
# png or svg
|
|
p.attr[:html_output_format] = "png"
|
|
orgshow(io::IO, MIME("text/html"), p::Plots.Plot; kwargs...)
|
|
end
|
|
end
|
|
|
|
function define_DataFrames()
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/csv", d::DataFrames.DataFrame)
|
|
orgshow(io, MIME("text/org"), d)
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/org", d::DataFrames.DataFrame)
|
|
out = join(string.(names(d)), ',') * '\n'
|
|
out *= join([join(x, ',') for x in eachrow(d) .|> collect],'\n')
|
|
print(io, out)
|
|
end
|
|
end
|
|
|
|
function define_CSVFiles()
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/csv", d::CSVFiles.CSVFile)
|
|
orgshow(io, MIME("text/org"), d)
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/html", d::CSVFiles.CSVFile)
|
|
show(io, MIME("text/html"), RES)
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"application/json", d::CSVFiles.CSVFile)
|
|
show(io, MIME("application/vnd.dataresource+json"), RES)
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/org", d::CSVFiles.CSVFile)
|
|
orgshow(io, MIME("text/org"), collect(d))
|
|
end
|
|
end
|
|
|
|
function define_NamedArrays()
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/org",
|
|
na::NamedArray{T,2} where T <: Any)
|
|
n = names(na)
|
|
a = collect(na)
|
|
# The char used by NamedArrays is '╲' but by default it's not
|
|
# shown in pdf export
|
|
print(io, join(string.(na.dimnames), " \\ ") * ',')
|
|
print(io, join(n[2], ',') * '\n')
|
|
print(io, join([join([string(n[1][i], ','),
|
|
join([a[i,j]
|
|
for j in 1:size(na,2)
|
|
], ',')])
|
|
for i in 1:size(na,1)
|
|
], '\n'))
|
|
end
|
|
Main.@eval function orgshow(io::IO, ::MIME"text/org", na::NamedArray{T,1} where T <: Any)
|
|
n = names(na)
|
|
a = collect(na)
|
|
print(io, string(na.dimnames[1], ',', '\n'))
|
|
print(io, join([join([n[1][i], a[i]], ',')
|
|
for i in 1:length(n[1])], '\n'))
|
|
end
|
|
end
|
|
|
|
define_package_functions(pkg::Symbol) = (@eval $pkg)()
|
|
|
|
function OrgBabelImport(imports; forced = false)
|
|
"Load dependencies. Do this before calling OrgBabelReload()"
|
|
# Reload this module, so that if new packages have been imported,
|
|
# we can use them to save the output
|
|
!forced && isempty(imports) && return
|
|
println("$imports")
|
|
try
|
|
Main.eval(Meta.parse(
|
|
"""begin
|
|
$imports
|
|
end"""))
|
|
true
|
|
catch e
|
|
@show e
|
|
end
|
|
end
|
|
|
|
function OrgBabelReload()
|
|
"Defines show method based on loaded packages"
|
|
for pkg in supported_packages
|
|
if isdefined(Main, pkg) && (isa(getfield(Main, pkg), Module) ||
|
|
isa(getfield(Main, pkg), UnionAll))
|
|
define_package_functions(Symbol("define_", pkg))
|
|
# Remove loaded packages from list to prevent multiple execution
|
|
filter!(x -> x != pkg, supported_packages)
|
|
end
|
|
end
|
|
end
|
|
|
|
const Mimes = Dict(:org => "text/org",
|
|
:csv => "text/csv",
|
|
:png => "image/png",
|
|
:svg => "image/svg+xml",
|
|
:pdf => "application/pdf",
|
|
:html => "text/html",
|
|
:auto => "text/org",
|
|
:ps => "application/postscript",
|
|
:eps => "image/eps",
|
|
:tex => "application/x-tex")
|
|
|
|
function OrgBabelFormat(output_type::Symbol,
|
|
output_file,
|
|
dir, vars_file,
|
|
src_file,
|
|
silently::Bool,
|
|
pure::Bool,
|
|
kwargs)
|
|
content = read(src_file, String)
|
|
vars = read(vars_file, String)
|
|
# Fake a prompt with the current input
|
|
try
|
|
printstyled(IOContext(stdout, :color => true),
|
|
"\njulia> ", color = :blue)
|
|
println(content)
|
|
catch
|
|
end
|
|
# Dispatch on output type
|
|
code = pure ? "let $vars; $content; end" : "begin $vars; $content;\n end"
|
|
if output_type == :value
|
|
# Run the code
|
|
result = cd(expanduser(dir)) do
|
|
try
|
|
Main.eval(Meta.parse(code))
|
|
catch e
|
|
(e, stacktrace())
|
|
end
|
|
end
|
|
if !silently
|
|
try
|
|
display(MIME("text/plain"), result)
|
|
catch e
|
|
println("Error $e while showing results")
|
|
end
|
|
end
|
|
# Decide output type.
|
|
# If the output has an extension, use it.
|
|
# else, use the exporter format. Fallback to text/org
|
|
output_ext = replace(splitext(output_file)[2], "." => "")
|
|
required_format = isempty(output_ext) ? :auto : Symbol(output_ext)
|
|
mime = get(Mimes, required_format, "text/org")
|
|
temporary_output = IOBuffer()
|
|
# Output directly to org (no :file, -> save to output_file)
|
|
try
|
|
orgshow(temporary_output,
|
|
MIME(mime), result; Base.eval(Meta.parse(kwargs))...)
|
|
catch e
|
|
@error "Probable ob-julia error! Please report to the author!"
|
|
@error "Error: $e"
|
|
print(temporary_output,
|
|
"Probable ob-julia error! Please report to the author!",
|
|
"Error: $e")
|
|
end
|
|
write(output_file, take!(temporary_output))
|
|
elseif output_type == :output
|
|
temporary_output_file = tempname()
|
|
open(temporary_output_file, create = true, write = true) do f
|
|
redirect_stdout(f) do
|
|
redirect_stderr(f) do
|
|
cd(expanduser(dir)) do
|
|
try
|
|
Main.eval(Meta.parse(code))
|
|
catch e
|
|
println(e)
|
|
println(join(stacktrace(), '\n'))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if !silently
|
|
# It's stupid to write and read it but I don't know how to
|
|
# save redirect_stdout to IOBuffer or similar
|
|
print(read(temporary_output_file, String))
|
|
end
|
|
mv(temporary_output_file, output_file, force = true)
|
|
else
|
|
"ERROR: invalid ouput type"
|
|
end
|
|
return nothing
|
|
end
|
|
|
|
OrgBabelReload()
|
|
|