Elixir - 从命令行运行时记录器输出是彩色的,从 iex 运行时不是这样

Posted

技术标签:

【中文标题】Elixir - 从命令行运行时记录器输出是彩色的,从 iex 运行时不是这样【英文标题】:Elixir - Logger output is colorful when run from command line, not so when run from iex 【发布时间】:2020-02-17 01:15:52 【问题描述】:

在我的 Elixir 混合应用程序中运行测试时,我有几个实例包括对 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 shell 以及 Mix 与 shell 和系统的各种交互,破解它可能有助于我更好地理解一般情况下发生了什么。这不是我所期望的,我想知道为什么。

【问题讨论】:

【参考方案1】:

推理很简单——当标准输出在“真实”终端连接到标准输出的情况下运行时以及它是管道或文件时,它具有不同的特性。运行时可以看到相同的行为:

mix test | cat

因为这将附加管道,而不是“真正的”终端(实际上它是终端仿真器,但这超出了问题的范围)。这意味着 Elixir 不能假设生成的流将支持 ANSI 转义码。当您将命令通过管道传输到单独的工具或文件以进行进一步处理时,这一点很重要,因为其中许多工具不理解 ANSI 转义码并会导致错误的结果。

IEx 中运行mix test 并保留所有当前配置的最佳方法是:

Mix.Task.rerun(:test)

这将重用当前配置。当然,这会有缺点,它会在当前环境下运行,但也可以通过运行MIX_ENV=test iex -S mix 来解决这个问题,以便在 shell 中访问整个测试环境。

【讨论】:

非常酷 - 这让我对我一直试图解决的一些相关问题/问题有了新的看法。非常感谢。【参考方案2】:

解释在 this 和 this 文章中,但 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] >"
)

仅此而已

【讨论】:

太好了,感谢您提供的文章和详细的示例 - 第二篇文章非常有帮助,让我对 IEx 有了很多了解。

以上是关于Elixir - 从命令行运行时记录器输出是彩色的,从 iex 运行时不是这样的主要内容,如果未能解决你的问题,请参考以下文章

从 php 脚本执行彩色命令

从命令行运行 gradle 时如何执行和显示友好的测试输出

[Logs] 日志功能 彩色命令行工具

为 PHP 的 Windows 命令行输出着色

有没有办法防止Windows命令行中env变量的百分比扩展?

从命令行执行时 MySQL 输出帮助/选项