69248
|
1 |
{- generated by Isabelle -}
|
|
2 |
|
|
3 |
{- Title: Tools/Haskell/Pretty.hs
|
|
4 |
Author: Makarius
|
|
5 |
LICENSE: BSD 3-clause (Isabelle)
|
|
6 |
|
|
7 |
Generic pretty printing module.
|
|
8 |
-}
|
|
9 |
|
|
10 |
module Isabelle.Pretty (
|
|
11 |
T, symbolic, formatted, unformatted,
|
|
12 |
|
|
13 |
str, brk_indent, brk, fbrk, breaks, fbreaks, blk, block, strs, markup, mark, mark_str, marks_str,
|
|
14 |
item, text_fold, keyword1, keyword2, text, paragraph, para, quote, cartouche, separate,
|
|
15 |
commas, enclose, enum, list, str_list, big_list)
|
|
16 |
where
|
|
17 |
|
|
18 |
import Isabelle.Library hiding (quote)
|
|
19 |
import qualified Data.List as List
|
|
20 |
import qualified Isabelle.Buffer as Buffer
|
|
21 |
import qualified Isabelle.Markup as Markup
|
|
22 |
import qualified Isabelle.XML as XML
|
|
23 |
import qualified Isabelle.YXML as YXML
|
|
24 |
|
|
25 |
|
|
26 |
data T =
|
|
27 |
Block Markup.T Bool Int [T]
|
|
28 |
| Break Int Int
|
|
29 |
| Str String
|
|
30 |
|
|
31 |
|
|
32 |
{- output -}
|
|
33 |
|
|
34 |
output_spaces n = replicate n ' '
|
|
35 |
|
|
36 |
symbolic_text "" = []
|
|
37 |
symbolic_text s = [XML.Text s]
|
|
38 |
|
|
39 |
symbolic_markup markup body =
|
|
40 |
if Markup.is_empty markup then body
|
|
41 |
else [XML.Elem markup body]
|
|
42 |
|
|
43 |
symbolic :: T -> XML.Body
|
|
44 |
symbolic (Block markup consistent indent prts) =
|
|
45 |
concatMap symbolic prts
|
|
46 |
|> symbolic_markup block_markup
|
|
47 |
|> symbolic_markup markup
|
|
48 |
where block_markup = if null prts then Markup.empty else Markup.block consistent indent
|
|
49 |
symbolic (Break wd ind) = [XML.Elem (Markup.break wd ind) (symbolic_text (output_spaces wd))]
|
|
50 |
symbolic (Str s) = symbolic_text s
|
|
51 |
|
|
52 |
formatted :: T -> String
|
|
53 |
formatted = YXML.string_of_body . symbolic
|
|
54 |
|
|
55 |
unformatted :: T -> String
|
|
56 |
unformatted prt = Buffer.empty |> out prt |> Buffer.content
|
|
57 |
where
|
|
58 |
out (Block markup _ _ prts) =
|
|
59 |
let (bg, en) = YXML.output_markup markup
|
|
60 |
in Buffer.add bg #> fold out prts #> Buffer.add en
|
|
61 |
out (Break _ wd) = Buffer.add (output_spaces wd)
|
|
62 |
out (Str s) = Buffer.add s
|
|
63 |
|
|
64 |
|
|
65 |
{- derived operations to create formatting expressions -}
|
|
66 |
|
|
67 |
force_nat n | n < 0 = 0
|
|
68 |
force_nat n = n
|
|
69 |
|
|
70 |
str :: String -> T
|
|
71 |
str = Str
|
|
72 |
|
|
73 |
brk_indent :: Int -> Int -> T
|
|
74 |
brk_indent wd ind = Break (force_nat wd) ind
|
|
75 |
|
|
76 |
brk :: Int -> T
|
|
77 |
brk wd = brk_indent wd 0
|
|
78 |
|
|
79 |
fbrk :: T
|
|
80 |
fbrk = str "\n"
|
|
81 |
|
|
82 |
breaks, fbreaks :: [T] -> [T]
|
|
83 |
breaks = List.intersperse (brk 1)
|
|
84 |
fbreaks = List.intersperse fbrk
|
|
85 |
|
|
86 |
blk :: (Int, [T]) -> T
|
|
87 |
blk (indent, es) = Block Markup.empty False (force_nat indent) es
|
|
88 |
|
|
89 |
block :: [T] -> T
|
|
90 |
block prts = blk (2, prts)
|
|
91 |
|
|
92 |
strs :: [String] -> T
|
|
93 |
strs = block . breaks . map str
|
|
94 |
|
|
95 |
markup :: Markup.T -> [T] -> T
|
|
96 |
markup m = Block m False 0
|
|
97 |
|
|
98 |
mark :: Markup.T -> T -> T
|
|
99 |
mark m prt = if m == Markup.empty then prt else markup m [prt]
|
|
100 |
|
|
101 |
mark_str :: (Markup.T, String) -> T
|
|
102 |
mark_str (m, s) = mark m (str s)
|
|
103 |
|
|
104 |
marks_str :: ([Markup.T], String) -> T
|
|
105 |
marks_str (ms, s) = fold_rev mark ms (str s)
|
|
106 |
|
|
107 |
item :: [T] -> T
|
|
108 |
item = markup Markup.item
|
|
109 |
|
|
110 |
text_fold :: [T] -> T
|
|
111 |
text_fold = markup Markup.text_fold
|
|
112 |
|
|
113 |
keyword1, keyword2 :: String -> T
|
|
114 |
keyword1 name = mark_str (Markup.keyword1, name)
|
|
115 |
keyword2 name = mark_str (Markup.keyword2, name)
|
|
116 |
|
|
117 |
text :: String -> [T]
|
|
118 |
text = breaks . map str . words
|
|
119 |
|
|
120 |
paragraph :: [T] -> T
|
|
121 |
paragraph = markup Markup.paragraph
|
|
122 |
|
|
123 |
para :: String -> T
|
|
124 |
para = paragraph . text
|
|
125 |
|
|
126 |
quote :: T -> T
|
|
127 |
quote prt = blk (1, [str "\"", prt, str "\""])
|
|
128 |
|
|
129 |
cartouche :: T -> T
|
|
130 |
cartouche prt = blk (1, [str "\92<open>", prt, str "\92<close>"])
|
|
131 |
|
|
132 |
separate :: String -> [T] -> [T]
|
|
133 |
separate sep = List.intercalate [str sep, brk 1] . map single
|
|
134 |
|
|
135 |
commas :: [T] -> [T]
|
|
136 |
commas = separate ","
|
|
137 |
|
|
138 |
enclose :: String -> String -> [T] -> T
|
|
139 |
enclose lpar rpar prts = block (str lpar : prts ++ [str rpar])
|
|
140 |
|
|
141 |
enum :: String -> String -> String -> [T] -> T
|
|
142 |
enum sep lpar rpar = enclose lpar rpar . separate sep
|
|
143 |
|
|
144 |
list :: String -> String -> [T] -> T
|
|
145 |
list = enum ","
|
|
146 |
|
|
147 |
str_list :: String -> String -> [String] -> T
|
|
148 |
str_list lpar rpar = list lpar rpar . map str
|
|
149 |
|
|
150 |
big_list :: String -> [T] -> T
|
|
151 |
big_list name prts = block (fbreaks (str name : prts))
|