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 358c0f2a7..475d23efe 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 |