Skip to main content

lib/mix/tasks/ttycast.rec.ex

defmodule Mix.Tasks.Ttycast.Rec do
  @moduledoc """
  Interactively record a command in the current terminal.

      mix ttycast.rec --output /tmp/demo.ttycast -- bash
  """

  use Mix.Task

  @shortdoc "Interactively record a command"

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

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

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

    record_opts = [path: path, input_policy: input_policy(opts)]

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

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

  defp input_policy(opts) do
    case Keyword.get(opts, :input, "redacted") do
      "raw" -> :raw
      "none" -> :none
      "redacted" -> :redacted
      value -> Mix.raise("--input must be raw, redacted, or none; got #{inspect(value)}")
    end
  end
end