我是elixir的新手并且构建了一个命令行应用程序,以熟悉mix和elixir而没有太多的依赖。
当我构建命令行应用程序时,我倾向于使用ansi颜色代码来使输出更具可读性。
IO.ANSI
似乎只支持8种颜色,可能会与bright
,underline
等内容结合使用。无法获得16种颜色中的其他8种颜色-color pallette。
当前来源包含以下代码:
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
看来,实现我之后所做的一项微不足道的修改就是将以下几行添加到现有函数中:
@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
如何在elixir中实现这样的事情(不需要代码)?或者是不可能的?
答案 0 :(得分:2)
您无法修改现有模块,这是设计使然。我不希望我团队中的任何人改变我已经知道的东西。
但应该可以创建满足您需求的新模块。
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
但是现在,您必须记住哪个函数来自原始ANSI
,哪个函数来自ExtendedANSI
。您可以为ANSI
中存在的所有函数创建委托:
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
现在,您可以致电IO.ExtendedANSI.blue()
和IO.ExtendedANSI.light_blue()
。
虽然解决方案并不完美:
colors
,因此如果原始版本发生变化,我们也需要更改代码。我不确定是否有办法获得它,因为它是内部实现细节def format(chardata, emit? \\ enabled?)
等参数的函数会在帮助中正确显示See IO.ANSI.format/2
,但它们会有签名def fromat(arg1, arg2)
。应该有办法以某种方式做到这一点。