Skip to main content

lib/mix/tasks/ttycast.record.ex

defmodule Mix.Tasks.Ttycast.Record do
  @moduledoc """
  Record a command under a pseudo-terminal.

      mix ttycast.record --output /tmp/demo.ttycast -- sh -lc 'echo hello'
  """

  use Mix.Task

  @shortdoc "Record a command to a .ttycast file"

  @impl true
  def run(argv) do
    {opts, command, invalid} =
      OptionParser.parse(argv,
        strict: [output: :string, width: :integer, height: :integer, timeout: :integer],
        aliases: [o: :output]
      )

    if invalid != [] or command == [] do
      Mix.raise("usage: mix ttycast.record --output PATH -- COMMAND [ARGS...]")
    end

    path = Keyword.get(opts, :output) || Mix.raise("--output is required")

    record_opts =
      [path: path]
      |> put_if_present(:width, opts[:width])
      |> put_if_present(:height, opts[:height])
      |> put_if_present(:timeout, opts[:timeout])

    case TTYCast.record(command, record_opts) do
      {:ok, result} ->
        Mix.shell().info(
          "recorded #{result.bytes} bytes to #{result.path}; exit=#{result.status}"
        )

      {:error, reason} ->
        Mix.raise("recording failed: #{inspect(reason)}")
    end
  end

  defp put_if_present(opts, _key, nil), do: opts
  defp put_if_present(opts, key, value), do: Keyword.put(opts, key, value)
end