1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
module Ninja.Pretty(
renderNinja, ppFile,
ppDecl, ppDef, ppDefs, ppTargets, ppImplicitTargets, ppOrderOnlyTargets
) where
import Text.Pretty
import Ninja.Types
renderNinja :: File -> String
renderNinja = showWidth 15 . ppFile
ppFile :: File -> Doc
ppFile (File decls) = (vsepBlank $ map ppDecl decls) <> hardline
ppDecl :: Decl -> Doc
ppDecl (Rule n ds) = nest 2 $ text "rule" <+> text n $$
ppDefs ds
ppDecl (Edge r eos ios eis iis ois ds) = nest 2 $
text "build" <+>
ppTargets eos <+>
ppImplicitTargets ios <>
colon <+>
text r <+>
ppTargets eis <+>
ppImplicitTargets iis <+>
ppOrderOnlyTargets ois $$ ppDefs ds
ppDecl (Var d) = ppDef d
ppDecl (Default t) = text "default" <+> text t
ppDecl (Subninja p) = text "subninja" <+> text p
ppDecl (Include p) = text "include" <+> text p
ppDecl (Pool n ds) = nest 2 $ text "pool" <+> text n $$
ppDefs ds
ppDef :: Def -> Doc
ppDef (k,v) = text k <+> equals <+> text v
ppDefs :: [Def] -> Doc
ppDefs = vsep . map ppDef
ppTargets :: [Target] -> Doc
ppTargets = hsep . map (text . escapeFilenames)
ppImplicitTargets :: [Target] -> Doc
ppImplicitTargets [] = empty
ppImplicitTargets ts@(_:_) = char '|' <+> ppTargets ts
ppOrderOnlyTargets :: [Target] -> Doc
ppOrderOnlyTargets [] = empty
ppOrderOnlyTargets ts@(_:_) = text "||" <+> ppTargets ts
escapeFilenames :: Target -> Target
escapeFilenames = concatMap $ \c -> case c of
' ' -> "$ "
'$' -> "$$"
'\n' -> "$\n"
':' -> "$:"
_ -> [c]
|