textmate-grammar-python 0.3.0__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/PKG-INFO +6 -21
  2. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/README.md +2 -19
  3. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/pyproject.toml +10 -3
  4. textmate_grammar_python-0.5.1/src/textmate_grammar/__init__.py +1 -0
  5. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/src/textmate_grammar/elements.py +4 -1
  6. {textmate_grammar_python-0.3.0/src/textmate_grammar/utils → textmate_grammar_python-0.5.1/src/textmate_grammar}/handler.py +23 -12
  7. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/src/textmate_grammar/parser.py +14 -14
  8. textmate_grammar_python-0.3.0/src/textmate_grammar/language.py → textmate_grammar_python-0.5.1/src/textmate_grammar/parsers/base.py +29 -12
  9. textmate_grammar_python-0.5.1/src/textmate_grammar/parsers/markdown/__init__.py +27 -0
  10. textmate_grammar_python-0.5.1/src/textmate_grammar/parsers/matlab/__init__.py +70 -0
  11. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/src/textmate_grammar/utils/cache.py +10 -7
  12. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/src/textmate_grammar/utils/exceptions.py +3 -0
  13. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/src/textmate_grammar/utils/logger.py +5 -3
  14. textmate_grammar_python-0.3.0/src/textmate_grammar/__init__.py +0 -1
  15. textmate_grammar_python-0.3.0/src/textmate_grammar/grammars/__pycache__/__init__.cpython-312.pyc +0 -0
  16. textmate_grammar_python-0.3.0/src/textmate_grammar/grammars/markdown/__init__.py +0 -19
  17. textmate_grammar_python-0.3.0/src/textmate_grammar/grammars/markdown/__pycache__/__init__.cpython-312.pyc +0 -0
  18. textmate_grammar_python-0.3.0/src/textmate_grammar/grammars/matlab/__init__.py +0 -27
  19. textmate_grammar_python-0.3.0/src/textmate_grammar/grammars/matlab/__pycache__/__init__.cpython-312.pyc +0 -0
  20. textmate_grammar_python-0.3.0/src/textmate_grammar/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  21. textmate_grammar_python-0.3.0/src/textmate_grammar/utils/__pycache__/cache.cpython-312.pyc +0 -0
  22. textmate_grammar_python-0.3.0/src/textmate_grammar/utils/__pycache__/exceptions.cpython-312.pyc +0 -0
  23. textmate_grammar_python-0.3.0/src/textmate_grammar/utils/__pycache__/handler.cpython-312.pyc +0 -0
  24. textmate_grammar_python-0.3.0/src/textmate_grammar/utils/__pycache__/logger.cpython-312.pyc +0 -0
  25. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/LICENSE +0 -0
  26. {textmate_grammar_python-0.3.0/src/textmate_grammar/grammars → textmate_grammar_python-0.5.1/src/textmate_grammar/parsers}/__init__.py +0 -0
  27. {textmate_grammar_python-0.3.0/src/textmate_grammar/grammars → textmate_grammar_python-0.5.1/src/textmate_grammar/parsers}/markdown/LICENSE.txt +0 -0
  28. {textmate_grammar_python-0.3.0/src/textmate_grammar/grammars → textmate_grammar_python-0.5.1/src/textmate_grammar/parsers}/markdown/grammar.yaml +0 -0
  29. {textmate_grammar_python-0.3.0/src/textmate_grammar/grammars → textmate_grammar_python-0.5.1/src/textmate_grammar/parsers}/matlab/grammar.yaml +0 -0
  30. {textmate_grammar_python-0.3.0/src/textmate_grammar/grammars → textmate_grammar_python-0.5.1/src/textmate_grammar/parsers}/matlab/license.txt +0 -0
  31. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/src/textmate_grammar/py.typed +0 -0
  32. {textmate_grammar_python-0.3.0 → textmate_grammar_python-0.5.1}/src/textmate_grammar/utils/__init__.py +0 -0
