Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在elixir中,如何向来自外部源(第三方、stdlib等)的模块添加功能?_Elixir - Fatal编程技术网

在elixir中,如何向来自外部源(第三方、stdlib等)的模块添加功能?

在elixir中,如何向来自外部源(第三方、stdlib等)的模块添加功能?,elixir,Elixir,我对elixir还不熟悉,我正在构建一个命令行应用程序来熟悉mix和elixir,而不需要太多依赖项 当我构建命令行应用程序时,我倾向于使用ansi颜色代码来提高输出的可读性 IO.ANSI似乎只支持8种颜色,它们可能与明亮的、下划线等组合在一起。在16色托盘中,无法获得其他8种颜色 当前源具有以下代码: colors = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white] for {color, code} <

我对elixir还不熟悉,我正在构建一个命令行应用程序来熟悉mix和elixir,而不需要太多依赖项

当我构建命令行应用程序时,我倾向于使用ansi颜色代码来提高输出的可读性

IO.ANSI
似乎只支持8种颜色,它们可能与
明亮的
下划线
等组合在一起。在16色托盘中,无法获得其他8种颜色

当前源具有以下代码:

colors = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]

for {color, code} <- Enum.with_index(colors) do
  @doc "Sets foreground color to #{color}."
  defsequence color, code + 30

  @doc "Sets background color to #{color}."
  defsequence :"#{color}_background", code + 40
end

如何在elixir中实现这样的操作(无需分叉代码)?还是不可能?

您不能修改现有模块,这是出于设计。我不希望团队中的任何人改变我已经知道的事情

但是应该可以创建一个新的模块来满足您的需求。
defsequence
是一个可以从其他模块导入的宏,因此您可以编写:

defmodule IO.ExtendedANSI do
  import IO.ANSI.Sequence

  colors = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]

  for {color, code} <- Enum.with_index(colors) do
    @doc "Sets foreground color to light #{color}."
    defsequence :"light_#{color}", code + 90

    @doc "Sets background color to light #{color}."
    defsequence :"light_#{color}_background", code + 100
  end
end
现在您可以调用
IO.ExtendedANSI.blue()
IO.ExtendedANSI.light\u blue()

但解决方案并不完美:

  • 我们需要重新定义
    颜色
    ,所以如果原来的颜色改变了,我们也需要改变我们的代码。我不确定是否有办法获得它,因为这是内部实现细节
  • 接受参数如
    def format(chardata,emit?\\enabled?
    的函数将正确显示
    请参见帮助中的IO.ANSI.format/2
    ,但它们将具有签名
    def fromat(arg1,arg2)
    。应该有办法做到这一点

这在很大程度上符合我当时的想法。但是,虽然这些函数现在包含在新模块中,但当尝试使用其中一个函数时,我仍然会得到
(ArgumentError)无效的ANSI序列规范::light_red
,即
IO.ExtendedANSI.format[:light_red,“foo”],true
。使用新模块,标准颜色可以正常工作。我知道,
ExtendedANSI
委托给
ANSI
,该模块内部只使用
ANSI
,不知道新颜色。也许有另一种方法可以实现你所需要的,但它更复杂。您可以使用此技术获取整个
ANSI
模块的AST,修改其内部(
color
变量)并将其另存为另一个模块。
defmodule IO.ExtendedANSI do
  import IO.ANSI.Sequence

  colors = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]

  for {color, code} <- Enum.with_index(colors) do
    @doc "Sets foreground color to light #{color}."
    defsequence :"light_#{color}", code + 90

    @doc "Sets background color to light #{color}."
    defsequence :"light_#{color}_background", code + 100
  end
end
defmodule IO.ExtendedANSI do
  import IO.ANSI.Sequence

  IO.ANSI.__info__(:functions)
  |> Enum.each(fn {name, arity} ->
    args = Enum.map(:lists.seq(1, arity), fn(i) -> {:"arg#{i}", [], Elixir} end)
    defdelegate unquote({name, [], args}), to: IO.ANSI
  end)

  colors = [...]
    ...
end