diff options
author | Philipp Gesang <phg@phi-gamma.net> | 2014-03-01 22:47:25 +0100 |
---|---|---|
committer | Philipp Gesang <phg@phi-gamma.net> | 2014-03-01 22:47:25 +0100 |
commit | 7d1114cd66025cc18535f3cdab3105e66bbda48d (patch) | |
tree | eca33193cdbb0d7923527b0c0bfb58cd893036b6 /src/rst_directives.lua | |
parent | 7652729ada000906e5e6b2b4d0c5dea01c73c29d (diff) | |
download | context-rst-7d1114cd66025cc18535f3cdab3105e66bbda48d.tar.gz |
adopt more conventional directory structure
Diffstat (limited to 'src/rst_directives.lua')
-rw-r--r-- | src/rst_directives.lua | 381 |
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 + |