Автоматически определяет все пакеты ctan, необходимые для компиляции

Автоматически определяет все пакеты ctan, необходимые для компиляции

Я держу относительно скудный texlive и устанавливаю отдельные пакеты по мере необходимости через tlmgr. Иногда я начинаю работать с коллегой и мне приходится составлять новую статью.

Прямо сейчас мой процесс заключается в попытке компиляции (обычно с помощью pdflatex). Если компилятор жалуется, например, говоря File 'cancel.sty' not found, то я устанавливаю необходимый пакет через tlmgr. Затем я пытаюсь скомпилировать снова и повторяю по мере необходимости.

Конечно, это не самое худшее. Чтобы вникнуть в новый проект, нужно, наверное, минут 5. Но было бы неплохо, если бы был инструмент для определениявсенеобходимые или отсутствующие пакеты сразу. Я представляю себе инструмент, который собирает все зависимости и пишет что-то вроде , dependencies.txtкоторые распространены в python.

Существует ли что-то подобное?


Я также отмечу, что я, возможно, пытаюсь оптимизировать неправильное решение этой проблемы. Если я должен думать об управлении зависимостями совершенно по-другому, то, пожалуйста, дайте мне знать. Но я не планирую устанавливать огромный texlive из-за нехватки места.

решение1

Можно написать скрипт, который сделает разумный объем работы в Lua. Скрипт ниже работает с использованием --recorderданных TeX Live, поэтому вам нужно сделать что-то вроде

pdflatex <name> --recorder

до

texlua depreader.lua <name>

(предполагая, что вы вызываете скрипт depreader.lua, что у меня и есть). Затем есть еще несколько ограничений

  • Могут быть извлечены только файлы, считываемые с помощью TeX; то, что нужно, например, Biber или MakeIndex, будет упущено ( kpseя подозреваю, что для их извлечения потребуется некая модифицированная версия, больше похожая на MiKTeX).
  • Вам необходимо убедиться, что для запуска регистратора все настроено (например, условная загрузка, многократные запуски и т. д. могут вызвать проблемы).
  • Он не распознает файлы, используемые при построении формата (шаблоны переносов и т. д.)
  • Это довольно медленно, так как для этого нужно tlmgrвызватькаждыйимя файла
  • Он не учитывает зависимости, перечисленные в базе данных TeX Live (поэтому каждый пакет TL указан явно)

Тем не менее, я думаю, это заставит вас двигаться дальше:

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

Если есть интерес, я могу попытаться сделать это немного более плавным, но не до такой степени, чтобы пытаться делать то latexmk, что и т. д., с точки зрения многократных запусков и т. п.

Связанный контент