Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/misc/displayhook.py
4045 views
1
"""
2
Implements a displayhook for Sage. The main improvement over the default
3
displayhook is a new facility for displaying lists of matrices in an easier to
4
read format.
5
6
AUTHORS:
7
8
- Bill Cauchois (2009): initial version
9
"""
10
11
import IPython, sys, __builtin__
12
from sage.matrix.matrix import is_Matrix
13
from sage.modular.arithgroup.arithgroup_element import ArithmeticSubgroupElement
14
15
# This is used to wrap lines when printing "tall" lists.
16
MAX_COLUMN = 70
17
18
def _check_tall_list_and_print(out_stream, the_list):
19
"""
20
First check whether a list is "tall" -- whether the reprs of the elements of
21
the list will span multiple lines and cause the list to be printed awkwardly.
22
If not, this function returns False and does nothing; you should revert back
23
to the normal method for printing an object (its repr). If so, return True and
24
print the list in the special format. Note that the special format isn't just
25
for matrices. Any object with a multiline repr will be formatted.
26
27
INPUT:
28
29
- ``out_stream`` - The output stream to use.
30
31
- ``the_list`` - The list (or a tuple).
32
33
TESTS::
34
35
sage: import sage.misc.displayhook, sys
36
37
We test _check_tall_list_and_print() indirectly by calling print_obj() on
38
a list of matrices::
39
40
sage: sage.misc.displayhook.print_obj(sys.stdout, \
41
[matrix([[1, 2, 3, 4], [5, 6, 7, 8]]) for i in xrange(7)])
42
[
43
[1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4]
44
[5 6 7 8], [5 6 7 8], [5 6 7 8], [5 6 7 8], [5 6 7 8], [5 6 7 8],
45
<BLANKLINE>
46
[1 2 3 4]
47
[5 6 7 8]
48
]
49
"""
50
# For every object to be printed, split its repr on newlines and store the
51
# result in this list.
52
split_reprs = []
53
tall = False
54
for elem in the_list:
55
split_reprs.append(`elem`.split('\n'))
56
if len(split_reprs[-1]) > 1:
57
# Meanwhile, check to make sure the list is actually "tall".
58
tall = True
59
if not tall:
60
return False
61
# Figure out which type of parenthesis to use, based on the type of the_list.
62
if isinstance(the_list, tuple):
63
parens = '()'
64
elif isinstance(the_list, list):
65
parens = '[]'
66
else:
67
raise TypeError, 'expected list or tuple'
68
69
# running_lines is a list of lines, which are stored as lists of strings
70
# to be joined later. For each split repr, we add its lines to the
71
# running_lines array. When current_column exceeds MAX_COLUMN, process
72
# and output running_lines using _print_tall_list_row.
73
running_lines = [[]]
74
current_column = 0
75
print >>out_stream, parens[0]
76
for split_repr in split_reprs:
77
width = max(len(x) for x in split_repr)
78
if current_column + width > MAX_COLUMN and not (width > MAX_COLUMN):
79
_print_tall_list_row(out_stream, running_lines)
80
running_lines = [[]]
81
current_column = 0
82
current_column += width + 2
83
# Add the lines from split_repr to the running_lines array. It may
84
# be necessary to add or remove lines from either one so that the
85
# number of lines matches up.
86
for i in xrange(len(running_lines), len(split_repr)):
87
running_lines.insert(0, [' ' * len(x) for x in running_lines[-1]])
88
line_diff = len(running_lines) - len(split_repr)
89
for i, x in enumerate(split_repr):
90
running_lines[i + line_diff].append(x.ljust(width))
91
for i in xrange(line_diff):
92
running_lines[i].append(' ' * width)
93
# Output any remaining entries.
94
if len(running_lines[0]) > 0:
95
_print_tall_list_row(out_stream, running_lines, True)
96
print >>out_stream, parens[1]
97
return True
98
99
# This helper function for _print_tall_list processes and outputs the
100
# contents of the running_lines array.
101
def _print_tall_list_row(out_stream, running_lines, last_row=False):
102
for i, line in enumerate(running_lines):
103
if i + 1 != len(running_lines):
104
sep, tail = ' ', ''
105
else:
106
# The commas go on the bottom line of this row.
107
sep, tail = ', ', '' if last_row else ','
108
print >>out_stream, sep.join(line) + tail
109
# Separate rows with a newline to make them stand out.
110
if not last_row:
111
print >>out_stream
112
113
def print_obj(out_stream, obj):
114
"""
115
Print an object. This function is used internally by the displayhook.
116
117
EXAMPLES::
118
119
sage: import sage.misc.displayhook, sys
120
121
For most objects, printing is done simply using their repr::
122
123
sage: sage.misc.displayhook.print_obj(sys.stdout, 'Hello, world!')
124
'Hello, world!'
125
sage: sage.misc.displayhook.print_obj(sys.stdout, (1, 2, 3, 4))
126
(1, 2, 3, 4)
127
128
We demonstrate the special format for lists of matrices::
129
130
sage: sage.misc.displayhook.print_obj(sys.stdout, \
131
[matrix([[1], [2]]), matrix([[3], [4]])])
132
[
133
[1] [3]
134
[2], [4]
135
]
136
"""
137
# We only apply the special formatting to lists (or tuples) where the first
138
# element is a matrix, or an ArithmeticSubgroupElement (a thin wrapper
139
# around a matrix). This should cover most cases.
140
if isinstance(obj, (tuple, list)):
141
if len(obj) > 0 and (is_Matrix(obj[0]) or isinstance(obj[0], ArithmeticSubgroupElement)):
142
if _check_tall_list_and_print(out_stream, obj):
143
return
144
print >>out_stream, `obj`
145
146
def result_display(ip_self, obj):
147
"""
148
This function implements the ``result_display`` hook for IPython.
149
"""
150
# IPython's default result_display() uses the IPython.genutils.Term.cout stream.
151
# See also local/lib/python2.6/site-packages/IPython/hooks.py.
152
print_obj(IPython.genutils.Term.cout, obj)
153
154
def displayhook(obj):
155
"""
156
This function adheres to the displayhook protocol described in `PEP 217`_.
157
In order to mimic the behavior of the default displayhook, we update the
158
variable ``__builtin__._`` every time an object is printed.
159
160
.. _`PEP 217`: http://www.python.org/dev/peps/pep-0217/
161
162
TESTS::
163
164
sage: import sage.misc.displayhook, sys
165
sage: sage.misc.displayhook.displayhook(1)
166
1
167
sage: print _
168
1
169
sage: sage.misc.displayhook.displayhook(None)
170
sage: print _
171
1
172
"""
173
if obj is None:
174
return
175
__builtin__._ = None
176
print_obj(sys.stdout, obj)
177
__builtin__._ = obj
178
179
def install():
180
"""
181
Install the new displayhook, so that subsequent output from the interpreter
182
will be preprocessed by the mechanisms in this module.
183
"""
184
# First, try to install the hook using the IPython hook API.
185
ipapi = IPython.ipapi.get()
186
if ipapi:
187
ipapi.set_hook('result_display', result_display)
188
else:
189
# In certain modes where IPython is not in use, it is necessary to fall
190
# back to setting Python's sys.displayhook.
191
sys.displayhook = displayhook
192
193