Determinar automáticamente todos los paquetes ctan necesarios para compilar

Determinar automáticamente todos los paquetes ctan necesarios para compilar

Mantengo un texlive relativamente sencillo e instalo paquetes individuales según sea necesario a través de tlmgr. A veces empiezo a trabajar con un colega y tengo que redactar un nuevo artículo.

En este momento, mi proceso es intentar compilar (normalmente con pdflatex). Si el compilador se queja, por ejemplo, diciendo File 'cancel.sty' not found, instalaré el paquete necesario a través de tlmgr. Luego intento compilar nuevamente y repetir según sea necesario.

Es cierto que esto no es lo peor. Se necesitan quizás 5 minutos para ponerse al día con un nuevo proyecto. Pero sería bueno si hubiera una herramienta para determinartodopaquetes necesarios o faltantes a la vez. Me estoy imaginando una herramienta que recopila todas las dependencias y escribe algo así como dependencies.txtque son comunes en Python.

Algo como eso existe?


También señalaré que es posible que esté intentando optimizar una solución incorrecta a este problema. Si debería pensar en la gestión de la dependencia de una manera totalmente diferente, hágamelo saber. Pero no tengo pensado instalar un texlive enorme por cuestiones de espacio.

Respuesta1

Se puede escribir algo para hacer una cantidad razonable del trabajo en Lua. El siguiente script funciona con --recorderlos datos de TeX Live, por lo que debes hacer algo como

pdflatex <name> --recorder

antes

texlua depreader.lua <name>

(suponiendo que llames al script depreader.lua, que es lo que tengo). Luego hay algunas restricciones más.

  • Sólo se pueden recoger archivos leídos mediante una ejecución TeX; Se perderán las cosas que necesitan, por ejemplo, Biber o MakeIndex ( kpsesospecho que para recogerlas necesitaría algún tipo de modificación, más parecido a MiKTeX)
  • Depende de usted asegurarse de que la ejecución de la grabadora tenga todo configurado (por ejemplo, la carga condicional, ejecuciones múltiples, etc. pueden causar problemas)
  • No recoge archivos utilizados en la creación de formatos (patrones de separación de palabras, etc.)
  • Es bastante lento ya que necesita tlmgrllamarcadaNombre del archivo
  • No tiene en cuenta las dependencias enumeradas en la base de datos de TeX Live (por lo que cada paquete TL se enumera explícitamente)

Dicho esto, creo que te pondrá en movimiento:

local name = arg[1] or "test"

local execute = os.execute
local find = string.find
local gmatch = string.gmatch
local gsub = string.gsub
local insert = table.insert
local match = string.match
local popen = io.popen
local sort = table.sort

local function extract_name(file)
  local path, name = match(file,"^(.*)/([^/]*)$")
  if path then
    return name
  else
    return file
  end
end

local f = io.open(name .. ".fls")
local data = gsub(f:read("*all") .. "\n","\r\n","\n")

local t = {}

for line in gmatch(data,"([^\n]*)\n") do
  if not (line == ""
       or match(line,name .. ".tex$")
       or match(line,"^PWD ")
       or match(line,"^OUTPUT")
       or match(line,"^INPUT %./")
       or match(line,"%.aux$")
       or match(line,"%.cnf$")
       or match(line,"%.fmt$")
       or match(line,"texmf%-var")) then
    local file = extract_name(gsub(line,"^INPUT ",""))
    t[file] = line
  end
end

local pkgs = {}
local unmatched = {}

for name,path in pairs(t) do
  local f = popen("tlmgr search --file /" .. name)
  local data = f:read("*all")
  local _,n = gsub(data,":","")
  if n == 1 then
    pkgs[match(data,"^([^:]*)")] = true
  elseif n == 0 then
    unmatched[name] = true
  else
    local function search(data,path)
      local pkgline = ""
      for line in gmatch(data,"([^\n]*)\n") do
        if match(line,":$") then
          pkgline = line
        else
          -- Find 'plain' - no patterns, also trimming spaces
          if find(path,gsub(line,"%s+",""),0,true) then
            return gsub(pkgline,":$","")
          end
        end
      end
      return false
    end
    local pkg = search(data,path)
    if pkg then
      pkgs[pkg] = true
    else
      unmatched[name] = true
    end
  end
end

local function print_sorted(t)
  local s = {}
  for k,_ in pairs(t) do
    insert(s,k)
  end
  sort(s)
  for _,v in ipairs(s) do
    print(v)
  end
end

print("TeX Live packages")
print_sorted(pkgs)

if next(unmatched) then
  print("\nNo match for")
  print_sorted(unmatched)
end

Si hay interés, puedo intentar hacer esto un poco más fluido, pero no hasta el punto de intentar hacer lo que haría latexmk, etc., en términos de ejecuciones múltiples, etc.

información relacionada