Haskell Leijen 漂亮打印机,无法处理缩进



我正在为Lua开发一台漂亮的打印机,我一直在处理函数语法的缩进。

我想要的是:如果函数定义足够短,所有的定义都可以写在一行中,但如果不是那么短,那么所有正文都需要打印在新行中并带有缩进。之后,end关键字应该放在一个新行中,没有缩进。

我想我还不完全理解雷人漂亮的打印机是如何工作的,但这就是我目前所拥有的:

import Text.PrettyPrint.Leijen
import System.IO (stdout)
sometext = text "short text" </> text "this is some long text at least long enough for my purposes"
p = parens (align (cat (punctuate (comma <> space) (map text ["first parameter", "second parameter", "third"]))))
doc3 = indent 4 (sep [text "function" </> p, indent 4 sometext, text "end"])
main :: IO ()
main = do
displayIO stdout (renderPretty 1 133 (doc3 <$> line))
displayIO stdout (renderPretty 1 134 (doc3 <$> line))
displayIO stdout (renderPretty 1 40 (doc3 <$> line))

除了输出的第二部分:之外,这实际上运行得很好

function (first parameter, second parameter, third)
short text this is some long text at least long enough for my purposes
end
function (first parameter, second parameter, third)     short text this is some long text at least long enough for my purposes end
function (first parameter, 
second parameter, 
third)
short text
this is some long text at least long enough for my purposes
end

在这里,我不希望在第二次输出中出现4个空格的缩进。但我找不到一种不破坏其他产出的方法。

任何帮助都将不胜感激。

编辑:这是另一个测试用例:

doc4 = sep [ text "if" </> text "test" </> text "then"
, indent 4 then_body
, text "elseif" </> elseif_conditions </> text "then"
, indent 4 elseif_body
, text "end"
]

我想要的是,如果输出足够短,则在同一行打印所有输出(但没有缩进空间)。分割多行时效果很好,但打印到同一行时会留出多余的空间。

首先,让我们尝试从最大值开始的每个宽度的文档,并且只打印不同的文档。这将有助于检查Doc的行为是否符合您的期望。

import Text.PrettyPrint.Leijen
import System.IO (stdout)
import Data.List
import Data.Function
testFrom :: Int -> Doc -> IO ()
testFrom w d = mapM_ printone . nubBy ((==) `on` snd) .map (`showAt` d). reverse $ [1..w] where
showAt n doc = (n,displayS (renderPretty 1 n doc) "")
printone (n,xs) = putStrLn (show n ++ ":") >> putStrLn xs

我(现在)认为你想要什么

现在,让我们充分利用您评论中的额外信息。对不起,我第一次误解了你的意思。

我想你的意思是,允许所有的函数都在一行上,但如果不允许,至少应该有三个,函数头在第一行,函数体缩进,结尾不缩进。您不介意sometext是否在断点处拆分为多行,在参数之后,等等,只要它不是内联的,缩进4即可。

nest函数允许我们缩进后面的行(如果有的话),而indent肯定会放空格,这就是为什么会有难看的额外4行。

因此,你的功能有三个部分:

functionhead = text "function" </> p
sometext = text "short text" 
</> text "this is some long text at least long enough for my purposes"
end = text "end"

用一种稍微重构的方法制作参数:

params = parens.align.cat.punctuate (comma <> space).map text 
p = params ["first parameter", "second parameter", "third"]

按照指定的间隔进行布置

如果我们需要换行,让我们具体说明我们希望它们如何排列:

tidyfunction = nest 4 (functionhead <$> sometext) <$> end

这表明了我们希望换行的方式:

*Main> testFrom 140 tidy
140:
function (first parameter, second parameter, third)
short text this is some long text at least long enough for my purposes
end
73:
function (first parameter, second parameter, third)
short text
this is some long text at least long enough for my purposes
end
50:
function (first parameter, 
second parameter, 
third)
short text
this is some long text at least long enough for my purposes
end
26:
function
(first parameter, 
second parameter, 
third)
short text
this is some long text at least long enough for my purposes
end

如果合适,将其全部放在一行

漂亮的打印库有一个组合子,如果它适合一行group,则可以消除所有换行符。让我们把整批货缩进4并分组。

nicefunction = group $ indent 4 tidyfunction

哪个给出:

*Main> testFrom 140 nicefunction
140:
function (first parameter, second parameter, third) short text this is some long text at least long enough for my purposes end
129:
function (first parameter, second parameter, third)
short text this is some long text at least long enough for my purposes
end
77:
function (first parameter, second parameter, third)
short text
this is some long text at least long enough for my purposes
end
54:
function (first parameter, 
second parameter, 
third)
short text
this is some long text at least long enough for my purposes
end
30:
function
(first parameter, 
second parameter, 
third)
short text
this is some long text at least long enough for my purposes
end

最新更新