Determine automaticamente todos os pacotes ctan necessários para compilar

Determine automaticamente todos os pacotes ctan necessários para compilar

Eu mantenho um texlive relativamente enxuto e instalo pacotes individuais conforme necessário através do tlmgr. Às vezes começo a trabalhar com um colega e tenho que compilar um novo artigo.

No momento, meu processo é tentar compilar (normalmente com pdflatex). Se o compilador reclamar, por exemplo, dizendo File 'cancel.sty' not found, então instalarei o pacote necessário através do tlmgr. Então tento compilar novamente e repito conforme necessário.

É certo que isso não é a pior coisa. Demora talvez 5 minutos para começar a trabalhar em um novo projeto. Mas seria bom se houvesse uma ferramenta para determinartodospacotes necessários ou faltantes de uma só vez. Estou imaginando uma ferramenta que coleta todas as dependências e escreve algo como um dependencies.txtque é comum em python.

Existe algo assim?


Também observarei que posso estar tentando otimizar uma solução incorreta para esse problema. Se eu estiver pensando sobre o gerenciamento de dependências de uma maneira totalmente diferente, por favor me avise. Mas não tenho planos de instalar um enorme texlive por questões de espaço.

Responder1

Pode-se criar um script para fazer uma quantidade razoável de trabalho em Lua. O script abaixo funciona usando --recorderdados do TeX Live, então você precisa fazer algo como

pdflatex <name> --recorder

antes

texlua depreader.lua <name>

(supondo que você chame o script depreader.lua, que é o que eu tenho). Existem então mais algumas restrições

  • Somente arquivos lidos por uma execução do TeX podem ser obtidos; coisas necessárias, por exemplo, Biber ou MakeIndex serão perdidas (escolhê-las precisaria de alguma forma de modificação, kpseeu suspeito, mais semelhante ao MiKTeX)
  • Cabe a você garantir que a execução do gravador tenha tudo configurado (por exemplo, carregamento condicional, múltiplas execuções, etc. podem causar problemas)
  • Ele não coleta arquivos usados ​​na construção de formatos (padrões de hifenização, etc.)
  • É bastante lento, pois precisa tlmgrexigirtodonome do arquivo
  • Ele não leva em conta as dependências listadas no banco de dados TeX Live (portanto, cada pacote TL é listado explicitamente)

Dito isto, acho que você vai se mexer:

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

Se houver interesse, posso tentar tornar isso um pouco mais suave, mas não ao ponto de tentar fazer o que latexmk, etc., faria em termos de múltiplas execuções, etc.

informação relacionada