@@ -1,15 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: textmate-grammar-python
3
- Version: 0.3.0
3
+ Version: 0.5.1
4
4
  Summary: A lexer and tokenizer for grammar files as defined by TextMate and used in VSCode, implemented in Python.
5
5
  Home-page: https://github.com/watermarkhu/textmate-grammar-python
6
6
  License: MIT
7
7
  Keywords: textmate,tokenization
8
8
  Author: Mark Shui Hu
9
9
  Author-email: watermarkhu@gmail.com
10
- Requires-Python: >=3.11,<4.0
10
+ Requires-Python: >=3.9,<4.0
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
13
15
  Classifier: Programming Language :: Python :: 3.11
14
16
  Classifier: Programming Language :: Python :: 3.12
15
17
  Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
@@ -33,22 +35,6 @@ A lexer and tokenizer for grammar files as defined by TextMate and used in VSCod
33
35
 
34
36
  Textmate grammars are made for [vscode-texmate](https://github.com/microsoft/vscode-textmate), allowing for syntax highlighting in VSCode after tokenization. This presents textmate-grammar-python with a large list of potentially supported languages.
35
37
 
36
- ```mermaid
37
- flowchart TD
38
- A[grammar file]
39
- Z[code]
40
- B("`vscode-textmate **js**`")
41
- C("`textmate-grammar-**python**`")
42
- D[tokens]
43
-
44
- click C "https://github.com/microsoft/vscode-textmate"
45
-
46
- Z --> B
47
- Z --> C
48
- A -.-> B --> D
49
- A -.-> C --> D
50
- ```
51
-
52
38
  ## Usage
53
39
  Install the module with:
54
40
  ```bash
@@ -58,9 +44,8 @@ pip install textmate-grammar-python
58
44
  Before tokenization is possible, a `LanguageParser` needs to be initialized using a loaded grammar.
59
45
 
60
46
  ```python
61
- from textmate_grammar.language import LanguageParser
62
- from textmate_grammar.grammars import matlab
63
- parser = LanguageParser(matlab.GRAMMAR)
47
+ from textmate_grammar.parsers.matlab import MatlabParser
48
+ parser = MatlabParser()
64
49
  ```
65
50
 
66
51
  After this, one can either choose to call [`parser.parsing_string`](https://textmate-grammar-python.readthedocs.io/en/latest/apidocs/textmate_grammar/textmate_grammar.language.html#textmate_grammar.language.LanguageParser.parse_string) to parse a input string directly, or call [`parser.parse_file`](https://textmate-grammar-python.readthedocs.io/en/latest/apidocs/textmate_grammar/textmate_grammar.language.html#textmate_grammar.language.LanguageParser.parse_file) with the path to the appropiate source file as the first argument, such as in the example [`example.py`](https://github.com/watermarkhu/textmate-grammar-python/blob/main/example.py).
@@ -13,22 +13,6 @@ A lexer and tokenizer for grammar files as defined by TextMate and used in VSCod
13
13
 
14
14
  Textmate grammars are made for [vscode-texmate](https://github.com/microsoft/vscode-textmate), allowing for syntax highlighting in VSCode after tokenization. This presents textmate-grammar-python with a large list of potentially supported languages.
15
15
 
16
- ```mermaid
17
- flowchart TD
18
- A[grammar file]
19
- Z[code]
20
- B("`vscode-textmate **js**`")
21
- C("`textmate-grammar-**python**`")
22
- D[tokens]
23
-
24
- click C "https://github.com/microsoft/vscode-textmate"
25
-
26
- Z --> B
27
- Z --> C
28
- A -.-> B --> D
29
- A -.-> C --> D
30
- ```
31
-
32
16
  ## Usage
33
17
  Install the module with:
34
18
  ```bash
@@ -38,9 +22,8 @@ pip install textmate-grammar-python
38
22
  Before tokenization is possible, a `LanguageParser` needs to be initialized using a loaded grammar.
39
23
 
40
24
  ```python
41
- from textmate_grammar.language import LanguageParser
42
- from textmate_grammar.grammars import matlab
43
- parser = LanguageParser(matlab.GRAMMAR)
25
+ from textmate_grammar.parsers.matlab import MatlabParser
26
+ parser = MatlabParser()
44
27
  ```
45
28
 
46
29
  After this, one can either choose to call [`parser.parsing_string`](https://textmate-grammar-python.readthedocs.io/en/latest/apidocs/textmate_grammar/textmate_grammar.language.html#textmate_grammar.language.LanguageParser.parse_string) to parse a input string directly, or call [`parser.parse_file`](https://textmate-grammar-python.readthedocs.io/en/latest/apidocs/textmate_grammar/textmate_grammar.language.html#textmate_grammar.language.LanguageParser.parse_file) with the path to the appropiate source file as the first argument, such as in the example [`example.py`](https://github.com/watermarkhu/textmate-grammar-python/blob/main/example.py).
@@ -1,10 +1,14 @@
1
+ [project]
2
+ name = "textmate-grammar-python"
3
+
4
+
1
5
  [build-system]
2
6
  requires = ["poetry-core"]
3
7
  build-backend = "poetry.core.masonry.api"
4
8
 
5
9
  [tool.poetry]
6
10
  name = "textmate-grammar-python"
7
- version = "0.3.0"
11
+ version = "0.5.1"
8
12
  description = "A lexer and tokenizer for grammar files as defined by TextMate and used in VSCode, implemented in Python."
9
13
  authors = ["Mark Shui Hu <watermarkhu@gmail.com>"]
10
14
  license = "MIT"
@@ -14,8 +18,11 @@ documentation = "https://textmate-grammar-python.readthedocs.io"
14
18
  keywords = ["textmate", "tokenization"]
15
19
  packages = [{include = "textmate_grammar", from = "src"}]
16
20
 
21
+ [tool.rye]
22
+ managed = true
23
+
17
24
  [tool.poetry.dependencies]
18
- python = "^3.11"
25
+ python = "^3.9"
19
26
  onigurumacffi = "^1.3.0"
20
27
  PyYAML = "^6.0.1"
21
28
 
@@ -80,7 +87,7 @@ legacy_tox_ini = """
80
87
  [testenv:mypy]
81
88
  skip_install = true
82
89
  allowlist_externals = mypy
83
- commands =
90
+ commands =
84
91
  mypy .
85
92
 
86
93
  [testenv:regression]
@@ -0,0 +1 @@
1
+ __version__ = "0.5.1"
@@ -6,7 +6,7 @@ from itertools import groupby
6
6
  from pprint import pprint
7
7
  from typing import TYPE_CHECKING, Generator
8
8
 
9
- from .utils.handler import POS, ContentHandler, Match, Pattern
9
+ from .handler import POS, ContentHandler, Match, Pattern
10
10
  from .utils.logger import LOGGER
11
11
 
12
12
  if TYPE_CHECKING:
@@ -130,6 +130,8 @@ def _dispatch_list(
130
130
  elements.extend(captured_elements)
131
131
  elif item != parent:
132
132
  elements.append(item)
133
+ for element in elements:
134
+ element.parent = parent
133
135
  return elements
134
136
 
135
137
 
@@ -168,6 +170,7 @@ class ContentElement:
168
170
  self.characters = characters
169
171
  self._children_captures = children
170
172
  self._dispatched: bool = False
173
+ self.parent: ContentElement | None = None
171
174
 
172
175
  @property
173
176
  def _subelements(self) -> list[ContentElement]:
@@ -1,15 +1,22 @@
1
+ from __future__ import annotations
2
+
1
3
  from pathlib import Path
4
+ from typing import Callable
2
5
 
3
6
  from onigurumacffi import _Match as Match
4
7
  from onigurumacffi import _Pattern as Pattern
5
8
  from onigurumacffi import compile
6
9
 
7
- from .exceptions import FileNotFound, ImpossibleSpan
8
- from .logger import LOGGER
10
+ from .utils.exceptions import FileNotFound, ImpossibleSpan
11
+ from .utils.logger import LOGGER
9
12
 
10
13
  POS = tuple[int, int]
11
14
 
12
15
 
16
+ def _dummy_pre_processor(input: str) -> str:
17
+ return input
18
+
19
+
13
20
  class ContentHandler:
14
21
  """The handler object targetted for parsing.
15
22
 
@@ -21,25 +28,31 @@ class ContentHandler:
21
28
 
22
29
  notLookForwardEOL = compile(r"(?<!\(\?=[^\(]*)\$")
23
30
 
24
- def __init__(self, source: str) -> None:
31
+ def __init__(
32
+ self, content: str, pre_processor: Callable[[str], str] = _dummy_pre_processor
33
+ ) -> None:
25
34
  """
26
35
  Initialize a new instance of the Handler class.
27
36
 
28
- :param source: The source code to be processed.
29
- :type source: str
37
+ :param content: The source code to be processed.
38
+ :type content: str
39
+ :param pre_processor: A pre-processor to use on the input string of the parser
40
+ :type pre_processor: BasePreProcessor
30
41
 
31
- :ivar source: The source code to be processed.
42
+ :ivar content: The source code to be processed.
32
43
  :ivar lines: A list of lines in the source code, with a newline character at the end of each line.
33
44
  :ivar line_lengths: A list of lengths of each line in the source code.
34
45
  :ivar anchor: The current position in the source code.
35
46
  """
36
- self.source = source
37
- self.lines = [line + "\n" for line in source.split("\n")]
47
+ prepared_content = pre_processor(content.replace("\r\n", "\n").replace("\r", "\n"))
48
+
49
+ self.content = prepared_content
50
+ self.lines = [line + "\n" for line in prepared_content.split("\n")]
38
51
  self.line_lengths = [len(line) for line in self.lines]
39
52
  self.anchor: int = 0
40
53
 
41
54
  @classmethod
42
- def from_path(cls, file_path: Path):
55
+ def from_path(cls, file_path: Path, **kwargs) -> ContentHandler:
43
56
  """Loads a file from a path"""
44
57
 
45
58
  if not file_path.exists():
@@ -48,10 +61,8 @@ class ContentHandler:
48
61
  # Open file and replace Windows/Mac line endings
49
62
  with open(file_path) as file:
50
63
  content = file.read()
51
- content = content.replace("\r\n", "\n")
52
- content = content.replace("\r", "\n")
53
64
 
54
- return cls(content)
65
+ return cls(content, **kwargs)
55
66
 
56
67
  def _check_pos(self, pos: POS):
57
68
  if pos[0] > len(self.lines) or pos[1] > self.line_lengths[pos[0]]:
@@ -6,12 +6,12 @@ from typing import TYPE_CHECKING
6
6
  import onigurumacffi as re
7
7
 
8
8
  from .elements import Capture, ContentBlockElement, ContentElement
9
+ from .handler import POS, ContentHandler, Pattern
9
10
  from .utils.exceptions import IncludedParserNotFound
10
- from .utils.handler import POS, ContentHandler, Pattern
11
11
  from .utils.logger import LOGGER, track_depth
12
12
 
13
13
  if TYPE_CHECKING:
14
- from .language import LanguageParser
14
+ from .parsers.base import LanguageParser
15
15
 
16
16
 
17
17
  class GrammarParser(ABC):
@@ -42,7 +42,7 @@ class GrammarParser(ABC):
42
42
  def __init__(
43
43
  self,
44
44
  grammar: dict,
45
- language: LanguageParser | None = None,
45
+ language_parser: LanguageParser | None = None,
46
46
  key: str = "",
47
47
  is_capture: bool = False,
48
48
  **kwargs,
@@ -59,7 +59,7 @@ class GrammarParser(ABC):
59
59
  :return: None
60
60
  """
61
61
  self.grammar = grammar
62
- self.language = language
62
+ self.language_parser = language_parser
63
63
  self.key = key
64
64
  self.token = grammar.get("name", "")
65
65
  self.is_capture = is_capture
@@ -83,21 +83,21 @@ class GrammarParser(ABC):
83
83
  if key in grammar:
84
84
  for group_id, pattern in grammar[key].items():
85
85
  captures[int(group_id)] = self.initialize(
86
- pattern, language=self.language, is_capture=True
86
+ pattern, language_parser=self.language_parser, is_capture=True
87
87
  )
88
88
  return captures
89
89
 
90
90
  def _find_include(self, key: str, **kwargs) -> GrammarParser:
91
91
  """Find the included grammars and during repository initialization"""
92
- if not self.language:
92
+ if not self.language_parser:
93
93
  raise IncludedParserNotFound(key)
94
94
 
95
95
  if key in ["$self", "$base"]: # TODO there is a difference between these
96
- return self.language
96
+ return self.language_parser
97
97
  elif key[0] == "#":
98
- return self.language.repository.get(key[1:], None)
98
+ return self.language_parser.repository.get(key[1:], None)
99
99
  else:
100
- return self.language._find_include_scopes(key)
100
+ return self.language_parser._find_include_scopes(key)
101
101
 
102
102
  @abstractmethod
103
103
  def _parse(
@@ -146,8 +146,8 @@ class GrammarParser(ABC):
146
146
  - elements: A list of Capture or ContentElement objects representing the parsed content.
147
147
  - span: A tuple containing the starting and ending positions of the parsed content, or None if parsing failed.
148
148
  """
149
- if not self.initialized and self.language is not None:
150
- self.language._initialize_repository()
149
+ if not self.initialized and self.language_parser is not None:
150
+ self.language_parser._initialize_repository()
151
151
  parsed, elements, span = self._parse(handler, starting, boundary=boundary, **kwargs)
152
152
  return parsed, elements, span
153
153
 
@@ -325,7 +325,7 @@ class ParserHasPatterns(GrammarParser, ABC):
325
325
  def __init__(self, grammar: dict, **kwargs) -> None:
326
326
  super().__init__(grammar, **kwargs)
327
327
  self.patterns = [
328
- self.initialize(pattern, language=self.language)
328
+ self.initialize(pattern, language_parser=self.language_parser)
329
329
  for pattern in grammar.get("patterns", [])
330
330
  ]
331
331
 
@@ -347,7 +347,7 @@ class ParserHasPatterns(GrammarParser, ABC):
347
347
  self.patterns[parser_index : parser_index + 1] = parser.patterns
348
348
 
349
349
  # Injection grammars
350
- for exception_scopes, injection_pattern in self.language.injections:
350
+ for exception_scopes, injection_pattern in self.language_parser.injections:
351
351
  if self.token:
352
352
  if self.token.split(".")[0] not in exception_scopes:
353
353
  self.patterns.append(injection_pattern)
@@ -442,7 +442,7 @@ class PatternsParser(ParserHasPatterns):
442
442
  current,
443
443
  kwargs.get("depth", 0),
444
444
  )
445
- elif self != self.language:
445
+ elif self != self.language_parser:
446
446
  break
447
447
  else:
448
448
  remainder = handler.read_line(current)
@@ -1,11 +1,13 @@
1
+ from __future__ import annotations
2
+
1
3
  from pathlib import Path
2
4
 
3
- from .elements import Capture, ContentElement
4
- from .parser import GrammarParser, PatternsParser
5
- from .utils.cache import TextmateCache, init_cache
6
- from .utils.exceptions import IncompatibleFileType
7
- from .utils.handler import POS, ContentHandler
8
- from .utils.logger import LOGGER
5
+ from ..elements import Capture, ContentElement
6
+ from ..handler import POS, ContentHandler
7
+ from ..parser import GrammarParser, PatternsParser
8
+ from ..utils.cache import TextmateCache, init_cache
9
+ from ..utils.exceptions import IncompatibleFileType
10
+ from ..utils.logger import LOGGER
9
11
 
10
12
  LANGUAGE_PARSERS = {}
11
13
 
@@ -32,6 +34,9 @@ class LanguageParser(PatternsParser):
32
34
  Initialize a Language object.
33
35
 
34
36
  :param grammar: The grammar definition for the language.
37
+ :type grammar: dict
38
+ :param pre_processor: A pre-processor to use on the input string of the parser
39
+ :type pre_processor: BasePreProcessor
35
40
  :param kwargs: Additional keyword arguments.
36
41
 
37
42
  :ivar name: The name of the language.
@@ -42,7 +47,10 @@ class LanguageParser(PatternsParser):
42
47
  :ivar injections: The list of injection rules for the language.
43
48
  :ivar _cache: The cache object for the language.
44
49
  """
45
- super().__init__(grammar, key=grammar.get("name", "myLanguage"), language=self, **kwargs)
50
+
51
+ super().__init__(
52
+ grammar, key=grammar.get("name", "myLanguage"), language_parser=self, **kwargs
53
+ )
46
54
 
47
55
  self.name = grammar.get("name", "")
48
56
  self.uuid = grammar.get("uuid", "")
@@ -56,7 +64,7 @@ class LanguageParser(PatternsParser):
56
64
  for repo in _gen_repositories(grammar):
57
65
  for key, parser_grammar in repo.items():
58
66
  self.repository[key] = GrammarParser.initialize(
59
- parser_grammar, key=key, language=self
67
+ parser_grammar, key=key, language_parser=self
60
68
  )
61
69
 
62
70
  # Update language parser store
@@ -65,6 +73,14 @@ class LanguageParser(PatternsParser):
65
73
 
66
74
  self._initialize_repository()
67
75
 
76
+ def pre_process(self, input: str) -> str:
77
+ """
78
+ Pre-processes the input string before parsing.
79
+
80
+ This method can be overloaded in language specific parsers with custom pre-processing logic.
81
+ """
82
+ return input
83
+
68
84
  def __repr__(self) -> str:
69
85
  return f"{self.__class__.__name__}:{self.key}"
70
86
 
@@ -86,7 +102,7 @@ class LanguageParser(PatternsParser):
86
102
  injected_parser = GrammarParser.initialize(
87
103
  injected_grammar,
88
104
  key=f"{target_string}.injection",
89
- language=target_language,
105
+ language_parser=target_language,
90
106
  )
91
107
  injected_parser._initialize_repository()
92
108
 
@@ -113,8 +129,8 @@ class LanguageParser(PatternsParser):
113
129
  if self._cache.cache_valid(filePath):
114
130
  element = self._cache.load(filePath)
115
131
  else:
116
- handler = ContentHandler.from_path(filePath)
117
- if handler.source == "":
132
+ handler = ContentHandler.from_path(filePath, pre_processor=self.pre_process, **kwargs)
133
+ if handler.content == "":
118
134
  return None
119
135
 
120
136
  # Configure logger
@@ -133,7 +149,8 @@ class LanguageParser(PatternsParser):
133
149
  :param kwargs: Additional keyword arguments.
134
150
  :return: The result of parsing the input string.
135
151
  """
136
- handler = ContentHandler(input)
152
+ handler = ContentHandler(input, pre_processor=self.pre_process, **kwargs)
153
+
137
154
  # Configure logger
138
155
  LOGGER.configure(self, height=len(handler.lines), width=max(handler.line_lengths))
139
156
 
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ import shutil
4
+ from pathlib import Path
5
+
6
+ import yaml
7
+
8
+ from ..base import LanguageParser
9
+
10
+
11
+ class MarkdownParser(LanguageParser):
12
+ def __init__(self, **kwargs):
13
+ tmLanguageFile = (
14
+ Path(__file__).parents[3] / "syntaxes" / "markdown" / "markdown.tmLanguage.base.yaml"
15
+ )
16
+ tmLanguageYAML = Path(__file__).parent / "grammar.yaml"
17
+
18
+ if tmLanguageFile.exists():
19
+ shutil.copyfile(tmLanguageFile, tmLanguageYAML)
20
+
21
+ with open(tmLanguageYAML) as file:
22
+ try:
23
+ grammar = yaml.load(file.read(), Loader=yaml.CLoader)
24
+ except ImportError:
25
+ grammar = yaml.load(file.read(), Loader=yaml.Loader)
26
+
27
+ super().__init__(grammar, **kwargs)
@@ -0,0 +1,70 @@
1
+ from __future__ import annotations
2
+
3
+ import plistlib
4
+ import re
5
+ from pathlib import Path
6
+
7
+ import yaml
8
+
9
+ from ..base import LanguageParser
10
+
11
+
12
+ class MatlabParser(LanguageParser):
13
+ """
14
+ Represents a grammar for the MATLAB language.
15
+ """
16
+
17
+ def __init__(self, remove_line_continuations: bool = False, **kwargs):
18
+ """
19
+ Initializes a new instance of the MatlabGrammar class.
20
+
21
+ Args:
22
+ remove_line_continuations (bool, optional): Whether to remove line continuations. Defaults to False.
23
+ """
24
+
25
+ self._rlc = remove_line_continuations
26
+
27
+ tmLanguageFile = (
28
+ Path(__file__).parents[3]
29
+ / "syntaxes"
30
+ / "matlab"
31
+ / "Matlab.tmbundle"
32
+ / "Syntaxes"
33
+ / "MATLAB.tmLanguage"
34
+ )
35
+ tmLanguageYAML = Path(__file__).parent / "grammar.yaml"
36
+
37
+ if tmLanguageFile.exists():
38
+ with open(tmLanguageFile, "rb") as tmFile:
39
+ grammar = plistlib.load(tmFile, fmt=plistlib.FMT_XML)
40
+ with open(tmLanguageYAML, "w") as ymlFile:
41
+ ymlFile.write(yaml.dump(grammar, indent=2))
42
+ else:
43
+ with open(tmLanguageYAML) as ymlFile:
44
+ try:
45
+ grammar = yaml.load(ymlFile.read(), Loader=yaml.CLoader)
46
+ except ImportError:
47
+ grammar = yaml.load(ymlFile.read(), Loader=yaml.Loader)
48
+
49
+ super().__init__(grammar, **kwargs)
50
+
51
+ def pre_process(self, input: str) -> str:
52
+ """
53
+ Pre-processes the input text.
54
+ """
55
+ if self._rlc:
56
+ input = self._remove_line_continuations(input)
57
+ return input
58
+
59
+ def _remove_line_continuations(self, input: str) -> str:
60
+ """
61
+ Removes line continuations from the input text.
62
+ """
63
+ output = ""
64
+ for split in input.split("..."):
65
+ matching = re.search(r"\n[\t\f\v ]*", split)
66
+ if matching:
67
+ output += split[matching.span()[1] :]
68
+ else:
69
+ output += split
70
+ return output
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import atexit
2
4
  from pathlib import Path
3
5
  from pickle import UnpicklingError
@@ -141,10 +143,10 @@ class ShelveCache(TextmateCache):
141
143
  self._database[key] = (timestamp, element)
142
144
 
143
145
 
144
- CACHE: "TextmateCache" = SimpleCache()
146
+ CACHE: TextmateCache = SimpleCache()
145
147
 
146
148
 
147
- def init_cache(type: str = "simple") -> "TextmateCache":
149
+ def init_cache(type: str = "simple") -> TextmateCache:
148
150
  """
149
151
  Initialize the cache based on the given type.
150
152
 
@@ -152,9 +154,10 @@ def init_cache(type: str = "simple") -> "TextmateCache":
152
154
  :return: The initialized cache object.
153
155
  """
154
156
  global CACHE
155
- match type:
156
- case "shelve":
157
- CACHE = ShelveCache()
158
- case "simple":
159
- CACHE = SimpleCache()
157
+ if type == "shelve":
158
+ CACHE = ShelveCache()
159
+ elif type == "simple":
160
+ CACHE = SimpleCache()
161
+ else:
162
+ raise NotImplementedError(f"Cache type {type} not implemented.")
160
163
  return CACHE
@@ -1,3 +1,6 @@
1
+ from __future__ import annotations
2
+
3
+
1
4
  class IncludedParserNotFound(Exception):
2
5
  """Exception raised when an included parser is not found in the store."""
3
6
 
@@ -1,6 +1,8 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  from functools import wraps
3
- from typing import TYPE_CHECKING, Optional
5
+ from typing import TYPE_CHECKING
4
6
 
5
7
  if TYPE_CHECKING:
6
8
  from ..parser import GrammarParser
@@ -70,7 +72,7 @@ class Logger:
70
72
  channel.setFormatter(LogFormatter())
71
73
  self.logger.addHandler(channel)
72
74
 
73
- def configure(self, parser: "GrammarParser", height: int, width: int, **kwargs) -> None:
75
+ def configure(self, parser: GrammarParser, height: int, width: int, **kwargs) -> None:
74
76
  """Configures the logger to a specific grammar and content length"""
75
77
  self.line_decimals = len(str(height))
76
78
  self.position_decimals = len(str(width))
@@ -84,7 +86,7 @@ class Logger:
84
86
  def format_message(
85
87
  self,
86
88
  message: str,
87
- parser: Optional["GrammarParser"] = None,
89
+ parser: GrammarParser | None = None,
88
90
  position: tuple[int, int] | None = None,
89
91
  depth: int = 0,
90
92
  ) -> str:
@@ -1 +0,0 @@
1
- __version__ = "0.3.0"
@@ -1,19 +0,0 @@
1
- import shutil
2
- from pathlib import Path
3
-
4
- import yaml
5
-
6
- tmLanguageFile = (
7
- Path(__file__).parents[3] / "syntaxes" / "markdown" / "markdown.tmLanguage.base.yaml"
8
- )
9
- tmLanguageYAML = Path(__file__).parent / "grammar.yaml"
10
-
11
-
12
- if tmLanguageFile.exists():
13
- shutil.copyfile(tmLanguageFile, tmLanguageYAML)
14
-
15
- with open(tmLanguageYAML) as file:
16
- try:
17
- GRAMMAR = yaml.load(file.read(), Loader=yaml.CLoader)
18
- except ImportError:
19
- GRAMMAR = yaml.load(file.read(), Loader=yaml.Loader)
@@ -1,27 +0,0 @@
1
- import plistlib
2
- from pathlib import Path
3
-
4
- import yaml
5
-
6
- tmLanguageFile = (
7
- Path(__file__).parents[3]
8
- / "syntaxes"
9
- / "matlab"
10
- / "Matlab.tmbundle"
11
- / "Syntaxes"
12
- / "MATLAB.tmLanguage"
13
- )
14
- tmLanguageYAML = Path(__file__).parent / "grammar.yaml"
15
-
16
-
17
- if tmLanguageFile.exists():
18
- with open(tmLanguageFile, "rb") as file:
19
- GRAMMAR = plistlib.load(file, fmt=plistlib.FMT_XML)
20
- with open(tmLanguageYAML, "w") as f:
21
- f.write(yaml.dump(GRAMMAR, indent=2))
22
- else:
23
- with open(tmLanguageYAML) as file:
24
- try:
25
- GRAMMAR = yaml.load(file.read(), Loader=yaml.CLoader)
26
- except ImportError:
27
- GRAMMAR = yaml.load(file.read(), Loader=yaml.Loader)