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

时间:2012-11-18 16:00:34

标签: haskell pretty-print

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

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

我想我并不完全了解Leijen漂亮的打印机如何工作,但这是我到目前为止所做的:

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"
           ]

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

1 个答案:

答案 0 :(得分:1)

首先让我们尝试从最大值开始尝试每个宽度的文档,然后只打印不同的文档。这将有助于检查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
相关问题