aboutsummaryrefslogtreecommitdiff
path: root/src/smp/builtins.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/smp/builtins.py')
-rw-r--r--src/smp/builtins.py105
1 files changed, 93 insertions, 12 deletions
diff --git a/src/smp/builtins.py b/src/smp/builtins.py
index 3ff15c6..0997165 100644
--- a/src/smp/builtins.py
+++ b/src/smp/builtins.py
@@ -1,11 +1,14 @@
# import smp.exceptions
+import os
import subprocess
import urllib.request
import urllib.error
import urllib.parse
import datetime
import markdown
+from skaldpress.metadata_parser import extract_parse_yaml_metadata
from gfm import AutolinkExtension, TaskListExtension # type: ignore
+from typing import Any
def smp_builtin_define(macro_processor, macro_name, macro_value=None):
@@ -66,11 +69,38 @@ def smp_builtin_ifneq(macro_processor, a, b, iftrue, iffalse=None):
return ""
+def smp_builtin_add_metadata(macro_processor, metadata: dict[str, Any], overwrite=True):
+ """
+ Not added to macro_processor as macro
+ """
+ for macro_name, value in metadata.items():
+ if not macro_name.startswith(
+ macro_processor._get_macro_with_prefix("metadata_prefix")
+ ):
+ macro_name = f"{macro_processor._get_macro_with_prefix('metadata_prefix')}{macro_name}"
+
+ macro_value = str(value)
+ if isinstance(value, list):
+ macro_value = [str(el) for el in value]
+
+ if macro_name in macro_processor.macros:
+ macro_value.extend(macro_processor.macros[macro_name])
+
+ if overwrite or macro_name not in macro_processor.macros:
+ macro_processor.define_macro(macro_name, macro_value)
+
+
def smp_builtin_include(macro_processor, filename):
- filename = macro_processor.process_input(filename)
- with open(filename, "r") as f:
- file_content = f.read()
- return macro_processor.process_input(file_content)
+ return smp_builtin_read(macro_processor, filename, template_content=None)
+
+
+def smp_builtin_parse_leading_yaml(macro_processor, content):
+ """
+ Not added to macro_processor as macro
+ """
+ metadata, content = extract_parse_yaml_metadata(content)
+ smp_builtin_add_metadata(macro_processor, metadata, overwrite=True)
+ return content
def smp_builtin_include_verbatim(macro_processor, filename):
@@ -147,6 +177,51 @@ def smp_builtin_html_from_markdown(macro_processor, text, extensions=list()):
return markdown.markdown(text, extensions=extensions)
+def _smp_builtin_template_content(content):
+ def inner(macro_processor):
+ """
+ This should do some kind of stack thing, so we can track which file we are processing.
+ entering the CONTENT is fine, the question is how to handle exiting it.
+
+ could have a "once" macro or something, that is added to the end of the content.
+ """
+ return content
+
+ return inner
+
+
+def smp_builtin_template(macro_processor, template, content):
+ return smp_builtin_read(macro_processor, template, template_content=content)
+
+
+def smp_builtin_read(macro_processor, filename, template_content=None):
+ with open(filename, "r") as f:
+ file_content = f.read()
+
+ metadata = {}
+ if macro_processor._get_macro_with_prefix("parse_file_yaml"):
+ metadata, file_content = extract_parse_yaml_metadata(file_content)
+ smp_builtin_add_metadata(macro_processor, metadata, overwrite=False)
+
+ extension = os.path.splitext(filename)[1][1:] or ""
+ macro_processor._define_macro_with_prefix("target_file_extension", extension)
+
+ if template_content is not None:
+ macro_processor._get_macro_with_prefix("template_stack").append(filename)
+ macro_processor.macros["CONTENT"] = template_content
+
+ content = macro_processor.process_input(file_content)
+
+ if extension == "md":
+ content = smp_builtin_html_from_markdown(macro_processor, content)
+
+ if (template := macro_processor.macros.get("METADATA_template")) is not None:
+ if template not in macro_processor._get_macro_with_prefix("template_stack"):
+ return smp_builtin_read(macro_processor, template, content)
+
+ return content
+
+
global LINK_CACHE
LINK_CACHE: dict[str, tuple[bool, int, str]] = dict()
@@ -168,14 +243,24 @@ def smp_builtin_wodl(macro_processor, link, timeout_seconds=5):
working_link = (r.status == 200) and (r.reason == "OK")
LINK_CACHE[link] = (working_link, r.status, r.reason)
if not working_link:
- macro_processor.warnings.append(
- f"Dead link {link} ({r.status} {r.reason})!"
- )
+ macro_processor.log_warning(f"Dead link {link} ({r.status} {r.reason})!")
except urllib.error.URLError as e:
- macro_processor.warnings.append(f"Dead link {link} ({e})!")
+ macro_processor.log_warning(f"Dead link {link} ({e})!")
return ""
+def smp_builtin_once(macro_processor, content):
+ if (cache := macro_processor._get_macro_with_prefix("once_cache")) is not None:
+ if (exp := cache.get(content)) is not None:
+ return exp
+ else:
+ macro_processor._define_macro_with_prefix("once_cache", {})
+
+ expanded_content = macro_processor.process_input(content)
+ macro_processor._get_macro_with_prefix("once_cache", expanded_content)
+ return expanded_content
+
+
def smp_builtin_dumpenv(macro_processor):
out = ""
out += "━ Macros ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
@@ -188,7 +273,3 @@ def smp_builtin_dumpenv(macro_processor):
out += f"{repr(key)}: {repr(val)}\n"
out += "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
return out
-
-
-# TODO Add macro that spawns a interactive shell with the python env. would allow interactive debugging :)
-# needs to have a continue function or something (probably on C-d