diff --git a/lib/livebook_app.ex b/lib/livebook_app.ex index c8598e155..e47a597ef 100644 --- a/lib/livebook_app.ex +++ b/lib/livebook_app.ex @@ -84,10 +84,7 @@ if Mix.target() == :app do end defp import_livebook(url) do - LivebookWeb.Endpoint.access_struct_url() - |> Map.replace!(:path, "/import") - |> append_query("url=#{URI.encode_www_form(url)}") - |> URI.to_string() + LivebookWeb.Helpers.notebook_import_url(url) |> Livebook.Utils.browser_open() end @@ -111,14 +108,5 @@ if Mix.target() == :app do defp macos?() do :os.type() == {:unix, :darwin} end - - # TODO: On Elixir v1.14, use URI.append_query/2 - defp append_query(%URI{query: query} = uri, query_to_add) when query in [nil, ""] do - %{uri | query: query_to_add} - end - - defp append_query(%URI{} = uri, query) do - %{uri | query: uri.query <> "&" <> query} - end end end diff --git a/lib/livebook_cli/server.ex b/lib/livebook_cli/server.ex index 3964eaf48..84711d632 100644 --- a/lib/livebook_cli/server.ex +++ b/lib/livebook_cli/server.ex @@ -15,9 +15,14 @@ defmodule LivebookCLI.Server do @impl true def usage() do """ - Usage: livebook server [options] + Usage: livebook server [url] [options] - Available options: + An optional url can be given as argument. If one is given, + a browser window will open importing the given url as a notebook: + + livebook server https://example.com/my-notebook.livemd + + ## Available options --autosave-path The directory where notebooks with no file are persisted. Defaults to livebook/notebooks/ under the default user cache @@ -52,7 +57,7 @@ defmodule LivebookCLI.Server do @impl true def call(args) do - opts = args_to_options(args) + {opts, extra_args} = args_to_options(args) config_entries = opts_to_config(opts, []) put_config_entries(config_entries) @@ -62,7 +67,7 @@ defmodule LivebookCLI.Server do case check_endpoint_availability(base_url) do :livebook_running -> IO.puts("Livebook already running on #{base_url}") - open_from_options(base_url, opts) + open_from_options(base_url, opts, extra_args) :taken -> print_error( @@ -75,7 +80,7 @@ defmodule LivebookCLI.Server do # so it's gonna start listening case Application.ensure_all_started(:livebook) do {:ok, _} -> - open_from_options(LivebookWeb.Endpoint.access_url(), opts) + open_from_options(LivebookWeb.Endpoint.access_url(), opts, extra_args) Process.sleep(:infinity) {:error, error} -> @@ -116,7 +121,7 @@ defmodule LivebookCLI.Server do end end - defp open_from_options(base_url, opts) do + defp open_from_options(base_url, opts, []) do if opts[:open] do Livebook.Utils.browser_open(base_url) end @@ -128,6 +133,18 @@ defmodule LivebookCLI.Server do end end + defp open_from_options(base_url, _opts, [url]) do + base_url + |> LivebookWeb.Helpers.notebook_import_url(url) + |> Livebook.Utils.browser_open() + end + + defp open_from_options(_base_url, _opts, _extra_args) do + print_error( + "Too many arguments entered. Ensure only one argument is used to specify the file path and all other arguments are preceded by the relevant switch" + ) + end + @switches [ autosave_path: :string, cookie: :string, @@ -147,9 +164,9 @@ defmodule LivebookCLI.Server do ] defp args_to_options(args) do - {opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases) + {opts, extra_args} = OptionParser.parse!(args, strict: @switches, aliases: @aliases) validate_options!(opts) - opts + {opts, extra_args} end defp validate_options!(opts) do diff --git a/lib/livebook_web/helpers.ex b/lib/livebook_web/helpers.ex index f6ada6776..ea6c8770f 100644 --- a/lib/livebook_web/helpers.ex +++ b/lib/livebook_web/helpers.ex @@ -376,6 +376,26 @@ defmodule LivebookWeb.Helpers do def file_system_label(%FileSystem.Local{}), do: "Local disk" def file_system_label(%FileSystem.S3{} = fs), do: fs.bucket_url + @doc """ + Returns a URL (including localhost) to import the given `url` as a notebook. + """ + def notebook_import_url(base_url \\ LivebookWeb.Endpoint.access_struct_url(), url) do + base_url + |> URI.parse() + |> Map.replace!(:path, "/import") + |> append_query("url=#{URI.encode_www_form(url)}") + |> URI.to_string() + end + + # TODO: On Elixir v1.14, use URI.append_query/2 + defp append_query(%URI{query: query} = uri, query_to_add) when query in [nil, ""] do + %{uri | query: query_to_add} + end + + defp append_query(%URI{} = uri, query) do + %{uri | query: uri.query <> "&" <> query} + end + @doc """ Returns the text in singular or plural depending on the quantity