diff options
Diffstat (limited to 'tex/context/base/buff-ini.lua')
-rw-r--r-- | tex/context/base/buff-ini.lua | 732 |
1 files changed, 366 insertions, 366 deletions
diff --git a/tex/context/base/buff-ini.lua b/tex/context/base/buff-ini.lua index 475d23efe..358c0f2a7 100644 --- a/tex/context/base/buff-ini.lua +++ b/tex/context/base/buff-ini.lua @@ -1,366 +1,366 @@ -if not modules then modules = { } end modules ['buff-ini'] = { - version = 1.001, - comment = "companion to buff-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local trace_run = false trackers.register("buffers.run", function(v) trace_run = v end) -local trace_grab = false trackers.register("buffers.grab", function(v) trace_grab = v end) -local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end) - -local report_buffers = logs.reporter("buffers","usage") -local report_grabbing = logs.reporter("buffers","grabbing") - -local context, commands = context, commands - -local concat = table.concat -local type, next, load = type, next, load -local sub, format = string.sub, string.format -local splitlines, validstring = string.splitlines, string.valid -local P, Cs, patterns, lpegmatch = lpeg.P, lpeg.Cs, lpeg.patterns, lpeg.match - -local variables = interfaces.variables -local settings_to_array = utilities.parsers.settings_to_array -local formatters = string.formatters - -local v_yes = variables.yes - -local catcodenumbers = catcodes.numbers - -local ctxcatcodes = catcodenumbers.ctxcatcodes -local txtcatcodes = catcodenumbers.txtcatcodes - -buffers = buffers or { } -local buffers = buffers - -local cache = { } - -local function erase(name) - cache[name] = nil -end - -local function assign(name,str,catcodes) - cache[name] = { data = str, catcodes = catcodes } -end - -local function append(name,str) - local buffer = cache[name] - if buffer then - buffer.data = buffer.data .. str - else - cache[name] = { data = str } - end -end - -local function exists(name) - return cache[name] -end - -local function getcontent(name) - local buffer = name and cache[name] - return buffer and buffer.data or "" -end - -local function getlines(name) - local buffer = name and cache[name] - return buffer and splitlines(buffer.data) -end - -local function collectcontent(names,separator) -- no print - if type(names) == "string" then - names = settings_to_array(names) - end - local nnames = #names - if nnames == 0 then - return getcontent("") -- default buffer - elseif nnames == 1 then - return getcontent(names[1]) - else - local t, n = { }, 0 - for i=1,nnames do - local c = getcontent(names[i]) - if c ~= "" then - n = n + 1 - t[n] = c - end - end - return concat(t,separator or "\n") -- was \r - end -end - -local function loadcontent(names) -- no print - if type(names) == "string" then - names = settings_to_array(names) - end - local nnames = #names - local ok = false - if nnames == 0 then - ok = load(getcontent("")) -- default buffer - elseif nnames == 1 then - ok = load(getcontent(names[1])) - else - -- lua 5.2 chunked load - local i = 0 - ok = load(function() - while true do - i = i + 1 - if i > nnames then - return nil - end - local c = getcontent(names[i]) - if c == "" then - -- would trigger end of load - else - return c - end - end - end) - end - if ok then - return ok() - elseif nnames == 0 then - report_buffers("invalid lua code in default buffer") - else - report_buffers("invalid lua code in buffer %a",concat(names,",")) - end -end - - -buffers.raw = getcontent -buffers.erase = erase -buffers.assign = assign -buffers.append = append -buffers.exists = exists -buffers.getcontent = getcontent -buffers.getlines = getlines -buffers.collectcontent = collectcontent -buffers.loadcontent = loadcontent - --- the context interface - -commands.erasebuffer = erase -commands.assignbuffer = assign - -local anything = patterns.anything -local alwaysmatched = patterns.alwaysmatched - -local function countnesting(b,e) - local n - local g = P(b) / function() n = n + 1 end - + P(e) / function() n = n - 1 end - + anything - local p = alwaysmatched / function() n = 0 end - * g^0 - * alwaysmatched / function() return n end - return p -end - -local counters = { } -local nesting = 0 -local autoundent = true -local continue = false - --- Beware: the first character of bufferdata has to be discarded as it's there to --- prevent gobbling of newlines in the case of nested buffers. The last one is --- a newlinechar and is removed too. --- --- An \n is unlikely to show up as \r is the endlinechar but \n is more generic --- for us. - --- This fits the way we fetch verbatim: the indentatio before the sentinel --- determines the stripping. - --- str = [[ --- test test test test test test test --- test test test test test test test --- test test test test test test test --- --- test test test test test test test --- test test test test test test test --- test test test test test test test --- ]] - --- local function undent(str) --- local margin = match(str,"[\n\r]( +)[\n\r]*$") or "" --- local indent = #margin --- if indent > 0 then --- local lines = splitlines(str) --- local ok = true --- local pattern = "^" .. margin --- for i=1,#lines do --- local l = lines[i] --- if find(l,pattern) then --- lines[i] = sub(l,indent+1) --- else --- ok = false --- break --- end --- end --- if ok then --- return concat(lines,"\n") --- end --- end --- return str --- end - --- how about tabs - -local getmargin = (Cs(P(" ")^1)*P(-1)+1)^1 -local eol = patterns.eol -local whatever = (P(1)-eol)^0 * eol^1 - -local strippers = { } - -local function undent(str) -- new version, needs testing - local margin = lpegmatch(getmargin,str) - if type(margin) ~= "string" then - return str - end - local indent = #margin - if indent == 0 then - return str - end - local stripper = strippers[indent] - if not stripper then - stripper = Cs((P(margin)/"" * whatever + eol^1)^1) - strippers[indent] = stripper - end - return lpegmatch(stripper,str) or str -end - -function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe move \\ to call - local dn = getcontent(name) - if dn == "" then - nesting = 0 - continue = false - end - if trace_grab then - if #bufferdata > 30 then - report_grabbing("%s => |%s..%s|",name,sub(bufferdata,1,10),sub(bufferdata,-10,#bufferdata)) - else - report_grabbing("%s => |%s|",name,bufferdata) - end - end - local counter = counters[begintag] - if not counter then - counter = countnesting(begintag,endtag) - counters[begintag] = counter - end - nesting = nesting + lpegmatch(counter,bufferdata) - local more = nesting > 0 - if more then - dn = dn .. sub(bufferdata,2,-1) .. endtag - nesting = nesting - 1 - continue = true - else - if continue then - dn = dn .. sub(bufferdata,2,-2) -- no \r, \n is more generic - elseif dn == "" then - dn = sub(bufferdata,2,-2) - else - dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic - end - local last = sub(dn,-1) - if last == "\n" or last == "\r" then -- \n is unlikely as \r is the endlinechar - dn = sub(dn,1,-2) - end - if autoundent then - dn = undent(dn) - end - end - assign(name,dn,catcodes) - commands.doifelse(more) -end - --- The optional prefix hack is there for the typesetbuffer feature and --- in mkii we needed that (this hidden feature is used in a manual). - -local function prepared(name,list,prefix) -- list is optional - if not list or list == "" then - list = name - end - if not name or name == "" then - name = list - end - local content = collectcontent(list,nil) or "" - if content == "" then - content = "empty buffer" - end - if prefix then - local name = file.addsuffix(name,"tmp") - return tex.jobname .. "-" .. name, content - else - return name, content - end -end - -local capsule = "\\starttext\n%s\n\\stoptext\n" -local command = "context %s" - -function commands.runbuffer(name,list,encapsulate) - local name, content = prepared(name,list) - if encapsulate then - content = format(capsule,content) - end - local data = io.loaddata(name) - if data ~= content then - if trace_run then - report_buffers("changes in %a, processing forced",name) - end - io.savedata(name,content) - os.execute(format(command,name)) - elseif trace_run then - report_buffers("no changes in %a, not processed",name) - end -end - -function commands.savebuffer(list,name,prefix) -- name is optional - local name, content = prepared(name,list,prefix==v_yes) - io.savedata(name,content) -end - -function commands.getbuffer(name) - local str = getcontent(name) - if str ~= "" then - context.viafile(str,formatters["buffer.%s"](validstring(name,"noname"))) - end -end - -function commands.getbuffermkvi(name) -- rather direct ! - context.viafile(resolvers.macros.preprocessed(getcontent(name)),formatters["buffer.%s.mkiv"](validstring(name,"noname"))) -end - -function commands.gettexbuffer(name) - local buffer = name and cache[name] - if buffer and buffer.data ~= "" then - context.pushcatcodetable() - if buffer.catcodes == txtcatcodes then - context.setcatcodetable(txtcatcodes) - else - context.setcatcodetable(ctxcatcodes) - end - -- context(function() context.viafile(buffer.data) end) - context.getbuffer { name } -- viafile flushes too soon - context.popcatcodetable() - end -end - -commands.getbufferctxlua = loadcontent - -function commands.doifelsebuffer(name) - commands.doifelse(exists(name)) -end - --- This only used for mp buffers and is a kludge. Don't change the --- texprint into texsprint as it fails because "p<nl>enddef" becomes --- "penddef" then. - --- function commands.feedback(names) --- texprint(ctxcatcodes,splitlines(collectcontent(names))) --- end - -function commands.feedback(names) -- bad name, maybe rename to injectbuffercontent - context.printlines(collectcontent(names)) -end +if not modules then modules = { } end modules ['buff-ini'] = {
+ version = 1.001,
+ comment = "companion to buff-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local trace_run = false trackers.register("buffers.run", function(v) trace_run = v end)
+local trace_grab = false trackers.register("buffers.grab", function(v) trace_grab = v end)
+local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end)
+
+local report_buffers = logs.reporter("buffers","usage")
+local report_grabbing = logs.reporter("buffers","grabbing")
+
+local context, commands = context, commands
+
+local concat = table.concat
+local type, next, load = type, next, load
+local sub, format = string.sub, string.format
+local splitlines, validstring = string.splitlines, string.valid
+local P, Cs, patterns, lpegmatch = lpeg.P, lpeg.Cs, lpeg.patterns, lpeg.match
+
+local variables = interfaces.variables
+local settings_to_array = utilities.parsers.settings_to_array
+local formatters = string.formatters
+
+local v_yes = variables.yes
+
+local catcodenumbers = catcodes.numbers
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+
+buffers = buffers or { }
+local buffers = buffers
+
+local cache = { }
+
+local function erase(name)
+ cache[name] = nil
+end
+
+local function assign(name,str,catcodes)
+ cache[name] = { data = str, catcodes = catcodes }
+end
+
+local function append(name,str)
+ local buffer = cache[name]
+ if buffer then
+ buffer.data = buffer.data .. str
+ else
+ cache[name] = { data = str }
+ end
+end
+
+local function exists(name)
+ return cache[name]
+end
+
+local function getcontent(name)
+ local buffer = name and cache[name]
+ return buffer and buffer.data or ""
+end
+
+local function getlines(name)
+ local buffer = name and cache[name]
+ return buffer and splitlines(buffer.data)
+end
+
+local function collectcontent(names,separator) -- no print
+ if type(names) == "string" then
+ names = settings_to_array(names)
+ end
+ local nnames = #names
+ if nnames == 0 then
+ return getcontent("") -- default buffer
+ elseif nnames == 1 then
+ return getcontent(names[1])
+ else
+ local t, n = { }, 0
+ for i=1,nnames do
+ local c = getcontent(names[i])
+ if c ~= "" then
+ n = n + 1
+ t[n] = c
+ end
+ end
+ return concat(t,separator or "\n") -- was \r
+ end
+end
+
+local function loadcontent(names) -- no print
+ if type(names) == "string" then
+ names = settings_to_array(names)
+ end
+ local nnames = #names
+ local ok = false
+ if nnames == 0 then
+ ok = load(getcontent("")) -- default buffer
+ elseif nnames == 1 then
+ ok = load(getcontent(names[1]))
+ else
+ -- lua 5.2 chunked load
+ local i = 0
+ ok = load(function()
+ while true do
+ i = i + 1
+ if i > nnames then
+ return nil
+ end
+ local c = getcontent(names[i])
+ if c == "" then
+ -- would trigger end of load
+ else
+ return c
+ end
+ end
+ end)
+ end
+ if ok then
+ return ok()
+ elseif nnames == 0 then
+ report_buffers("invalid lua code in default buffer")
+ else
+ report_buffers("invalid lua code in buffer %a",concat(names,","))
+ end
+end
+
+
+buffers.raw = getcontent
+buffers.erase = erase
+buffers.assign = assign
+buffers.append = append
+buffers.exists = exists
+buffers.getcontent = getcontent
+buffers.getlines = getlines
+buffers.collectcontent = collectcontent
+buffers.loadcontent = loadcontent
+
+-- the context interface
+
+commands.erasebuffer = erase
+commands.assignbuffer = assign
+
+local anything = patterns.anything
+local alwaysmatched = patterns.alwaysmatched
+
+local function countnesting(b,e)
+ local n
+ local g = P(b) / function() n = n + 1 end
+ + P(e) / function() n = n - 1 end
+ + anything
+ local p = alwaysmatched / function() n = 0 end
+ * g^0
+ * alwaysmatched / function() return n end
+ return p
+end
+
+local counters = { }
+local nesting = 0
+local autoundent = true
+local continue = false
+
+-- Beware: the first character of bufferdata has to be discarded as it's there to
+-- prevent gobbling of newlines in the case of nested buffers. The last one is
+-- a newlinechar and is removed too.
+--
+-- An \n is unlikely to show up as \r is the endlinechar but \n is more generic
+-- for us.
+
+-- This fits the way we fetch verbatim: the indentatio before the sentinel
+-- determines the stripping.
+
+-- str = [[
+-- test test test test test test test
+-- test test test test test test test
+-- test test test test test test test
+--
+-- test test test test test test test
+-- test test test test test test test
+-- test test test test test test test
+-- ]]
+
+-- local function undent(str)
+-- local margin = match(str,"[\n\r]( +)[\n\r]*$") or ""
+-- local indent = #margin
+-- if indent > 0 then
+-- local lines = splitlines(str)
+-- local ok = true
+-- local pattern = "^" .. margin
+-- for i=1,#lines do
+-- local l = lines[i]
+-- if find(l,pattern) then
+-- lines[i] = sub(l,indent+1)
+-- else
+-- ok = false
+-- break
+-- end
+-- end
+-- if ok then
+-- return concat(lines,"\n")
+-- end
+-- end
+-- return str
+-- end
+
+-- how about tabs
+
+local getmargin = (Cs(P(" ")^1)*P(-1)+1)^1
+local eol = patterns.eol
+local whatever = (P(1)-eol)^0 * eol^1
+
+local strippers = { }
+
+local function undent(str) -- new version, needs testing
+ local margin = lpegmatch(getmargin,str)
+ if type(margin) ~= "string" then
+ return str
+ end
+ local indent = #margin
+ if indent == 0 then
+ return str
+ end
+ local stripper = strippers[indent]
+ if not stripper then
+ stripper = Cs((P(margin)/"" * whatever + eol^1)^1)
+ strippers[indent] = stripper
+ end
+ return lpegmatch(stripper,str) or str
+end
+
+function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe move \\ to call
+ local dn = getcontent(name)
+ if dn == "" then
+ nesting = 0
+ continue = false
+ end
+ if trace_grab then
+ if #bufferdata > 30 then
+ report_grabbing("%s => |%s..%s|",name,sub(bufferdata,1,10),sub(bufferdata,-10,#bufferdata))
+ else
+ report_grabbing("%s => |%s|",name,bufferdata)
+ end
+ end
+ local counter = counters[begintag]
+ if not counter then
+ counter = countnesting(begintag,endtag)
+ counters[begintag] = counter
+ end
+ nesting = nesting + lpegmatch(counter,bufferdata)
+ local more = nesting > 0
+ if more then
+ dn = dn .. sub(bufferdata,2,-1) .. endtag
+ nesting = nesting - 1
+ continue = true
+ else
+ if continue then
+ dn = dn .. sub(bufferdata,2,-2) -- no \r, \n is more generic
+ elseif dn == "" then
+ dn = sub(bufferdata,2,-2)
+ else
+ dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic
+ end
+ local last = sub(dn,-1)
+ if last == "\n" or last == "\r" then -- \n is unlikely as \r is the endlinechar
+ dn = sub(dn,1,-2)
+ end
+ if autoundent then
+ dn = undent(dn)
+ end
+ end
+ assign(name,dn,catcodes)
+ commands.doifelse(more)
+end
+
+-- The optional prefix hack is there for the typesetbuffer feature and
+-- in mkii we needed that (this hidden feature is used in a manual).
+
+local function prepared(name,list,prefix) -- list is optional
+ if not list or list == "" then
+ list = name
+ end
+ if not name or name == "" then
+ name = list
+ end
+ local content = collectcontent(list,nil) or ""
+ if content == "" then
+ content = "empty buffer"
+ end
+ if prefix then
+ local name = file.addsuffix(name,"tmp")
+ return tex.jobname .. "-" .. name, content
+ else
+ return name, content
+ end
+end
+
+local capsule = "\\starttext\n%s\n\\stoptext\n"
+local command = "context %s"
+
+function commands.runbuffer(name,list,encapsulate)
+ local name, content = prepared(name,list)
+ if encapsulate then
+ content = format(capsule,content)
+ end
+ local data = io.loaddata(name)
+ if data ~= content then
+ if trace_run then
+ report_buffers("changes in %a, processing forced",name)
+ end
+ io.savedata(name,content)
+ os.execute(format(command,name))
+ elseif trace_run then
+ report_buffers("no changes in %a, not processed",name)
+ end
+end
+
+function commands.savebuffer(list,name,prefix) -- name is optional
+ local name, content = prepared(name,list,prefix==v_yes)
+ io.savedata(name,content)
+end
+
+function commands.getbuffer(name)
+ local str = getcontent(name)
+ if str ~= "" then
+ context.viafile(str,formatters["buffer.%s"](validstring(name,"noname")))
+ end
+end
+
+function commands.getbuffermkvi(name) -- rather direct !
+ context.viafile(resolvers.macros.preprocessed(getcontent(name)),formatters["buffer.%s.mkiv"](validstring(name,"noname")))
+end
+
+function commands.gettexbuffer(name)
+ local buffer = name and cache[name]
+ if buffer and buffer.data ~= "" then
+ context.pushcatcodetable()
+ if buffer.catcodes == txtcatcodes then
+ context.setcatcodetable(txtcatcodes)
+ else
+ context.setcatcodetable(ctxcatcodes)
+ end
+ -- context(function() context.viafile(buffer.data) end)
+ context.getbuffer { name } -- viafile flushes too soon
+ context.popcatcodetable()
+ end
+end
+
+commands.getbufferctxlua = loadcontent
+
+function commands.doifelsebuffer(name)
+ commands.doifelse(exists(name))
+end
+
+-- This only used for mp buffers and is a kludge. Don't change the
+-- texprint into texsprint as it fails because "p<nl>enddef" becomes
+-- "penddef" then.
+
+-- function commands.feedback(names)
+-- texprint(ctxcatcodes,splitlines(collectcontent(names)))
+-- end
+
+function commands.feedback(names) -- bad name, maybe rename to injectbuffercontent
+ context.printlines(collectcontent(names))
+end
|