summaryrefslogtreecommitdiff
path: root/tex/context/base/chem-str.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/chem-str.lua')
-rw-r--r--tex/context/base/chem-str.lua448
1 files changed, 289 insertions, 159 deletions
diff --git a/tex/context/base/chem-str.lua b/tex/context/base/chem-str.lua
index dc4bd746f..3ab2e53b6 100644
--- a/tex/context/base/chem-str.lua
+++ b/tex/context/base/chem-str.lua
@@ -21,24 +21,40 @@ if not modules then modules = { } end modules ['chem-str'] = {
-- the current user interface is slightly different from the old one but hopefully users
-- will like the added value.
-local trace_structure = false trackers.register("chemistry.structure", function(v) trace_structure = v end)
-local trace_metapost = false trackers.register("chemistry.metapost", function(v) trace_metapost = v end)
-local trace_textstack = false trackers.register("chemistry.textstack", function(v) trace_textstack = v end)
+-- directive_strictorder: one might set this to off when associated texts are disordered too
+
+local trace_structure = false trackers .register("chemistry.structure", function(v) trace_structure = v end)
+local trace_metapost = false trackers .register("chemistry.metapost", function(v) trace_metapost = v end)
+local trace_textstack = false trackers .register("chemistry.textstack", function(v) trace_textstack = v end)
+local directive_strictorder = true directives.register("chemistry.strictorder", function(v) directive_strictorder = v end)
+local directive_strictindex = false directives.register("chemistry.strictindex", function(v) directive_strictindex = v end)
local report_chemistry = logs.reporter("chemistry")
local format, gmatch, match, lower, gsub = string.format, string.gmatch, string.match, string.lower, string.gsub
-local concat, insert, remove = table.concat, table.insert, table.remove
+local concat, insert, remove, unique, sorted = table.concat, table.insert, table.remove, table.unique, table.sorted
local processor_tostring = typesetters and typesetters.processors.tostring
local settings_to_array = utilities.parsers.settings_to_array
local settings_to_array_with_repeat = utilities.parsers.settings_to_array_with_repeat
local lpegmatch = lpeg.match
-local P, R, S, C, Cs, Ct, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc
+local P, R, S, C, Cs, Ct, Cc, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cmt
local variables = interfaces and interfaces.variables
local context = context
+local v_default = variables.default
+local v_small = variables.small
+local v_medium = variables.medium
+local v_big = variables.big
+local v_normal = variables.normal
+local v_fit = variables.fit
+local v_on = variables.on
+
+local mpnamedcolor = attributes.colors.mpnamedcolor
+local topoints = number.topoints
+local todimen = string.todimen
+
chemistry = chemistry or { }
local chemistry = chemistry
@@ -47,39 +63,44 @@ chemistry.format = "metafun"
chemistry.structures = 0
local common_keys = {
- b = "line",
- r = "line",
- sb = "line",
- sr = "line",
- rd = "line",
- rh = "line",
- cc = "line",
- ccd = "line",
- line = "line",
- dash = "line",
- arrow = "line",
- c = "fixed",
- cd = "fixed",
- z = "text",
- zt = "text",
- zlt = "text",
- zrt = "text",
- rz = "text",
- rt = "text",
- lrt = "text",
- rrt = "text",
- zln = "number",
- zrn = "number",
- rn = "number",
- lrn = "number",
- rrn = "number",
- zn = "number",
- mov = "transform",
- mark = "transform",
- move = "transform",
- off = "transform",
- adj = "transform",
- sub = "transform",
+ b = "line",
+ r = "line",
+ sb = "line",
+ sr = "line",
+ rd = "line",
+ rh = "line",
+ rb = "line",
+ rbd = "line",
+ cc = "line",
+ ccd = "line",
+ line = "line",
+ dash = "line",
+ arrow = "line",
+ c = "fixed",
+ cd = "fixed",
+ z = "text",
+ zt = "text",
+ zlt = "text",
+ zrt = "text",
+ rz = "text",
+ rt = "text",
+ lrt = "text",
+ rrt = "text",
+ label = "text",
+ zln = "number",
+ zrn = "number",
+ rn = "number",
+ lrn = "number",
+ rrn = "number",
+ zn = "number",
+ number = "number",
+ mov = "transform",
+ mark = "transform",
+ move = "transform",
+ diff = "transform",
+ off = "transform",
+ adj = "transform",
+ sub = "transform",
}
local front_keys = {
@@ -89,6 +110,14 @@ local front_keys = {
lr = "line",
lsr = "line",
rsr = "line",
+ lrd = "line",
+ rrd = "line",
+ lrh = "line",
+ rrh = "line",
+ lrbd = "line",
+ rrbd = "line",
+ lrb = "line",
+ rrb = "line",
lrz = "text",
rrz = "text",
lsub = "transform",
@@ -99,15 +128,14 @@ local one_keys = {
db = "line",
tb = "line",
bb = "line",
- rb = "line",
dr = "line",
hb = "line",
bd = "line",
bw = "line",
oe = "line",
sd = "line",
- ld = "line",
- rd = "line",
+ rdb = "line",
+ ldb = "line",
ldd = "line",
rdd = "line",
ep = "line",
@@ -130,9 +158,12 @@ local ring_keys = {
rsr = "line",
lrd = "line",
rrd = "line",
- rb = "line",
lrb = "line",
rrb = "line",
+ lrh = "line",
+ rrh = "line",
+ lrbd = "line",
+ rrbd = "line",
dr = "line",
eb = "line",
er = "line",
@@ -199,7 +230,10 @@ local syntax = {
mp = { direct = '%s', arguments = 1 }, -- backdoor MP code - dangerous!
}
-local definitions = { }
+chemistry.definitions = chemistry.definitions or { }
+local definitions = chemistry.definitions
+
+storage.register("chemistry/definitions",definitions,"chemistry.definitions")
function chemistry.undefine(name)
definitions[lower(name)] = nil
@@ -218,7 +252,7 @@ function chemistry.define(name,spec,text)
}
end
-local metacode, variant, keys, max, txt, pstack, sstack
+local metacode, variant, keys, max, txt, pstack, sstack, align
local molecule = chemistry.molecule -- or use lpegmatch(chemistry.moleculeparser,...)
local function fetch(txt)
@@ -260,10 +294,10 @@ local special = (colon * C(other^1)) + Cc("")
local text = (equal * C(P(1)^0)) + Cc(false)
local pattern =
- (amount + Cc(1)) *
- (remapped + Cc("")) *
- Cs(operation/lower) *
- Cs(special/lower) * (
+ (amount + Cc(1))
+ * (remapped + Cc(""))
+ * Cs(operation/lower)
+ * Cs(special/lower) * (
range * Cc(false) * text +
Cc(false) * Cc(false) * set * text +
single * Cc(false) * Cc(false) * text +
@@ -278,43 +312,88 @@ local pattern =
-- print(lpegmatch(pattern,"RZ13=x")) -- 1 RZ false false table x
local t_initialize = 'if unknown context_chem : input mp-chem.mpiv ; fi ;'
-local t_start_structure = 'chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);'
+local t_start_structure = 'chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);'
local t_stop_structure = 'chem_stop_structure;'
local t_start_component = 'chem_start_component;'
local t_stop_component = 'chem_stop_component;'
local t_line = 'chem_%s%s(%s,%s,%s,%s,%s);'
local t_set = 'chem_set(%s);'
-local t_number = 'chem_%s(%s,%s,"\\chemicaltext{%s}");'
+local t_number = 'chem_%s%s(%s,%s,"\\chemicaltext{%s}");'
local t_text = t_number
local t_empty_normal = 'chem_%s(%s,%s,"");'
local t_empty_center = 'chem_c%s(%s,%s,"");'
local t_transform = 'chem_%s(%s,%s,%s);'
-local function process(spec,text,n,rulethickness,rulecolor,offset)
- insert(stack,{ spec=spec, text=text, n=n })
+local prepareMPvariable = commands and commands.prepareMPvariable
+
+local function process(level,spec,text,n,rulethickness,rulecolor,offset,default_variant)
+ insert(stack,{ spec = spec, text = text, n = n })
local txt = #stack
local m = #metacode
+ local saved_rulethickness = rulethickness
+ local saved_rulecolor = rulecolor
+ local saved_align = align
+ local current_variant = default_variant or "six"
for i=1,#spec do
local step = spec[i]
local s = lower(step)
- local d = definitions[s]
+ local n = current_variant .. ":" .. s
+ local d = definitions[n]
+ if not d then
+ n = s
+ d = definitions[n]
+ end
if d then
if trace_structure then
- report_chemistry("%s => definition: %s",step,s)
+ report_chemistry("%s > %s => definition: %s (%s snippets)",level,step,n,#d)
end
for i=1,#d do
local di = d[i]
- process(di.spec,di.text,1,rulethickness,rulecolor) -- offset?
+ current_variant = process(level+1,di.spec,di.text,1,rulethickness,rulecolor,offset,current_variant) -- offset?
end
else
- --~local rep, operation, special, index, upto, set, text = lpegmatch(pattern,step)
local factor, osign, operation, special, index, upto, set, text = lpegmatch(pattern,step)
if trace_structure then
local set = set and concat(set," ") or "-"
- report_chemistry("%s => factor: %s, osign: %s operation: %s, special: %s, index: %s, upto: %s, set: %s, text: %s",
- step,factor or "",osign or "",operation or "-",special and special ~= "" or "-",index or "-",upto or "-",set or "-",text or "-")
+ report_chemistry("%s > %s => factor: %s, osign: %s operation: %s, special: %s, index: %s, upto: %s, set: %s, text: %s",
+ level,step,factor or "",osign or "",operation or "-",special and special ~= "" or "-",index or "-",upto or "-",set or "-",text or "-")
end
- if operation == "pb" then
+ if operation == "rulecolor" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal or t == "" then
+ rulecolor = saved_rulecolor
+ elseif t then
+ rulecolor = mpnamedcolor(t)
+ end
+ elseif operation == "rulethickness" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal or t == t_medium or t == "" then
+ rulethickness = saved_rulethickness
+ elseif t == v_small then
+ rulethickness = topoints(1/1.2 * todimen(saved_rulethickness))
+ elseif t == v_big then
+ rulethickness = topoints(1.2 * todimen(saved_rulethickness))
+ elseif t then
+ -- rulethickness = topoints(todimen(t)) -- mp can't handle sp
+ rulethickness = topoints(tonumber(t) * todimen(saved_rulethickness))
+ end
+ elseif operation == "symalign" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal then
+ align = saved_align
+ elseif t and t ~= "" then
+ align = "." .. t
+ end
+ elseif operation == "pb" then
insert(pstack,variant)
m = m + 1 ; metacode[m] = syntax.pb.direct
if keys[special] == "text" and index then
@@ -330,6 +409,7 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
keys, max = ss.keys, ss.max
m = m + 1 ; metacode[m] = syntax[operation].direct
m = m + 1 ; metacode[m] = format(t_set,variant)
+ current_variant = variant
elseif operation == "save" then
insert(sstack,variant)
m = m + 1 ; metacode[m] = syntax.save.direct
@@ -339,8 +419,52 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
keys, max = ss.keys, ss.max
m = m + 1 ; metacode[m] = syntax[operation].direct
m = m + 1 ; metacode[m] = format(t_set,variant)
+ current_variant = variant
elseif operation then
local ss = syntax[operation]
+ local what = keys[operation]
+ local ns = 0
+ if set then
+ local sv = syntax[current_variant]
+ local ms = sv and sv.max
+ set = unique(set)
+ ns = #set
+ if directive_strictorder then
+ if what == "line" then
+ set = sorted(set)
+ end
+ if directive_strictindex and ms then
+ for i=ns,1,-1 do
+ local si = set[i]
+ if si > ms then
+ report_chemistry("%s > operation %s: limited to %s steps, ignoring %s",
+ level,operation,ms,si)
+ set[i] = nil
+ ns = ns - 1
+ else
+ break
+ end
+ end
+ end
+ else
+ if directive_strictindex and ms then
+ local t, nt = { }, 0
+ for i=1,ns do
+ local si = set[i]
+ if si > ms then
+ report_chemistry("%s > operation %s: limited to %s steps, ignoring %s",
+ level,operation,ms,si)
+ set[i] = nil
+ else
+ nt = nt + 1
+ t[nt] = si
+ end
+ end
+ ns = nt
+ set = t
+ end
+ end
+ end
if ss then
local ds = ss.direct
if ds then
@@ -348,7 +472,7 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if sa == 1 then
local one ; txt, one = fetch(txt)
m = m + 1 ; metacode[m] = format(ds,one or "")
- elseif sa ==2 then
+ elseif sa == 2 then
local one ; txt, one = fetch(txt)
local two ; txt, two = fetch(txt)
m = m + 1 ; metacode[m] = format(ds,one or "",two or "")
@@ -358,118 +482,120 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
elseif ss.keys then
variant, keys, max = s, ss.keys, ss.max
m = m + 1 ; metacode[m] = format(t_set,variant)
+ current_variant = variant
end
- else
- local what = keys[operation]
- if what == "line" then
- local s = osign
- if s ~= "" then s = "." .. s end
- if set then
- -- condense consecutive numbers in a set to a range
- -- (numbers modulo max are currently not dealt with...)
- table.sort(set)
- local sf, st = set[1]
- for i=1,#set do
- if i > 1 and set[i] ~= set[i-1]+1 then
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,sf,st,rulethickness,rulecolor)
- sf = set[i]
- end
- st = set[i]
+ elseif what == "line" then
+ local s = osign
+ if s ~= "" then
+ s = "." .. s
+ end
+ if set then
+ -- condense consecutive numbers in a set to a range
+ local sf, st = set[1]
+ for i=1,ns do
+ if i > 1 and set[i] ~= set[i-1]+1 then
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,sf,st,rulethickness,rulecolor)
+ sf = set[i]
end
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,sf,st,rulethickness,rulecolor)
- elseif upto then
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,index,upto,rulethickness,rulecolor)
- elseif index then
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,index,index,rulethickness,rulecolor)
- else
- m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,1,max,rulethickness,rulecolor)
+ st = set[i]
end
- elseif what == "number" then
- if set then
- for i=1,#set do
- local si = set[i]
- m = m + 1 ; metacode[m] = format(t_number,operation,variant,si,si)
- end
- elseif upto then
- for i=index,upto do
- local si = set[i]
- m = m + 1 ; metacode[m] = format(t_number,operation,variant,si,si)
- end
- elseif index then
- m = m + 1 ; metacode[m] = format(t_number,operation,variant,index,index)
- else
- for i=1,max do
- m = m + 1 ; metacode[m] = format(t_number,operation,variant,i,i)
- end
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,sf,st,rulethickness,rulecolor)
+ elseif upto then
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,index,upto,rulethickness,rulecolor)
+ elseif index then
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,index,index,rulethickness,rulecolor)
+ else
+ m = m + 1 ; metacode[m] = format(t_line,operation,s,variant,1,max,rulethickness,rulecolor)
+ end
+ elseif what == "number" then
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = format(t_number,operation,align,variant,si,si)
end
- elseif what == "text" then
- if set then
- for i=1,#set do
- local si = set[i]
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,si,t)
- end
- end
- elseif upto then
- for i=index,upto do
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,i,t)
- end
- end
- elseif index == 0 then
+ elseif upto then
+ for i=index,upto do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = format(t_number,operation,align,variant,si,si)
+ end
+ elseif index then
+ m = m + 1 ; metacode[m] = format(t_number,operation,align,variant,index,index)
+ else
+ for i=1,max do
+ m = m + 1 ; metacode[m] = format(t_number,operation,align,variant,i,i)
+ end
+ end
+ elseif what == "text" then
+ if set then
+ for i=1,ns do
+ local si = set[i]
local t = text
if not t then txt, t = fetch(txt) end
if t then
t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,index,t)
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,si,t)
end
- elseif index then
+ end
+ elseif upto then
+ for i=index,upto do
local t = text
if not t then txt, t = fetch(txt) end
if t then
t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,index,t)
- end
- else
- for i=1,max do
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format(t_text,operation,variant,i,t)
- end
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,i,t)
end
end
- elseif what == "transform" then
- if osign == "m" then factor = -factor end
- if set then
- for i=1,#set do
- local si = set[i]
- m = m + 1 ; metacode[m] = format(t_transform,operation,variant,si,factor)
- end
- elseif upto then
- for i=index,upto do
- m = m + 1 ; metacode[m] = format(t_transform,operation,variant,i,factor)
+ elseif index == 0 then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,index,t)
+ end
+ elseif index then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,index,t)
+ end
+ else
+ for i=1,max do
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format(t_text,operation,align,variant,i,t)
end
- else
- m = m + 1 ; metacode[m] = format(t_transform,operation,variant,index or 1,factor)
end
- elseif what == "fixed" then
- m = m + 1 ; metacode[m] = format(t_transform,operation,variant,rulethickness,rulecolor)
- elseif trace_structure then
- report_chemistry("warning: undefined operation %s ignored here", operation or "")
end
+ elseif what == "transform" then
+ if osign == "m" then
+ factor = -factor
+ end
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = format(t_transform,operation,variant,si,factor)
+ end
+ elseif upto then
+ for i=index,upto do
+ m = m + 1 ; metacode[m] = format(t_transform,operation,variant,i,factor)
+ end
+ else
+ m = m + 1 ; metacode[m] = format(t_transform,operation,variant,index or 1,factor)
+ end
+ elseif what == "fixed" then
+ m = m + 1 ; metacode[m] = format(t_transform,operation,variant,rulethickness,rulecolor)
+ elseif trace_structure then
+ report_chemistry("%s > warning: undefined operation %s ignored here",
+ level, operation or "")
end
end
end
end
remove(stack)
+ return current_variant
end
-- the size related values are somewhat special but we want to be
@@ -480,19 +606,22 @@ end
function chemistry.start(settings)
chemistry.structures = chemistry.structures + 1
local emwidth, rulethickness, rulecolor, axiscolor = settings.emwidth, settings.rulethickness, settings.rulecolor, settings.framecolor
- local width, height, scale, offset = settings.width or 0, settings.height or 0, settings.scale or "normal", settings.offset or 0
+ local width, height, scale, rotation, offset = settings.width or 0, settings.height or 0, settings.scale or "normal", settings.rotation or 0, settings.offset or 0
local l, r, t, b = settings.left or 0, settings.right or 0, settings.top or 0, settings.bottom or 0
--
metacode = { }
--
+ align = settings.symalign or "auto"
if trace_structure then
- report_chemistry("scale: %s, width: %s, height: %s, l: %s, r: %s, t: %s, b: %s", scale, width, height, l, r, t, b)
+ report_chemistry("scale: %s, rotation: %s, width: %s, height: %s, l: %s, r: %s, t: %s, b: %s", scale, rotation, width, height, l, r, t, b)
+ report_chemistry("symalign: %s", align)
end
- if scale == variables.small then
+ if align ~= "" then align = "." .. align end
+ if scale == v_small then
scale = 1/1.2
- elseif scale == variables.normal or scale == variables.medium or scale == 0 then
+ elseif scale == v_normal or scale == v_medium or scale == 0 then
scale = 1
- elseif scale == variables.big then
+ elseif scale == v_big then
scale = 1.2
else
scale = tonumber(scale)
@@ -504,7 +633,7 @@ function chemistry.start(settings)
scale = .01
end
end
- if width == variables.fit then
+ if width == v_fit then
width = true
else
width = tonumber(width) or 0
@@ -529,7 +658,7 @@ function chemistry.start(settings)
end
width = false
end
- if height == variables.fit then
+ if height == v_fit then
height = true
else
height = tonumber(height) or 0
@@ -554,12 +683,13 @@ function chemistry.start(settings)
end
height = false
end
+ rotation = tonumber(rotation) or 0
--
metacode[#metacode+1] = format(t_start_structure,
chemistry.structures,
- l, r, t, b, scale,
+ l, r, t, b, scale, rotation,
tostring(width), tostring(height), tostring(emwidth), tostring(offset),
- tostring(settings.axis == variables.on), tostring(rulethickness), tostring(axiscolor)
+ tostring(settings.axis == v_on), tostring(rulethickness), tostring(axiscolor)
)
--
variant, keys, stack, pstack, sstack = "one", { }, { }, { }, { }
@@ -590,7 +720,7 @@ function chemistry.component(spec,text,settings)
local text = settings_to_array_with_repeat(text,true)
-- inspect(spec)
metacode[#metacode+1] = t_start_component
- process(spec,text,1,rulethickness,rulecolor) -- offset?
+ process(1,spec,text,1,rulethickness,rulecolor) -- offset?
metacode[#metacode+1] = t_stop_component
end