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

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

""" 

    pygments.formatters.terminal 

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

 

    Formatter for terminal output with ANSI sequences. 

 

    :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS. 

    :license: BSD, see LICENSE for details. 

""" 

 

import sys 

 

from pygments.formatter import Formatter 

from pygments.token import Keyword, Name, Comment, String, Error, \ 

    Number, Operator, Generic, Token, Whitespace 

from pygments.console import ansiformat 

from pygments.util import get_choice_opt 

 

 

__all__ = ['TerminalFormatter'] 

 

 

#: Map token types to a tuple of color values for light and dark 

#: backgrounds. 

TERMINAL_COLORS = { 

    Token:              ('',            ''), 

 

    Whitespace:         ('lightgray',   'darkgray'), 

    Comment:            ('lightgray',   'darkgray'), 

    Comment.Preproc:    ('teal',        'turquoise'), 

    Keyword:            ('darkblue',    'blue'), 

    Keyword.Type:       ('teal',        'turquoise'), 

    Operator.Word:      ('purple',      'fuchsia'), 

    Name.Builtin:       ('teal',        'turquoise'), 

    Name.Function:      ('darkgreen',   'green'), 

    Name.Namespace:     ('_teal_',      '_turquoise_'), 

    Name.Class:         ('_darkgreen_', '_green_'), 

    Name.Exception:     ('teal',        'turquoise'), 

    Name.Decorator:     ('darkgray',    'lightgray'), 

    Name.Variable:      ('darkred',     'red'), 

    Name.Constant:      ('darkred',     'red'), 

    Name.Attribute:     ('teal',        'turquoise'), 

    Name.Tag:           ('blue',        'blue'), 

    String:             ('brown',       'brown'), 

    Number:             ('darkblue',    'blue'), 

 

    Generic.Deleted:    ('red',        'red'), 

    Generic.Inserted:   ('darkgreen',  'green'), 

    Generic.Heading:    ('**',         '**'), 

    Generic.Subheading: ('*purple*',   '*fuchsia*'), 

    Generic.Error:      ('red',        'red'), 

 

    Error:              ('_red_',      '_red_'), 

} 

 

 

class TerminalFormatter(Formatter): 

    r""" 

    Format tokens with ANSI color sequences, for output in a text console. 

    Color sequences are terminated at newlines, so that paging the output 

    works correctly. 

 

    The `get_style_defs()` method doesn't do anything special since there is 

    no support for common styles. 

 

    Options accepted: 

 

    `bg` 

        Set to ``"light"`` or ``"dark"`` depending on the terminal's background 

        (default: ``"light"``). 

 

    `colorscheme` 

        A dictionary mapping token types to (lightbg, darkbg) color names or 

        ``None`` (default: ``None`` = use builtin colorscheme). 

 

    `linenos` 

        Set to ``True`` to have line numbers on the terminal output as well 

        (default: ``False`` = no line numbers). 

    """ 

    name = 'Terminal' 

    aliases = ['terminal', 'console'] 

    filenames = [] 

 

    def __init__(self, **options): 

        Formatter.__init__(self, **options) 

        self.darkbg = get_choice_opt(options, 'bg', 

                                     ['light', 'dark'], 'light') == 'dark' 

        self.colorscheme = options.get('colorscheme', None) or TERMINAL_COLORS 

        self.linenos = options.get('linenos', False) 

        self._lineno = 0 

 

    def format(self, tokensource, outfile): 

        # hack: if the output is a terminal and has an encoding set, 

        # use that to avoid unicode encode problems 

        if not self.encoding and hasattr(outfile, "encoding") and \ 

           hasattr(outfile, "isatty") and outfile.isatty() and \ 

           sys.version_info < (3,): 

            self.encoding = outfile.encoding 

        return Formatter.format(self, tokensource, outfile) 

 

    def _write_lineno(self, outfile): 

        self._lineno += 1 

        outfile.write("\n%04d: " % self._lineno) 

 

    def _format_unencoded_with_lineno(self, tokensource, outfile): 

        self._write_lineno(outfile) 

 

        for ttype, value in tokensource: 

            if value.endswith("\n"): 

                self._write_lineno(outfile) 

                value = value[:-1] 

            color = self.colorscheme.get(ttype) 

            while color is None: 

                ttype = ttype[:-1] 

                color = self.colorscheme.get(ttype) 

            if color: 

                color = color[self.darkbg] 

                spl = value.split('\n') 

                for line in spl[:-1]: 

                    self._write_lineno(outfile) 

                    if line: 

                        outfile.write(ansiformat(color, line[:-1])) 

                if spl[-1]: 

                    outfile.write(ansiformat(color, spl[-1])) 

            else: 

                outfile.write(value) 

 

        outfile.write("\n") 

 

    def format_unencoded(self, tokensource, outfile): 

        if self.linenos: 

            self._format_unencoded_with_lineno(tokensource, outfile) 

            return 

 

        for ttype, value in tokensource: 

            color = self.colorscheme.get(ttype) 

            while color is None: 

                ttype = ttype[:-1] 

                color = self.colorscheme.get(ttype) 

            if color: 

                color = color[self.darkbg] 

                spl = value.split('\n') 

                for line in spl[:-1]: 

                    if line: 

                        outfile.write(ansiformat(color, line)) 

                    outfile.write('\n') 

                if spl[-1]: 

                    outfile.write(ansiformat(color, spl[-1])) 

            else: 

                outfile.write(value)