コンパイルに必要なすべてのctanパッケージを自動的に決定します

コンパイルに必要なすべてのctanパッケージを自動的に決定します

私は比較的シンプルな texlive を維持し、必要に応じて tlmgr を通じて個別のパッケージをインストールします。同僚と共同作業を開始し、新しい論文をコンパイルしなければならないこともあります。

現時点での私のプロセスは、コンパイルを試みることです (通常は pdflatex を使用)。コンパイラが、たとえば とエラーを出力した場合はFile 'cancel.sty' not found、tlmgr を通じて必要なパッケージをインストールします。その後、再度コンパイルを試み、必要に応じてこれを繰り返します。

確かに、これは最悪なことではありません。新しいプロジェクトに慣れるのに5分ほどかかるかもしれません。しかし、それを判断できるツールがあればいいのですが全てdependencies.txt必要なパッケージや不足しているパッケージを一度に見つけます。すべての依存関係を収集し、 Python で一般的な のようなものを書き込むツールを想像しています。

そのようなものは存在するのでしょうか?


また、この問題に対して間違った解決策を最適化しようとしている可能性があることにも留意します。依存関係の管理についてまったく異なる方法で考えるべきであれば、お知らせください。ただし、スペース上の理由から、巨大な texlive をインストールする予定はありません。

答え1

Luaである程度の処理をスクリプト化することができます。以下のスクリプトはTeX Liveの--recorderデータを使用して動作します。そのため、次のようなことをする必要があります。

pdflatex <name> --recorder

前に

texlua depreader.lua <name>

(スクリプトを呼び出すと仮定しますdepreader.lua。これは私が持っているものです)。さらにいくつかの制限があります。

  • 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興味があれば、これをもう少しスムーズにするかもしれませんが、複数回の実行などに関して、などが行うことをしようとするほどではありません。

関連情報