aboutsummaryrefslogtreecommitdiffstats
path: root/alv/template_string.moon
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2025-03-14 23:44:10 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-15 14:14:04 +0000
commit79696a272d1d8f2959a0b9cfdd8487d356416a05 (patch)
tree0d6e28f00b6a62e2fd7488b1df772305f56a812a /alv/template_string.moon
parentsomewhat clean up alv.parsing (diff)
downloadalive-79696a272d1d8f2959a0b9cfdd8487d356416a05.tar.gz
alive-79696a272d1d8f2959a0b9cfdd8487d356416a05.zip
implement template strings
Diffstat (limited to 'alv/template_string.moon')
-rw-r--r--alv/template_string.moon83
1 files changed, 83 insertions, 0 deletions
diff --git a/alv/template_string.moon b/alv/template_string.moon
new file mode 100644
index 0000000..bd6ae0f
--- /dev/null
+++ b/alv/template_string.moon
@@ -0,0 +1,83 @@
+----
+-- A string with substitutions, partially implements the `AST` interface.
+--
+-- Is automatically "splatted" into multiple expressions when the containing
+-- `Cell` is evaluated: the original string (str=), but with with substitution
+-- markers like `#{1}`, `#{2}` and so on and one expression for each substitution.
+--
+-- `#` symbols in the original string are escaped to `##`.
+--
+-- @classmod TemplateString
+import Constant from require 'alv.result'
+
+-- @type TemplateString
+class TemplateString
+--- AST interface
+--
+-- `TemplateString` partially implements the `AST` interface.
+-- @section ast
+
+ --- create a clone with its own identity.
+ --
+ -- creates a clone of this TemplateString by cloning all child expressions
+ -- recursively.
+ --
+ -- @tparam Tag parent
+ -- @treturn TemplateString
+ clone: (parent) =>
+ children = [child\clone parent for child in *@children]
+ @@ @string, children
+
+ --- stringify this TemplateString.
+ --
+ -- if `depth` is passed, does not faithfully recreate the original string but
+ -- rather create useful debug output.
+ --
+ -- @tparam[opt] int depth the maximum depth, defaults to infinite
+ -- @treturn string the exact string this TemplateString was parsed from
+ stringify: (depth=-1) =>
+ children = ['#' .. child\stringify depth for child in *@children]
+ str = @@.subst @.string!, (i) -> '#' .. @children[i]\stringify depth
+ '#"' .. str .. '"'
+
+--- static functions
+-- @section static
+
+ new: (@string, @children) =>
+
+ --- apply substitutions to a template string.
+ --
+ -- This also reverses the escaping that the parser applied.
+ --
+ -- @classmethod
+ -- @tparam string str the evaluated `TemplateString.string`
+ -- @tparam function fn function called with index i to obtain string to substitute
+ -- @treturn string
+ @subst: (str, fn) ->
+ str = str\gsub '##', '#'
+ str\gsub '#{(%d+)}', (i) -> fn tonumber i
+
+ --- parse a TemplateString (for parsing with Lpeg).
+ --
+ -- @classmethod
+ -- @tparam {string|AST,...} pieces
+ -- @treturn TemplateString
+ @parse: (...) =>
+ string = ''
+ children = {}
+
+ i = 1
+ for elem in *{...}
+ string ..= if elem == '##' then elem
+ elseif 'string' == type elem then elem\gsub '#', '##'
+ else
+ table.insert children, elem
+ '#{' .. #children .. '}'
+
+ string = Constant.str string
+
+ @@ string, children
+
+{
+ :TemplateString
+}