codekingpro/portable-devtools
114k
1"""2 pygments.lexers.r3 ~~~~~~~~~~~~~~~~~4 5 Lexers for the R/S languages.6 7 :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS.8 :license: BSD, see LICENSE for details.9"""10 11import re12 13from pygments.lexer import Lexer, RegexLexer, include, do_insertions14from pygments.token import Text, Comment, Operator, Keyword, Name, String, \15 Number, Punctuation, Generic, Whitespace16 17__all__ = ['RConsoleLexer', 'SLexer', 'RdLexer']18 19 20line_re = re.compile('.*?\n')21 22 23class RConsoleLexer(Lexer):24 """25 For R console transcripts or R CMD BATCH output files.26 """27 28 name = 'RConsole'29 aliases = ['rconsole', 'rout']30 filenames = ['*.Rout']31 url = 'https://www.r-project.org'32 version_added = ''33 34 def get_tokens_unprocessed(self, text):35 slexer = SLexer(**self.options)36 37 current_code_block = ''38 insertions = []39 40 for match in line_re.finditer(text):41 line = match.group()42 if line.startswith('>') or line.startswith('+'):43 # Colorize the prompt as such,44 # then put rest of line into current_code_block45 insertions.append((len(current_code_block),46 [(0, Generic.Prompt, line[:2])]))47 current_code_block += line[2:]48 else:49 # We have reached a non-prompt line!50 # If we have stored prompt lines, need to process them first.51 if current_code_block:52 # Weave together the prompts and highlight code.53 yield from do_insertions(54 insertions, slexer.get_tokens_unprocessed(current_code_block))55 # Reset vars for next code block.56 current_code_block = ''57 insertions = []58 # Now process the actual line itself, this is output from R.59 yield match.start(), Generic.Output, line60 61 # If we happen to end on a code block with nothing after it, need to62 # process the last code block. This is neither elegant nor DRY so63 # should be changed.64 if current_code_block:65 yield from do_insertions(66 insertions, slexer.get_tokens_unprocessed(current_code_block))67 68 69class SLexer(RegexLexer):70 """71 For S, S-plus, and R source code.72 """73 74 name = 'S'75 aliases = ['splus', 's', 'r']76 filenames = ['*.S', '*.R', '.Rhistory', '.Rprofile', '.Renviron']77 mimetypes = ['text/S-plus', 'text/S', 'text/x-r-source', 'text/x-r',78 'text/x-R', 'text/x-r-history', 'text/x-r-profile']79 url = 'https://www.r-project.org'80 version_added = '0.10'81 82 valid_name = r'`[^`\\]*(?:\\.[^`\\]*)*`|(?:[a-zA-Z]|\.[A-Za-z_.])[\w.]*|\.'83 tokens = {84 'comments': [85 (r'#.*$', Comment.Single),86 ],87 'valid_name': [88 (valid_name, Name),89 ],90 'punctuation': [91 (r'\[{1,2}|\]{1,2}|\(|\)|;|,', Punctuation),92 ],93 'keywords': [94 (r'(if|else|for|while|repeat|in|next|break|return|switch|function)'95 r'(?![\w.])',96 Keyword.Reserved),97 ],98 'operators': [99 (r'<<?-|->>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|\?', Operator),100 (r'\*|\+|\^|/|!|%[^%]*%|=|~|\$|@|:{1,3}', Operator),101 ],102 'builtin_symbols': [103 (r'(NULL|NA(_(integer|real|complex|character)_)?|'104 r'letters|LETTERS|Inf|TRUE|FALSE|NaN|pi|\.\.(\.|[0-9]+))'105 r'(?![\w.])',106 Keyword.Constant),107 (r'(T|F)\b', Name.Builtin.Pseudo),108 ],109 'numbers': [110 # hex number111 (r'0[xX][a-fA-F0-9]+([pP][0-9]+)?[Li]?', Number.Hex),112 # decimal number113 (r'[+-]?([0-9]+(\.[0-9]+)?|\.[0-9]+|\.)([eE][+-]?[0-9]+)?[Li]?',114 Number),115 ],116 'statements': [117 include('comments'),118 # whitespaces119 (r'\s+', Whitespace),120 (r'\'', String, 'string_squote'),121 (r'\"', String, 'string_dquote'),122 include('builtin_symbols'),123 include('valid_name'),124 include('numbers'),125 include('keywords'),126 include('punctuation'),127 include('operators'),128 ],129 'root': [130 # calls:131 (rf'({valid_name})\s*(?=\()', Name.Function),132 include('statements'),133 # blocks:134 (r'\{|\}', Punctuation),135 # (r'\{', Punctuation, 'block'),136 (r'.', Text),137 ],138 # 'block': [139 # include('statements'),140 # ('\{', Punctuation, '#push'),141 # ('\}', Punctuation, '#pop')142 # ],143 'string_squote': [144 (r'([^\'\\]|\\.)*\'', String, '#pop'),145 ],146 'string_dquote': [147 (r'([^"\\]|\\.)*"', String, '#pop'),148 ],149 }150 151 def analyse_text(text):152 if re.search(r'[a-z0-9_\])\s]<-(?!-)', text):153 return 0.11154 155 156class RdLexer(RegexLexer):157 """158 Pygments Lexer for R documentation (Rd) files159 160 This is a very minimal implementation, highlighting little more161 than the macros. A description of Rd syntax is found in `Writing R162 Extensions <http://cran.r-project.org/doc/manuals/R-exts.html>`_163 and `Parsing Rd files <http://developer.r-project.org/parseRd.pdf>`_.164 """165 name = 'Rd'166 aliases = ['rd']167 filenames = ['*.Rd']168 mimetypes = ['text/x-r-doc']169 url = 'http://cran.r-project.org/doc/manuals/R-exts.html'170 version_added = '1.6'171 172 # To account for verbatim / LaTeX-like / and R-like areas173 # would require parsing.174 tokens = {175 'root': [176 # catch escaped brackets and percent sign177 (r'\\[\\{}%]', String.Escape),178 # comments179 (r'%.*$', Comment),180 # special macros with no arguments181 (r'\\(?:cr|l?dots|R|tab)\b', Keyword.Constant),182 # macros183 (r'\\[a-zA-Z]+\b', Keyword),184 # special preprocessor macros185 (r'^\s*#(?:ifn?def|endif).*\b', Comment.Preproc),186 # non-escaped brackets187 (r'[{}]', Name.Builtin),188 # everything else189 (r'[^\\%\n{}]+', Text),190 (r'.', Text),191 ]192 }193 