summaryrefslogtreecommitdiff
path: root/src/rst_directives.lua
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2014-03-01 22:47:25 +0100
committerPhilipp Gesang <phg@phi-gamma.net>2014-03-01 22:47:25 +0100
commit7d1114cd66025cc18535f3cdab3105e66bbda48d (patch)
treeeca33193cdbb0d7923527b0c0bfb58cd893036b6 /src/rst_directives.lua
parent7652729ada000906e5e6b2b4d0c5dea01c73c29d (diff)
downloadcontext-rst-7d1114cd66025cc18535f3cdab3105e66bbda48d.tar.gz
adopt more conventional directory structure
Diffstat (limited to 'src/rst_directives.lua')
-rw-r--r--src/rst_directives.lua381
1 files changed, 381 insertions, 0 deletions
diff --git a/src/rst_directives.lua b/src/rst_directives.lua
new file mode 100644
index 0000000..f5572b7
--- /dev/null
+++ b/src/rst_directives.lua
@@ -0,0 +1,381 @@
+#!/usr/bin/env texlua
+--------------------------------------------------------------------------------
+-- FILE: rst_directives.lua
+-- USAGE: called by rst_parser.lua
+-- DESCRIPTION: Complement to the reStructuredText parser
+-- AUTHOR: Philipp Gesang (Phg), <phg42.2a@gmail.com>
+-- CHANGED: 2013-06-03 18:52:35+0200
+--------------------------------------------------------------------------------
+--
+
+local helpers = helpers or thirddata and thirddata.rst_helpers
+
+--------------------------------------------------------------------------------
+-- Directives for use with |substitutions|
+--------------------------------------------------------------------------------
+
+local rst_directives = { }
+thirddata.rst_directives = rst_directives
+local rst_context = thirddata.rst
+
+local lpegmatch = lpeg.match
+local stringformat = string.format
+local stringstrip = string.strip
+local tableconcat = table.concat
+local tableflattened = table.flattened
+local type = type
+
+--rst_directives.anonymous = 0
+rst_directives.images = {}
+rst_directives.images.done = {}
+rst_directives.images.values = {}
+
+
+rst_directives.images.keys = {
+ ["width"] = "width",
+ ["size"] = "width",
+ ["caption"] = "caption",
+ ["alt"] = "caption",
+ ["scale"] = "scale",
+}
+
+rst_directives.images.values.scale = function (orig)
+ -- http://wiki.contextgarden.net/Reference/en/useexternalfigure
+ -- scale=1000 is original size; to get 72%, use scale=720.
+ return tonumber(orig) * 1000
+end
+
+rst_directives.images.values.width = {
+ ["fit"] = "\\hsize",
+ ["hsize"] = "\\hsize",
+ ["broad"] = "\\hsize",
+ ["normal"] = "local",
+ ["normal"] = "local",
+}
+
+-- we won't allow passing arbitrary setups to context
+local permitted_setups = {
+ "width",
+ "scale"
+}
+
+local function img_setup (properties)
+ local result = ""
+ for _, prop in next, permitted_setups do
+ if properties[prop] then
+ result = result .. prop .. "=" .. properties[prop] .. ","
+ end
+ end
+ if result ~= "" then
+ result = "[" .. result .. "]"
+ end
+ return result
+end
+
+local collect_image_properties = function (data)
+ local image_directives = rst_directives.images
+ local p_keyval = helpers.patterns.colon_keyval
+ local properties = { }
+
+ data = tableflattened(data)
+ for i=1, #data do
+ local str = stringstrip(data[i])
+ local key, val = lpegmatch(p_keyval, str)
+ if key and val then
+ key = image_directives.keys[key] -- sanitize key expression
+ local valtype = type(image_directives.values[key])
+ if valtype == "table" then
+ val = image_directives.values[key][val]
+ elseif valtype == "function" then
+ val = image_directives.values[key](val)
+ end
+ properties[key] = val
+ end
+ end
+ return properties
+end
+
+--- ordinary image directives are converted to floats
+
+local float_image = function (data)
+ rst_context.addsetups "image"
+ local inline_parser = rst_context.inline_parser
+ local properties
+ local anon = false
+ local rdi = rst_directives.images
+ local hp = helpers.patterns
+ local caption = ""
+ local name = ""
+
+ if data.name then
+ name = stringstrip(data.name)
+ data.name = nil
+ else
+ if next(data[1]) then
+ name = data[1][1]
+ end
+ end
+
+ --rd.anonymous = rd.anonymous + 1
+ --anon = true -- indicates a nameless picture
+ --name = "anonymous" .. rd.anonymous
+
+ properties = collect_image_properties(data)
+
+ if properties.caption then
+ caption = lpegmatch(inline_parser, properties.caption)
+ caption = rst_context.escape(caption)
+ end
+
+ properties.setup = img_setup(properties) or ""
+ local img = ""
+-- local images_done = rdi.done
+-- if not anon then -- TODO: implement?
+-- if not images_done[name] then
+-- img = img .. stringformat([[
+--
+--\useexternalfigure[%s][%s][]%%
+--]], name, data)
+-- images_done[name] = true
+-- end
+-- img = img .. stringformat([[
+--\def\RSTsubstitution%s{%%
+-- \placefigure[here]{%s}{\externalfigure[%s]%s}%%
+--}
+--]], name, rst_context.escape(lpegmatch(inline_parser, properties.caption)), name, properties.setup)
+-- else -- image won't be referenced but used instantly
+ img = stringformat(
+ "\n\\placefigure[here]{%s}{\\externalfigure[%s]%s}",
+ caption,
+ name,
+ properties.setup)
+-- end
+ return img
+end
+
+--- inline substitutions are converted to bare external figures
+local inline_image = function (name, data)
+ rst_context.addsetups "image"
+ local filename = data.first
+ local p_keyval = helpers.patterns.colon_keyval
+ local properties
+
+ if not filename then --- garbage, ignore
+ return ""
+ end
+ data.first = nil
+ filename = stringstrip(filename)
+ properties = collect_image_properties(data)
+
+ local scheme = "\n\\def\\RSTsubstitution%s{\n \\externalfigure[%s]%s%%\n}\n"
+ local options = ""
+ if next(properties) then
+ local tmp = { }
+ tmp[#tmp+1] = "["
+ for key, value in next, properties do
+ tmp[#tmp+1] = key
+ tmp[#tmp+1] = "={"
+ tmp[#tmp+1] = rst_context.escape(value)
+ tmp[#tmp+1] = "},"
+ end
+ tmp[#tmp+1] = "]"
+ options = tableconcat(tmp)
+ end
+ return stringformat(scheme, name, filename, options)
+end
+
+rst_directives.image = float_image
+rst_directives.inline_image = inline_image
+
+rst_directives.caution = function(data)
+ local inline_parser = rst_context.inline_parser
+ rst_context.addsetups("dbend")
+ rst_context.addsetups("caution")
+ local text = { }
+ for i=1, #data do -- paragraphs
+ local current = tableconcat(data[i], "\n")
+ current = lpegmatch(inline_parser, current)
+ current = rst_context.escape(current)
+ text[i] = current
+ end
+ return stringformat([[
+\startRSTcaution
+%s
+\stopRSTcaution
+]], tableconcat(text, "\n\n"))
+end
+
+rst_directives.danger = function(data)
+ local inline_parser = rst_context.inline_parser
+ rst_context.addsetups("dbend")
+ rst_context.addsetups("danger")
+ local text = { }
+ for i=1, #data do -- paragraphs
+ local current = tableconcat(data[i], "\n")
+ current = lpegmatch(inline_parser, current)
+ current = rst_context.escape(current)
+ text[i] = current
+ end
+ return stringformat([[
+\startRSTdanger
+%s
+\stopRSTdanger
+]], tableconcat(text, "\n\n"))
+end
+
+-- http://docutils.sourceforge.net/docs/ref/rst/directives.html
+rst_directives.DANGER = function(data)
+ local inline_parser = rst_context.inline_parser
+ local text = { }
+ for i=1, #data do -- paragraphs
+ local current = tableconcat(data[i], "\n")
+ current = lpegmatch(inline_parser, current)
+ current = rst_context.escape(current)
+ text[i] = current
+ end
+ return stringformat([[
+
+%% The Rabbit of Caerbannog
+\startlinecorrection
+\blank[force,big]
+\framed[frame=on,
+ corner=round,
+ rulethickness=5pt,
+ align=middle,
+ width=\hsize,
+ frameoffset=.5em,
+ backgroundoffset=1em,
+ background=color,
+ backgroundcolor=red,
+ foreground=color,
+ foregroundcolor=black]{%%
+ \language[en-gb]\tfb\bf
+ Follow only if ye be men of valour, for the entrance to this cave is guarded
+ by a creature so foul, so cruel that no man yet has fought with it and lived.
+ Bones of full fifty men lie strewn about its lair. So, brave knights, if you
+ do doubt your courage or your strength, come no further, for death awaits you
+ all with nasty, big, pointy teeth.%%
+ \blank[force,big]
+ %s%%
+}
+\blank[force,big]
+\stoplinecorrection
+]], tableconcat(text, "\n\n"))
+end
+
+rst_directives.mp = function(name, data)
+ local mpcode = stringformat([[
+\startreusableMPgraphic{%s}
+%s
+\stopreusableMPgraphic
+]], name, data)
+ mpcode = mpcode .. stringformat([[
+\def\RSTsubstitution%s{%%
+ \reuseMPgraphic{%s}%%
+}
+]], name, name)
+ return mpcode
+end
+
+--- There’s an issue with buffers leaving trailing spaces due to their
+--- implementation.
+--- http://archive.contextgarden.net/message/20111108.175913.1d994624.en.html
+rst_directives.ctx = function(name, data)
+ local ctx = stringformat([[
+
+\startbuffer[%s]
+%s\stopbuffer
+\def\RSTsubstitution%s{%%
+ \getbuffer[%s]\removeunwantedspaces%%
+}
+]], name, data, name, name)
+ return ctx
+end
+
+rst_directives.lua = function(name, data)
+ local luacode = stringformat([[
+
+\startbuffer[%s]
+\startluacode
+%s
+\stopluacode
+\stopbuffer
+\def\RSTsubstitution%s{%%
+ \getbuffer[%s]\removeunwantedspaces%%
+}
+]], name, data, name, name)
+ return luacode
+end
+
+--------------------------------------------------------------------------------
+--- Experimental math directive
+--------------------------------------------------------------------------------
+
+rst_directives.math = function (name, data)
+ data = data or name
+ local formula
+ if type(data) == "table" then
+ local last, i = #data, 1
+ while i <= last do
+ local line = stringstrip(data[i])
+ if line and line ~= "" then
+ formula = formula and formula .. " " .. line or line
+ end
+ i = i + 1
+ end
+ end
+ return stringformat([[
+\startformula
+%s
+\stopformula
+]], formula)
+end
+
+--------------------------------------------------------------------------------
+--- End math directive
+--------------------------------------------------------------------------------
+
+rst_directives.replace = function(name, data)
+ return stringformat([[
+
+\def\RSTsubstitution%s{%s}
+]], name, data)
+end
+
+--------------------------------------------------------------------------------
+--- Containers.
+--------------------------------------------------------------------------------
+
+--- *data*:
+--- { [1] -> directive name,
+--- [>1] -> paragraphs }
+
+rst_directives.container = function(data)
+ local inline_parser = rst_context.inline_parser
+ local tmp = { }
+ for i=1, #data do -- paragraphs
+ local current = tableconcat(data[i], "\n")
+ current = lpegmatch(inline_parser, current)
+ current = rst_context.escape(current)
+ tmp[i] = current
+ end
+ local content = tableconcat(tmp, "\n\n")
+ local name = data.name
+ if name and name ~= "" then
+ name = stringstrip(data.name)
+ return stringformat([[
+\start[%s]%%
+%s%%
+\stop
+]], name, content)
+ else
+ return stringformat([[
+\begingroup%%
+%s%%
+\endgroup
+]], content)
+ end
+end
+
+-- vim:ft=lua:sw=4:ts=4:expandtab
+