컴파일에 필요한 모든 ctan 패키지를 자동으로 결정

컴파일에 필요한 모든 ctan 패키지를 자동으로 결정

나는 상대적으로 간결한 texlive를 유지하고 tlmgr을 통해 필요에 따라 개별 패키지를 설치합니다. 때로는 동료와 함께 작업을 시작하고 새 논문을 작성해야 할 때도 있습니다.

현재 내 프로세스는 컴파일(일반적으로 pdflatex 사용)을 시도하는 것입니다. 예를 들어 컴파일러가 이라고 불평하면 File 'cancel.sty' not foundtlmgr을 통해 필요한 패키지를 설치합니다. 그런 다음 다시 컴파일하고 필요에 따라 반복합니다.

물론 이것이 최악의 상황은 아닙니다. 새로운 프로젝트를 진행하는 데 5분 정도 걸립니다. 하지만 판단할 수 있는 도구가 있으면 좋을 것 같아요.모두필요하거나 누락된 패키지를 한 번에. 저는 모든 종속성을 수집하고 dependencies.txtPython에서 흔히 볼 수 있는 것과 같은 것을 작성하는 도구를 상상하고 있습니다 .

그런 것이 존재합니까?


또한 나는 이 문제에 대한 잘못된 해결책을 최적화하려고 노력할 수도 있다는 점에 유의할 것입니다. 종속성 관리에 대해 완전히 다른 방식으로 생각해야 한다면 알려주시기 바랍니다. 하지만 공간상의 이유로 거대한 texlive를 설치할 계획은 없습니다.

답변1

Lua에서 합리적인 양의 작업을 수행하기 위해 스크립트를 작성할 수 있습니다. 아래 스크립트는 TeX Live의 --recorder데이터를 사용하여 작동하므로 다음과 같은 작업을 수행해야 합니다.

pdflatex <name> --recorder

~ 전에

texlua depreader.lua <name>

depreader.lua(당신이 내가 가지고 있는 script 를 호출한다고 가정합니다 ). 그 다음에는 몇 가지 제한 사항이 더 있습니다.

  • TeX 실행으로 읽은 파일만 선택할 수 있습니다. 예를 들어 Biber 또는 MakeIndex에 필요한 것들은 누락될 것입니다(이것을 선택하려면 kpseMiKTeX와 더 유사한 수정된 형태가 필요할 것입니다 ).
  • 레코더 실행에 모든 것이 설정되어 있는지 확인하는 것은 사용자의 몫입니다(예: 조건부 로드, 다중 실행 등으로 인해 문제가 발생할 수 있음).
  • 형식 작성(하이픈 연결 패턴 등)에 사용된 파일은 선택하지 않습니다.
  • 전화를 걸어야 하기 때문에 꽤 느립니다 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다중 실행 등의 측면에서 , 등이 수행할 작업을 시도할 정도는 아닙니다.

관련 정보