单独的 LaTeX 样式文件中的 Lua 脚本

单独的 LaTeX 样式文件中的 Lua 脚本

我已XML在 的帮助下成功加载了 LuaLaTeX Michal.h21。现在我想将所有自定义定义存储Lua Script在单独的 LaTeX 样式文件中,例如bibr.sty,以便我只\usepackage{bibr}在 LaTeX 文件中调用。

该文件中bibr.sty所有自定义的定义都lua script需要进行定义。

我的 BIBR 交叉链接 XML 文件如下:

\documentclass{article}
\usepackage{luacode}
\usepackage{natbib}

\begin{document}

\begin{luacode*}
local domobject = require "luaxml-domobject"
local transform = require "luaxml-transform"
sample = [[
<?xml version="1.0" encoding="utf-8"?>
<art>
<title>Scattering of flexural waves an electric current</title>
<para>The first <xref ref-type="section" rid="Sec1">Section 1</xref> description and correlation between gait impairment and hydrocephalus were made in 1965 by Hakim and Adam (<xref ref-type="bibr" rid="B1">1</xref>). The etiology of idiopathic normal pressure hydrocephalus (iNPH) has not yet been entirely understood (<xref ref-type="bibr" rid="B2">2</xref>&#x02013;<xref ref-type="bibr" rid="B5">5</xref>). In elderly patients, other conditions such as spinal canal stenosis, Parkinson&#x00027;s disease, and polyneuropathy may influence the gait negatively.</para>
</art>]]

local dom = domobject.parse(sample)
local function process_instructions(el)

-- try to find <xref> followed by dash and another <xref>
-- we then expand rid attributes
for _, xref in ipairs(dom:query_selector("xref[ref-type='bibr']")) do
  local first = xref:get_sibling_node(1)
  local second = xref:get_sibling_node(2)
  if first and second and
     first:is_text() and first:get_text() == "–" and -- next node must be "–" text
     second:is_element() and second:get_element_name() == "xref" -- second element must be <xref>
  then
    local rid1 = xref:get_attribute("rid") or ""
    local rid2 = second:get_attribute("rid") or ""
    local prefix1, number1 = rid1:match("(%a+)(%d+)")
    local prefix2, number2 = rid2:match("(%a+)(%d+)")
    -- expand only if prefixes match each other
    if prefix1 and prefix2 and prefix1 == prefix2 then
      -- expand numbers
      local t = {}
      for i = number1, number2 do
        t[#t+1] = prefix1 .. math.floor(i)
      end
      -- save expanded numbers
      xref:set_attribute("rid", table.concat(t, ","))
      -- remove unnecessary elements
      first:remove_node()
      second:remove_node()
    end
  end

  
end
end

process_instructions(dom:root_node())

local transformer = transform.new()
transformer:add_action("title", "\\section{@<.>}")
transformer:add_action("para", "@<.>\\par")
transformer:add_action("xref[ref-type='bibr']", "\\citep{@{rid}}")
-- handle the processing instruction
transformer:add_custom_action("lualatex-instruction",
    function(el)
        return el:get_attribute("text")
    end)
local result = transformer:process_dom(dom)
-- Print Output Result in Command-Prompt/Terminal
print(result)
-- Print Output Result in PDF uncomment below
--transform.print_tex(result)
\end{luacode*}
\end{document}

如何实现这一点?

答案1

正如 David 所建议的,将 Lua 代码移至独立文件是一个好主意,以防止 TeX 和 Lua 之间的一些交互问题。它可能看起来像这样bibr.lua

local M = {}
local domobject = require "luaxml-domobject"
local transform = require "luaxml-transform"

local function process_instructions(el)
  for _, child in ipairs(el:get_children()) do
    local ntype = child:get_node_type()
    if ntype == "PI" and child._name=="LuaLaTeX" then
      local text = child._attr[ "_text" ]
      local newel = el:create_element("lualatex-instruction", {text = text})
      child:replace_node(newel)
    end
    if child:is_element() then
      process_instructions(child)
    end
  end
end

function M.process(sample)
  local dom = domobject.parse(sample)
  -- try to find <xref> followed by dash and another <xref>
  -- we then expand rid attributes
  for _, xref in ipairs(dom:query_selector("xref[ref-type='bibr']")) do
    local first = xref:get_sibling_node(1)
    local second = xref:get_sibling_node(2)
    if first and second and
      first:is_text() and first:get_text() == "–" and -- next node must be "–" text
      second:is_element() and second:get_element_name() == "xref" -- second element must be <xref>
    then
      local rid1 = xref:get_attribute("rid") or ""
      local rid2 = second:get_attribute("rid") or ""
      local prefix1, number1 = rid1:match("(%a+)(%d+)")
      local prefix2, number2 = rid2:match("(%a+)(%d+)")
      -- expand only if prefixes match each other
      if prefix1 and prefix2 and prefix1 == prefix2 then
        -- expand numbers
        local t = {}
        for i = number1, number2 do
          t[#t+1] = prefix1 .. math.floor(i)
        end
        -- save expanded numbers
        xref:set_attribute("rid", table.concat(t, ","))
        -- remove unnecessary elements
        first:remove_node()
        second:remove_node()
      end
    end


  end

  process_instructions(dom:root_node())

  local transformer = transform.new()
  transformer:add_action("title", "\\section{@<.>}")
  transformer:add_action("para", "@<.>\\par")
  transformer:add_action("xref[ref-type='bibr']", "\\citep{@{rid}}")
  -- handle the processing instruction
  transformer:add_custom_action("lualatex-instruction",
  function(el)
    return el:get_attribute("text")
  end)
  local result = transformer:process_dom(dom)
  print(result)
  transform.print_tex(result)
end

function M.process_file(filename)
  local f = io.open(filename, "r")
  if not f then return nil, "Cannot open file: " .. filename end
  local content = f:read("*all")
  f:close()
  M.process(content)
end

return M

我已将环境主体中原来的代码移至luacode函数中M.process。该M表从此库返回,因此您可以按以下方式使用此代码:

 local bibr = require "bibr"
 bibr.process("xml code...")

我还制作了另一个函数,M.process_file它将转换 XML 文件,因此您不需要将 XML 代码传递给您的文档。

然后,您需要一个 LaTeX 包,它将提供可以在您的文档中使用的命令。它看起来像这样bibr.sty

\ProvidesPackage{bibr}

\NewDocumentEnvironment{processbibr}{+b}{%
  \directlua{
    local bibr = require "bibr"
    bibr.process([[\unexpanded{#1}]])
  }
}{}

\NewDocumentCommand\processbibrfile{m}{%
  \directlua{%
    local bibr = require "bibr"
    bibr.process_file("#1")
  }
}

\endinput

它提供processbibr环境和\processbibrfile命令。如果要将 XML 代码放入文档中,可以使用环境;如果要包含外部 XML 文件,可以使用命令。

它可以像这样使用:

\documentclass{article}
\usepackage{natbib}
\usepackage{bibr}
\begin{document}
\begin{processbibr}
<?xml version="1.0" encoding="utf-8"?>
<art>
<title>Scattering of flexural waves an electric current</title>
<para>Smart testing structures are $a+b$ components Reduce acoustic noise used in engineering applications that are capable of sensing or reacting to their environment change <?LuaLaTeX Sample XXX1?> their mechanical properties. in a predictable and desired manner. In addition to carrying mechanical loads, <?LuaLaTeX \hspace*{12pt}Abc?> alleviate vibration, reduce acoustic noise, change their mechanical properties as required or monitor their own condition.</para>
<para>The first <xref ref-type="section" rid="Sec1">Section 1</xref> description and correlation between gait impairment and hydrocephalus were made in 1965 by Hakim and Adam (<xref ref-type="bibr" rid="B1">1</xref>). The etiology of idiopathic normal pressure hydrocephalus (iNPH) has not yet been entirely understood (<xref ref-type="bibr" rid="B2">2</xref>&#x02013;<xref ref-type="bibr" rid="B5">5</xref>). In elderly patients, other conditions such as spinal canal stenosis, Parkinson&#x00027;s disease, and polyneuropathy may influence the gait negatively.</para>
</art>
\end{processbibr}

\processbibrfile{test.xml}
\end{document}

总的来说,我认为最好使用\processbibrfile,因为当您将 XML 文件直接包含到 TeX 文件中时,您不会遇到可能发生的奇怪错误。

结果如下:

在此处输入图片描述

答案2

你把这个

\ProvidesPackage{bibr}
\RequirePackage{luacode}
\begin{luacode*}
% HERE YOUR CODE, exactly as it is in your example
\end{luacode*}

在文件中,并将其以.sty扩展名保存在与您的.tex.

相关内容