1 from sympy
.core
import Basic
, Function
# XXX remove Function from here
2 from printer
import Printer
3 from stringpict
import *
9 def pprint_use_unicode(flag
= None):
10 """Set whether pretty-printer should use unicode by default"""
15 use_unicode_prev
= _use_unicode
17 return use_unicode_prev
19 class PrettyPrinter(Printer
):
21 A class that prints a prettified expression, one that is not limited
22 to one dimension like casting the expression to a string would return.
24 def __init__(self
, use_unicode
=None):
25 Printer
.__init
__(self
)
26 if use_unicode
is None:
27 use_unicode
= _use_unicode
28 self
._use
_unicode
= use_unicode
31 self
.emptyPrinter
= lambda x
: prettyForm(self
._str
(x
), prettyForm
.ATOM
)
33 def doprint(self
, expr
):
34 Printer
.doprint
.__doc
__
35 return self
._print
(expr
).terminal_string()
37 def _print_Symbol(self
, e
):
39 # letter: (uppercase, lowercase)
41 'alpha': (u
'\u0391', u
'\u03b1'),
42 'beta': (u
'\u0392', u
'\u03b2'),
43 'gamma': (u
'\u0393', u
'\u03b3'),
44 'delta': (u
'\u0394', u
'\u03b4'),
45 'epsilon': (u
'\u0395', u
'\u03b5'),
46 'zeta': (u
'\u0396', u
'\u03b6'),
47 'eta': (u
'\u0397', u
'\u03b7'),
48 'theta': (u
'\u0398', u
'\u03b8'),
49 'iota': (u
'\u0399', u
'\u03b9'),
50 'kappa': (u
'\u039a', u
'\u03ba'),
51 'lambda': (u
'\u039b', u
'\u03bb'),
52 'mu': (u
'\u039c', u
'\u03bc'),
53 'nu': (u
'\u039d', u
'\u03bd'),
54 'xi': (u
'\u039e', u
'\u03be'),
55 'omicron': (u
'\u039f', u
'\u03bf'),
56 'pi': (u
'\u03a0', u
'\u03c0'),
57 'rho': (u
'\u03a1', u
'\u03c1'),
58 'sigma': (u
'\u03a3', u
'\u03c3'),
59 'tau': (u
'\u03a4', u
'\u03c4'),
60 'upsilon': (u
'\u03a5', u
'\u03c5'),
61 'phi': (u
'\u03a6', u
'\u03c6'),
62 'chi': (u
'\u03a7', u
'\u03c7'),
63 'psi': (u
'\u03a8', u
'\u03c8'),
64 'omega': (u
'\u03a9', u
'\u03c9')
69 # let's split name into symbol + index
71 m
= re
.match('(\D+)(\d*)$', name
)
75 name
= m
.expand(r
'\1')
79 # If first character lowercase, use lowercase greek letter
80 if name
[0] == e
.name
[0]:
81 greek_name
= greek
[name
][1]
83 greek_name
= greek
[name
][0]
85 return prettyForm(greek_name
+idx
, binding
=prettyForm
.ATOM
)
87 def _print_Factorial(self
, e
):
89 if (isinstance(x
, Basic
.Integer
) and x
.is_nonnegative
) or \
90 isinstance(x
, Basic
.Symbol
):
93 s
= "(" + self
._print
(x
) + ")"
96 def _print_Exp1(self
, e
):
98 return prettyForm(u
'\u212f', binding
=prettyForm
.ATOM
)
100 def _print_Pi(self
, e
):
101 if self
._use
_unicode
:
102 return prettyForm(u
'\u03c0', binding
=prettyForm
.ATOM
)
104 def _print_Infinity(self
, e
):
105 if self
._use
_unicode
:
106 return prettyForm(u
'\u221e', binding
=prettyForm
.ATOM
)
108 def _print_NegativeInfinity(self
, e
):
109 if self
._use
_unicode
:
110 return prettyForm(u
'-\u221e', binding
=prettyForm
.ATOM
)
112 def _print_ImaginaryUnit(self
, e
):
113 if self
._use
_unicode
:
114 return prettyForm(u
'\u03b9', binding
=prettyForm
.ATOM
)
116 def _print_Relational(self
, e
):
120 '<=': ('<=', u
'\u2264'),
121 '!=': ('!=', u
'\u2260')
123 if self
._use
_unicode
:
124 op
= charmap
[e
.rel_op
][1]
126 op
= charmap
[e
.rel_op
][0]
127 op
= prettyForm(' ' + op
+ ' ')
129 l
= self
._print
(e
.lhs
)
130 r
= self
._print
(e
.rhs
)
131 pform
= prettyForm(*stringPict
.next(l
, op
))
132 pform
= prettyForm(*stringPict
.next(pform
, r
))
135 def _print_ApplyConjugate(self
, e
):
136 pform
= self
._print
(e
[0])
137 return prettyForm(*stringPict
.above(pform
, '_'*pform
.width()))
139 def _print_abs(self
, e
):
140 pform
= self
._print
(e
[0])
142 bars
= '|' + ('\n|' * (pform
.height()-1))
143 pform
= prettyForm(*stringPict
.next(bars
, pform
))
144 pform
= prettyForm(*stringPict
.next(pform
, bars
))
147 def _print_Derivative(self
, deriv
):
148 syms
= list(deriv
.symbols
)
153 x
= prettyForm('d' + str(sym
))
155 x
= prettyForm(*stringPict
.next(x
, ' d' + str(sym
)))
157 f
= prettyForm(binding
=prettyForm
.FUNC
, *self
._print
(deriv
.expr
).parens())
159 pform
= prettyForm('d')
161 pform
= pform
** prettyForm(str(len(deriv
.symbols
)))
163 pform
= prettyForm(*pform
.below(stringPict
.LINE
, x
))
164 pform
.baseline
= pform
.baseline
+ 1
165 pform
= prettyForm(*stringPict
.next(pform
, f
))
168 def _print_Integral(self
, integral
):
169 f
= integral
.function
171 # Add parentheses if a sum and create pretty form for argument
172 prettyF
= self
._print
(f
)
173 if isinstance(f
, Basic
.Add
):
174 prettyF
= prettyForm(*prettyF
.parens())
178 for x
,ab
in integral
.limits
:
179 prettyArg
= self
._print
(x
)
180 if prettyArg
.width() > 1:
181 arg
= prettyForm(*arg
.right(' d(', prettyArg
, ')'))
183 arg
= prettyForm(*arg
.right(' d', prettyArg
))
190 for x
,ab
in integral
.limits
:
191 # Create bar based on the height of the argument
192 bar
= ' |' + ('\r |' * (arg
.height()+1))
194 # Construct the pretty form with the integral sign and the argument
195 pform
= prettyForm(bar
)
196 pform
= prettyForm(*pform
.below(' / '))
197 pform
= prettyForm(*pform
.above(' /'))
198 pform
.baseline
= (arg
.height() + 3)/2
201 # Create pretty forms for endpoints, if definite integral
202 prettyA
= self
._print
(ab
[0])
203 prettyB
= self
._print
(ab
[1])
205 # Add spacing so that endpoint can more easily be
206 # identified with the correct integral sign
207 spc
= max(1, 4 - prettyB
.width())
208 prettyB
= prettyForm(*prettyB
.left(' ' * spc
))
210 pform
= prettyForm(*pform
.above(prettyB
))
211 pform
= prettyForm(*pform
.below(prettyA
))
212 pform
= prettyForm(*pform
.right(' '))
215 S
= pform
# first term
218 S
= prettyForm(*S
.left(pform
))
220 pform
= prettyForm(*arg
.left(S
))
223 def _print_exp(self
, e
):
224 if self
._use
_unicode
:
225 base
= prettyForm(u
'\u212f', binding
=prettyForm
.ATOM
)
227 base
= prettyForm('e', binding
=prettyForm
.ATOM
)
228 return base
** self
._print
(e
[0])
230 # TODO: rename to _print_Function
231 # after 'Function -> Function' transition is done
232 def _print_Function(self
, e
):
233 return self
._print
_Apply
(e
) # XXX this is temporary
235 def _print_Apply(self
, e
):
240 # XXX temp. hack -- remove when 'Function -> Function' is done
241 #if isinstance(func, Function):
242 # func_name = func.name
244 func_name
= func
.__name
__
246 prettyFunc
= self
._print
(Basic
.Symbol(func_name
));
247 prettyArgs
= self
._print
(args
[0])
248 for i
in xrange(1, n
):
249 pform
= self
._print
(args
[i
])
250 prettyArgs
= prettyForm(*stringPict
.next(prettyArgs
, ', '))
251 prettyArgs
= prettyForm(*stringPict
.next(prettyArgs
, pform
))
253 prettyArgs
= prettyForm(*prettyArgs
.left('('))
254 prettyArgs
= prettyForm(*prettyArgs
.right(')'))
256 pform
= prettyForm(binding
=prettyForm
.FUNC
, *stringPict
.next(prettyFunc
, prettyArgs
))
258 # store pform parts so it can be reassembled e.g. when powered
259 pform
.prettyFunc
= prettyFunc
260 pform
.prettyArgs
= prettyArgs
264 def _print_Add(self
, sum):
267 # Check for negative "things" so that this information can be enforce upon
268 # the pretty form so that it can be made of use (such as in a sum).
269 if isinstance(x
, Basic
.Mul
) and x
.as_coeff_terms()[0] < 0:
270 pform1
= self
._print
(-x
)
272 if pform1
.height() > 1:
278 pform
= stringPict
.next(pform2
, pform1
)
279 pforms
.append(prettyForm(binding
=prettyForm
.NEG
, *pform
))
280 elif isinstance(x
, Basic
.Number
) and x
< 0:
281 pform1
= self
._print
(-x
)
283 if pform1
.height() > 1:
287 pform
= stringPict
.next(pform2
, pform1
)
289 pform
= stringPict
.next(' - ', pform1
)
290 pforms
.append(prettyForm(binding
=prettyForm
.NEG
, *pform
))
292 pforms
.append(self
._print
(x
))
293 return prettyForm
.__add
__(*pforms
)
295 def _print_Mul(self
, product
):
296 a
= [] # items in the numerator
297 b
= [] # items that are in the denominator (if any)
299 # Gather terms for numerator/denominator
301 if isinstance(item
, Basic
.Pow
) and item
.exp
== -1:
303 elif isinstance(item
, Basic
.Rational
):
305 a
.append( Basic
.Rational(item
.p
) )
307 b
.append( Basic
.Rational(item
.q
) )
311 # Convert to pretty forms. Add parens to Add instances if there
312 # is more than one term in the numer/denom
313 for i
in xrange(0, len(a
)):
314 if isinstance(a
[i
], Basic
.Add
) and len(a
) > 1:
315 a
[i
] = prettyForm(*self
._print
(a
[i
]).parens())
317 a
[i
] = self
._print
(a
[i
])
319 for i
in xrange(0, len(b
)):
320 if isinstance(b
[i
], Basic
.Add
) and len(b
) > 1:
321 b
[i
] = prettyForm(*self
._print
(b
[i
]).parens())
323 b
[i
] = self
._print
(b
[i
])
325 # Construct a pretty form
327 return prettyForm
.__mul
__(*a
)
330 a
.append( self
._print
(Basic
.One()) )
331 return prettyForm
.__mul
__(*a
) / prettyForm
.__mul
__(*b
)
333 def _print_Pow(self
, power
):
334 if isinstance(power
.exp
, Basic
.Half
):
335 # If it's a square root
336 bpretty
= self
._print
(power
.base
)
337 bl
= int((bpretty
.height() / 2.0) + 0.5)
339 s2
= stringPict("\\/")
340 for x
in xrange(1, bpretty
.height()):
341 s3
= stringPict(" " * (2*x
+1) + "/")
342 s2
= stringPict(*s2
.above(s3
))
345 s
= prettyForm("__" + "_" * bpretty
.width())
346 s
= prettyForm(*stringPict
.below(s
, bpretty
))
347 s
= prettyForm(*stringPict
.left(s
, s2
))
350 elif power
.exp
== -1:
352 return prettyForm("1") / self
._print
(power
.base
)
354 # None of the above special forms, do a standard power
355 b
,e
= power
.as_base_exp()
356 return self
._print
(b
)**self
._print
(e
)
358 def _print_Rational(self
, r
):
360 return prettyForm(str(r
.p
), prettyForm
.ATOM
)
361 elif abs(r
.p
) > 10 and abs(r
.q
) > 10:
362 # If more than one digit in numer and denom, print larger fraction
364 pform
= prettyForm(str(-r
.p
))/prettyForm(str(r
.q
))
365 return prettyForm(binding
=prettyForm
.NEG
, *pform
.left('- '))
367 return prettyForm(str(r
.p
))/prettyForm(str(r
.q
))
369 def pretty(expr
, use_unicode
=None):
371 Returns a string containing the prettified form of expr. If use_unicode
372 is set to True then certain expressions will use unicode characters,
373 such as the greek letter pi for Basic.Pi instances.
375 pp
= PrettyPrinter(use_unicode
)
376 return pp
.doprint(expr
)
378 def pretty_print(expr
, use_unicode
=None):
380 Prints expr in pretty form.
382 pprint is just a shortcut for this function
384 print pretty(expr
, use_unicode
)
386 pprint
= pretty_print