Elixir - вывод логгера красочный при запуске из командной строки, а не при iex - PullRequest
1 голос
/ 21 октября 2019

Когда я запускаю тесты в моем приложении Elixir mix, у меня есть несколько случаев, когда я включаю несколько вызовов Logger.debug() для мониторинга поведения. Я обнаружил, что когда я вызываю mix test из командной строки, вывод Logger окрашивается в светло-синий цвет, и если я делаю что-то вроде добавления пользовательского цвета к вызову .debug(), вывод окрашивается соответственно -

test "some behavior" do
  Logger.debug("foo", ansi_color: :yellow)
  assert true
end

записывает строки журнала желтым цветом, как и ожидалось.

Однако я заметил, что если я запускаю свои тесты из сеанса iex, цвета не применяются, просто пишутсяк терминалу с цветом шрифта по умолчанию (в моем случае серым) -

iex(1)> Mix.shell().cmd(
          "mix test --color",
          env: [{"MIX_ENV", "test"}]
        )

Почему запуск тестов из командной строки bash приводит к красочным выводам, а запуск их из iex приводит кмой цвет шрифта по умолчанию?

Для контекста - я запускаю его на Mac (Mojave), из командной строки bash (как уже упоминалось), Elixir версии 1.8.1.

По общему признанию,сам по себе это довольно тривиальный вопрос - но я пытаюсь лучше понять оболочку Elixir и различные взаимодействия Mix с оболочкой и системой, и взломать это может помочь мне лучше разобратьсяПонимание того, что вообще происходит под капотом. Это не то, чего я ожидал бы, я хотел бы знать, почему.

Ответы [ 2 ]

3 голосов
/ 21 октября 2019

Объяснение в этой и этой статье, но TL; DR ниже:

Вам необходимо включить цвета в iex через:

iex> Application.put_env(:elixir, :ansi_enabled, true)

но это только область действия сеанса. Если вы хотите сделать его постоянным, вам нужно создать файл .iex.exs в текущем каталоге или в вашем домашнем каталоге:

timestamp = fn ->
  {_date, {hour, minute, _second}} = :calendar.local_time
  [hour, minute]
  |> Enum.map(&(String.pad_leading(Integer.to_string(&1), 2, "0")))
  |> Enum.join(":")
end

IEx.configure(
  colors: [
    syntax_colors: [
      number: :light_yellow,
      atom: :light_cyan,
      string: :light_black,
      boolean: :red,
      nil: [:magenta, :bright],
    ],
    ls_directory: :cyan,
    ls_device: :yellow,
    doc_code: :green,
    doc_inline_code: :magenta,
    doc_headings: [:cyan, :underline],
    doc_title: [:cyan, :bright, :underline],
  ],
)

IEx.configure(
  default_prompt:
    "#{IO.ANSI.green}%prefix#{IO.ANSI.reset} " <>
    "[#{IO.ANSI.magenta}#{timestamp.()}#{IO.ANSI.reset} " <>
    ":: #{IO.ANSI.cyan}%counter#{IO.ANSI.reset}] >"
)

И это все

2 голосов
/ 21 октября 2019

Причина проста: стандартный вывод имеет разные характеристики, когда он работает с «реальным» терминалом, подключенным к стандартному выводу, и когда это канал или файл. Такое же поведение можно увидеть при запуске:

mix test | cat

Поскольку это будет подключать канал, а не «реальный» терминал (на самом деле это эмулятор терминала, но это выходит за рамки вопроса). Это означает, что Elixir не может предположить, что результирующий поток будет поддерживать управляющие коды ANSI. Это важно, когда вы передаете команды отдельным инструментам или файлам для дальнейшей обработки, так как многие из этих инструментов не понимают управляющих кодов ANSI и могут привести к неверным результатам.

Лучший способ запустить mix test из IEx и сохранить всю текущую конфигурацию просто:

Mix.Task.rerun(:test)

И это будет повторно использовать текущую конфигурацию. Конечно, это будет иметь недостаток в том, что он будет работать с текущей средой, но это также можно исправить, запустив MIX_ENV=test iex -S mix, чтобы иметь доступ ко всей тестовой среде внутри оболочки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...