我正在尝试使用Text.PrettyPrint
生成Javascript。问题是nest
在放在另一个漂亮元素旁边时会产生巨大的缩进。例如,在此代码中:
import Text.PrettyPrint
fun :: Doc
fun = vcat [ text "function" <+> lbrace
, nest 4 $ vcat $ replicate 5 $ text "// foo"
, rbrace
]
var :: Doc
var = text "var" <+> text "x"
test :: Doc
test = var <+> equals <+> fun <> semi
fun
从test
中的第9列开始(因为它左边是var <+> equals <> empty
),因此其后续行缩进了9 + 4 = 13列:
var x = function {
// foo
// foo
// foo
// foo
// foo
};
有没有办法从左边距渲染缩进,以便将上面的内容呈现为
var x = function {
// foo
// foo
// foo
// foo
// foo
};
答案 0 :(得分:2)
offset = 1 + length (render $ var <+> equals) hang empty (negate offset) test
答案 1 :(得分:2)
解决方案确实是使用wl-pprint
(并将nest
替换为indent
)。然后,给出的代码产生
var x = function {
// foo
// foo
// foo
// foo
// foo
};
根据需要。对于仍然打算尝试攻击pretty
的人,请注意虽然Doc
的构造函数未公开,但您仍然可以通过Generic
{{1}来获取它们}}:
-XPatternSynonyms
问题主要是没有违反图书馆的许多不变量。
作为旁注,我还发现了wl-pprint-annotated
,这是对-- | Means of exposing the data constructors of `Doc` from `pretty`
pattern GEmpty = M1 (L1 (L1 (L1 (M1 U1))))
pattern GNilAbove doc = M1 (L1 (L1 (R1 (M1 (M1 (K1 doc))))))
pattern GTextBeside d doc = M1 (L1 (R1 (L1 (M1 (M1 (K1 d) :*: M1 (K1 doc))))))
pattern GNest n doc = M1 (L1 (R1 (R1 (M1 (M1 (K1 n) :*: M1 (K1 doc))))))
pattern GUnion ldoc rdoc = M1 (R1 (L1 (L1 (M1 (M1 (K1 ldoc) :*: M1 (K1 rdoc))))))
pattern GNoDoc = M1 (R1 (L1 (R1 (M1 U1))))
pattern GBeside ldoc s rdoc = M1 (R1 (R1 (L1 (M1 (M1 (K1 ldoc) :*: M1 (K1 s) :*: M1 (K1 rdoc))))))
pattern GAbove ldoc b rdoc = M1 (R1 (R1 (R1 (M1 (M1 (K1 ldoc) :*: M1 (K1 b) :*: M1 (K1 rdoc))))))
的现代重写,使用它可以访问底层数据构造函数(代价是需要记住不变量)参与)。这实际上是我最终会使用的包。
特别是,它允许我制作这种支撑块,如果它足够小,它只会在一行上出现:
wl-pprint
然后我得到了很好的结果,自动执行或不跨越多行:
-- | Asserts a 'Doc a' cannot render on multiple lines.
oneLine :: Doc a -> Bool
oneLine (WL.FlatAlt d _) = oneLine d
oneLine (WL.Cat a b) = oneLine a && oneLine b
oneLine (WL.Union a b) = oneLine a && oneLine b
oneLine (WL.Annotate _ d) = oneLine d
oneLine WL.Line = False
oneLine _ = True
-- | Make a curly-brace delimited block. When possible, permit fitting everything on one line
block :: Doc a -> Doc a
block b | oneLine b = hsep ["{", b, "}"] `WL.Union` vsep [ "{", indent 2 b, "}" ]
| otherwise = vsep [ "{", indent 2 b, "}" ]
答案 2 :(得分:1)
通过将vcat
应用于第一项还包含变量定义和赋值的列表,您可以获得所需的结果。
示例:
fun :: Doc
fun = vcat [ var <+> equals <+> text "function" <+> lbrace
, nest 4 $ vcat $ replicate 5 $ text "// foo"
, rbrace
]
var :: Doc
var = text "var" <+> text "x"
test :: Doc
test = fun <> semi