Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

# -*- coding: utf-8 -*- 

""" 

Utility functions for pretty-printing  

 

These utility functions are used in the implementations of ``_repr_`` 

methods elsewhere. 

""" 

 

#***************************************************************************** 

# Copyright (C) 2014 Volker Braun <vbraun.name@gmail.com> 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# as published by the Free Software Foundation; either version 2 of 

# the License, or (at your option) any later version. 

# http://www.gnu.org/licenses/ 

#***************************************************************************** 

from __future__ import print_function 

from six.moves import range 

 

 

class TallListFormatter(object): 

""" 

Special representation for lists with tall entries (e.g. matrices) 

 

.. automethod:: __call__ 

""" 

 

# This is used to wrap lines when printing "tall" lists. 

MAX_COLUMN = 70 

 

def _tall_list_row(self, running_lines, last_row=False): 

""" 

Helper for :meth:`_check_tall_list_and_format` 

 

This helper function processes and outputs the contents of the 

running_lines array. 

 

TESTS:: 

 

sage: from sage.repl.display.util import format_list 

sage: format_list._tall_list_row(['a b', 'b c', 'c']) 

['a b', 'b c', 'c,', ''] 

""" 

s=[] 

for i, line in enumerate(running_lines): 

if i + 1 != len(running_lines): 

sep, tail = ' ', '' 

else: 

# The commas go on the bottom line of this row. 

sep, tail = ', ', '' if last_row else ',' 

s.append(sep.join(line) + tail) 

# Separate rows with a newline to make them stand out. 

if not last_row: 

s.append("") 

return s 

 

def try_format(self, the_list): 

""" 

First check whether a list is "tall" -- whether the reprs of the 

elements of the list will span multiple lines and cause the list 

to be printed awkwardly. If not, this function returns ``None`` and 

does nothing; you should revert back to the normal method for 

printing an object (its repr). If so, return the string in the 

special format. Note that the special format isn't just for 

matrices. Any object with a multiline repr will be formatted. 

 

INPUT: 

 

- ``the_list`` - The list (or a tuple). 

 

OUTPUT: 

 

String or ``None``. The latter is returned if the list is not 

deemed to be tall enough and another formatter should be used. 

 

TESTS:: 

 

sage: from sage.repl.display.util import format_list 

sage: print(format_list.try_format( 

....: [matrix([[1, 2, 3, 4], [5, 6, 7, 8]]) for i in range(7)])) 

[ 

[1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4] [1 2 3 4] 

[5 6 7 8], [5 6 7 8], [5 6 7 8], [5 6 7 8], [5 6 7 8], [5 6 7 8], 

<BLANKLINE> 

[1 2 3 4] 

[5 6 7 8] 

] 

 

sage: format_list.try_format(['not', 'tall']) is None 

True 

""" 

# For every object to be printed, split its repr on newlines and store the 

# result in this list. 

split_reprs = [] 

tall = False 

for elem in the_list: 

split_reprs.append(repr(elem).split('\n')) 

if len(split_reprs[-1]) > 1: 

# Meanwhile, check to make sure the list is actually "tall". 

tall = True 

if not tall: 

return None 

# Figure out which type of parenthesis to use, based on the type of the_list. 

if isinstance(the_list, tuple): 

parens = '()' 

elif isinstance(the_list, list): 

parens = '[]' 

else: 

raise TypeError('expected list or tuple') 

 

# running_lines is a list of lines, which are stored as lists of strings 

# to be joined later. For each split repr, we add its lines to the 

# running_lines array. When current_column exceeds MAX_COLUMN, process 

# and output running_lines using _print_tall_list_row. 

running_lines = [[]] 

current_column = 0 

s = [parens[0]] 

for split_repr in split_reprs: 

width = max(len(x) for x in split_repr) 

if current_column + width > self.MAX_COLUMN and not (width > self.MAX_COLUMN): 

s.extend(self._tall_list_row(running_lines)) 

running_lines = [[]] 

current_column = 0 

current_column += width + 2 

# Add the lines from split_repr to the running_lines array. It may 

# be necessary to add or remove lines from either one so that the 

# number of lines matches up. 

for i in range(len(running_lines), len(split_repr)): 

running_lines.insert(0, [' ' * len(x) for x in running_lines[-1]]) 

line_diff = len(running_lines) - len(split_repr) 

for i, x in enumerate(split_repr): 

running_lines[i + line_diff].append(x.ljust(width)) 

for i in range(line_diff): 

running_lines[i].append(' ' * width) 

# Output any remaining entries. 

if len(running_lines[0]) > 0: 

s.extend(self._tall_list_row(running_lines, True)) 

s.append(parens[1]) 

return "\n".join(s) 

 

def __call__(self, the_list): 

""" 

Return "tall list" string representation. 

 

See also :meth:`try_format`. 

 

INPUT: 

 

- ``the_list`` -- list or tuple. 

 

OUTPUT: 

 

String. 

 

EXAMPLES:: 

 

sage: from sage.repl.display.util import format_list 

sage: format_list(['not', 'tall']) 

"['not', 'tall']" 

""" 

output = self.try_format(the_list) 

if output is None: 

output = repr(the_list) 

return output 

 

 

format_list = TallListFormatter()