diff --git a/lib/rouge/demos/mojo b/lib/rouge/demos/mojo new file mode 100644 index 0000000000..dacbefa104 --- /dev/null +++ b/lib/rouge/demos/mojo @@ -0,0 +1,10 @@ +fn fib(n: Int): # write Fibonacci series up to n + """Print a Fibonacci series up to n.""" + var a = 0 + var b = 1 + while a < n: + print(a) + a, b = b, a+b + +fn main(): + fib(10) diff --git a/lib/rouge/lexers/mojo.rb b/lib/rouge/lexers/mojo.rb new file mode 100644 index 0000000000..d28af4efbb --- /dev/null +++ b/lib/rouge/lexers/mojo.rb @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + class Mojo < Python + title "Mojo" + desc "The Mojo programming language (modular.com)" + tag 'mojo' + aliases 'mojo' + filenames '*.mojo', '*.🔥' + mimetypes 'text/x-mojo', 'application/x-mojo' + + def self.detect?(text) + return true if text.shebang?(/mojow?(?:[23](?:\.\d+)?)?/) + end + + def self.keywords + @keywords ||= super + %w( + fn self alias inout borrowed owned ref var + struct trait raises with in match case + ) + end + + def self.builtins + @builtins ||= super + %w( + __mlir_attr __mlir_type __mlir_op parameter alwaysinline + register_passable + ) + end + end + end +end diff --git a/spec/lexers/mojo_spec.rb b/spec/lexers/mojo_spec.rb new file mode 100644 index 0000000000..0f13b5dd9a --- /dev/null +++ b/spec/lexers/mojo_spec.rb @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::Mojo do + let(:subject) { Rouge::Lexers::Mojo.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.mojo' + assert_guess :filename => 'foo.🔥' + end + + it 'guesses by mimetype' do + assert_guess :mimetype => 'text/x-mojo' + assert_guess :mimetype => 'application/x-mojo' + end + + it 'guesses by source' do + assert_guess :source => '#!/usr/bin/env mojo' + assert_guess :source => '#!/usr/bin/mojo' + end + end +end diff --git a/spec/visual/samples/mojo b/spec/visual/samples/mojo new file mode 100644 index 0000000000..1642018ada --- /dev/null +++ b/spec/visual/samples/mojo @@ -0,0 +1,229 @@ +fn lex(code: String, lexer: Lexer) raises: + """ + Lex ``code`` with ``lexer`` and return an iterable of tokens. + """ + try: + return lexer.get_tokens(code) + except e: + raise + +alias lst = List[Int] + +# quotes in strings +def foo(): + "it's working" + +def foo(): + 'he said "hi"' + +def foo(): + """it's working""" + """he said "hi" """ + +def foo(): + '''he said "hi"''' + '''it's working''' + +# unicode docstrings +def foo(): + ur"""unicode-raw""" + +def bar(): + u"""unicode""" + +def baz(): + r'raw' + +def zap(): + """docstring""" + +# escaped characters in string literals +fn baz(): + '\a\b\f\n\r\t\v\"\'' + '\N{DEGREE SIGN}' + '\uaF09' + '\UaaaaAF09' + '\xaf\xAF\x09' + '\007' + '.*\[p00t_(d\d{4})\].*' # There are no escape sequences in this string + +# escaped characters in raw strings +def baz(): + r'\a\b\f\n\r\t\v\"\'' + r'\N{DEGREE SIGN}' + r'\uaF09' + r'\UaaaaAF09' + r'\xaf\xAF\x09' + r'\007' + r'.*\[p00t_(d\d{4})\].*' + +# line continuations +apple.filter(x, y) +apple.\ + filter(x, y) + +1 \ + . \ + __str__ + +from os import path +from \ + os \ + import \ + path + +import os.path as something + +import \ + os.path \ + as \ + something + +class \ + Spam: + pass + +class Spam: pass + +trait Spam: pass + +@register_passable +struct Spam: + var x: Int + fn __init__(inout self): + self.x = 0 + @parameter + for i in (range(10)): + pass + +class Spam(object): + pass + +class \ + Spam \ + ( + object + ) \ + : + pass + + +def \ + spam \ + ( \ + ) \ + : \ + pass + +def the_word_strand(): + a = b.strip() + a = strand + b = band + c = strand + b = error + c = stror + c = string + +py2_long = -123L + +# Python 3 + +def test(): + raise Exception from foo + +def exceptions(): + try: + print("Hello") + except Exception as e: + print("Exception") + +# PEP 515 +integer_literals = [ + 123, -1_2_0, 0, 00, 0_0_00, 0b1, 0B1_0, 0b_1, 0b00_0, + 0o1, 0O1_2, 0O_1, 0o00_0, 0x1, 0X1_2, 0x_1, 0x00_0 +] +float_literals = [ + 0., 1., 00., 0_00., 1_0_0., 0_1., .0, + .1_2, 3.4_5, 1_2.3_4, 00_0.0_0_0, 0_0.1_2, + 0_1_2j, 0_00J, 1.2J, 0.1j, 1_0.J, + 0_00E+2_34_5, 0.e+1, 00_1.E-0_2, -100.e+20, 1e01, + 0_00E+2_34_5j, 0.e+1J, 00_1.E-0_2j, -100.e+20J 1e01j +] +floats = (19.0, 19.) + +# PEP 465 +a = b @ c +x @= y + +# PEP 498 +f'{hello} world {int(x) + 1}' +f'{{ {4*10} }}' +f'result: {value:{width}.{precision}}' +f'{value!r}' + +# Unicode identifiers +α = 10 +def coöperative(б): + return f"{б} is Russian" + +def __init__(self, input_dim: list, output_dim: int, **kwargs): + super(AverageEmbedding, self).__init__(**kwargs) + self.input_dim = input_dim + self.output_dim = output_dim + +@abstractmethod +def evaluate(self, *args, **kwargs): + raise NotImplementedError + +def _get_metadata(self, input_samples: list[InputSample]) -> Tuple[str, str, int]: + project_name, id = self._get_info() + +class Spam: + pass + +spam = Spam() + +# Doctest +def factorial(n): + """Return the factorial of n, an exact integer >= 0. + + >>> [factorial(n) for n in range(6)] + [1, 1, 2, 6, 24, 120] + + >>> for i in [factorial(n) for n in range(2)]: + ... print(i) + 1 + 1 + >>> factorial(30) + 265252859812191058636308480000000 + >>> factorial(-1) + Traceback (most recent call last): + ... + ValueError: n must be >= 0 + + Factorials of floats are OK, but the float must be an exact integer: + >>> factorial(30.1) + Traceback (most recent call last): + ... + ValueError: n must be exact integer + >>> factorial(30.0) + 265252859812191058636308480000000 + + It must also not be ridiculously large: + >>> factorial(1e100) + Traceback (most recent call last): + ... + OverflowError: n too large + """ + print("hello world") + +def do_nothing(): + if False: + return + print("a...a") + + with tracer.start_as_current_span('App Init'): + logger.info('OTEL Initialized...') + + app = FastAPI() + FastAPIInstrumentor.instrument_app(app)