prettyprinter:窄边距换行,否则为空

prettyprinter: Linebreak on narrow margin, mempty otherwise

我正在使用 prettyprinter 库来漂亮打印 foo(bar, baz),当边距太窄时,我希望它看起来像:

foo(
  bar,
  baz)

我该怎么做?

我迄今为止最好的尝试:

> import Prettyprinter
> import Prettyprinter.Util
> let commas = punctuate comma

-- 'sep' and 'nest' seem to go well together, but the result lacks the linebreak
> putDocW 10 ("foo" <> parens (nest 2 (sep (commas ["bar", "baz"]))))
foo(bar,
  baz)

-- Using 'line'' inside 'nest' almost does the trick
> putDocW 10 ("foo" <> parens (nest 2 (line' <> sep (commas ["bar", "baz"]))))
foo(
  bar,
  baz)

-- Except 'line'' doesn't seem "mempty" enough
> putDocW 20 ("foo" <> parens (nest 2 (line' <> sep (commas ["bar", "baz"]))))
foo(
  bar, baz)

我以为我想要的是 line' 因为提到 mempty:

line' is like line, but behaves like mempty if the line break is undone by group (instead of space).

但也许我误解了“由 group 撤消”的含义。

其他 none(linesoftlinesoftline')的结果似乎更好。

我不确定这是“正确”的方式,但这是一种方式:

hcat
  [ "prefix"
  , nest 2 $ cat
    $ "("
    : punctuate (flatAlt "," ", ")
      [ "first"
      , "second"
      , "third"
      ]
  , ")"
  ]

也就是说,在前缀后悬挂左括号和标点符号的串联,根据它们是否折叠将它们分开或不带尾随 space,并附加在右括号上。

或者,您可以制作自己的 encloseSep 变体,在末尾而不是开头添加分隔符,并在 cat:

中包含开始定界符
encloseSepEnd
  :: Doc ann -> Doc ann -> Doc ann -> [Doc ann] -> Doc ann
encloseSepEnd open close sep docs = case docs of
  [] -> open <> close
  [doc] -> open <> doc <> close
  _ -> cat (open : suffixReverse (close : repeat sep) docs)

suffixReverse
  :: (Foldable t, Semigroup a)
  => [a] -> t a -> [a]
suffixReverse separators
  = snd . foldr go (separators, [])
  where
    go doc (sep : seps, acc) = (seps, doc <> sep : acc)
hcat
  [ "prefix"
  , nest 2 $ encloseSepEnd "(" ")" ", "
    ["first", "second", "third"]
  ]

顺便说一句,老实说,我发现我总是不得不用它们的单独部分替换像 parens 这样的括号函数,以达到我想要的结果,而 group 从来没有像我希望的那样表现.