Automatische Ermittlung aller zum Kompilieren notwendigen Ctan-Pakete

Automatische Ermittlung aller zum Kompilieren notwendigen Ctan-Pakete

Ich halte Texlive relativ schlank und installiere einzelne Pakete bei Bedarf über tlmgr. Manchmal beginne ich mit der Arbeit mit einem Kollegen und muss ein neues Paper zusammenstellen.

Im Moment versuche ich, zu kompilieren (normalerweise mit pdflatex). Wenn der Compiler beispielsweise eine Fehlermeldung ausgibt File 'cancel.sty' not found, installiere ich das erforderliche Paket über tlmgr. Dann versuche ich erneut zu kompilieren und wiederhole dies bei Bedarf.

Zugegeben, das ist nicht das Schlimmste. Es dauert vielleicht 5 Minuten, um in ein neues Projekt einzusteigen. Aber es wäre schön, wenn es ein Tool gäbe, um festzustellenallenotwendige oder fehlende Pakete auf einmal. Ich stelle mir ein Tool vor, das alle Abhängigkeiten sammelt und so etwas wie ein schreibt, dependencies.txtdas in Python üblich ist.

Gibt es so etwas?


Ich möchte auch darauf hinweisen, dass ich möglicherweise versuche, eine falsche Lösung für dieses Problem zu optimieren. Wenn ich über die Abhängigkeitsverwaltung ganz anders nachdenken sollte, lassen Sie es mich bitte wissen. Aus Platzgründen habe ich jedoch nicht vor, ein riesiges Texlive zu installieren.

Antwort1

Man kann ein Skript erstellen, das einen Großteil der Arbeit in Lua erledigt. Das folgende Skript verwendet --recorderdie Daten von TeX Live, Sie müssen also etwas wie

pdflatex <name> --recorder

Vor

texlua depreader.lua <name>

(vorausgesetzt, Sie rufen das Skript auf depreader.lua, was bei mir der Fall ist). Es gibt dann noch ein paar weitere Einschränkungen

  • Es können nur Dateien abgerufen werden, die von einem TeX-Lauf gelesen werden; Dinge, die z. B. von Biber oder MakeIndex benötigt werden, werden übersehen (um diese abzurufen, müsste kpseich vermutlich eine Art Modifikation vornehmen, die eher MiKTeX ähnelt).
  • Es liegt in Ihrer Verantwortung, sicherzustellen, dass beim Rekorderdurchlauf alles eingerichtet ist (bedingtes Laden, mehrere Durchläufe usw. können beispielsweise zu Problemen führen).
  • Es werden keine Dateien erkannt, die beim Formataufbau verwendet werden (Silbentrennungsmuster usw.).
  • Es ist ziemlich langsam, da es aufrufen tlmgrmussjedenDateiname
  • Es berücksichtigt keine Abhängigkeiten, die in der TeX Live-Datenbank aufgeführt sind (deshalb wird jedes TL-Paket explizit aufgeführt).

Dennoch denke ich, dass es Sie in Bewegung bringen wird:

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

Wenn Interesse besteht, werde ich vielleicht versuchen, es ein bisschen reibungsloser zu gestalten, aber nicht in dem Maße, wie ich versuche, das zu tun latexmk, was usw. im Hinblick auf mehrere Durchläufe usw. tun würde.

verwandte Informationen