aboutsummaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authorGravatar jesopo2020-02-09 10:49:10 +0000
committerGravatar jesopo2020-02-09 10:49:18 +0000
commit29f0a282a8efb9ea93d33670ad42f1c151f70243 (patch)
tree4b3e2b6048d78cc5bf3b70e6a5a6e3b28e7bb8a2 /src/utils
parentadd ModuleManager.try_reload_module(), use it for !reloadmodule (diff)
signature
add utils.parse.sed.
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/parse/__init__.py3
-rw-r--r--src/utils/parse/sed.py73
2 files changed, 75 insertions, 1 deletions
diff --git a/src/utils/parse/__init__.py b/src/utils/parse/__init__.py
index cf32d8f5..dd13ecbc 100644
--- a/src/utils/parse/__init__.py
+++ b/src/utils/parse/__init__.py
@@ -1,9 +1,10 @@
-import decimal, io, typing
+import decimal, io, re, typing
from src.utils import datetime, errors
from .spec import *
from .time import duration
from .types import try_int
+from . import sed
COMMENT_TYPES = ["#", "//"]
def hashflags(filename: str
diff --git a/src/utils/parse/sed.py b/src/utils/parse/sed.py
new file mode 100644
index 00000000..96234063
--- /dev/null
+++ b/src/utils/parse/sed.py
@@ -0,0 +1,73 @@
+import dataclasses, re, typing
+
+class Sed(object):
+ type: str
+ def match(self, s: str) -> typing.Optional[str]:
+ return None
+
+@dataclasses.dataclass
+class SedReplace(Sed):
+ type: str
+ pattern: typing.Pattern
+ replace: str
+ count: int
+
+ def match(self, s):
+ return self.pattern.sub(self.replace, s, self.count)
+
+@dataclasses.dataclass
+class SedMatch(Sed):
+ type: str
+ pattern: typing.Pattern
+
+ def match(self, s):
+ match = self.pattern.search(s)
+ if match:
+ return match.group(0)
+ return None
+
+def _sed_split(s):
+ backslash = False
+ forward_slash = []
+ for i, c in enumerate(s):
+ if not backslash:
+ if c == "/":
+ forward_slash.append(i)
+ if c == "\\":
+ backslash = True
+ else:
+ backslash = False
+ if forward_slash and (not forward_slash[-1] == (len(s)-1)):
+ forward_slash.append(len(s))
+
+ last = 0
+ out = []
+ for i in forward_slash:
+ out.append(s[last:i])
+ last = i+1
+ return out
+
+def _sed_flags(s: str) -> typing.Tuple[int, int]:
+ count = 1
+ re_flags = 0
+ if "g" in s:
+ count = 0
+ if "i" in s:
+ re_flags |= re.I
+ return count, re_flags
+
+def parse_sed(sed_s: str) -> typing.Optional[Sed]:
+ type, pattern, *args = _sed_split(sed_s)
+ if type == "s":
+ replace, *args = args
+ count, flags = _sed_flags((args or [""])[0])
+ pattern = re.compile(pattern, flags)
+ return SedReplace(type, pattern, replace, count)
+ elif type == "m":
+ count, flags = _sed_flags((args or [""])[0])
+ return SedMatch(type, re.compile(pattern, flags))
+ return None
+
+def sed(sed_obj: Sed, s: str) -> typing.Tuple[str, typing.Optional[str]]:
+ out = sed_obj.match(s)
+ return sed_obj.type, out