Skip to content

Commit eff06db

Browse files
committed
Fixed #244.
Added core.Tokenize and core.ConfigFile helper classes.
1 parent 312ecba commit eff06db

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

addons/source-python/packages/source-python/commands/typed.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from auth.manager import auth_manager
1919
# Core
2020
from core import AutoUnload
21+
from core import Tokenize
2122
# Commands
2223
from commands import commands_logger
2324
from commands import CommandReturn
@@ -449,7 +450,7 @@ def parse_command(self, command):
449450
passed.
450451
:rtype: tuple
451452
"""
452-
args = list(command)
453+
args = Tokenize(command.command_string)
453454
store = self
454455
while args and isinstance(store, Store):
455456
sub_command = args.pop(0).lower()

addons/source-python/packages/source-python/core/__init__.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
from path import Path
2525
# Platform
2626
from platform import system
27+
# RE
28+
from re import compile as re_compile
29+
from re import finditer
2730
# Sys
2831
import sys
2932
# Urllib
@@ -178,6 +181,89 @@ def __init__(self, infile, *args, **kwargs):
178181
self.merge(ConfigObj(path / GAME_NAME / name, *args, **kwargs))
179182

180183

184+
class Tokenize(list):
185+
"""Parses the arguments from the given string."""
186+
187+
_pattern = re_compile('"[^"]*"|[^ ]+')
188+
189+
def __init__(self, string, comment_prefix=None):
190+
"""Splits the arguments from the given string."""
191+
# Initialize the list
192+
super().__init__()
193+
194+
# Store the given string as is
195+
self.string = string
196+
197+
# Loop through all tokens
198+
for match in finditer(self._pattern, string):
199+
200+
# Get the current match as a string
201+
arg = match.group()
202+
203+
# Strip end line comment
204+
if comment_prefix is not None and arg.startswith(comment_prefix):
205+
self.string = self.string[:match.start()]
206+
break
207+
208+
# Add the current argument to the list
209+
self.append(arg.strip('"'))
210+
211+
def __str__(self):
212+
"""Returns the original string (without end-line comment)."""
213+
return self.string
214+
215+
def __hash__(self):
216+
"""Hashes the original string."""
217+
return hash(self.string)
218+
219+
220+
class ConfigFile(list):
221+
"""Class used to parse a configuration file."""
222+
223+
def __init__(
224+
self, path, encoding='utf-8', comment_prefix='//', as_strings=False):
225+
"""Parses the given configuation file path.
226+
227+
:param Path path:
228+
The path of the file to parse.
229+
:param str encoding:
230+
The encoding to use when opening the file.
231+
:param str comment_prefix:
232+
The prefix of end line comments.
233+
:param bool as_strings:
234+
Whether the parsed lines should be stored as strings rather than
235+
argument lists.
236+
"""
237+
# If the given path doesn't exist, search for it in the cfg directory
238+
if not path.isfile():
239+
path = CFG_PATH.joinpath(path)
240+
241+
# If no file was found, return an empty list
242+
if not path.isfile():
243+
return
244+
245+
# Import this here to fix cyclic imports
246+
from translations.strings import LangStrings
247+
248+
# Open the given file and parse its content
249+
with open(path, 'r', encoding=encoding) as f:
250+
251+
# Loop through all lines
252+
for line in f.read().splitlines():
253+
254+
# Parse the argument from the current line
255+
args = Tokenize(
256+
LangStrings._replace_escaped_sequences(line),
257+
comment_prefix)
258+
259+
# Skip empty/commented lines
260+
if not args:
261+
continue
262+
263+
# Add the current line to the list
264+
self.append(args if not as_strings else str(args))
265+
266+
181267
# =============================================================================
182268
# >> FUNCTIONS
183269
# =============================================================================

0 commit comments

Comments
 (0)