heetbeet / juliawin

A portable Julia for Windows, bundled with VSCode, Pluto, Conda & PyCall, and more.
MIT License
55 stars 2 forks source link

Better Pluto.jl behaviour #51

Closed heetbeet closed 3 years ago

heetbeet commented 3 years ago

It's nice to have pluto.exe, but I think we can do even better:

heetbeet commented 3 years ago

Progress on julia-or-pluto

@echo off
setlocal

:: Read first line of file and sanitize it for testing
set plutoheader=xxx
if exist "%~1" (
    set /p plutoheader=<"%~1"
)
set plutoheader=%plutoheader:&=%
set plutoheader=%plutoheader:"=%

:: Dispatch to the correct program
if "%plutoheader%" equ "### A Pluto.jl notebook ###" (
    call "%~dp0\pluto.bat" %*
) else (
    call "%~dp0\julia.bat" %*
)
exit /b %errorlevel%
heetbeet commented 3 years ago

And for Pluto determining if it's already running, we can use something like this

@eval 1# 2>nul & @call "%~dp0julia.bat" "%~dp0%~n0.bat" %* & @goto:eof

pluto_secret_file = joinpath((@__DIR__), "..", "userdata", ".julia", "plutosecret.txt")
using Sockets
using HTTP

get_open_pluto() = begin

    if isfile(pluto_secret_file)
        secret = open(pluto_secret_file, "r") do f
            strip(String(read(f)))
        end
    else
        return nothing
    end

    for port in 1234:1250
        pluto_entry = "http://localhost:$(port)/?secret=$(secret)"
        pluto_ping = "http://localhost:$(port)/ping"

        sock = try
            listen(port)
        catch e 
        end

        sock isa Sockets.TCPServer && close(sock)

        if sock == nothing && try 
            String(HTTP.request(
                "GET", pluto_ping; connect_timeout=1, readtimeout=1, retry=false, redirect=false
            ).body)
        catch e end == "OK!" && try
            HTTP.request(
                "GET", pluto_entry; connect_timeout=1, readtimeout=1, retry=false, redirect=false
                ).status
        catch e end == 200
            return pluto_entry
        end
    end
end

if length(ARGS) == 1 && lowercase(ARGS[1]) == "--help"
    println("Usage: pluto filename.jl")
    println("Usage: pluto --kwarg1 val1 --kwarg2 val2 ...")
    println()
    println("The available kwargs to Pluto isn't straight-forward and more tailored towards developers.")
    println("The full kwargs configuration logic for Pluto is available here:")
    println("  https://github.com/fonsp/Pluto.jl/blob/master/src/Configuration.jl")
    exit()
end

kwargs = Dict{Symbol, Any}()

if length(ARGS) == 1
    kwargs[:notebook] = ARGS[1]
elseif length(ARGS)%2 != 0
    error("Commandline arguments must come in pairs, like --foo 1 --bar 2")
end

for i = (1:floor(Int, length(ARGS)/2))
    key = Symbol(lstrip(ARGS[i*2-1], ['-']))
    value = ARGS[i*2]
    try
        value = parse(Bool, ARGS[i*2])
    catch e end
    try
        value = parse(Float, ARGS[i*2])
    catch e end
    try
        value = parse(Int, ARGS[i*2])
    catch e end
end

plutourl = if keys(kwargs) in [keys(Dict(:notebook=>0)), keys(Dict())]
    get_open_pluto()
end

if plutourl === nothing
    # Open new instance of Pluto

    using Pluto
    options = Pluto.Configuration.from_flat_kwargs(; kwargs...)
    session = Pluto.ServerSession(;options=options)
    session.secret = String(rand(union('a':'z', 'A':'Z', '0':'9'), 8))

    try
        open(pluto_secret_file, "w") do f
            write(f, session.secret)
        end
    catch e end

    try
        Pluto.run(session)
    finally
        rm(pluto_secret_file)
    end
else
    # Open Old instance of Pluto directly

    if haskey(kwargs, :notebook) # open a file
        plutourl = replace(plutourl, "?secret=" => "open?path=$(kwargs[:notebook])&secret=")
    end

    Base.run(`powershell.exe Start "'$plutourl'"`)
end
heetbeet commented 3 years ago

Possible icon launcher icons.zip

heetbeet commented 3 years ago

Branch https://github.com/heetbeet/juliawin/tree/better-pluto-support

heetbeet commented 3 years ago

https://github.com/heetbeet/juliawin/pull/54