summaryrefslogtreecommitdiff
path: root/tex/context/base/lang-rep.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/lang-rep.lua')
-rw-r--r--tex/context/base/lang-rep.lua98
1 files changed, 91 insertions, 7 deletions
diff --git a/tex/context/base/lang-rep.lua b/tex/context/base/lang-rep.lua
index fb136b551..be74d597a 100644
--- a/tex/context/base/lang-rep.lua
+++ b/tex/context/base/lang-rep.lua
@@ -7,9 +7,21 @@ if not modules then modules = { } end modules ['lang-rep'] = {
}
-- A BachoTeX 2013 experiment, probably not that useful. Eventually I used a simpler
--- more generic example.
+-- more generic example. I'm sure no one ever notices of even needs this code.
+--
+-- As a follow up on a question by Alan about special treatment of dropped caps I wonder
+-- if I can make this one more clever (probably in a few more dev steps). For instance
+-- injecting nodes or replacing nodes. It's a prelude to a kind of lpeg for nodes,
+-- although (given experiences so far) we don't really need that. After all, each problem
+-- is somewhat unique.
+local type = type
local utfbyte, utfsplit = utf.byte, utf.split
+local P, C, U, Cc, Ct, lpegmatch = lpeg.P, lpeg.C, lpeg.patterns.utf8character, lpeg.Cc, lpeg.Ct, lpeg.match
+local find = string.find
+
+local grouped = P("{") * ( Ct((U/utfbyte-P("}"))^1) + Cc(false) ) * P("}")-- grouped
+local splitter = Ct((Ct(Cc("discretionary") * grouped * grouped * grouped) + U/utfbyte)^1)
local trace_replacements = false trackers.register("languages.replacements", function(v) trace_replacements = v end)
local trace_detail = false trackers.register("languages.replacements.detail", function(v) trace_detail = v end)
@@ -24,6 +36,7 @@ local tonode = nuts.tonode
local setfield = nuts.setfield
local getnext = nuts.getnext
+local getprev = nuts.getprev
local getattr = nuts.getattr
local getid = nuts.getid
local getchar = nuts.getchar
@@ -31,6 +44,12 @@ local getchar = nuts.getchar
local insert_node_before = nuts.insert_before
local remove_node = nuts.remove
local copy_node = nuts.copy
+local flush_list = nuts.flush_list
+local insert_after = nuts.insert_after
+
+local nodepool = nuts.pool
+local new_glyph = nodepool.glyph
+local new_disc = nodepool.disc
local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
@@ -56,6 +75,8 @@ table.setmetatableindex(lists,function(lists,name)
return data
end)
+-- todo: glue kern
+
local function add(root,word,replacement)
local list = utfsplit(word,true)
local size = #list
@@ -65,15 +86,19 @@ local function add(root,word,replacement)
root[l] = { }
end
if i == size then
- local newlist = utfsplit(replacement,true)
- for i=1,#newlist do
- newlist[i] = utfbyte(newlist[i])
- end
+ -- local newlist = utfsplit(replacement,true)
+ -- for i=1,#newlist do
+ -- newlist[i] = utfbyte(newlist[i])
+ -- end
+ local special = find(replacement,"{")
+ local newlist = lpegmatch(splitter,replacement)
+ --
root[l].final = {
word = word,
replacement = replacement,
oldlength = size,
newcodes = newlist,
+ special = special,
}
end
root = root[l]
@@ -124,6 +149,21 @@ local function hit(a,head)
end
end
+local function tonodes(list,template)
+ local head, current
+ for i=1,#list do
+ local new = copy_node(template)
+ setfield(new,"char",list[i])
+ if head then
+ head, current = insert_after(head,current,new)
+ else
+ head, current = new, new
+ end
+ end
+ return head
+end
+
+
function replacements.handler(head)
head = tonut(head)
local current = head
@@ -137,10 +177,54 @@ function replacements.handler(head)
local oldlength = final.oldlength
local newcodes = final.newcodes
local newlength = #newcodes
- if report_replacement then
+ if trace_replacement then
report_replacement("replacing word %a by %a",final.word,final.replacement)
end
- if oldlength == newlength then -- #old == #new
+ if final.special then
+ -- easier is to delete and insert (a simple callout to tex would be more efficient)
+ -- maybe just walk over a replacement string instead
+ local prev = getprev(current)
+ local next = getnext(last)
+ local list = current
+ setfield(last,"next",nil)
+ setfield(prev,"next",next)
+ if next then
+ setfield(next,"prev",prev)
+ end
+ current = prev
+ if not current then
+ head = nil
+ end
+ for i=1,newlength do
+ local codes = newcodes[i]
+ local new = nil
+ if type(codes) == "table" then
+ local method = codes[1]
+ if method == "discretionary" then
+ local pre, post, replace = codes[2], codes[3], codes[4]
+ new = new_disc()
+ if pre then
+ setfield(new,"pre",tonodes(pre,last))
+ end
+ if post then
+ setfield(new,"post",tonodes(post,last))
+ end
+ if replace then
+ setfield(new,"replace",tonodes(replace,last))
+ end
+ else
+ -- todo
+ end
+ else
+ new = copy_node(last)
+ setfield(new,"char",codes)
+ end
+ if new then
+ head, current = insert_after(head,current,new)
+ end
+ end
+ flush_list(list)
+ elseif oldlength == newlength then -- #old == #new
for i=1,newlength do
setfield(current,"char",newcodes[i])
current = getnext(current)