Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Pluto.jl #90

Closed
arlk opened this issue Jun 13, 2020 · 7 comments
Closed

Support for Pluto.jl #90

arlk opened this issue Jun 13, 2020 · 7 comments

Comments

@arlk
Copy link

arlk commented Jun 13, 2020

MWE (from the docs):

@draw begin
    radius=80
    setdash("dot")
    sethue("gray30")
    A, B = [Point(x, 0) for x in [-radius, radius]]
    line(A, B, :stroke)
    circle(O, radius, :stroke)
# >>>>
    label("A", :NW, A)
    label("O", :N,  O)
    label("B", :NE, B)

    circle.([A, O, B], 2, :fill)
    circle.([A, B], 2radius, :stroke)
end

and we get:

[ Info: Use Juno or Jupyter; the drawing is stored in memory, not in a file.

The @png macro or preview() also don't seem to work right now. But that might be an issue related to the Pluto.jl backend (although it supports pngs from Images.jl - see fonsp/Pluto.jl#60)

@cormullion
Copy link
Member

Good idea. At the moment Jupyter is hard-wired in, so if I can work out the equivalent runes for Pluto it should be easy to add.

@fonsp
Copy link
Contributor

fonsp commented Jun 13, 2020

First of all, thank you so much for reaching out to me! I like Luxor and I think it would be super fun to work with it inside Pluto!

I do have solution, but it would lead to (minor) breaking changes to the behavior inside Jupyter, that's why I didn't suggest it before.

As an example of what I mean, here's the current @svg macro:

macro svg(body, width=600, height=600, fname="luxor-drawing-$(Dates.format(Dates.now(), "HHMMSS_s")).svg")
    quote
        local lfname = _add_ext($(esc(fname)), :svg)
        Drawing($width, $height, lfname)
        origin()
        background("white")
        sethue("black")
        $(esc(body))
        finish()
        preview()
    end
end

Luxor uses an internal state, CURRENTDRAWING (which makes the API easier to use 😊), and the last call, preview() goes through the OS and environment checks to call the appropriate display functions, and it returns either Nothing or a String. (Does it return Nothing to prevent IJulia from showing both the filename and the image?)

Instead, the preview function could be replaced with

function preview()
    return CURRENTDRAWING[1]
end

The goal here is to use Julia's built-in display system to do the OS & environment switches - it would still give rich output on environments that support it, because any environment that runs an @svg will get the Drawing object as a result of that expression, and all Julia environments call show on the returned expression. A quick test showed that this works on Pluto (heyo), Jupyter and Juno.

However, this would lead to two changes:

  1. A Jupyter cell that calls @svg multiple times (inside a loop, for example) would not display every drawing on top of eachother. People would have to write show( @svg begin .... end ) inside the loop if they want that. Similarly, a Jupyter cell that contains a second expression after an @svg expression will not show the drawing, because the drawing is not the returned object of that cell.
  2. This would no longer open an image viewer when running in a text-only environment. However, this could be solved by adding a text/plain show method for a Drawing:
function Base.show(io::IO, ::MIME"text/plain", d::Drawing)
    returnvalue = d.filename
    if Sys.isapple()
        run(`open $(returnvalue)`)
    elseif Sys.iswindows()
        cmd = get(ENV, "COMSPEC", "cmd")
        run(`$(ENV["COMSPEC"]) /c start $(returnvalue)`)
    elseif Sys.isunix()
        run(`xdg-open $(returnvalue)`)
    end
    print(io, returnvalue)
end

Note: one could argue that 1. has the silver lining of making the Julia display system more uniform and easier to understand. For example, why does the Jupyter cell

@svg begin ... end
@svg begin ... end

show two drawings, while

sqrt(1)
sqrt(2)

only shows the second result?

So that was my breaking suggestion, and I completely understand that this might not be what we want, and that there were deliberate design choices for the current display system. I also see that you just released v2.0.0, so this suggestion might come too late.

Let me know what you think! I can also help to figure out a non-breaking fix that just adds an extra check to preview.

-fonsi

@cormullion
Copy link
Member

Thanks so much! I'll study this and see what I think.

@cormullion
Copy link
Member

cormullion commented Jun 13, 2020

OK, this is looking good! (This area of Luxor is very old, predating Juno etc, so it's good to have a rework...)

In fact Pluto is working perfectly so far:

Screenshot 2020-06-13 at 17 45 02

I have two problems - first to include the SVG cleaning code somewhere, which was here:

function display_ijulia(m::MIME"image/svg+xml", fname)
    # rename the elements to avoid display issues
    # I pinched this from Simon's RCall.jl
    open(fname) do f
        r = string(rand(100000:999999))
        d = read(f, String)
        d = replace(d, "id=\"glyph" => "id=\"glyph"*r)
        d = replace(d, "href=\"#glyph" => "href=\"#glyph"*r)
        display(m, d)
    end
end

which is basically needed to avoid the SVG namespace errors when two or more SVG files are stored in the same document. (Eg

Screenshot 2020-06-13 at 17 47 51

And second, to work out why the images in Juno and Jupyter are displayed in the right place and also opened in the Finder as well... (two previews are not always what you want...:)).

The current master of Luxor.jl has these updates...

@fonsp
Copy link
Contributor

fonsp commented Jun 13, 2020

Wow that's looking great! You can put the SVG cleaning at the start of finish right? I'll take a look at the double opening issue now!

@fonsp
Copy link
Contributor

fonsp commented Jun 13, 2020

Have a look at #91

@cormullion
Copy link
Member

Thanks to @fonsp, now supported... :)

pluto

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants