Inspect.Algebra
Inspect.Algebra
一组用于创建和操作代数文档的函数。
这个模块实现了Christian Lindig在“Strictly Pretty”(2000)中所描述的功能,并增加了一些小功能,比如对String节点的支持以及最大化水平空间使用的自定义渲染功能。
iex> Inspect.Algebra.empty
:doc_nil
iex> "foo"
"foo"
通过本模块中的功能,我们可以将不同的元素连接在一起并呈现它们:
iex> doc = Inspect.Algebra.concat(Inspect.Algebra.empty, "foo")
iex> Inspect.Algebra.format(doc, 80)
["foo"]
功能nest/2
,space/2
和line/2
帮助您将文档合并成一个严格的结构。然而,当使用如下函数时,文档代数变得很有趣break/1
,它根据要打印的空间大小将给定的字符串转换为换行。让我们将两个文档粘合在一起,然后呈现:
iex> doc = Inspect.Algebra.glue("a", " ", "b")
iex> Inspect.Algebra.format(doc, 80)
["a", " ", "b"]
注意,中断是按原样表示的,因为我们还没有达到行限制。一旦我们这样做了,它就会被换行符所取代:
iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b")
iex> Inspect.Algebra.format(doc, 10)
["aaaaaaaaaaaaaaaaaaaa", "\n", "b"]
最后,本模块还包含与elxir相关的函数,与elxir格式有一点关联,即surround/3
和surround_many/5
...
实施细节
Wadler对算法的原始Haskell实现依赖懒惰评估来展开两个备选文档组:flat
(以空格分隔)和:break
(以新行分隔)。以Elixir这样严格的语言实现相同的逻辑会导致可能文档的指数增长,除非文档组被明确地编码为:flat
或:break
。然后,这些组被缩减为一个简单的文档,每个Lindig都已经确定了布局。
这个实现略微改变了Lindig算法的语义,以允许属于同一组的元素在同一行中一起打印,即使它们完全不符合该行。这是通过改变:break
意味着可能的休息和:flat
强制平面结构来实现的。然后决定一个休息是否作为一个换行符工作,只是检查是否有足够的空间,直到下一个休息时间不在一个组内(仍然持平)。
自定义漂亮的打印机可以使用本模块返回的文档并提供自己的渲染功能来实现。
摘要
类型
t()
功能
break()
返回一个" "
字符串为break 的文档实体
break(string)
根据给定值返回表示中断的文档实体 string
color(doc, color_key, opts)
如果color_key
选项中有颜色,则对文档着色
concat(docs)
连接返回新文档的文档列表
concat(doc1, doc2)
连接两个文档实体,返回一个新文档
empty()
返回用于表示虚无的文档实体
fold_doc(docs, folder_fun)
使用给定的文件夹功能将文档列表折叠到文档中
format(doc, width)
为给定宽度格式化给定的文档
glue(doc1, doc2)
将两个文档粘合在一起插入," "
作为它们之间的中断
glue(doc1, break_string, doc2)
将两个文档(doc1
和doc2
)粘合在一起,break_string
在它们之间插入给定的中断
group(doc)
返回包含指定文档的组 doc
line(doc1, doc2)
在两个文档之间插入强制换行符
nest(doc, level)
在指定的文件中嵌套给定的文档 level
space(doc1, doc2)
在两个文档之间插入一个必填单个空格
surround(left, doc, right)
用字符围绕文档
surround_many(left, docs, right, opts, fun, separator \ ",")
贴图和粘贴一组物品
to_doc(term, opts)
根据Inspect
协议将Elixir术语转换为代数文档
类型
t()
t ::
:doc_nil |
:doc_line |
doc_cons |
doc_nest |
doc_break |
doc_group |
doc_color |
binary
功能
break()
break() :: doc_break
返回一个" "
字符串为break 的文档实体。
查看break/1
更多信息。
break(string)
break(binary) :: doc_break
根据给定值返回表示中断的文档实体string
。
这个中断可以被渲染为换行符或给定的string
,这取决于mode
所选布局或提供的分隔符。
例子
让我们通过连接两个字符串并在它们之间创建一个中断来创建一个文档:
iex> doc = Inspect.Algebra.concat(["a", Inspect.Algebra.break("\t"), "b"])
iex> Inspect.Algebra.format(doc, 80)
["a", "\t", "b"]
请注意,中断是由给定的字符串表示的,因为我们没有达到线路限制。一旦我们做到了,它将被换行符所取代:
iex> break = Inspect.Algebra.break("\t")
iex> doc = Inspect.Algebra.concat([String.duplicate("a", 20), break, "b"])
iex> Inspect.Algebra.format(doc, 10)
["aaaaaaaaaaaaaaaaaaaa", "\n", "b"]
color(doc, color_key, opts)
color(t, Inspect.Opts.color_key, Inspect.Opts.t) :: doc_color
如果color_key
选项中有颜色,则对文档着色。
concat(docs)
concat(t, t) :: t
连接两个返回新文档的文档实体。
实例
iex> doc = Inspect.Algebra.concat("hello", "world")
iex> Inspect.Algebra.format(doc, 80)
["hello", "world"]
concat(doc1, doc2)
empty() :: :doc_nil
返回用于表示虚无的文档实体。
实例
iex> doc = Inspect.Algebra.concat("hello", "world")
iex> Inspect.Algebra.format(doc, 80)
["hello", "world"]
empty()
fold_doc([t], (t, t -> t)) :: t
返回用于表示虚无的文档实体。
例子
iex> Inspect.Algebra.empty
:doc_nil
fold_doc(docs, folder_fun)
fold_doc([t], (t, t -> t)) :: t
使用给定的文件夹功能将文档列表折叠到文档中。
文件清单“从右边”折叠; 在这个函数中List.foldr/3
,除了它不期望初始累加器并且使用最后一个元素docs
作为初始累加器之外,该函数与之类似。
例子
iex> docs = ["A", "B", "C"]
iex> docs = Inspect.Algebra.fold_doc(docs, fn(doc, acc) ->
...> Inspect.Algebra.concat([doc, "!", acc])
...> end)
iex> Inspect.Algebra.format(docs, 80)
["A", "!", "B", "!", "C"]
format(doc, width)
format(t, non_neg_integer | :infinity) :: iodata
为给定宽度格式化给定的文档。
将最大宽度和文档作为其参数进行打印,并返回文档的最佳布局的IO数据表示以适合给定的宽度。
例子
iex> doc = Inspect.Algebra.glue("hello", " ", "world")
iex> Inspect.Algebra.format(doc, 30) |> IO.iodata_to_binary()
"hello world"
iex> Inspect.Algebra.format(doc, 10) |> IO.iodata_to_binary()
"hello\nworld"
glue(doc1, doc2)
glue(t, t) :: t
将两个文档粘合在一起插入," "
作为它们之间的中断。
这意味着这两个文件将分开" "
,以防他们适合在同一行。否则使用换行符。
例子
iex> doc = Inspect.Algebra.glue("hello", "world")
iex> Inspect.Algebra.format(doc, 80)
["hello", " ", "world"]
glue(doc1, break_string, doc2)
glue(t, binary, t) :: t
将两个文档(doc1
和doc2
)粘合在一起,break_string
在它们之间插入给定的中断。
有关如何插入中断的更多信息,请参阅break/1
。
例子
iex> doc = Inspect.Algebra.glue("hello", "\t", "world")
iex> Inspect.Algebra.format(doc, 80)
["hello", "\t", "world"]
group(doc)
group(t) :: doc_group
返回包含指定文档的组doc
。
尝试将组中的文档渲染到最佳渲染能力。
实例
iex> doc = Inspect.Algebra.group(
...> Inspect.Algebra.concat(
...> Inspect.Algebra.group(
...> Inspect.Algebra.concat(
...> "Hello,",
...> Inspect.Algebra.concat(
...> Inspect.Algebra.break,
...> "A"
...> )
...> )
...> ),
...> Inspect.Algebra.concat(
...> Inspect.Algebra.break,
...> "B"
...> )
...> ))
iex> Inspect.Algebra.format(doc, 80)
["Hello,", " ", "A", " ", "B"]
iex> Inspect.Algebra.format(doc, 6)
["Hello,", "\n", "A", " ", "B"]
line(doc1, doc2)
line(t, t) :: t
在两个文档之间插入强制换行符。
例子
iex> doc = Inspect.Algebra.line("Hughes", "Wadler")
iex> Inspect.Algebra.format(doc, 80)
["Hughes", "\n", "Wadler"]
nest(doc, level)
nest(t, non_neg_integer) :: doc_nest
在指定的文件中嵌套给定的文档level
。
嵌套将被附加到换行符。
实例
iex> doc = Inspect.Algebra.space("Hughes", "Wadler")
iex> Inspect.Algebra.format(doc, 5)
["Hughes", " ", "Wadler"]
space(doc1, doc2)
surround(t, t) :: t
在两个文档之间插入一个必填单个空格。
例子
iex> doc = Inspect.Algebra.space("Hughes", "Wadler")
iex> Inspect.Algebra.format(doc, 5)
["Hughes", " ", "Wadler"]
surround(left, doc, right)
surround(t, t, t) :: t
Surrounds a document with characters.
使给定文件doc
之间left
和right
文件封装和嵌套它。该文件被标记为一组,以尽可能简明地显示最大值。
例子
iex> doc = Inspect.Algebra.surround("[", Inspect.Algebra.glue("a", "b"), "]")
iex> Inspect.Algebra.format(doc, 3)
["[", "a", "\n ", "b", "]"]
surround_many(left, docs, right, opts, fun, separator \ ",")
surround_many(t, [any], t, Inspect.Opts.t, (term, Inspect.Opts.t -> t), t) :: t
贴图和粘贴一组物品。
它使用给定left
和right
文档作为周边和分离文件separator
,以在不同的项目docs
。可以传递一个限制:达到此限制时,此功能将停止胶合并输出"..."
。
例子
iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]",
...> %Inspect.Opts{limit: :infinity}, fn i, _opts -> to_string(i) end)
iex> Inspect.Algebra.format(doc, 5) |> IO.iodata_to_binary
"[1,\n 2,\n 3,\n 4,\n 5]"
iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]",
...> %Inspect.Opts{limit: 3}, fn i, _opts -> to_string(i) end)
iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary
"[1, 2, 3, ...]"
iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]",
...> %Inspect.Opts{limit: 3}, fn i, _opts -> to_string(i) end, "!")
iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary
"[1! 2! 3! ...]"