在elixir中,如何向来自外部源(第三方、stdlib等)的模块添加功能?
我对elixir还不熟悉,我正在构建一个命令行应用程序来熟悉mix和elixir,而不需要太多依赖项 当我构建命令行应用程序时,我倾向于使用ansi颜色代码来提高输出的可读性在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} <
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