Pluto: Get current notebook file path


I would like to get the filepath for the current Pluto notebook.
Is there a way to get this information?



My purpose is to write a SaveAsIpynb function that would keep a Jupyter notebook copy of the current Pluto notebook.

You can get the folder that the notebook is in with @__DIR__(), and you can get files in that directory with readdir, but I don’t know how to get the name of the notebook directly.

You can use the @__FILE__ macro and remove the trailing characters after the #==#<...>. By doing something like:

notebookpath() = replace(@__FILE__, r"#==#.*" => "")

Thanks both!
I also found pathof and splitdir to help.
It is not yet clear how I will do it.
I’ll come back if I am stuck!

Just tested.
In a Jupyter notebook, @FILE returns “In[12]” , the cell in the notebook.

In Pluto it rerturn something like:
“C:\Users\myPC\Pluto notebooks\myPackage\examples\Pluto\example.jl#==#06f9b601-36bf-440d-812f-a858b101fb2a”

So, for Pluto this would be enough, but not for Jupyter!
I hope there is a way to have that working for both Jupyet and Pluto.
I want to have this code inside the package.



This is an old unsolved issue for jupyter notebooks.

Hello Pangoraw

I just realised that @FILE returns the path of the file where the macro is used.
Actually, I need the path of the notebook (Pluto), but the macro will be in a package used by the notebook.
Is there a way to find the path of the topmost “caller”, in a sense ?



I think the only way you could have knowledge about the caller scope is by using a macro.

Quoting the Julia documentation:

In addition to the given argument list, every macro is passed extra arguments named __source__ and __module__ .

The argument __source__ provides information (in the form of a LineNumberNode object) about the parser location of the @ sign from the macro invocation. This allows macros to include better error diagnostic information, and is commonly used by logging, string-parser macros, and docs, for example, as well as to implement the @__LINE__ , @__FILE__ , and @__DIR__ macros.

The location information can be accessed by referencing __source__.line and __source__.file

So you could do something like this:

macro export_to_jupyter(...)
  notebook_name = __source__.file
  return quote
    ... # code using $notebook_name

Thanks Pangoraw!

A one liner to wrap my function and that’s is, thanks to you:

macro toJupiter()

Now I can convert a Pluto nb to Jupyter without thinking.

From Jupyter to Pluto it will not work, because I do not get the path, I get the cell instead.
But that’s less important for me.



1 Like

that does not seem to be the case anymore. how can i get the pwd from which I started the julia session that called

It’s not this directory:

I tried something like this

julia> Pluto.Configuration.Options(server=Pluto.Configuration.ServerOptions(root_url = pwd()))
Pluto.Configuration.Options(Pluto.Configuration.ServerOptions("/Users/florian.oswald/.julia/pluto_notebooks", "", nothing, true, false, true, "/Users/florian.oswald/git/ClimateNotebooks/notebooks/", false, false, 0.4, false, nothing, false, 0.0), Pluto.Configuration.SecurityOptions(true, true), Pluto.Configuration.EvaluationOptions(true, true, false), Pluto.Configuration.CompilerOptions(nothing, nothing, nothing, nothing, nothing, "no", "no", 2))

julia> = pwd())))
ERROR: AssertionError: endswith(session.options.server.root_url, "/")

This discussion is about getting the file path to the actual notebook file. Since each notebook runs in a different Julia process, they each get their own pwd(). You can use an environment variable to get the working directory of the Pluto process:

julia> withenv("PLUTO_ROOT_DIR" => pwd()) do
  # launch Pluto with PLUTO_ROOT_DIR in the env

and then in the notebook you can get it with ENV["PLUTO_ROOT_DIR"]. Also note that root_url refers to the url of the Pluto webserver and is not related to the directory in which the draft notebooks are created.

Great thanks! That’s what I need. I could not make this work with the advised solution of using Base.current_project() because it would always look for a project at ~. When trying to use a local project file that is shared with a local package.